gmp 0.5.41 → 0.5.47

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/CHANGELOG +21 -0
  2. data/FEATURES.html +37 -38
  3. data/README.html +511 -0
  4. data/README.markdown +494 -0
  5. data/benchmark/divide +0 -0
  6. data/benchmark/gcd +0 -0
  7. data/benchmark/multiply +0 -0
  8. data/benchmark/multiply.fnl +0 -0
  9. data/benchmark/multiply.gc +0 -0
  10. data/benchmark/pi +0 -0
  11. data/benchmark/rsa +0 -0
  12. data/benchmark/runbench +0 -0
  13. data/benchmark/srb.sh +0 -0
  14. data/ext/gmp.c +0 -42
  15. data/ext/gmpf.c +64 -33
  16. data/ext/gmpq.c +88 -1
  17. data/ext/gmpz.c +151 -19
  18. data/ext/ruby_gmp.h +16 -10
  19. data/manual.pdf +0 -0
  20. data/manual.tex +50 -14
  21. data/test/gmp_tgcd.rb +18 -18
  22. data/test/mpfr_tcbrt.rb +1 -1
  23. data/test/mpfr_tconst_euler.rb +10 -7
  24. data/test/mpfr_tisnan.rb +1 -1
  25. data/test/mpfr_trec_sqrt.rb +1 -1
  26. data/test/mpfr_tsqrt.rb +1 -1
  27. data/test/tc_cmp.rb +7 -2
  28. data/test/tc_constants.rb +1 -1
  29. data/test/tc_division.rb +1 -1
  30. data/test/tc_f_arithmetics_coersion.rb +1 -1
  31. data/test/tc_f_precision.rb +1 -1
  32. data/test/tc_fib_fac_nextprime.rb +1 -1
  33. data/test/tc_floor_ceil_truncate.rb +1 -1
  34. data/test/tc_hashes.rb +26 -1
  35. data/test/tc_logical_roots.rb +1 -1
  36. data/test/tc_mpfr_constants.rb +1 -1
  37. data/test/tc_mpfr_functions.rb +1 -1
  38. data/test/tc_mpfr_random.rb +1 -1
  39. data/test/tc_mpfr_rounding.rb +3 -3
  40. data/test/tc_q.rb +1 -1
  41. data/test/tc_q_basic.rb +1 -1
  42. data/test/tc_random.rb +1 -1
  43. data/test/tc_sgn_neg_abs.rb +1 -1
  44. data/test/tc_swap.rb +1 -1
  45. data/test/tc_z.rb +34 -1
  46. data/test/tc_z_addmul.rb +1 -1
  47. data/test/tc_z_basic.rb +1 -1
  48. data/test/tc_z_exponentiation.rb +1 -1
  49. data/test/tc_z_functional_mappings.rb +42 -6
  50. data/test/tc_z_gcd_lcm_invert.rb +1 -1
  51. data/test/tc_z_jac_leg_rem.rb +1 -1
  52. data/test/tc_z_logic.rb +1 -1
  53. data/test/tc_z_shifts_last_bits.rb +1 -1
  54. data/test/tc_z_submul.rb +1 -1
  55. data/test/tc_z_to_dis.rb +1 -1
  56. data/test/tc_zerodivisionexceptions.rb +1 -1
  57. data/test/test_helper.rb +2 -1
  58. data/test/unit_tests.rb +1 -1
  59. metadata +70 -89
  60. data/README.rdoc +0 -450
