gmp 0.5.23 → 0.5.41
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/FEATURES.html +145 -2
- data/README.rdoc +70 -68
- data/benchmark/multiply.fnl +47 -0
- data/ext/extconf.rb +4 -0
- data/ext/gmpf.c +1 -0
- data/ext/gmpz.c +302 -4
- data/ext/ruby_gmp.h +10 -4
- data/manual.pdf +0 -0
- data/manual.tex +84 -61
- data/test/tc_f_precision.rb +1 -1
- data/test/tc_hashes.rb +2 -0
- data/test/tc_logical_roots.rb +2 -0
- data/test/tc_mpfr_constants.rb +2 -0
- data/test/tc_mpfr_functions.rb +2 -0
- data/test/tc_mpfr_random.rb +2 -0
- data/test/tc_mpfr_rounding.rb +2 -0
- data/test/tc_q.rb +2 -0
- data/test/tc_q_basic.rb +2 -0
- data/test/tc_random.rb +2 -0
- data/test/tc_sgn_neg_abs.rb +2 -0
- data/test/tc_swap.rb +2 -0
- data/test/tc_z.rb +2 -2
- data/test/tc_z_addmul.rb +2 -0
- data/test/tc_z_basic.rb +2 -0
- data/test/tc_z_exponentiation.rb +3 -1
- data/test/tc_z_functional_mappings.rb +100 -0
- data/test/tc_z_gcd_lcm_invert.rb +2 -0
- data/test/tc_z_jac_leg_rem.rb +2 -0
- data/test/tc_zerodivisionexceptions.rb +3 -1
- data/test/unit_tests.rb +5 -4
- metadata +6 -4
data/ext/gmpz.c
CHANGED
@@ -180,6 +180,280 @@ static VALUE r_gmpz_##fname(VALUE self) \
|
|
180
180
|
return mpz_fname (self_val) ? Qtrue : Qfalse; \
|
181
181
|
}
|
182
182
|
|
183
|
+
|
184
|
+
/**********************************************************************
|
185
|
+
* Functional Mappings *
|
186
|
+
**********************************************************************/
|
187
|
+
|
188
|
+
/*
|
189
|
+
* 01 mpz_t__mpz_t_or_ui__to__mpz_t__returns__void
|
190
|
+
* FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID defines a GMP::Z singleton function that takes a
|
191
|
+
* GMP::Z as rop, a GMP::Z as op1, and a GMP::Z, Bignum, or Fixnum as op2. It calls
|
192
|
+
* mpz_fname, whose arguments are rop (the return argument), op1, and op2. If op2 is a
|
193
|
+
* Fixnum, and >= 0, the ui variant of mpz_fname will be used.
|
194
|
+
*
|
195
|
+
* TODO: Accept Fixnum, Bignum as op1 and just convert to GMP::Z.
|
196
|
+
*/
|
197
|
+
#define FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(fname,mpz_fname) \
|
198
|
+
static VALUE r_gmpzsg_##fname(VALUE klass, VALUE rop, VALUE op1, VALUE op2) \
|
199
|
+
{ \
|
200
|
+
MP_INT *rop_val, *op1_val, *op2_val; \
|
201
|
+
(void)klass; \
|
202
|
+
\
|
203
|
+
if (! GMPZ_P (rop)) { \
|
204
|
+
typeerror_as(Z, "rop"); \
|
205
|
+
} \
|
206
|
+
mpz_get_struct (rop, rop_val); \
|
207
|
+
\
|
208
|
+
if (! GMPZ_P (op1)) { \
|
209
|
+
typeerror_as (Z, "op1"); \
|
210
|
+
} \
|
211
|
+
mpz_get_struct (op1, op1_val); \
|
212
|
+
\
|
213
|
+
if (FIXNUM_P (op2)) { \
|
214
|
+
if (FIX2NUM (op2) >= 0) { \
|
215
|
+
mpz_fname##_ui (rop_val, op1_val, FIX2NUM (op2)); \
|
216
|
+
} else { \
|
217
|
+
mpz_set_si (rop_val, FIX2NUM (op2)); \
|
218
|
+
mpz_fname (rop_val, op1_val, rop_val); \
|
219
|
+
} \
|
220
|
+
} else if (BIGNUM_P (op2)) { \
|
221
|
+
mpz_set_bignum (rop_val, op2); \
|
222
|
+
mpz_fname (rop_val, op1_val, rop_val); \
|
223
|
+
} else if (GMPZ_P (op2)) { \
|
224
|
+
mpz_get_struct (op2, op2_val); \
|
225
|
+
mpz_fname (rop_val, op1_val, op2_val); \
|
226
|
+
} else { \
|
227
|
+
typeerror_as (ZXB, "op2"); \
|
228
|
+
} \
|
229
|
+
\
|
230
|
+
return Qnil; \
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
* Document-method: GMP::Z.add
|
235
|
+
*
|
236
|
+
* call-seq:
|
237
|
+
* GMP::Z.add(rop, op1, op2)
|
238
|
+
*
|
239
|
+
* ...
|
240
|
+
*/
|
241
|
+
FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(add,mpz_add)
|
242
|
+
FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(addmul,mpz_addmul)
|
243
|
+
FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(submul,mpz_submul)
|
244
|
+
FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(divexact,mpz_divexact)
|
245
|
+
FUNC_MAP__Z_ZUI__TO__Z__RETURNS__VOID(lcm,mpz_lcm)
|
246
|
+
|
247
|
+
/*
|
248
|
+
* 02 mpz_t_or_ui__mpz_t_or_ui__to__mpz_t__returns__void
|
249
|
+
* FUNC_MAP__ZUI_ZUI__TO__Z__RETURNS__VOID defines a GMP::Z singleton function that takes
|
250
|
+
* a GMP::Z as rop, a GMP::Z, Bignum, or Fixnum as op1, and a GMP::Z, Bignum, or Fixnum
|
251
|
+
* as op2. It calls mpz_fname, whose arguments are rop (the return argument), op1, and
|
252
|
+
* op2. If op1 is a Fixnum and >=0, xor if op2 is a Fixnum and >= 0, one ui variant or
|
253
|
+
* the other of mpz_fname will be used:
|
254
|
+
*
|
255
|
+
* op2 --> | FIXNUM >=0 | FIXNUM < 0 | BIGNUM | GMP::Z |
|
256
|
+
* v op1 v +--------------+--------------+--------------+--------------+
|
257
|
+
* FIXNUM >= 0 | mpz_ui_fname | mpz_ui_fname | mpz_ui_fname | mpz_ui_fname |
|
258
|
+
* FIXNUM < 0 | mpz_fname_ui | mpz_fname | mpz_fname | mpz_fname |
|
259
|
+
* BIGNUM | mpz_fname_ui | mpz_fname | mpz_fname | mpz_fname |
|
260
|
+
* GMP::Z | mpz_fname_ui | mpz_fname | mpz_fname | mpz_fname |
|
261
|
+
*
|
262
|
+
* TODO: Maybe take si's, negate them, and perform mpz_additive_inverse_fname *choke*
|
263
|
+
*/
|
264
|
+
#define FUNC_MAP__ZUI_ZUI__TO__Z__RETURNS__VOID(fname,mpz_fname) \
|
265
|
+
static VALUE r_gmpzsg_##fname(VALUE klass, VALUE rop, VALUE op1, VALUE op2) \
|
266
|
+
{ \
|
267
|
+
MP_INT *rop_val, *op1_val, *op2_val; \
|
268
|
+
int free_op1_val = 0; \
|
269
|
+
(void)klass; \
|
270
|
+
\
|
271
|
+
if (! GMPZ_P (rop)) { \
|
272
|
+
typeerror_as(Z, "rop"); \
|
273
|
+
} \
|
274
|
+
mpz_get_struct (rop, rop_val); \
|
275
|
+
\
|
276
|
+
if (FIXNUM_P (op1) && FIX2NUM (op1) >= 0) { \
|
277
|
+
if (FIXNUM_P (op2)) { \
|
278
|
+
mpz_set_si (rop_val, FIX2NUM (op2)); \
|
279
|
+
mpz_ui_##fname (rop_val, FIX2NUM (op1), rop_val); \
|
280
|
+
} else if (BIGNUM_P (op2)) { \
|
281
|
+
mpz_set_bignum (rop_val, op2); \
|
282
|
+
mpz_ui_##fname (rop_val, FIX2NUM (op1), rop_val); \
|
283
|
+
} else if (GMPZ_P (op2)) { \
|
284
|
+
mpz_get_struct (op2, op2_val); \
|
285
|
+
mpz_ui_##fname (rop_val, FIX2NUM (op1), op2_val); \
|
286
|
+
} else { \
|
287
|
+
typeerror_as (ZXB, "op2"); \
|
288
|
+
} \
|
289
|
+
} else { \
|
290
|
+
if (FIXNUM_P (op1)) { \
|
291
|
+
mpz_temp_alloc (op1_val); \
|
292
|
+
mpz_init_set_si (op1_val, FIX2NUM (op1)); \
|
293
|
+
free_op1_val = 1; \
|
294
|
+
} else if (BIGNUM_P (op1)) { \
|
295
|
+
mpz_temp_from_bignum (op1_val, op1); \
|
296
|
+
free_op1_val = 1; \
|
297
|
+
} else if (GMPZ_P (op1)) { \
|
298
|
+
mpz_get_struct (op1, op1_val); \
|
299
|
+
} else { \
|
300
|
+
typeerror_as (ZXB, "op1"); \
|
301
|
+
} \
|
302
|
+
\
|
303
|
+
if (FIXNUM_P (op2)) { \
|
304
|
+
if (FIX2NUM (op2) >= 0) { \
|
305
|
+
mpz_fname##_ui (rop_val, op1_val, FIX2NUM (op2)); \
|
306
|
+
} else { \
|
307
|
+
mpz_set_si (rop_val, FIX2NUM (op2)); \
|
308
|
+
mpz_fname (rop_val, op1_val, rop_val); \
|
309
|
+
} \
|
310
|
+
} else if (BIGNUM_P (op2)) { \
|
311
|
+
mpz_set_bignum (rop_val, op2); \
|
312
|
+
mpz_fname (rop_val, op1_val, rop_val); \
|
313
|
+
} else if (GMPZ_P (op2)) { \
|
314
|
+
mpz_get_struct (op2, op2_val); \
|
315
|
+
mpz_fname (rop_val, op1_val, op2_val); \
|
316
|
+
} else { \
|
317
|
+
typeerror_as (ZXB, "op2"); \
|
318
|
+
} \
|
319
|
+
\
|
320
|
+
if (free_op1_val) \
|
321
|
+
mpz_temp_free (op1_val); \
|
322
|
+
} \
|
323
|
+
\
|
324
|
+
return Qnil; \
|
325
|
+
}
|
326
|
+
|
327
|
+
FUNC_MAP__ZUI_ZUI__TO__Z__RETURNS__VOID(sub,mpz_sub)
|
328
|
+
|
329
|
+
/*
|
330
|
+
* 03 mpz_t__mpz_t_or_si_or_ui__to__mpz_t__returns__void
|
331
|
+
* FUNC_MAP__Z_ZSIUI__TO__Z__RETURNS__VOID defines a GMP::Z singleton function that takes
|
332
|
+
* a GMP::Z as rop, a GMP::Z as op1, and a GMP::Z, Bignum, or Fixnum as op2. It calls
|
333
|
+
* mpz_fname, whose arguments are rop (the return argument), op1, and op2. If op2 is a
|
334
|
+
* Fixnum, then if op2 >= 0 the ui variant of mpz_fname (else the si variant of
|
335
|
+
* mpz_fname) will be used.
|
336
|
+
*
|
337
|
+
* TODO: Accept Fixnum, Bignum as op1 and just convert to GMP::Z.
|
338
|
+
*/
|
339
|
+
#define FUNC_MAP__Z_ZSIUI__TO__Z__RETURNS__VOID(fname,mpz_fname) \
|
340
|
+
static VALUE r_gmpzsg_##fname(VALUE klass, VALUE rop, VALUE op1, VALUE op2) \
|
341
|
+
{ \
|
342
|
+
MP_INT *rop_val, *op1_val, *op2_val; \
|
343
|
+
(void)klass; \
|
344
|
+
\
|
345
|
+
if (! GMPZ_P (rop)) { \
|
346
|
+
typeerror_as(Z, "rop"); \
|
347
|
+
} \
|
348
|
+
mpz_get_struct (rop, rop_val); \
|
349
|
+
\
|
350
|
+
if (! GMPZ_P (op1)) { \
|
351
|
+
typeerror_as (Z, "op1"); \
|
352
|
+
} \
|
353
|
+
mpz_get_struct (op1, op1_val); \
|
354
|
+
\
|
355
|
+
if (FIXNUM_P (op2)) { \
|
356
|
+
if (FIX2NUM (op2) >= 0) { \
|
357
|
+
mpz_fname##_ui (rop_val, op1_val, FIX2NUM (op2)); \
|
358
|
+
} else { \
|
359
|
+
mpz_fname##_si (rop_val, op1_val, FIX2NUM (op2)); \
|
360
|
+
} \
|
361
|
+
} else if (BIGNUM_P (op2)) { \
|
362
|
+
mpz_set_bignum (rop_val, op2); \
|
363
|
+
mpz_fname (rop_val, op1_val, rop_val); \
|
364
|
+
} else if (GMPZ_P (op2)) { \
|
365
|
+
mpz_get_struct (op2, op2_val); \
|
366
|
+
mpz_fname (rop_val, op1_val, op2_val); \
|
367
|
+
} else { \
|
368
|
+
typeerror_as (ZXB, "op2"); \
|
369
|
+
} \
|
370
|
+
\
|
371
|
+
return Qnil; \
|
372
|
+
}
|
373
|
+
|
374
|
+
FUNC_MAP__Z_ZSIUI__TO__Z__RETURNS__VOID(mul,mpz_mul)
|
375
|
+
|
376
|
+
/*
|
377
|
+
* 04 mpz_t__mp_bitcnt_t__to__mpz_t__returns__void
|
378
|
+
* FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID defines a GMP::Z singleton function that takes a
|
379
|
+
* GMP::Z as rop, a GMP::Z as op1, and a Fixnum as op2. It calls mpz_fname, whose
|
380
|
+
* arguments are rop (the return argument), op1, and op2. op2 must be >= 0.
|
381
|
+
*
|
382
|
+
* TODO: Accept Fixnum, Bignum as op1 and just convert to GMP::Z.
|
383
|
+
*/
|
384
|
+
#define FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(fname,mpz_fname) \
|
385
|
+
static VALUE r_gmpzsg_##fname(VALUE klass, VALUE rop, VALUE op1, VALUE op2) \
|
386
|
+
{ \
|
387
|
+
MP_INT *rop_val, *op1_val; \
|
388
|
+
(void)klass; \
|
389
|
+
\
|
390
|
+
if (! GMPZ_P (rop)) { \
|
391
|
+
typeerror_as(Z, "rop"); \
|
392
|
+
} \
|
393
|
+
mpz_get_struct (rop, rop_val); \
|
394
|
+
\
|
395
|
+
if (! GMPZ_P (op1)) { \
|
396
|
+
typeerror_as (Z, "op1"); \
|
397
|
+
} \
|
398
|
+
mpz_get_struct (op1, op1_val); \
|
399
|
+
\
|
400
|
+
if (! FIXNUM_P (op2)) { \
|
401
|
+
typeerror_as (X, "op2"); \
|
402
|
+
} \
|
403
|
+
\
|
404
|
+
if (FIX2NUM (op2) >= 0) { \
|
405
|
+
mpz_fname (rop_val, op1_val, FIX2NUM (op2)); \
|
406
|
+
} else { \
|
407
|
+
rb_raise(rb_eRangeError, "op2 (Fixnum) must be nonnegative"); \
|
408
|
+
} \
|
409
|
+
\
|
410
|
+
return Qnil; \
|
411
|
+
}
|
412
|
+
|
413
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(mul_2exp,mpz_mul_2exp)
|
414
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(cdiv_q_2exp,mpz_cdiv_q_2exp)
|
415
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(cdiv_r_2exp,mpz_cdiv_r_2exp)
|
416
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(fdiv_q_2exp,mpz_fdiv_q_2exp)
|
417
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(fdiv_r_2exp,mpz_fdiv_r_2exp)
|
418
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(tdiv_q_2exp,mpz_tdiv_q_2exp)
|
419
|
+
FUNC_MAP__Z_BITCNT__TO__Z__RETURNS__VOID(tdiv_r_2exp,mpz_tdiv_r_2exp)
|
420
|
+
|
421
|
+
/*
|
422
|
+
* 05 mpz_t__mpz_t__to__mpz_t__returns__void
|
423
|
+
* FUNC_MAP__Z__TO__Z__RETURNS__VOID defines a GMP::Z singleton function that takes a
|
424
|
+
* GMP::Z as rop, and a GMP::Z as op1. It calls mpz_fname, whose arguments are rop (the
|
425
|
+
* return argument), and op1.
|
426
|
+
*
|
427
|
+
* TODO: Accept Fixnum, Bignum as op1 and just convert to GMP::Z.
|
428
|
+
*/
|
429
|
+
#define FUNC_MAP__Z__TO__Z__RETURNS__VOID(fname,mpz_fname) \
|
430
|
+
static VALUE r_gmpzsg_##fname(VALUE klass, VALUE rop, VALUE op1) \
|
431
|
+
{ \
|
432
|
+
MP_INT *rop_val, *op1_val; \
|
433
|
+
(void)klass; \
|
434
|
+
\
|
435
|
+
if (! GMPZ_P (rop)) { \
|
436
|
+
typeerror_as(Z, "rop"); \
|
437
|
+
} \
|
438
|
+
mpz_get_struct (rop, rop_val); \
|
439
|
+
\
|
440
|
+
if (! GMPZ_P (op1)) { \
|
441
|
+
typeerror_as (Z, "op1"); \
|
442
|
+
} \
|
443
|
+
mpz_get_struct (op1, op1_val); \
|
444
|
+
\
|
445
|
+
mpz_fname (rop_val, op1_val); \
|
446
|
+
\
|
447
|
+
return Qnil; \
|
448
|
+
}
|
449
|
+
|
450
|
+
FUNC_MAP__Z__TO__Z__RETURNS__VOID(neg,mpz_neg)
|
451
|
+
FUNC_MAP__Z__TO__Z__RETURNS__VOID(abs,mpz_abs)
|
452
|
+
FUNC_MAP__Z__TO__Z__RETURNS__VOID(sqrt,mpz_sqrt)
|
453
|
+
FUNC_MAP__Z__TO__Z__RETURNS__VOID(nextprime,mpz_nextprime)
|
454
|
+
FUNC_MAP__Z__TO__Z__RETURNS__VOID(com,mpz_com)
|
455
|
+
|
456
|
+
|
183
457
|
/**********************************************************************
|
184
458
|
* Initializing, Assigning Integers *
|
185
459
|
**********************************************************************/
|
@@ -1612,10 +1886,10 @@ DEFUN_INT_SINGLETON_UI(fac, mpz_fac_ui)
|
|
1612
1886
|
* * GMP::Z.fib(1) #=> 1
|
1613
1887
|
* * GMP::Z.fib(2) #=> 1
|
1614
1888
|
* * GMP::Z.fib(3) #=> 2
|
1615
|
-
* * GMP::Z.
|
1616
|
-
* * GMP::Z.
|
1617
|
-
* * GMP::Z.
|
1618
|
-
* * GMP::Z.
|
1889
|
+
* * GMP::Z.fib(4) #=> 3
|
1890
|
+
* * GMP::Z.fib(5) #=> 5
|
1891
|
+
* * GMP::Z.fib(6) #=> 8
|
1892
|
+
* * GMP::Z.fib(7) #=> 13
|
1619
1893
|
*/
|
1620
1894
|
DEFUN_INT_SINGLETON_UI(fib, mpz_fib_ui)
|
1621
1895
|
|
@@ -2155,6 +2429,15 @@ void init_gmpz()
|
|
2155
2429
|
rb_define_method(cGMP_Z, "-@", r_gmpz_neg, 0);
|
2156
2430
|
rb_define_method(cGMP_Z, "abs", r_gmpz_abs, 0);
|
2157
2431
|
rb_define_method(cGMP_Z, "abs!", r_gmpz_abs_self, 0);
|
2432
|
+
// Functional Mappings
|
2433
|
+
rb_define_singleton_method(cGMP_Z, "add", r_gmpzsg_add, 3);
|
2434
|
+
rb_define_singleton_method(cGMP_Z, "sub", r_gmpzsg_sub, 3);
|
2435
|
+
rb_define_singleton_method(cGMP_Z, "mul", r_gmpzsg_mul, 3);
|
2436
|
+
rb_define_singleton_method(cGMP_Z, "addmul", r_gmpzsg_addmul, 3);
|
2437
|
+
rb_define_singleton_method(cGMP_Z, "submul", r_gmpzsg_submul, 3);
|
2438
|
+
rb_define_singleton_method(cGMP_Z, "mul_2exp", r_gmpzsg_mul_2exp, 3);
|
2439
|
+
rb_define_singleton_method(cGMP_Z, "neg", r_gmpzsg_neg, 2);
|
2440
|
+
rb_define_singleton_method(cGMP_Z, "abs", r_gmpzsg_abs, 2);
|
2158
2441
|
|
2159
2442
|
// Integer Division
|
2160
2443
|
rb_define_method(cGMP_Z, "/", r_gmpz_div, 1);
|
@@ -2168,6 +2451,14 @@ void init_gmpz()
|
|
2168
2451
|
rb_define_method(cGMP_Z, "cmod", r_gmpz_cmod, 1);
|
2169
2452
|
rb_define_method(cGMP_Z, "%", r_gmpz_mod, 1);
|
2170
2453
|
rb_define_method(cGMP_Z, "divisible?", r_gmpz_divisible, 1);
|
2454
|
+
// Functional Mappings
|
2455
|
+
rb_define_singleton_method(cGMP_Z, "divexact", r_gmpzsg_divexact, 3);
|
2456
|
+
rb_define_singleton_method(cGMP_Z, "cdiv_q_2exp", r_gmpzsg_cdiv_q_2exp, 3);
|
2457
|
+
rb_define_singleton_method(cGMP_Z, "cdiv_r_2exp", r_gmpzsg_cdiv_r_2exp, 3);
|
2458
|
+
rb_define_singleton_method(cGMP_Z, "fdiv_q_2exp", r_gmpzsg_fdiv_q_2exp, 3);
|
2459
|
+
rb_define_singleton_method(cGMP_Z, "fdiv_r_2exp", r_gmpzsg_fdiv_r_2exp, 3);
|
2460
|
+
rb_define_singleton_method(cGMP_Z, "tdiv_q_2exp", r_gmpzsg_tdiv_q_2exp, 3);
|
2461
|
+
rb_define_singleton_method(cGMP_Z, "tdiv_r_2exp", r_gmpzsg_tdiv_r_2exp, 3);
|
2171
2462
|
|
2172
2463
|
// Integer Exponentiation
|
2173
2464
|
rb_define_singleton_method(cGMP_Z, "pow", r_gmpzsg_pow, 2);
|
@@ -2181,6 +2472,8 @@ void init_gmpz()
|
|
2181
2472
|
rb_define_method(cGMP_Z, "sqrtrem", r_gmpz_sqrtrem, 0);
|
2182
2473
|
rb_define_method(cGMP_Z, "square?", r_gmpz_is_square, 0);
|
2183
2474
|
rb_define_method(cGMP_Z, "power?", r_gmpz_is_power, 0);
|
2475
|
+
// Functional Mappings
|
2476
|
+
rb_define_singleton_method(cGMP_Z, "sqrt", r_gmpzsg_sqrt, 2);
|
2184
2477
|
|
2185
2478
|
// Number Theoretic Functions
|
2186
2479
|
rb_define_method( cGMP_Z, "probab_prime?", r_gmpz_is_probab_prime, -1);
|
@@ -2197,6 +2490,9 @@ void init_gmpz()
|
|
2197
2490
|
rb_define_method( cGMP_Z, "remove", r_gmpz_remove, 1);
|
2198
2491
|
rb_define_singleton_method(cGMP_Z, "fac", r_gmpzsg_fac, 1);
|
2199
2492
|
rb_define_singleton_method(cGMP_Z, "fib", r_gmpzsg_fib, 1);
|
2493
|
+
// Functional Mappings
|
2494
|
+
rb_define_singleton_method(cGMP_Z, "lcm", r_gmpzsg_lcm, 3);
|
2495
|
+
rb_define_singleton_method(cGMP_Z, "nextprime", r_gmpzsg_nextprime, 2);
|
2200
2496
|
|
2201
2497
|
// Integer Comparisons
|
2202
2498
|
rb_define_method(cGMP_Z, "<=>", r_gmpz_cmp, 1);
|
@@ -2222,6 +2518,8 @@ void init_gmpz()
|
|
2222
2518
|
rb_define_method(cGMP_Z, "scan1", r_gmpz_scan1, 1);
|
2223
2519
|
rb_define_method(cGMP_Z, "[]=", r_gmpz_setbit, 2);
|
2224
2520
|
rb_define_method(cGMP_Z, "[]", r_gmpz_getbit, 1);
|
2521
|
+
// Functional Mappings
|
2522
|
+
rb_define_singleton_method(cGMP_Z, "com", r_gmpzsg_com, 2);
|
2225
2523
|
|
2226
2524
|
// Miscellaneous Integer Functions
|
2227
2525
|
rb_define_method(cGMP_Z, "even?", r_gmpz_is_even, 0);
|
data/ext/ruby_gmp.h
CHANGED
@@ -110,13 +110,19 @@ typedef __gmp_randstate_struct MP_RANDSTATE;
|
|
110
110
|
#define r_mpf_cmp(var1, var2) (mpf_cmp(var1, var2))
|
111
111
|
#endif
|
112
112
|
|
113
|
-
#
|
114
|
-
/* 64-bit */
|
113
|
+
#ifdef FIXNUM_WIDTH /* RBX check */
|
114
|
+
#if (((8*SIZEOF_INTPTR_T) - TAG_FIXNUM_SHIFT -1) == 63) /* 64-bit */
|
115
115
|
#define FIX2NUM(x) FIX2LONG(x)
|
116
|
-
#else
|
117
|
-
/* 32-bit */
|
116
|
+
#else /* 32-bit */
|
118
117
|
#define FIX2NUM(x) FIX2INT(x)
|
119
118
|
#endif
|
119
|
+
#else /* RBX check */
|
120
|
+
#if SIZEOF_INT < SIZEOF_LONG /* 64-bit */
|
121
|
+
#define FIX2NUM(x) FIX2LONG(x)
|
122
|
+
#else /* 32-bit */
|
123
|
+
#define FIX2NUM(x) FIX2INT(x)
|
124
|
+
#endif /* MRI's 32-vs-64 check */
|
125
|
+
#endif /* RBX check */
|
120
126
|
|
121
127
|
#define EXPECTED_ZQFXBD "Expected GMP::Z, GMP::Q, GMP::F, Fixnum, Bignum or Float"
|
122
128
|
#define EXPECTED_ZQFXB "Expected GMP::Z, GMP::Q, GMP::F, Fixnum or Bignum"
|
data/manual.pdf
CHANGED
Binary file
|
data/manual.tex
CHANGED
@@ -34,8 +34,8 @@
|
|
34
34
|
\huge{gmp} &\\
|
35
35
|
\midrule[3pt]
|
36
36
|
\multicolumn{2}{r}{\large{Ruby bindings to the GMP library}}\\
|
37
|
-
\multicolumn{2}{r}{\large{Edition 0.5.
|
38
|
-
\multicolumn{2}{r}{\large{
|
37
|
+
\multicolumn{2}{r}{\large{Edition 0.5.41}}\\
|
38
|
+
\multicolumn{2}{r}{\large{17 November 2010}}
|
39
39
|
\end{tabular}
|
40
40
|
|
41
41
|
\vfill
|
@@ -147,9 +147,12 @@ of the following versions of Ruby:
|
|
147
147
|
\item (MRI) Ruby 1.9.1 - tested seriously.
|
148
148
|
\item (MRI) Ruby 1.9.2 - tested seriously.
|
149
149
|
\item (REE) Ruby 1.8.7 - tested lightly.
|
150
|
+
\item (RBX) Rubinius 1.1 - tested lightly.
|
150
151
|
\end{itemize}
|
151
|
-
As you can see only Matz's Ruby Interpreter (MRI) is supported. I've just
|
152
|
-
around with REE. Everything seems to work on REE 1.8.7 on Linux, x86 and
|
152
|
+
As you can see only Matz's Ruby Interpreter (MRI) is seriously supported. I've just
|
153
|
+
started to poke around with REE. Everything seems to work on REE 1.8.7 on Linux, x86 and
|
154
|
+
x86\_64. Also, Rubinius 1.1 seems to work great on Linux, but support won't be official
|
155
|
+
until Rubinius 1.1.1.\\
|
153
156
|
|
154
157
|
Next is the platform, the combination of the architecture (processor) and OS.
|
155
158
|
As far as I can tell, if you can compile GMP and Ruby (and optionally MPFR) on
|
@@ -174,35 +177,42 @@ The (MPFR) version denotes that the gmp gem was tested both with and without
|
|
174
177
|
the given version of MPFR:\\\\
|
175
178
|
|
176
179
|
\begin{tabular}{lrrr} \hline
|
177
|
-
Platform & Ruby
|
178
|
-
Linux (Ubuntu NR 10.04) on x86 (32-bit) & (MRI) Ruby 1.8.7
|
179
|
-
& (MRI) Ruby 1.8.7
|
180
|
-
& (MRI) Ruby 1.9.1
|
181
|
-
& (MRI) Ruby 1.9.1
|
182
|
-
& (MRI) Ruby 1.9.2
|
183
|
-
& (MRI) Ruby 1.9.2
|
184
|
-
|
185
|
-
& (
|
186
|
-
|
187
|
-
& (MRI) Ruby 1.
|
188
|
-
& (MRI) Ruby 1.9.
|
189
|
-
& (MRI) Ruby 1.9.
|
190
|
-
|
191
|
-
& (MRI) Ruby 1.
|
192
|
-
& (
|
193
|
-
& (
|
194
|
-
|
195
|
-
& (MRI) Ruby 1.
|
196
|
-
|
197
|
-
& (MRI) Ruby 1.
|
198
|
-
& (MRI) Ruby 1.9.
|
199
|
-
& (MRI) Ruby 1.9.
|
200
|
-
& (
|
201
|
-
& (
|
202
|
-
Windows
|
203
|
-
& (MRI) Ruby 1.
|
180
|
+
Platform & Ruby & GMP & (MPFR) \\ \midrule[1pt]
|
181
|
+
Linux (Ubuntu NR 10.04) on x86 (32-bit) & (MRI) Ruby 1.8.7 & GMP 4.3.2 & (2.4.2) \\
|
182
|
+
& (MRI) Ruby 1.8.7 & GMP 5.0.1 & (3.0.0) \\
|
183
|
+
& (MRI) Ruby 1.9.1 & GMP 4.3.2 & (2.4.2) \\
|
184
|
+
& (MRI) Ruby 1.9.1 & GMP 5.0.1 & (3.0.0) \\
|
185
|
+
& (MRI) Ruby 1.9.2 & GMP 4.3.2 & (2.4.2) \\
|
186
|
+
& (MRI) Ruby 1.9.2 & GMP 5.0.1 & (3.0.0) \\
|
187
|
+
& (RBX) Rubinius 1.1 & GMP 4.3.2 & (2.4.2) \\
|
188
|
+
& (RBX) Rubinius 1.1 & GMP 5.0.1 & (3.0.0) \\ \hline
|
189
|
+
Linux (Ubuntu 10.04) on x86\_64 (64-bit) & (MRI) Ruby 1.8.7 & GMP 4.3.2 & (2.4.2) \\
|
190
|
+
& (MRI) Ruby 1.8.7 & GMP 5.0.1 & (3.0.0) \\
|
191
|
+
& (MRI) Ruby 1.9.1 & GMP 4.3.2 & (2.4.2) \\
|
192
|
+
& (MRI) Ruby 1.9.1 & GMP 5.0.1 & (3.0.0) \\
|
193
|
+
& (MRI) Ruby 1.9.2 & GMP 4.3.2 & (2.4.2) \\
|
194
|
+
& (MRI) Ruby 1.9.2 & GMP 5.0.1 & (3.0.0) \\
|
195
|
+
& (RBX) Rubinius 1.1 & GMP 4.3.2 & (2.4.2) \\
|
196
|
+
& (RBX) Rubinius 1.1 & GMP 5.0.1 & (3.0.0) \\ \hline
|
197
|
+
Mac OS X 10.6.4 on x86\_64 (64-bit) & (MRI) Ruby 1.8.7 & GMP 4.3.2 & (2.4.2) \\
|
198
|
+
& (MRI) Ruby 1.8.7 & GMP 5.0.1 & (3.0.0) \\
|
199
|
+
& (MRI) Ruby 1.9.1 & GMP 4.3.2 & (2.4.2) \\
|
200
|
+
& (MRI) Ruby 1.9.1 & GMP 5.0.1 & (3.0.0) \\
|
201
|
+
& (MRI) Ruby 1.9.2 & GMP 4.3.2 & (2.4.2) \\
|
202
|
+
& (MRI) Ruby 1.9.2 & GMP 5.0.1 & (3.0.0) \\
|
203
|
+
& (RBX) Rubinius 1.1 & GMP 4.3.2 & (2.4.2) \\
|
204
|
+
& (RBX) Rubinius 1.1 & GMP 5.0.1 & (3.0.0) \\ \hline
|
205
|
+
Windows 7 on x86\_64 (64-bit) & (MRI) Ruby 1.8.7 & GMP 4.3.2 & (2.4.2) \\
|
206
|
+
& (MRI) Ruby 1.8.7 & GMP 5.0.1 & (3.0.0) \\
|
207
|
+
& (MRI) Ruby 1.9.1 & GMP 4.3.2 & (2.4.2) \\
|
208
|
+
& (MRI) Ruby 1.9.1 & GMP 5.0.1 & (3.0.0) \\
|
209
|
+
& (MRI) Ruby 1.9.2 & GMP 4.3.2 & (2.4.2) \\
|
210
|
+
& (MRI) Ruby 1.9.2 & GMP 5.0.1 & (3.0.0) \\ \hline
|
211
|
+
Windows XP on x86 (32-bit) & (MRI) Ruby 1.9.1 & GMP 4.3.2 & (2.4.2) \\
|
212
|
+
& (MRI) Ruby 1.9.1 & GMP 5.0.1 & (3.0.0) \\ \hline
|
204
213
|
\end{tabular}\\\\
|
205
214
|
|
215
|
+
\newpage
|
206
216
|
In addition, I \textit{used to test} on the following environments, in versions
|
207
217
|
0.4.7 and earlier of the gmp gem:\\\\
|
208
218
|
|
@@ -1520,56 +1530,69 @@ for 'base' and 'app' are not listed; they cannot be compared with GMPbench resul
|
|
1520
1530
|
|
1521
1531
|
Mac OS X 10.6.4, x86 (32-bit)\\
|
1522
1532
|
Ruby and GMP compiled with gcc 4.2.1 (Apple Inc. build 5664)\\
|
1523
|
-
\begin{tabular}{|l|l|r|r|r|r|}
|
1533
|
+
\begin{tabular}{|l|l|r|r|r|r|r|}
|
1524
1534
|
\hline
|
1525
|
-
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & C \\
|
1535
|
+
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & RBX 1.1 & C \\
|
1526
1536
|
\hline
|
1527
|
-
4.3.2 & multiply &
|
1528
|
-
& divide &
|
1529
|
-
& gcd &
|
1530
|
-
& rsa &
|
1537
|
+
4.3.2 & multiply & 7734.2 & 7505.9 & 7637.9 & 7469.3 & 16789 \\
|
1538
|
+
& divide & 7336.1 & 7180 & 7223.7 & 7121.2 & 9872.5 \\
|
1539
|
+
& gcd & 2356 & 2436.8 & 2448.8 & 2385.6 & 2938.9 \\
|
1540
|
+
& rsa & 2035.2 & 1995.3 & 2068.4 & 2051.1 & 2136.7 \\
|
1531
1541
|
\hline
|
1532
|
-
5.0.1 & multiply &
|
1533
|
-
& divide &
|
1534
|
-
& gcd &
|
1535
|
-
& rsa &
|
1542
|
+
5.0.1 & multiply & 8030.5 & 7926.7 & 8019.3 & 7944.1 & 17925 \\
|
1543
|
+
& divide & 10341 & 10070 & 10218 & 10018 & 16069 \\
|
1544
|
+
& gcd & 2501 & 2535.4 & 2578.7 & 2537.3 & 3063.7 \\
|
1545
|
+
& rsa & 2128 & 2159.1 & 2170.5 & 2162 & 2229.2 \\
|
1536
1546
|
\hline
|
1537
1547
|
\end{tabular}\\\\
|
1538
1548
|
|
1539
|
-
Ubuntu 10.04, Kernel 2.6.32-
|
1549
|
+
Ubuntu 10.04, Kernel 2.6.32-25, x86\_64 (64-bit)\\
|
1540
1550
|
Ruby and GMP compiled with gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)\\
|
1541
|
-
\begin{
|
1551
|
+
\begin{small}In these tests, the classic multiply benchmark crashes with OutOfMemory. There are
|
1552
|
+
two ways this has been remedied. The first (tests marked multiply.gc) is to manually
|
1553
|
+
kick off garbage collection every so often. This solves the memory problem in all
|
1554
|
+
interpreters except Rubinius 1.1 (investigation pending). The second, and far better
|
1555
|
+
solution is to employ the new functional mapping methods. These have not been
|
1556
|
+
documented yet, but documentation is pending, and high on my priority list. Simply
|
1557
|
+
put, these methods overcome the overhead (memory and time) of instantiating new
|
1558
|
+
objects all the time.\end{small}\\
|
1559
|
+
\begin{tabular}{|l|l|r|r|r|r|r|}
|
1542
1560
|
\hline
|
1543
|
-
GMP & bench
|
1561
|
+
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & RBX 1.1 & C \\
|
1544
1562
|
\hline
|
1545
|
-
4.3.2 & multiply &
|
1546
|
-
&
|
1547
|
-
&
|
1548
|
-
&
|
1563
|
+
4.3.2 & multiply & x & x & x & x & 14716 \\
|
1564
|
+
& multiply.gc & 7849.2 & 6911.4 & 7703.5 & x & 14716 \\
|
1565
|
+
& multiply.fnl & 9532.6 & 11182 & 10886 & 5131.3 & 14716 \\
|
1566
|
+
& divide & 7704.6 & 7591.8 & 7527.2 & 4265.1 & 8614.3 \\
|
1567
|
+
& gcd & 2420.1 & 2453.6 & 2487.4 & 1676.4 & 2779.8 \\
|
1568
|
+
& rsa & 2040.5 & 2069.2 & 2044.2 & 1758.9 & 1984.3 \\
|
1549
1569
|
\hline
|
1550
|
-
5.0.1 & multiply &
|
1551
|
-
&
|
1552
|
-
&
|
1553
|
-
&
|
1570
|
+
5.0.1 & multiply & x & x & x & x & 17695 \\
|
1571
|
+
& multiply.gc & 8265.3 & 7289.4 & 8105.1 & x & 17695 \\
|
1572
|
+
& multiply.fnl & 10029 & 11807 & 11493 & 6036.7 & 17695 \\
|
1573
|
+
& divide & 10988 & 10935 & 10799 & 6164.9 & 15629 \\
|
1574
|
+
& gcd & 2554.2 & 2510.2 & 2538.6 & 1802.8 & 2925.1 \\
|
1575
|
+
& rsa & 2128.7 & 2189 & 2179.9 & 1941.2 & 2233.4 \\
|
1554
1576
|
\hline
|
1555
1577
|
\end{tabular}\\\\
|
1556
1578
|
|
1579
|
+
\newpage
|
1557
1580
|
Windows 7 (64-bit)\\
|
1558
1581
|
Ruby and GMP compiled with gcc 4.5.0 (tdm-1)\\
|
1559
1582
|
\begin{tabular}{|l|l|r|r|r|r|}
|
1560
1583
|
\hline
|
1561
1584
|
GMP & bench & Ruby 1.8.7 & Ruby 1.9.1 & Ruby 1.9.2 & C \\
|
1562
1585
|
\hline
|
1563
|
-
4.3.2 & multiply &
|
1564
|
-
& divide &
|
1565
|
-
& gcd &
|
1566
|
-
& rsa &
|
1586
|
+
4.3.2 & multiply & 3607.9 & 3679.3 & 3655.5 & 6448.7 \\
|
1587
|
+
& divide & 3062.6 & 3103.7 & 3074.5 & 3717.5 \\
|
1588
|
+
& gcd & 1165 & 1190.6 & 1211.8 & 1359.4 \\
|
1589
|
+
& rsa & 733.87 & 729.9 & 742.22 & 757.97 \\
|
1567
1590
|
\hline
|
1568
|
-
5.0.1 & multiply &
|
1569
|
-
& divide &
|
1570
|
-
& gcd &
|
1571
|
-
& rsa &
|
1591
|
+
5.0.1 & multiply & 3792.1 & 3869 & 3785.9 & 6835.2 \\
|
1592
|
+
& divide & 4662.2 & 4704.4 & 4692.3 & 6497.4 \\
|
1593
|
+
& gcd & 1222.8 & 1249.7 & 1245 & 1394.2 \\
|
1594
|
+
& rsa & 742.78 & 745.66 & 739.9 & 754.72 \\
|
1572
1595
|
\hline
|
1573
1596
|
\end{tabular}\\
|
1574
1597
|
|
1575
|
-
\end{document}
|
1598
|
+
\end{document}
|