-
Notifications
You must be signed in to change notification settings - Fork 4
/
README.html
506 lines (449 loc) · 19.9 KB
/
README.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
<h1>gmp</h1>
<p>gmp is library providing Ruby bindings to GMP library. Here is the introduction
paragraph at <a href="http://gmplib.org/#WHAT">their homepage</a>:</p>
<blockquote>
<p>GMP is a free library for arbitrary precision arithmetic, operating on
signed integers, rational numbers, and floating point numbers. There is no
practical limit to the precision except the ones implied by the available
memory in the machine GMP runs on. GMP has a rich set of functions, and the
functions have a regular interface.</p>
<p>The main target applications for GMP are cryptography applications and
research, Internet security applications, algebra systems, computational
algebra research, etc.</p>
<p>GMP is carefully designed to be as fast as possible, both for small operands
and for huge operands. The speed is achieved by using fullwords as the basic
arithmetic type, by using fast algorithms, with highly optimised assembly
code for the most common inner loops for a lot of CPUs, and by a general
emphasis on speed.</p>
<p>GMP is faster than any other bignum library. The advantage for GMP increases
with the operand sizes for many operations, since GMP uses asymptotically
faster algorithms.</p>
<p>The first GMP release was made in 1991. It is continually developed and
maintained, with a new release about once a year.</p>
<p>GMP is distributed under the GNU LGPL. This license makes the library free to
use, share, and improve, and allows you to pass on the result. The license
gives freedoms, but also sets firm restrictions on the use with non-free
programs.</p>
<p>GMP is part of the GNU project. For more information about the GNU project,
please see the official GNU web site.</p>
<p>GMP's main target platforms are Unix-type systems, such as GNU/Linux,
Solaris, HP-UX, Mac OS X/Darwin, BSD, AIX, etc. It also is known to work on
Windoze in 32-bit mode.</p>
<p>GMP is brought to you by a team listed in the manual.</p>
<p>GMP is carefully developed and maintained, both technically and legally. We
of course inspect and test contributed code carefully, but equally
importantly we make sure we have the legal right to distribute the
contributions, meaning users can safely use GMP. To achieve this, we will ask
contributors to sign paperwork where they allow us to distribute their work."</p>
</blockquote>
<p>Only GMP 4 or newer is supported. The following environments have been tested
by me: gmp gem 0.5.47 on:</p>
<table border="1">
<tr>
<th>Platform</th>
<th>Ruby</th>
<th>GMP (MPFR)</th>
</tr>
<tr>
<td rowspan="3">Linux (Ubuntu NR 10.04) on x86 (32-bit)</td>
<td>(MRI) Ruby 1.8.7</td>
<td>GMP 4.3.1 (2.4.2)<br />
GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.1</td>
<td>GMP 4.3.1 (2.4.2)<br />
GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.2</td>
<td>GMP 4.3.1 (2.4.2)<br />
GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td rowspan="4">Linux (Ubuntu 10.04) on x86_64 (64-bit)</td>
<td>(MRI) Ruby 1.8.7</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.1</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.2</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(RBX) Rubinius 1.1.0</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td rowspan="3">Mac OS X 10.6.8 on x86_64 (64-bit)</td>
<td>(MRI) Ruby 1.8.7</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.5 (3.1.1)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.3</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.5 (3.1.1)</td>
</tr>
<tr>
<td>(RBX) Rubinius 1.1.0</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td rowspan="3">Windows 7 on x86_64 (64-bit)</td>
<td>(MRI) Ruby 1.8.7</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.1</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>(MRI) Ruby 1.9.2</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
<tr>
<td>Windows XP on x86 (32-bit)</td>
<td>(MRI) Ruby 1.9.1</td>
<td>GMP 4.3.2 (2.4.2)<br />
GMP 5.0.1 (3.0.0)</td>
</tr>
</table>
<h2>Authors</h2>
<ul>
<li>Tomasz Wegrzanowski</li>
<li>srawlins</li>
</ul>
<h2>Constants</h2>
<p>The GMP module includes the following constants. Mathematical constants, such
as pi, are defined under class methods of GMP::F, listed below.</p>
<ul>
<li><code>GMP::GMP_VERSION</code> - A string like "5.0.1"</li>
<li><code>GMP::GMP_CC</code> - The compiler used to compile GMP</li>
<li><code>GMP::GMP_CFLAGS</code> - The CFLAGS used to compile GMP</li>
<li><code>GMP::GMP\_BITS_PER_LIMB</code> The number of bits per limb</li>
<li><code>GMP::GMP_NUMB_MAX</code> - The maximum value that can be stored in the number part of a limb</li>
</ul>
<p>if MPFR is available:
* <code>GMP::MPFR_VERSION</code> - A string like "2.4.2"
* <code>GMP::MPFR\_PREC_MIN</code> - The minimum precision available
* <code>GMP::MPFR_PREC_MAX</code> - The maximum precision available
* <code>GMP::GMP_RNDN</code> - The constant representing "round to nearest"
* <code>GMP::GMP_RNDZ</code> - The constant representing "round toward zero"
* <code>GMP::GMP_RNDU</code> - The constant representing "round toward plus infinity"
* <code>GMP::GMP_RNDD</code> - The constant representing "round toward minus infinity"</p>
<p>New in MPFR 3.0.0:
* <code>GMP::MPFR_RNDN</code>
* <code>GMP::MPFR_RNDZ</code>
* <code>GMP::MPFR_RNDU</code>
* <code>GMP::MPFR_RNDD</code>
* <code>GMP::MPFR_RNDA</code> - The constant representing "round away from zero"</p>
<h2>Classes</h2>
<p>The GMP module is provided with following classes:
* <code>GMP::Z</code> - infinite precision integer numbers
* <code>GMP::Q</code> - infinite precision rational numbers
* <code>GMP::F</code> - arbitrary precision floating point numbers
* <code>GMP::RandState</code> - states of individual random number generators</p>
<p>Numbers are created by using <code>new()</code>. Constructors can take following arguments:</p>
<pre><code>GMP::Z.new()
GMP::Z.new(GMP::Z)
GMP::Z.new(Fixnum)
GMP::Z.new(Bignum)
GMP::Z.new(String)
GMP::Q.new()
GMP::Q.new(GMP::Q)
GMP::Q.new(String)
GMP::Q.new(any GMP::Z initializer)
GMP::Q.new(any GMP::Z initializer, any GMP::Z initializer)
GMP::F.new()
GMP::F.new(GMP::Z, precision=0)
GMP::F.new(GMP::Q, precision=0)
GMP::F.new(GMP::F)
GMP::F.new(GMP::F, precision)
GMP::F.new(String, precision=0)
GMP::F.new(Fixnum, precision=0)
GMP::F.new(Bignum, precision=0)
GMP::F.new(Float, precision=0)
GMP::RandState.new(\[algorithm\] \[, algorithm_args\])
</code></pre>
<p>You can also call them as:</p>
<pre><code>GMP.Z(args)
GMP.Q(args)
GMP.F(args)
GMP.RandState()
</code></pre>
<h2>Methods</h2>
<pre><code>GMP::Z, GMP::Q and GMP::F
+ addition
- substraction
* multiplication
/ division
to_s convert to string. For GMP::Z, this method takes
one optional argument, a base. The base can be a
Fixnum in the ranges \[2, 62\] or \[-36, -2\] or a
Symbol: :bin, :oct, :dec, or :hex.
-@ negation
neg! in-place negation
abs absolute value
asb! in-place absolute value
coerce promotion of arguments
== equality test
<=>,>=,>,<=,< comparisons
class methods of GMP::Z
fac(n) factorial of n
2fac(n), double_fac(n) double factorial of n
mfac(n) m-multi-factorial of n
primorial(n) primorial of n
fib(n) nth fibonacci number
pow(n,m) n to mth power
GMP::Z and GMP::Q
swap efficiently swap contents of two objects, there
is no GMP::F.swap because various GMP::F objects
may have different precisions, which would make
them unswapable
GMP::Z
to_i convert to Fixnum or Bignum
add! in-place addition
sub! in-place subtraction
addmul!(b,c) in-place += b*c
submul!(b,c) in-place -= b*c
tdiv,fdiv,cdiv truncate, floor and ceil division
tmod,fmod,cmod truncate, floor and ceil modulus
>> shift right, floor
divisible?(b) true if divisible by b
congruent?(c,d) true if congruent to c modulus d
** power
powmod power modulo
\[\],\[\]= testing and setting bits (as booleans)
scan0,scan1 starting at bitnr (1st arg), scan for a 0 or 1
(respectively), then return the index of the
first instance.
cmpabs comparison of absolute value
com 2's complement
com! in-place 2's complement
&,|,^ logical operations: and, or, xor
even? is even
odd? is odd
<< shift left
tshr shift right, truncate
lastbits_pos(n) last n bits of object, modulo if negative
lastbits_sgn(n) last n bits of object, preserve sign
power? is perfect power
square? is perfect square
sqrt square root
sqrt! change the object into its square root
sqrtrem square root, remainder
root(n) nth root
probab_prime? 0 if composite, 1 if probably prime, 2 if
certainly prime
nextprime next *probable* prime
nextprime! change the object into its next *probable* prime
gcd, gcdext, gcdext2 greatest common divisor
lcm least common multiple
invert(m) invert mod m
jacobi jacobi symbol
legendre legendre symbol
remove(n) remove all occurences of factor n
popcount the number of bits equal to 1
hamdist the hamming distance between two integers
out_raw output to IO object
inp_raw input from IO object
export export to a byte array (String)
import import from a byte array (String)
sizeinbase(b) digits in base b
size_in_bin digits in binary
size number of limbs
GMP::Q
num numerator
den denominator
inv inversion
inv! in-place inversion
floor,ceil,trunc nearest integer
class methods of GMP::F
default_prec get default precision
default_prec= set default precision
GMP::F
prec get precision
floor,ceil,trunc nearest integer, GMP::F is returned, not GMP::Z
floor!,ceil!,trunc! in-place nearest integer
GMP::RandState
seed(integer) seed the generator with a Fixnum or GMP::Z
urandomb(fixnum) get uniformly distributed random number between 0
and 2^fixnum-1, inclusive
urandomm(integer) get uniformly distributed random number between 0
and integer-1, inclusive
GMP (timing functions for GMPbench (0.2))
cputime milliseconds of cpu time since Ruby start
time times the execution of a block
*only if MPFR is available*
class methods of GMP::F
const_log2 returns the natural log of 2
const_pi returns pi
const_euler returns euler
const_catalan returns catalan
mpfr_buildopt_tls_p returns whether MPFR was built as thread safe
mpfr_buildopt_decimal_p returns whether MPFR was compiled with decimal
float support
GMP::F
sqrt square root of the object
rec_sqrt square root of the recprical of the object
cbrt cube root of the object
** power
log natural logarithm of object
log2 binary logarithm of object
log10 decimal logarithm of object
exp e^object
exp2 2^object
exp10 10^object
log1p the same as (object + 1).log, with better
precision
expm1 the same as (object.exp) - 1, with better
precision
eint exponential integral of object
li2 real part of the dilogarithm of object
gamma Gamma fucntion of object
lngamma logarithm of the Gamma function of object
digamma Digamma function of object (MPFR_VERSION >= "3.0.0")
zeta Reimann Zeta function of object
erf error function of object
erfc complementary error function of object
j0 first kind Bessel function of order 0 of object
j1 first kind Bessel function of order 1 of object
jn first kind Bessel function of order n of object
y0 second kind Bessel function of order 0 of object
y1 second kind Bessel function of order 1 of object
yn second kind Bessel function of order n of object
agm arithmetic-geometric mean
hypot
cos \
sin |
tan |
sin_cos |
sec |
csc |
cot |
acos |
asin |
atan | trigonometric functions
atan2 |
cosh | of the object
sinh |
tanh |
sinh_cosh |
sec |
csc |
cot |
acosh |
asinh |
atanh /
nan? \
infinite? | type of floating point number
finite? |
number? |
regular? / (MPFR_VERSION >= "3.0.0")
GMP::RandState
mpfr_urandomb(fixnum) get uniformly distributed random floating-point
number within 0 <= rop < 1
</code></pre>
<h2>Functional Mappings</h2>
<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>
<pre><code>a = GMP::Z(0)
b = GMP::Z(13)
c = GMP::Z(17)
GMP::Z.add(a, b, c)
a #=> 30
</code></pre>
<p>Here's a fun list of all of the functional mappings written so far:</p>
<pre><code>GMP::Z
.abs .add .addmul .cdiv_q_2exp .cdiv_r_2exp .com
.congruent? .divexact .divisible? .fdiv_q_2exp .fdiv_r_2exp .lcm
.mul .mul_2exp
.neg .nextprime .sqrt .sub .submul .tdiv_q_2exp
.tdiv_r_2exp
</code></pre>
<h2>Documentation</h2>
<ul>
<li><a href="https://github.com/srawlins/gmp">This README</a></li>
<li>Loren Segal and the guys at RubyGems.org are awesome: <a href="http://rubydoc.info/gems/gmp/frames">YARDoc</a>.</li>
<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>
<li><a href="https://github.com/srawlins/gmp/blob/master/CHANGELOG">CHANGELOG</a></li>
</ul>
<h2>Testing</h2>
<p>Tests can be run with:</p>
<pre><code>cd test
ruby unit_tests.rb
</code></pre>
<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>
<p>You can also use the following shiny new rake tasks:</p>
<pre><code>rake test
rake report
MPFR=no-mpfr rake report
</code></pre>
<h2>Known Issues</h2>
<p>Don't call <code>GMP::RandState(:lc_2exp_size)</code>. Give a 2nd arg.
Don't use multiple assignment (<code>a = b = GMP::Z(0)</code>) with functional mappings:</p>
<p><code>ruby
>> a = b = GMP::Z(0)
=> 0
>> GMP::Z.mul(a, GMP::Z(2), GMP::Z(3))
=> nil
>> a
=> 6
>> b
=> 6
</code></p>
<p>JRuby has some interesting bugs and flickering tests. GMP::Z(GMP::GMP<em>NUMB</em>MAX) for example, blows up.</p>
<h2>Precision</h2>
<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>
<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>
<pre><code>new_obj = GMP::F.new(old_obj, 0)
</code></pre>
<p>Precision argument, and default_precision will be rounded up to whatever GMP thinks is appropriate.</p>
<h2>Benchmarking</h2>
<p>Please see <a href="performance.md">performance</a></p>
<h2>Todo</h2>
<ul>
<li><code>GMP::Z#to_d_2exp</code>, <code>#rootrem</code>, <code>#kronecker</code>, <code>#bin</code>, <code>#fib2</code>, <code>#lucnum</code>, <code>#lucnum2</code>, <code>#combit</code>, <code>#fits_x?</code></li>
<li><code>GMP::Q#to_s(base)</code>, <code>GMP::F#to_s(base)</code> (test it!)</li>
<li>benchmark pi</li>
<li>a butt-load of functional mappings. 47-ish sets.</li>
<li>investigate possible memory leaks when using <code>GMP::Q(22/7)</code> for example</li>
<li>beef up <code>r_gmpq_initialize</code>; I don't like to rely on <code>mpz_set_value</code>.</li>
<li>finish compile-results.rb</li>
<li>New in MPFR 3.1.0: mpfr<em>frexp, mpfr</em>grandom, mpfr<em>z</em>sub, divide-by-zero exception (?)</li>
<li>benchmark different orderings of type checks</li>
</ul>
<p>The below are inherited from Tomasz. I will go through these and see which are
still relevant, and which I understand.</p>
<ul>
<li><code>mpz_fits_*</code> and 31 vs. 32 integer variables</li>
<li>fix all sign issues (don't know what these are)</li>
<li><code>to_s</code> vs. <code>inspect</code></li>
<li>check if <code>mpz_addmul_ui</code> would optimize some statements</li>
<li>some system that allows using denref and numref as normal ruby objects</li>
<li>takeover code that replaces all <code>Bignums</code> with <code>GMP::Z</code></li>
<li>better bignum parser (crawling into the Bignum extension)</li>
<li>zero-copy method for strings generation</li>
<li>benchmarks against Python GMP and Perl GMP</li>
<li><code>dup</code> methods for GMP::Q and GMP::F</li>
<li>integrate <code>F</code> into system</li>
<li>should <code>Z.\[\]</code> bits be 0/1 or true/false, 0 is true, which might surprise users</li>
<li><code>any2small_integer()</code></li>
<li>powm with negative exponents</li>
<li>check if different sorting of operations gives better cache usage</li>
<li><code>GMP::\*</code> op <code>RubyFloat</code> and <code>RubyFloat</code> op <code>GMP::\*</code></li>
</ul>