data/CHANGELOG CHANGED
@@ -1,3 +1,24 @@
1
+ 0.6.7:
2
+ * Added 9th set of Functional Mappings: GMP::Z.divisible?
3
+ * Added 11th set of Functional Mappings: GMP::Z.congruent?
4
+
5
+ 0.5.47:
6
+ * Probably last release before 0.6.7
7
+ * Added GMP::Q#hash and GMP::Q#eql?; tested.
8
+ * Added optional parameter to GMP::Z.new(String), the base; tested.
9
+ * Added GMP::F.mpfr_buildopt_tls_p() when MPFR > 2.x.x.
10
+ * Added GMP::F.mpfr_buildopt_decimal_p() when MPFR > 2.x.x.
11
+ * I'm seeing weird failures on tests with JRuby 1.6.5... they are flickering though.
12
+ GMP::Z(GMP::GMP_NUMB_MAX) is not happy... need to research.
13
+ * If using MPFR 3.1.0, the random number generator tests will fail, I imagine because
14
+ of this new functionality, documented on the MPFR site:
15
+ "The mpfr_urandom and mpfr_urandomb functions now return identical values on
16
+ processors with different word size (assuming the same random seed, and since the
17
+ GMP random generator does not depend itself on the word size, cf
18
+ http://gmplib.org/list-archives/gmp-devel/2010-September/001642.html)."
19
+ * Unit test results: 118 tests, 16396 assertions, 0 failures, 0 errors
20
+ * Unit test results: 99 tests, 5118 assertions, 0 failures, 0 errors (w/o MPFR)
21
+
1
22
  0.5.41:
2
23
  * Added first five sets of Functional Mappings. These will be the primary new features
3
24
  of 0.6.
@@ -57,7 +57,7 @@ Ext.onReady(function(){
57
57
  ['GMP::Z#-<br />GMP::Z#sub!', "mpz_sub<br />mpz_sub_ui<br />mpz_add_ui", "yes","yes","yes", "no"],
58
58
  ['GMP::Z#*', "mpz_mul<br />mpz_mul_si", "yes","yes","yes", "no"],
59
59
  ['GMP::Z#addmul!', "mpz_addmul<br />mpz_addmul_ui", "yes","yes","yes", "no"],
60
- ['GMP::Z#submul!', "mpz_submul<br />mpz_submul_ui", "no","yes","yes", "no"],
60
+ ['GMP::Z#submul!', "mpz_submul<br />mpz_submul_ui", "yes","yes","yes", "no"],
61
61
  ['GMP::Z#<<', "mpz_mul_2exp", "yes","yes", "", "no"],
62
62
  ['GMP::Z#-@<br />' +
63
63
  'GMP::Z#neg<br />GMP::Z#neg!', "mpz_neg", "yes","yes", "", "no"],
@@ -79,7 +79,7 @@ Ext.onReady(function(){
79
79
  ['', "mpz_cdiv_q_2exp", "no", "no", "no", "no"],
80
80
  ['', "mpz_cdiv_r_2exp", "no", "no", "no", "no"],
81
81
  ['GMP::Z#%', "mpz_mod<br />mpz_mod_ui", "yes","yes", "", "no"],
82
- ['GMP::Z#divisible?', "mpz_divisible_p<br />mpz_divisible_ui_p", "no","yes","yes", "no"],
82
+ ['GMP::Z#divisible?', "mpz_divisible_p<br />mpz_divisible_ui_p", "yes","yes","yes", "no"],
83
83
  ['', "mpz_divisible_2exp_p", "no", "no", "no", "no"],
84
84
  ['', "mpz_congruent_p<br />mpz_congruent_ui_p", "no", "no", "no", "no"],
85
85
  ['', "mpz_congruent_2exp_p", "no", "no", "no", "no"],
@@ -95,7 +95,7 @@ Ext.onReady(function(){
95
95
  ['GMP::Z#next_prime<br />' +
96
96
  'GMP::Z#next_prime!', "mpz_nextprime", "yes","yes", "", "no"],
97
97
  ['GMP::Z#gcd', "mpz_gcd<br />mpz_gcd_ui", "yes","yes", "", "no"],
98
- ['GMP::Z#gcdext', "mpz_gcdext", "no","yes", "", "no"],
98
+ ['GMP::Z#gcdext', "mpz_gcdext", "yes","yes", "", "no"],
99
99
  ['', "mpz_lcm<br />mpz_lcm_ui", "no", "no", "no", "no"],
100
100
  ['GMP::Z#invert', "mpz_invert", "yes","yes", "", "no"],
101
101
  ['GMP::Z#jacobi<br />GMP::Z.jacobi',"mpz_jacobi", "yes","yes", "", "no"],
@@ -115,8 +115,8 @@ Ext.onReady(function(){
115
115
  'GMP::Z#&gt;<br />GMP::Z#&gt;=', "mpz_cmp<br />mpz_cmp_si<br />mpz_cmp_ui", "yes","yes", "", "no"],
116
116
  ['GMP::Z#cmpabs', "mpz_cmpabs", "yes","yes", "", "no"],
117
117
  ['GMP::Z#sgn', "mpz_sgn", "yes","yes", "", "no"],
118
- ['GMP::Z#eql?', "mpz_get_str", "no","yes", "","n/a"],
119
- ['GMP::Z#hash', "mpz_get_str", "no","yes", "","n/a"],
118
+ ['GMP::Z#eql?', "mpz_get_str", "yes","yes", "","n/a"],
119
+ ['GMP::Z#hash', "mpz_get_str", "yes","yes", "","n/a"],
120
120
  ['GMP::Z#&', "mpz_and", "yes","yes", "", "no"],
121
121
  ['GMP::Z#|', "mpz_ior", "yes","yes", "", "no"],
122
122
  ['GMP::Z#^', "mpz_xor", "yes","yes", "", "no"],
@@ -154,41 +154,40 @@ Ext.onReady(function(){
154
154
  ['GMP::Z.mul', "mpz_mul<br />mpz_mul_si<br />mpz_mul_ui", "no", "no", "no", "no"],
155
155
  ['GMP::Z.addmul', "mpz_addmul<br />mpz_addmul_ui", "no", "no", "no", "no"],
156
156
  ['GMP::Z.submul', "mpz_submul<br />mpz_submul_ui", "no", "no", "no", "no"],
157
- ['', "mpz_mul_2exp", "no", "no", "no", "no"],
158
- ['', "mpz_neg", "no", "no", "no", "no"],
159
- ['', "mpz_abs", "no", "no", "no", "no"],
157
+ ['GMP::Z.mul_2exp', "mpz_mul_2exp", "no", "no", "no", "no"],
158
+ ['GMP::Z.neg', "mpz_neg", "no", "no", "no", "no"],
159
+ ['GMP::Z.abs', "mpz_abs", "no", "no", "no", "no"],
160
160
  ['GMP::Z.divexact', "mpz_divexact<br />mpz_divexact_ui", "no", "no", "no", "no"],
161
161
  ['', "mpz_tdiv_q", "no", "no", "no", "no"],
162
162
  ['', "mpz_tdiv_r", "no", "no", "no", "no"],
163
163
  ['', "mpz_tdiv_qr", "no", "no", "no", "no"],
164
- /*['GMP::Z#tshr', "mpz_tdiv_q_2exp", "","yes", "no", "no"],
165
- ['GMP::Z#tshrm', "mpz_tdiv_r_2exp", "", "no", "no", "no"],
166
- ['GMP::Z#fdiv', "mpz_fdiv_q", "yes","yes","yes", "no"],
167
- ['GMP::Z#fmod', "mpz_fdiv_r", "yes","yes","yes", "no"],
168
- ['GMP::Z#fdivmod', "mpz_fdiv_rq", "no", "no", "no", "no"],
169
- ['GMP::Z#fshr', "mpz_fdiv_q_2exp", "", "no", "no", "no"],
170
- ['GMP::Z#fshrm', "mpz_fdiv_r_2exp", "", "no", "no", "no"],
171
- ['GMP::Z#cdiv', "mpz_cdiv_q", "yes","yes","yes", "no"],
164
+ ['GMP::Z.tdiv_q_2exp', "mpz_tdiv_q_2exp", "no", "no", "no", "no"],
165
+ ['GMP::Z.tdiv_r_2exp', "mpz_tdiv_r_2exp", "no", "no", "no", "no"],
166
+ ['', "mpz_fdiv_q", "no", "no", "no", "no"],
167
+ ['', "mpz_fdiv_r", "no", "no", "no", "no"],
168
+ ['', "mpz_fdiv_rq", "no", "no", "no", "no"],
169
+ ['GMP::Z.fdiv_q_2exp', "mpz_fdiv_q_2exp", "no", "no", "no", "no"],
170
+ ['GMP::Z.fdiv_r_2exp', "mpz_fdiv_r_2exp", "no", "no", "no", "no"],
171
+ /*['GMP::Z#cdiv', "mpz_cdiv_q", "yes","yes","yes", "no"],
172
172
  ['GMP::Z#cmod', "mpz_cdiv_r", "yes","yes","yes", "no"],
173
- ['GMP::Z#cdivmod', "mpz_cdiv_qr", "no", "no", "no", "no"],
174
- ['', "mpz_cdiv_q_2exp", "no", "no", "no", "no"],
175
- ['', "mpz_cdiv_r_2exp", "no", "no", "no", "no"],
176
- ['GMP::Z#%', "mpz_mod<br />mpz_mod_ui", "yes","yes", "", "no"],
177
- ['GMP::Z#divisible?', "mpz_divisible_p<br />mpz_divisible_ui_p", "no","yes","yes", "no"],
178
- ['', "mpz_divisible_2exp_p", "no", "no", "no", "no"],
179
- ['', "mpz_congruent_p<br />mpz_congruent_ui_p", "no", "no", "no", "no"],
180
- ['', "mpz_congruent_2exp_p", "no", "no", "no", "no"],
173
+ ['GMP::Z#cdivmod', "mpz_cdiv_qr", "no", "no", "no", "no"],*/
174
+ ['GMP::Z.cdiv_q_2exp', "mpz_cdiv_q_2exp", "no", "no", "no", "no"],
175
+ ['GMP::Z.fdiv_r_2exp', "mpz_cdiv_r_2exp", "no", "no", "no", "no"],
176
+ /*['GMP::Z#%', "mpz_mod<br />mpz_mod_ui", "yes","yes", "", "no"],*/
177
+ ['GMP::Z.divisible?', "mpz_divisible_p<br />mpz_divisible_ui_p", "no", "no", "no", "no"],
178
+ /*['', "mpz_divisible_2exp_p", "no", "no", "no", "no"],*/
179
+ ['GMP::Z.congruent?', "mpz_congruent_p<br />mpz_congruent_ui_p", "no", "no", "no", "no"],
180
+ /*['', "mpz_congruent_2exp_p", "no", "no", "no", "no"],
181
181
  ['GMP::Z#**<br />GMP::Z.pow', "mpz_pow_ui", "yes","yes", "", "no"],
182
182
  ['GMP::Z#powmod', "mpz_powm<br />mpz_powm_ui", "yes","yes", "", "no"],
183
183
  ['GMP::Z#root', "mpz_root", "yes","yes", "", "no"],
184
- ['', "mpz_rootrem", "no", "no", "no", "no"],
185
- ['GMP::Z#sqrt<br />GMP::Z#sqrt!', "mpz_sqrt", "yes","yes", "", "no"],
186
- ['GMP::Z#sqrtrem', "mpz_sqrtrem", "yes","yes", "", "no"],
187
- ['GMP::Z#power?', "mpz_perfect_power_p", "yes","yes", "", "no"],
188
- ['GMP::Z#square?', "mpz_perfect_square_p", "yes","yes", "", "no"],
189
- ['GMP::Z#probab_prime?', "mpz_probab_prime_p", "yes","yes", "", "no"],
190
- ['GMP::Z#next_prime<br />' +
191
- 'GMP::Z#next_prime!', "mpz_nextprime", "yes","yes", "", "no"],*/
184
+ ['', "mpz_rootrem", "no", "no", "no", "no"],*/
185
+ ['GMP::Z.sqrt', "mpz_sqrt", "no", "no", "no", "no"],
186
+ ['', "mpz_sqrtrem", "no", "no", "no", "no"],
187
+ ['', "mpz_perfect_power_p", "no", "no", "no", "no"],
188
+ ['', "mpz_perfect_square_p", "no", "no", "no", "no"],
189
+ ['', "mpz_probab_prime_p", "no", "no", "no", "no"],
190
+ ['GMP::Z.nextprime', "mpz_nextprime", "no", "no", "no", "no"],
192
191
  ['', "mpz_gcd<br />mpz_gcd_ui", "no", "no", "no", "no"],
193
192
  ['', "mpz_gcdext", "no", "no", "no", "no"],
194
193
  ['GMP::Z.lcm', "mpz_lcm<br />mpz_lcm_ui", "no", "no", "no", "no"],
@@ -214,22 +213,22 @@ Ext.onReady(function(){
214
213
  ['GMP::Z#hash', "mpz_get_str", "no","yes", "","n/a"],
215
214
  ['GMP::Z#&', "mpz_and", "yes","yes", "", "no"],
216
215
  ['GMP::Z#|', "mpz_ior", "yes","yes", "", "no"],
217
- ['GMP::Z#^', "mpz_xor", "yes","yes", "", "no"],
218
- ['GMP::Z#com<br />GMP::Z#com!', "mpz_com", "yes","yes", "", "no"],
219
- ['GMP::Z#popcount', "mpz_popcount", "yes","yes", "", "no"],
216
+ ['GMP::Z#^', "mpz_xor", "yes","yes", "", "no"],*/
217
+ ['GMP::Z.com', "mpz_com", "no", "no", "no", "no"],
218
+ /*['GMP::Z#popcount', "mpz_popcount", "yes","yes", "", "no"],
220
219
  ['', "mpz_hamdist", "no", "no", "no", "no"],
221
220
  ['GMP::Z#scan0', "mpz_scan0", "yes","yes", "", "no"],
222
221
  ['GMP::Z#scan1', "mpz_scan1", "yes","yes", "", "no"],
223
222
  ['GMP::Z#[]=', "mpz_setbit<br />mpz_clrbit", "yes","yes", "", "no"],
224
223
  ['', "mpz_combit", "no", "no", "no", "no"],
225
- ['GMP::Z#[]', "mpz_tstbit", "yes","yes", "", "no"],
224
+ ['GMP::Z#[]', "mpz_tstbit", "yes","yes", "", "no"],*/
226
225
  ['', "mpz_fits_ulong_p", "no", "no", "no", "no"],
227
226
  ['', "mpz_fits_slong_p", "no", "no", "no", "no"],
228
227
  ['', "mpz_fits_uint_p", "no", "no", "no", "no"],
229
228
  ['', "mpz_fits_sint_p", "no", "no", "no", "no"],
230
229
  ['', "mpz_fits_ushort_p", "no", "no", "no", "no"],
231
230
  ['', "mpz_fits_sshort_p", "no", "no", "no", "no"],
232
- ['GMP::Z#even?', "mpz_even_p", "yes","yes", "", "no"],
231
+ /*['GMP::Z#even?', "mpz_even_p", "yes","yes", "", "no"],
233
232
  ['GMP::Z#odd?', "mpz_odd_p", "yes","yes", "", "no"],
234
233
  ['GMP::Z#sizeinbase<br />' +
235
234
  'GMP::Z#size_in_base', "mpz_sizeinbase", "yes","yes", "", "no"],
@@ -533,4 +532,4 @@ Ext.onReady(function(){
533
532
  <div id='mpq-grid'></div>
534
533
  <div id='mpf-grid'></div>
535
534
  </body>
536
- </html>
535
+ </html>
@@ -0,0 +1,511 @@
1
+ <h1>gmp</h1>
2
+
3
+ <p>gmp is library providing Ruby bindings to GMP library. Here is the introduction
4
+ paragraph at <a href="http://gmplib.org/#WHAT">their homepage</a>:</p>
5
+
6
+ <blockquote><p>GMP is a free library for arbitrary precision arithmetic, operating on
7
+ signed integers, rational numbers, and floating point numbers. There is no
8
+ practical limit to the precision except the ones implied by the available
9
+ memory in the machine GMP runs on. GMP has a rich set of functions, and the
10
+ functions have a regular interface.</p>
11
+
12
+ <p>The main target applications for GMP are cryptography applications and
13
+ research, Internet security applications, algebra systems, computational
14
+ algebra research, etc.</p>
15
+
16
+ <p>GMP is carefully designed to be as fast as possible, both for small operands
17
+ and for huge operands. The speed is achieved by using fullwords as the basic
18
+ arithmetic type, by using fast algorithms, with highly optimised assembly
19
+ code for the most common inner loops for a lot of CPUs, and by a general
20
+ emphasis on speed.</p>
21
+
22
+ <p>GMP is faster than any other bignum library. The advantage for GMP increases
23
+ with the operand sizes for many operations, since GMP uses asymptotically
24
+ faster algorithms.</p>
25
+
26
+ <p>The first GMP release was made in 1991. It is continually developed and
27
+ maintained, with a new release about once a year.</p>
28
+
29
+ <p>GMP is distributed under the GNU LGPL. This license makes the library free to
30
+ use, share, and improve, and allows you to pass on the result. The license
31
+ gives freedoms, but also sets firm restrictions on the use with non-free
32
+ programs.</p>
33
+
34
+ <p>GMP is part of the GNU project. For more information about the GNU project,
35
+ please see the official GNU web site.</p>
36
+
37
+ <p>GMP's main target platforms are Unix-type systems, such as GNU/Linux,
38
+ Solaris, HP-UX, Mac OS X/Darwin, BSD, AIX, etc. It also is known to work on
39
+ Windoze in 32-bit mode.</p>
40
+
41
+ <p>GMP is brought to you by a team listed in the manual.</p>
42
+
43
+ <p>GMP is carefully developed and maintained, both technically and legally. We
44
+ of course inspect and test contributed code carefully, but equally
45
+ importantly we make sure we have the legal right to distribute the
46
+ contributions, meaning users can safely use GMP. To achieve this, we will ask
47
+ contributors to sign paperwork where they allow us to distribute their work."</p></blockquote>
48
+
49
+ <p>Only GMP 4 or newer is supported. The following environments have been tested
50
+ by me: gmp gem 0.5.41 on:</p>
51
+
52
+ <table border="1">
53
+ <tr>
54
+ <th>Platform</th>
55
+ <th>Ruby</th>
56
+ <th>GMP (MPFR)</th>
57
+ </tr>
58
+ <tr>
59
+ <td rowspan="3">Linux (Ubuntu NR 10.04) on x86 (32-bit)</td>
60
+ <td>(MRI) Ruby 1.8.7</td>
61
+ <td>GMP 4.3.1 (2.4.2)<br />
62
+ GMP 4.3.2 (2.4.2)<br />
63
+ GMP 5.0.1 (3.0.0)</td>
64
+ </tr>
65
+ <tr>
66
+ <td>(MRI) Ruby 1.9.1</td>
67
+ <td>GMP 4.3.1 (2.4.2)<br />
68
+ GMP 4.3.2 (2.4.2)<br />
69
+ GMP 5.0.1 (3.0.0)</td>
70
+ </tr>
71
+ <tr>
72
+ <td>(MRI) Ruby 1.9.2</td>
73
+ <td>GMP 4.3.1 (2.4.2)<br />
74
+ GMP 4.3.2 (2.4.2)<br />
75
+ GMP 5.0.1 (3.0.0)</td>
76
+ </tr>
77
+ <tr>
78
+ <td rowspan="4">Linux (Ubuntu 10.04) on x86_64 (64-bit)</td>
79
+ <td>(MRI) Ruby 1.8.7</td>
80
+ <td>GMP 4.3.2 (2.4.2)<br />
81
+ GMP 5.0.1 (3.0.0)</td>
82
+ </tr>
83
+ <tr>
84
+ <td>(MRI) Ruby 1.9.1</td>
85
+ <td>GMP 4.3.2 (2.4.2)<br />
86
+ GMP 5.0.1 (3.0.0)</td>
87
+ </tr>
88
+ <tr>
89
+ <td>(MRI) Ruby 1.9.2</td>
90
+ <td>GMP 4.3.2 (2.4.2)<br />
91
+ GMP 5.0.1 (3.0.0)</td>
92
+ </tr>
93
+ <tr>
94
+ <td>(RBX) Rubinius 1.1.0</td>
95
+ <td>GMP 4.3.2 (2.4.2)<br />
96
+ GMP 5.0.1 (3.0.0)</td>
97
+ </tr>
98
+ <tr>
99
+ <td rowspan="4">Mac OS X 10.6.4 on x86_64 (64-bit)</td>
100
+ <td>(MRI) Ruby 1.8.7</td>
101
+ <td>GMP 4.3.2 (2.4.2)<br />
102
+ GMP 5.0.1 (3.0.0)</td>
103
+ </tr>
104
+ <tr>
105
+ <td>(MRI) Ruby 1.9.1</td>
106
+ <td>GMP 4.3.2 (2.4.2)<br />
107
+ GMP 5.0.1 (3.0.0)</td>
108
+ </tr>
109
+ <tr>
110
+ <td>(MRI) Ruby 1.9.2</td>
111
+ <td>GMP 4.3.2 (2.4.2)<br />
112
+ GMP 5.0.1 (3.0.0)</td>
113
+ </tr>
114
+ <tr>
115
+ <td>(RBX) Rubinius 1.1.0</td>
116
+ <td>GMP 4.3.2 (2.4.2)<br />
117
+ GMP 5.0.1 (3.0.0)</td>
118
+ </tr>
119
+ <tr>
120
+ <td rowspan="3">Windows 7 on x86_64 (64-bit)</td>
121
+ <td>(MRI) Ruby 1.8.7</td>
122
+ <td>GMP 4.3.2 (2.4.2)<br />
123
+ GMP 5.0.1 (3.0.0)</td>
124
+ </tr>
125
+ <tr>
126
+ <td>(MRI) Ruby 1.9.1</td>
127
+ <td>GMP 4.3.2 (2.4.2)<br />
128
+ GMP 5.0.1 (3.0.0)</td>
129
+ </tr>
130
+ <tr>
131
+ <td>(MRI) Ruby 1.9.2</td>
132
+ <td>GMP 4.3.2 (2.4.2)<br />
133
+ GMP 5.0.1 (3.0.0)</td>
134
+ </tr>
135
+ <tr>
136
+ <td>Windows XP on x86 (32-bit)</td>
137
+ <td>(MRI) Ruby 1.9.1</td>
138
+ <td>GMP 4.3.2 (2.4.2)<br />
139
+ GMP 5.0.1 (3.0.0)</td>
140
+ </tr>
141
+ </table>
142
+
143
+
144
+ <h2>Authors</h2>
145
+
146
+ <ul>
147
+ <li>Tomasz Wegrzanowski</li>
148
+ <li>srawlins</li>
149
+ </ul>
150
+
151
+
152
+ <h2>Constants</h2>
153
+
154
+ <p>The GMP module includes the following constants. Mathematical constants, such
155
+ as pi, are defined under class methods of GMP::F, listed below.</p>
156
+
157
+ <ul>
158
+ <li><code>GMP::GMP_VERSION</code> - A string like "5.0.1"</li>
159
+ <li><code>GMP::GMP_CC</code> - The compiler used to compile GMP</li>
160
+ <li><code>GMP::GMP_CFLAGS</code> - The CFLAGS used to compile GMP</li>
161
+ <li><code>GMP::GMP\_BITS_PER_LIMB</code> The number of bits per limb</li>
162
+ <li><code>GMP::GMP_NUMB_MAX</code> - The maximum value that can be stored in the number part of a limb</li>
163
+ </ul>
164
+
165
+
166
+ <p>if MPFR is available:
167
+ * <code>GMP::MPFR_VERSION</code> - A string like "2.4.2"
168
+ * <code>GMP::MPFR\_PREC_MIN</code> - The minimum precision available
169
+ * <code>GMP::MPFR_PREC_MAX</code> - The maximum precision available
170
+ * <code>GMP::GMP_RNDN</code> - The constant representing "round to nearest"
171
+ * <code>GMP::GMP_RNDZ</code> - The constant representing "round toward zero"
172
+ * <code>GMP::GMP_RNDU</code> - The constant representing "round toward plus infinity"
173
+ * <code>GMP::GMP_RNDD</code> - The constant representing "round toward minus infinity"</p>
174
+
175
+ <p>New in MPFR 3.0.0:
176
+ * <code>GMP::MPFR_RNDN</code>
177
+ * <code>GMP::MPFR_RNDZ</code>
178
+ * <code>GMP::MPFR_RNDU</code>
179
+ * <code>GMP::MPFR_RNDD</code>
180
+ * <code>GMP::MPFR_RNDA</code> - The constant representing "round away from zero"</p>
181
+
182
+ <h2>Classes</h2>
183
+
184
+ <p>The GMP module is provided with following classes:
185
+ * <code>GMP::Z</code> - infinite precision integer numbers
186
+ * <code>GMP::Q</code> - infinite precision rational numbers
187
+ * <code>GMP::F</code> - arbitrary precision floating point numbers
188
+ * <code>GMP::RandState</code> - states of individual random number generators</p>
189
+
190
+ <p>Numbers are created by using <code>new()</code>. Constructors can take following arguments:</p>
191
+
192
+ <pre><code>GMP::Z.new()
193
+ GMP::Z.new(GMP::Z)
194
+ GMP::Z.new(Fixnum)
195
+ GMP::Z.new(Bignum)
196
+ GMP::Z.new(String)
197
+ GMP::Q.new()
198
+ GMP::Q.new(GMP::Q)
199
+ GMP::Q.new(String)
200
+ GMP::Q.new(any GMP::Z initializer)
201
+ GMP::Q.new(any GMP::Z initializer, any GMP::Z initializer)
202
+ GMP::F.new()
203
+ GMP::F.new(GMP::Z, precision=0)
204
+ GMP::F.new(GMP::Q, precision=0)
205
+ GMP::F.new(GMP::F)
206
+ GMP::F.new(GMP::F, precision)
207
+ GMP::F.new(String, precision=0)
208
+ GMP::F.new(Fixnum, precision=0)
209
+ GMP::F.new(Bignum, precision=0)
210
+ GMP::F.new(Float, precision=0)
211
+ GMP::RandState.new(\[algorithm\] \[, algorithm_args\])
212
+ </code></pre>
213
+
214
+ <p>You can also call them as:</p>
215
+
216
+ <pre><code>GMP.Z(args)
217
+ GMP.Q(args)
218
+ GMP.F(args)
219
+ GMP.RandState()
220
+ </code></pre>
221
+
222
+ <h2>Methods</h2>
223
+
224
+ <pre><code>GMP::Z, GMP::Q and GMP::F
225
+ + addition
226
+ - substraction
227
+ * multiplication
228
+ / division
229
+ to_s convert to string. For GMP::Z, this method takes
230
+ one optional argument, a base. The base can be a
231
+ Fixnum in the ranges \[2, 62\] or \[-36, -2\] or a
232
+ Symbol: :bin, :oct, :dec, or :hex.
233
+ -@ negation
234
+ neg! in-place negation
235
+ abs absolute value
236
+ asb! in-place absolute value
237
+ coerce promotion of arguments
238
+ == equality test
239
+ &lt;=&gt;,&gt;=,&gt;,&lt;=,&lt; comparisions
240
+ class methods of GMP::Z
241
+ fac(n) factorial of n
242
+ fib(n) nth fibonacci number
243
+ pow(n,m) n to mth power
244
+ GMP::Z and GMP::Q
245
+ swap efficiently swap contents of two objects, there
246
+ is no GMP::F.swap because various GMP::F objects
247
+ may have different precisions, which would make
248
+ them unswapable
249
+ GMP::Z
250
+ to_i convert to Fixnum or Bignum
251
+ add! in-place addition
252
+ sub! in-place subtraction
253
+ addmul!(b,c) in-place += b*c
254
+ submul!(b,c) in-place -= b*c
255
+ tdiv,fdiv,cdiv truncate, floor and ceil division
256
+ tmod,fmod,cmod truncate, floor and ceil modulus
257
+ &gt;&gt; shift right, floor
258
+ divisible?(b) true if divisible by b
259
+ ** power
260
+ powmod power modulo
261
+ \[\],\[\]= testing and setting bits (as booleans)
262
+ scan0,scan1 starting at bitnr (1st arg), scan for a 0 or 1
263
+ (respectively), then return the index of the
264
+ first instance.
265
+ cmpabs comparison of absolute value
266
+ com 2's complement
267
+ com! in-place 2's complement
268
+ &amp;,|,^ logical operations: and, or, xor
269
+ even? is even
270
+ odd? is odd
271
+ &lt;&lt; shift left
272
+ tshr shift right, truncate
273
+ lastbits_pos(n) last n bits of object, modulo if negative
274
+ lastbits_sgn(n) last n bits of object, preserve sign
275
+ power? is perfect power
276
+ square? is perfect square
277
+ sqrt square root
278
+ sqrt! change the object into its square root
279
+ sqrtrem square root, remainder
280
+ root(n) nth root
281
+ probab_prime? 0 if composite, 1 if probably prime, 2 if
282
+ certainly prime
283
+ nextprime next *probable* prime
284
+ nextprime! change the object into its next *probable* prime
285
+ gcd, gcdext greatest common divisor
286
+ invert(m) invert mod m
287
+ jacobi jacobi symbol
288
+ legendre legendre symbol
289
+ remove(n) remove all occurences of factor n
290
+ popcount the number of bits equal to 1
291
+ sizeinbase(b) digits in base b
292
+ size_in_bin digits in binary
293
+ size number of limbs
294
+ GMP::Q
295
+ num numerator
296
+ den denominator
297
+ inv inversion
298
+ inv! in-place inversion
299
+ floor,ceil,trunc nearest integer
300
+ class methods of GMP::F
301
+ default_prec get default precision
302
+ default_prec= set default precision
303
+ GMP::F
304
+ prec get precision
305
+ floor,ceil,trunc nearest integer, GMP::F is returned, not GMP::Z
306
+ floor!,ceil!,trunc! in-place nearest integer
307
+ GMP::RandState
308
+ seed(integer) seed the generator with a Fixnum or GMP::Z
309
+ urandomb(fixnum) get uniformly distributed random number between 0
310
+ and 2^fixnum-1, inclusive
311
+ urandomm(integer) get uniformly distributed random number between 0
312
+ and integer-1, inclusive
313
+ GMP (timing functions for GMPbench (0.2))
314
+ cputime milliseconds of cpu time since Ruby start
315
+ time times the execution of a block
316
+
317
+ *only if MPFR is available*
318
+ class methods of GMP::F
319
+ const_log2 returns the natural log of 2
320
+ const_pi returns pi
321
+ const_euler returns euler
322
+ const_catalan returns catalan
323
+ mpfr_buildopt_tls_p returns whether MPFR was built as thread safe
324
+ mpfr_buildopt_decimal_p returns whether MPFR was compiled with decimal
325
+ float support
326
+ GMP::F
327
+ sqrt square root of the object
328
+ rec_sqrt square root of the recprical of the object
329
+ cbrt cube root of the object
330
+ ** power
331
+ log natural logarithm of object
332
+ log2 binary logarithm of object
333
+ log10 decimal logarithm of object
334
+ exp e^object
335
+ exp2 2^object
336
+ exp10 10^object
337
+ log1p the same as (object + 1).log, with better
338
+ precision
339
+ expm1 the same as (object.exp) - 1, with better
340
+ precision
341
+ eint exponential integral of object
342
+ li2 real part of the dilogarithm of object
343
+ gamma Gamma fucntion of object
344
+ lngamma logarithm of the Gamma function of object
345
+ digamma Digamma function of object (MPFR_VERSION &gt;= "3.0.0")
346
+ zeta Reimann Zeta function of object
347
+ erf error function of object
348
+ erfc complementary error function of object
349
+ j0 first kind Bessel function of order 0 of object
350
+ j1 first kind Bessel function of order 1 of object
351
+ jn first kind Bessel function of order n of object
352
+ y0 second kind Bessel function of order 0 of object
353
+ y1 second kind Bessel function of order 1 of object
354
+ yn second kind Bessel function of order n of object
355
+ agm arithmetic-geometric mean
356
+ hypot
357
+ cos \
358
+ sin |
359
+ tan |
360
+ sin_cos |
361
+ sec |
362
+ csc |
363
+ cot |
364
+ acos |
365
+ asin |
366
+ atan | trigonometric functions
367
+ atan2 |
368
+ cosh | of the object
369
+ sinh |
370
+ tanh |
371
+ sinh_cosh |
372
+ sec |
373
+ csc |
374
+ cot |
375
+ acosh |
376
+ asinh |
377
+ atanh /
378
+ nan? \
379
+ infinite? | type of floating point number
380
+ finite? |
381
+ number? |
382
+ regular? / (MPFR_VERSION &gt;= "3.0.0")
383
+ GMP::RandState
384
+ mpfr_urandomb(fixnum) get uniformly distributed random floating-point
385
+ number within 0 &lt;= rop &lt; 1
386
+ </code></pre>
387
+
388
+ <h2>Functional Mappings</h2>
389
+
390
+ <p>In order to align better with the GMP paradigms of using return arguments, I have started creating "functional mappings", singleton methods that map directly to functions in GMP. These methods take return arguments, so that passing an object to a functional mapping may change the object itself. For example:</p>
391
+
392
+ <pre><code>a = GMP::Z(0)
393
+ b = GMP::Z(13)
394
+ c = GMP::Z(17)
395
+ GMP::Z.add(a, b, c)
396
+ a #=&gt; 30
397
+ </code></pre>
398
+
399
+ <p>Here's a fun list of all of the functional mappings written so far:</p>
400
+
401
+ <pre><code>GMP::Z
402
+ .abs .add .addmul .cdiv_q_2exp .cdiv_r_2exp .com
403
+ .congruent? .divexact .divisible? .fdiv_q_2exp .fdiv_r_2exp .lcm
404
+ .mul .mul_2exp
405
+ .neg .nextprime .sqrt .sub .submul .tdiv_q_2exp
406
+ .tdiv_r_2exp
407
+ </code></pre>
408
+
409
+ <h2>Documentation</h2>
410
+
411
+ <ul>
412
+ <li><a href="https://github.com/srawlins/gmp">This README</a></li>
413
+ <li>Loren Segal and the guys at RubyGems.org are badasses: <a href="http://rubydoc.info/gems/gmp/frames">YARDoc</a>.</li>
414
+ <li>There should be a manual.pdf <a href="https://github.com/srawlins/gmp/blob/master/manual.pdf">here</a>. I spend waaay too much time working on this, but it looks very pretty.</li>
415
+ <li><a href="https://github.com/srawlins/gmp/blob/master/CHANGELOG">CHANGELOG</a></li>
416
+ </ul>
417
+
418
+
419
+ <h2>Testing</h2>
420
+
421
+ <p>Tests can be run with:</p>
422
+
423
+ <pre><code>cd test
424
+ ruby unit_tests.rb
425
+ </code></pre>
426
+
427
+ <p>If you have the unit_test gem installed, all tests should pass. Otherwise, one test may error. I imagine there is a bug in Ruby's built-in <code>Test::Unit</code> package that is fixed with the unit_test gem.</p>
428
+
429
+ <h2>Known Issues</h2>
430
+
431
+ <ul>
432
+ <li>Don't call <code>GMP::RandState(:lc_2exp_size)</code>. Give a 2nd arg.</li>
433
+ <li>Don't use multiple assignment (<code>a = b = GMP::Z(0)</code>) with functional mappings.</li>
434
+ <li>JRuby has some interesting bugs and flickering tests. GMP::Z(GMP::GMP_NUMB_MAX) for example, blows up.</li>
435
+ <li>MPFR 3.1.0 breaks some of the random tests. This is because of a known change in MPFR. I just need my tests to become aware of the change.</li>
436
+ </ul>
437
+
438
+
439
+ <h2>Precision</h2>
440
+
441
+ <p>Precision can be explicitely set as second argument for <code>GMP::F.new()</code>. If there is no explicit precision, highest precision of all <code>GMP::F</code> arguments is used. That doesn't ensure that result will be exact. For details, consult any paper about floating point arithmetics.</p>
442
+
443
+ <p>Default precision can be explicitely set by passing <code>0</code> as the second argument for to <code>GMP::F.new()</code>. In particular, you can set precision of copy of <code>GMP::F</code> object by:</p>
444
+
445
+ <pre><code>new_obj = GMP::F.new(old_obj, 0)
446
+ </code></pre>
447
+
448
+ <p>Precision argument, and default_precision will be rounded up to whatever GMP thinks is appropriate.</p>
449
+
450
+ <h2>Benchmarking</h2>
451
+
452
+ <p>"GMP is carefully designed to be as fast as possible." Therefore, I believe it is very important for GMP, and its various language bindings to be benchmarked. In recent years, the GMP team developed GMPbench, an elegant, weighted benchmark. Currently, they maintain a list of recent benchmark <a href="http://www.gmplib.org/gmpbench.html">results</a>, broken down by CPU, CPU freq, ABI, and compiler flags; GMPbench compares different processor's performance against eachother, rather than GMP against other bignum libraries, or comparing different versions of GMP.</p>
453
+
454
+ <p>I intend to build a plug-in to GMPbench that will test the ruby gmp gem. The results of this benchmark should be directly comparable with the results of GMP (on same CPU, etc.). Rather than write a benchmark from the ground up, or try to emulate what GMPbench does, a plug-in will allow for this type of comparison. And in fact, GMPbench is (perhaps intentionally) written perfectly to allow for plugging in.</p>
455
+
456
+ <p>Various scores are derived from GMPbench by running the <code>runbench</code> script. This script compiles and runs various individual programs that measure the performance of base functions, such as multiply, and app functions such as rsa.</p>
457
+
458
+ <p>The gmp gem benchmark uses the GMPbench framework (that is, runbench, gexpr, and the timing methods), and plugs in ruby scripts as the individual programs. Right now, there are only four (of six) such plugged in ruby scripts:</p>
459
+
460
+ <ul>
461
+ <li>multiply - measures performance of multiplying (or squaring) <code>GMP::Z</code> objects whose size (in bits) is given by one or two operands.</li>
462
+ <li>divide - measures performance of dividing two <code>GMP::Z</code> objects (using <code>tdiv</code>) whose size (in bits) is given by two operands.</li>
463
+ <li>gcd - measure...</li>
464
+ <li>rsa - measures performance of using RSA to sign messages. The size of <code>pq</code>, the product of the two co-prime <code>GMP::Z</code> objects, <code>p</code> and <code>q</code>, is given by one operand.</li>
465
+ </ul>
466
+
467
+
468
+ <p><strong>insert table here</strong></p>
469
+
470
+ <p>My guess is that the increase in ruby gmp gem overhead is caused by increased efficiency in GMP; the inefficiencies of the gmp gem are relatively greater.</p>
471
+
472
+ <h2>Todo</h2>
473
+
474
+ <ul>
475
+ <li><code>GMP::Z#to_d_2exp</code>, <code>#congruent?</code>, <code>#rootrem</code>, <code>#lcm</code>, <code>#kronecker</code>, <code>#bin</code>, <code>#fib2</code>, <code>#lucnum</code>, <code>#lucnum2</code>, <code>#hamdist</code>, <code>#combit</code>, <code>#fits_x?</code></li>
476
+ <li><code>GMP::Q#to_s(base)</code>, <code>GMP::F#to_s(base)</code> (test it!)</li>
477
+ <li>benchmark gcdext, pi</li>
478
+ <li>a butt-load of functional mappings. 47-ish sets.</li>
479
+ <li>use Rake use Rake use Rake</li>
480
+ <li>investigate possible memory leaks when using <code>GMP::Q(22/7)</code> for example</li>
481
+ <li>beef up <code>r_gmpq_initialize</code>; I don't like to rely on <code>mpz_set_value</code>.</li>
482
+ <li>finish compile-results.rb</li>
483
+ <li>New in MPFR 3.1.0: mpfr_frexp, mpfr_grandom, mpfr_z_sub, divide-by-zero exception (?)</li>
484
+ </ul>
485
+
486
+
487
+ <p>The below are inherited from Tomasz. I will go through these and see which are
488
+ still relevant, and which I understand.</p>
489
+
490
+ <ul>
491
+ <li><code>mpz_fits_*</code> and 31 vs. 32 integer variables</li>
492
+ <li>fix all sign issues (don't know what these are)</li>
493
+ <li><code>to_s</code> vs. <code>inspect</code></li>
494
+ <li>check if <code>mpz_addmul_ui</code> would optimize some statements</li>
495
+ <li>some system that allows using denref and numref as normal ruby objects</li>
496
+ <li>takeover code that replaces all <code>Bignums</code> with <code>GMP::Z</code></li>
497
+ <li>better bignum parser (how? <code>to_s</code> seems good to me.)</li>
498
+ <li>zero-copy method for strings generation</li>
499
+ <li>benchmarks against Python GMP and Perl GMP</li>
500
+ <li><code>dup</code> methods</li>
501
+ <li>integrate <code>F</code> into system</li>
502
+ <li>should <code>Z.\[\]</code> bits be 0/1 or true/false, 0 is true, which might surprise users</li>
503
+ <li><code>any2small_integer()</code></li>
504
+ <li>check asm output, especially local memory efficiency (uh... no)</li>
505
+ <li>it might be better to use 'register' for some local variables (uh... no)</li>
506
+ <li>powm with negative exponents</li>
507
+ <li>check if different sorting of operatations gives better cache usage</li>
508
+ <li><code>GMP::\*</code> op <code>RubyFloat</code> and <code>RubyFloat</code> op <code>GMP::\*</code></li>
509
+ <li>sort checks</li>
510
+ </ul>
511
+