gmp 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ #ifndef _GMPQ_H_
2
+ #define _GMPQ_H_
3
+
4
+ /*
5
+ * gmpq.h
6
+ *
7
+ * This file contains GMP::Q stuff.
8
+ */
9
+
10
+ #include <ruby_gmp.h>
11
+
12
+ #endif
@@ -0,0 +1,1774 @@
1
+ #include <gmpz.h>
2
+ #include <gmpq.h>
3
+ #include <gmpf.h>
4
+
5
+ /*
6
+ * Document-class: GMP::Z
7
+ *
8
+ * GMP Multiple Precision Integer.
9
+ *
10
+ * Instances of this class can store variables of the type mpz_t. This class
11
+ * also contains many methods that act as the functions for mpz_t variables,
12
+ * as well as a few methods that attempt to make this library more Ruby-ish.
13
+ *
14
+ * The following list is just a simple checklist for me, really. A better
15
+ * reference should be found in the rdocs.
16
+ *
17
+ * Ruby method C Extension function GMP function
18
+ * to_d r_gmpz_to_d mpz_get_d
19
+ * to_i r_gmpz_to_i mpz_get_i
20
+ * to_s r_gmpz_to_s mpz_get_s
21
+ * + r_gmpz_add mpz_add
22
+ * add! r_gmpz_add_self mpz_add
23
+ * - r_gmpz_sub mpz_sub
24
+ * sub! r_gmpz_sub_self mpz_sub
25
+ * * r_gmpz_mul mpz_mul
26
+ * / r_gmpz_div ...
27
+ * tdiv r_gmpz_tdiv mpz_tdiv_q
28
+ * tmod r_gmpz_tmod mpz_tdiv_r
29
+ * fdiv r_gmpz_fdiv mpz_fdiv_q
30
+ * fmod r_gmpz_fmod mpz_fdiv_r
31
+ * cdiv r_gmpz_cdiv mpz_cdiv_q
32
+ * cmod r_gmpz_cmod mpz_cdiv_r
33
+ * -@ r_gmpz_neg mpz_neg
34
+ * neg r_gmpz_neg mpz_neg
35
+ * neg! r_gmpz_neg_self mpz_neg
36
+ * abs r_gmpz_abs mpz_abs
37
+ * abs! r_gmpz_abs_self mpz_abs
38
+ * root r_gmpz_root mpz_root
39
+ * sqrt r_gmpz_sqrt mpz_sqrt
40
+ * sqrt! r_gmpz_sqrt_self mpz_sqrt
41
+ * sqrtrem r_gmpz_sqrtrem mpz_sqrtrem
42
+ * remove r_gmpz_remove mpz_remove
43
+ * fac r_gmpz_fac mpz_fac_ui
44
+ * fib r_gmpz_fib mpz_fib_ui
45
+ * com r_gmpz_com mpz_com
46
+ * com! r_gmpz_com_self mpz_com
47
+ * []= r_gmpz_setbit mpz_setbit
48
+ * [] r_gmpz_getbit mpz_tstbit
49
+ * scan0 r_gmpz_scan0 mpz_scan0
50
+ * scan1 r_gmpz_scan1 mpz_scan1
51
+ * even? r_gmpz_is_even mpz_even
52
+ * odd? r_gmpz_is_odd mpz_odd
53
+ * ...
54
+ */
55
+
56
+ /*
57
+ * The goal is to organize this file in the same order that the GMP Manual
58
+ * is organized.
59
+ */
60
+
61
+ /**********************************************************************
62
+ * Macros *
63
+ **********************************************************************/
64
+
65
+ #define DEFUN_INT2INT(fname,mpz_fname) \
66
+ static VALUE r_gmpz_##fname(VALUE self) \
67
+ { \
68
+ MP_INT *self_val, *res_val; \
69
+ VALUE res; \
70
+ mpz_get_struct(self, self_val); \
71
+ mpz_make_struct_init(res, res_val); \
72
+ mpz_fname(res_val, self_val); \
73
+ return res; \
74
+ } \
75
+ \
76
+ static VALUE r_gmpz_##fname##_self(VALUE self) \
77
+ { \
78
+ MP_INT *self_val; \
79
+ mpz_get_struct(self, self_val); \
80
+ mpz_fname(self_val, self_val); \
81
+ return Qnil; \
82
+ }
83
+
84
+ #define DEFUN_INT_F_UL(fname,mpz_fname,argname) \
85
+ static VALUE r_gmpz_##fname(VALUE self, VALUE exp) \
86
+ { \
87
+ MP_INT *self_val, *res_val; \
88
+ VALUE res; \
89
+ unsigned long exp_val; \
90
+ \
91
+ if (FIXNUM_P(exp)) { \
92
+ if (FIX2INT(exp) < 0) \
93
+ rb_raise(rb_eRangeError, argname " out of range"); \
94
+ exp_val = FIX2INT(exp); \
95
+ } else if (GMPZ_P(exp)) { \
96
+ mpz_get_struct(exp, res_val); \
97
+ if (!mpz_fits_ulong_p(res_val)) \
98
+ rb_raise(rb_eRangeError, argname " out of range"); \
99
+ exp_val = mpz_get_ui(res_val); \
100
+ if (exp_val == 0) \
101
+ rb_raise(rb_eRangeError, argname " out of range"); \
102
+ } else { \
103
+ typeerror_as(ZX, argname); \
104
+ } \
105
+ \
106
+ mpz_make_struct_init(res, res_val); \
107
+ mpz_get_struct(self, self_val); \
108
+ mpz_fname(res_val, self_val, exp_val); \
109
+ \
110
+ return res; \
111
+ }
112
+
113
+ #define DEFUN_INT_CMP(name,CMP_OP) \
114
+ static VALUE r_gmpz_cmp_##name(VALUE self, VALUE arg) \
115
+ { \
116
+ MP_INT *self_val; \
117
+ mpz_get_struct(self,self_val); \
118
+ return (mpz_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
119
+ }
120
+
121
+ #define DEFUN_INT_DIV(fname,gmp_fname) \
122
+ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \
123
+ { \
124
+ MP_INT *self_val, *arg_val, *res_val; \
125
+ VALUE res; \
126
+ int arg_val_i; \
127
+ \
128
+ mpz_get_struct(self, self_val); \
129
+ mpz_make_struct_init(res, res_val); \
130
+ \
131
+ if (GMPZ_P(arg)) { \
132
+ mpz_get_struct(arg,arg_val); \
133
+ if (mpz_cmp_ui(arg_val, 0) == 0) \
134
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
135
+ gmp_fname (res_val, self_val, arg_val); \
136
+ } else if (FIXNUM_P(arg)) { \
137
+ arg_val_i = FIX2INT(arg); \
138
+ if (arg_val_i > 0) { \
139
+ gmp_fname##_ui (res_val, self_val, arg_val_i); \
140
+ } else if (arg_val_i == 0) { \
141
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
142
+ } else { \
143
+ mpz_neg (res_val, self_val); \
144
+ gmp_fname##_ui (res_val, self_val, -arg_val_i); \
145
+ } \
146
+ } else if (BIGNUM_P(arg)) { \
147
+ mpz_set_bignum (res_val, arg); \
148
+ if (mpz_cmp_ui(res_val, 0) == 0) \
149
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
150
+ gmp_fname (res_val, self_val, res_val); \
151
+ } else { \
152
+ typeerror(ZXB); \
153
+ } \
154
+ return res; \
155
+ }
156
+
157
+ #define DEFUN_INT_LOGIC(fname, mpz_fname) \
158
+ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \
159
+ { \
160
+ MP_INT *self_val, *arg_val, *res_val; \
161
+ VALUE res; \
162
+ \
163
+ mpz_get_struct(self, self_val); \
164
+ \
165
+ mpz_make_struct(res, res_val); \
166
+ if (GMPZ_P(arg)) { \
167
+ mpz_get_struct(arg,arg_val); \
168
+ mpz_init(res_val); \
169
+ mpz_fname(res_val, self_val, arg_val); \
170
+ } else if (FIXNUM_P(arg)) { \
171
+ mpz_init_set_si(res_val, FIX2INT(arg)); \
172
+ mpz_fname(res_val, self_val, res_val); \
173
+ } else if (BIGNUM_P(arg)) { \
174
+ mpz_init(res_val); \
175
+ mpz_set_bignum(res_val, arg); \
176
+ mpz_fname(res_val, self_val, res_val); \
177
+ } else { \
178
+ typeerror(ZXB); \
179
+ } \
180
+ return res; \
181
+ }
182
+
183
+ #define DEFUN_INT_SINGLETON_UI(fname,mpz_fname) \
184
+ static VALUE r_gmpzsg_##fname(VALUE klass, VALUE arg) \
185
+ { \
186
+ MP_INT *arg_val_z, *res_val; \
187
+ unsigned long arg_val_ul; \
188
+ VALUE res; \
189
+ \
190
+ (void)klass; \
191
+ \
192
+ if (FIXNUM_P(arg)) { \
193
+ arg_val_ul = FIX2INT (arg); \
194
+ } else if (GMPZ_P(arg)) { \
195
+ mpz_get_struct(arg, arg_val_z); \
196
+ if (!mpz_fits_ulong_p (arg_val_z)) \
197
+ rb_raise(rb_eRangeError, "argument out of range"); \
198
+ arg_val_ul = mpz_get_ui(arg_val_z); \
199
+ if (arg_val_ul == 0) \
200
+ rb_raise(rb_eRangeError, "argument out of range"); \
201
+ } else { \
202
+ typeerror_as(ZX, "argument"); \
203
+ } \
204
+ mpz_make_struct_init(res, res_val); \
205
+ mpz_fname(res_val, arg_val_ul); \
206
+ return res; \
207
+ }
208
+
209
+ /**********************************************************************
210
+ * Initializing, Assigning Integers *
211
+ **********************************************************************/
212
+
213
+ /*
214
+ * call-seq:
215
+ * GMP::Z.new(arg)
216
+ *
217
+ * Creates a new GMP::Z integer, with arg as its value, converting where
218
+ * necessary.
219
+ */
220
+ VALUE r_gmpzsg_new(int argc, VALUE *argv, VALUE klass)
221
+ {
222
+ MP_INT *res_val;
223
+ VALUE res;
224
+
225
+ (void)klass;
226
+
227
+ if (argc > 1)
228
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0 or 1)", argc);
229
+
230
+ mpz_make_struct(res, res_val);
231
+ mpz_init(res_val);
232
+
233
+ rb_obj_call_init(res, argc, argv);
234
+
235
+ return res;
236
+ }
237
+
238
+ VALUE r_gmpz_initialize(int argc, VALUE *argv, VALUE self)
239
+ {
240
+ MP_INT *self_val;
241
+
242
+ if (argc != 0) {
243
+ mpz_get_struct(self,self_val);
244
+ mpz_set_value (self_val, argv[0]);
245
+ }
246
+ return Qnil;
247
+ }
248
+
249
+ /*
250
+ * call-seq:
251
+ * a = b
252
+ *
253
+ * Sets the value of +a+ to the value of +b+. +b+ may be one of the following
254
+ * classes:
255
+ *
256
+ * * GMP::Z
257
+ * * Fixnum
258
+ * * String
259
+ * * Bignum
260
+ */
261
+ void mpz_set_value(MP_INT *target, VALUE source)
262
+ {
263
+ MP_INT *source_val;
264
+
265
+ if (GMPZ_P(source)) {
266
+ mpz_get_struct(source, source_val);
267
+ mpz_set(target, source_val);
268
+ } else if (FIXNUM_P(source)) {
269
+ mpz_set_si(target, NUM2INT(source));
270
+ } else if (STRING_P(source)) {
271
+ mpz_set_str(target, STR2CSTR(source), 0);
272
+ } else if (BIGNUM_P(source)) {
273
+ mpz_set_bignum(target, source);
274
+ } else {
275
+ rb_raise(rb_eTypeError, "Don't know how to convert %s into GMP_Z", rb_class2name(rb_class_of(source)));
276
+ }
277
+ }
278
+
279
+ /*
280
+ * call-seq:
281
+ * GMP::Z(arg)
282
+ *
283
+ * A convenience method for +GMP::Z.new(arg)+.
284
+ */
285
+ VALUE r_gmpmod_z(int argc, VALUE *argv, VALUE module)
286
+ {
287
+ (void)module;
288
+ return r_gmpzsg_new(argc, argv, cGMP_Z);
289
+ }
290
+
291
+ /*
292
+ * call-seq:
293
+ * int1.swap int2
294
+ *
295
+ * Efficiently swaps the contents of +int1+ with +int2+.
296
+ */
297
+ VALUE r_gmpz_swap(VALUE self, VALUE arg)
298
+ {
299
+ MP_INT *self_val, *arg_val;
300
+ if (!GMPZ_P(arg)) {
301
+ rb_raise(rb_eTypeError, "Can't swap GMP::Z with object of other class");
302
+ }
303
+ mpz_get_struct(self, self_val);
304
+ mpz_get_struct(arg, arg_val);
305
+ mpz_swap(self_val,arg_val);
306
+ return Qnil;
307
+ }
308
+
309
+
310
+ /**********************************************************************
311
+ * Converting Integers *
312
+ **********************************************************************/
313
+
314
+ /*
315
+ * call-seq:
316
+ * integer.to_i
317
+ *
318
+ * Returns +integer+ as an Fixnum if +integer+ fits in a Fixnum.
319
+ *
320
+ * Otherwise returns the least significant part of +integer+, with the same
321
+ * sign as +integer+.
322
+ *
323
+ * If +integer+ is too big to fit in a Fixnum, the returned result is probably
324
+ * not very useful. To find out if the value will fit, use the function
325
+ * mpz_fits_slong_p (<b>Unimplemented</b>).
326
+ */
327
+ VALUE r_gmpz_to_i(VALUE self)
328
+ {
329
+ MP_INT *self_val;
330
+ char *str;
331
+ VALUE res;
332
+
333
+ mpz_get_struct(self, self_val);
334
+ if (mpz_fits_slong_p(self_val))
335
+ return rb_int2inum(mpz_get_si(self_val));
336
+ str = mpz_get_str(NULL, 0, self_val);
337
+ res = rb_cstr2inum(str, 10);
338
+ free(str);
339
+ return res;
340
+ }
341
+
342
+ /*
343
+ * call-seq:
344
+ * integer.to_d
345
+ *
346
+ * Returns +integer+ as an Float if +integer+ fits in a Float.
347
+ *
348
+ * Otherwise returns the least significant part of +integer+, with the same
349
+ * sign as +integer+.
350
+ *
351
+ * If +integer+ is too big to fit in a Float, the returned result is probably
352
+ * not very useful. To find out if the value will fit, use the function
353
+ * mpz_fits_slong_p (<b>Unimplemented</b>).
354
+ */
355
+ VALUE r_gmpz_to_d(VALUE self)
356
+ {
357
+ MP_INT *self_val;
358
+ mpz_get_struct(self, self_val);
359
+
360
+ return rb_float_new(mpz_get_d(self_val));
361
+ }
362
+
363
+ /*
364
+ * Document-method: to_s
365
+ *
366
+ * call-seq:
367
+ * integer.to_s(base = 10)
368
+ *
369
+ * Returns +integer+, as a Ruby string. If +base+ is not provided, then
370
+ * the string will be the decimal representation.
371
+ *
372
+ * From the GMP Manual:
373
+ *
374
+ * Convert +integer+ to a string of digits in base +base+. The +base+ argument
375
+ * may vary from 2 to 62 or from -2 to -36.
376
+ *
377
+ * For +base+ in the range 2..36, digits and lower-case letters are used; for
378
+ * -2..-36, digits and upper-case letters are used; for 37..62, digits,
379
+ * upper-case letters, and lower-case letters (in that significance order) are
380
+ * used.
381
+ */
382
+ VALUE r_gmpz_to_s(int argc, VALUE *argv, VALUE self)
383
+ {
384
+ MP_INT *self_val;
385
+ char *str;
386
+ VALUE res;
387
+ VALUE base;
388
+ int base_val = 10;
389
+ ID base_id;
390
+ const char * bin_base = "bin"; /* binary */
391
+ const char * oct_base = "oct"; /* octal */
392
+ const char * dec_base = "dec"; /* decimal */
393
+ const char * hex_base = "hex"; /* hexadecimal */
394
+ ID bin_base_id = rb_intern(bin_base);
395
+ ID oct_base_id = rb_intern(oct_base);
396
+ ID dec_base_id = rb_intern(dec_base);
397
+ ID hex_base_id = rb_intern(hex_base);
398
+
399
+ rb_scan_args(argc, argv, "01", &base);
400
+ if (NIL_P(base)) { base = INT2FIX(10); } /* default value */
401
+ if (FIXNUM_P(base)) {
402
+ base_val = FIX2INT(base);
403
+ if ((base_val >= 2 && base_val <= 62) ||
404
+ (base_val >= -36 && base_val <= -2)) {
405
+ /* good base */
406
+ } else {
407
+ base_val = 10;
408
+ rb_raise(rb_eRangeError, "base must be within [2, 62] or [-36, -2].");
409
+ }
410
+ } else if (SYMBOL_P(base)) {
411
+ base_id = rb_to_id(base);
412
+ if (base_id == bin_base_id) {
413
+ base_val = 2;
414
+ } else if (base_id == oct_base_id) {
415
+ base_val = 8;
416
+ } else if (base_id == dec_base_id) {
417
+ base_val = 10;
418
+ } else if (base_id == hex_base_id) {
419
+ base_val = 16;
420
+ } else {
421
+ base_val = 10; /* should raise an exception here. */
422
+ }
423
+ }
424
+
425
+ Data_Get_Struct(self, MP_INT, self_val);
426
+ str = mpz_get_str(NULL, base_val, self_val);
427
+ res = rb_str_new2(str);
428
+ free (str);
429
+
430
+ return res;
431
+ }
432
+
433
+
434
+ /**********************************************************************
435
+ * Integer Arithmetic *
436
+ **********************************************************************/
437
+
438
+ /*
439
+ * call-seq:
440
+ * +(other)
441
+ *
442
+ * Adds this GMP::Z to other. Other can be
443
+ * * GMP::Z
444
+ * * Fixnum
445
+ * * GMP::Q
446
+ * * GMP::F
447
+ * * Bignum
448
+ */
449
+ VALUE r_gmpz_add(VALUE self, VALUE arg)
450
+ {
451
+ MP_INT *self_val, *arg_val, *res_val;
452
+ VALUE res;
453
+
454
+ mpz_get_struct(self,self_val);
455
+
456
+ if (GMPZ_P(arg)) {
457
+ mpz_get_struct(arg,arg_val);
458
+ mpz_make_struct_init(res, res_val);
459
+ mpz_add(res_val, self_val, arg_val);
460
+ } else if (FIXNUM_P(arg)) {
461
+ mpz_make_struct_init(res, res_val);
462
+ if (FIX2INT(arg) > 0)
463
+ mpz_add_ui(res_val, self_val, FIX2INT(arg));
464
+ else
465
+ mpz_sub_ui(res_val, self_val, -FIX2INT(arg));
466
+ } else if (GMPQ_P(arg)) {
467
+ return r_gmpq_add(arg, self);
468
+ } else if (GMPF_P(arg)) {
469
+ return r_gmpf_add(arg, self);
470
+ } else if (BIGNUM_P(arg)) {
471
+ mpz_make_struct_init(res, res_val);
472
+ mpz_init(res_val);
473
+ mpz_set_bignum(res_val, arg);
474
+ mpz_add(res_val, res_val, self_val);
475
+ } else {
476
+ typeerror(ZQFXB);
477
+ }
478
+ return res;
479
+ }
480
+
481
+ /*
482
+ * call-seq:
483
+ * add!(other)
484
+ *
485
+ * Adds this GMP::Z to other, and sets this GMP::Z's value to the result. Other
486
+ * can be
487
+ * * GMP::Z
488
+ * * Fixnum
489
+ * * GMP::Q
490
+ * * GMP::F
491
+ * * Bignum
492
+ */
493
+ VALUE r_gmpz_add_self(VALUE self, VALUE arg)
494
+ {
495
+ MP_INT *self_val, *arg_val;
496
+
497
+ mpz_get_struct(self,self_val);
498
+
499
+ if (GMPZ_P(arg)) {
500
+ mpz_get_struct(arg,arg_val);
501
+ mpz_add(self_val, self_val, arg_val);
502
+ } else if (FIXNUM_P(arg)) {
503
+ if (FIX2INT(arg) > 0)
504
+ mpz_add_ui(self_val, self_val, FIX2INT(arg));
505
+ else
506
+ mpz_sub_ui(self_val, self_val, -FIX2INT(arg));
507
+ } else if (BIGNUM_P(arg)) {
508
+ mpz_temp_from_bignum(arg_val, arg);
509
+ mpz_add(self_val, self_val, arg_val);
510
+ mpz_temp_free(arg_val);
511
+ } else {
512
+ typeerror(ZXB);
513
+ }
514
+ return Qnil;
515
+ }
516
+
517
+ /*
518
+ * call-seq:
519
+ * -(other)
520
+ *
521
+ * Subtracts other from this GMP::Z. Other can be
522
+ * * GMP::Z
523
+ * * Fixnum
524
+ * * GMP::Q
525
+ * * GMP::F
526
+ * * Bignum
527
+ */
528
+ VALUE r_gmpz_sub(VALUE self, VALUE arg)
529
+ {
530
+ MP_RAT *res_val_q, *arg_val_q;
531
+ MP_INT *self_val, *arg_val, *res_val;
532
+ MP_FLOAT *arg_val_f, *res_val_f;
533
+ VALUE res;
534
+ unsigned long prec;
535
+
536
+ mpz_get_struct(self,self_val);
537
+
538
+ if (GMPZ_P(arg)) {
539
+ mpz_make_struct_init(res, res_val);
540
+ mpz_get_struct(arg,arg_val);
541
+ mpz_sub (res_val, self_val, arg_val);
542
+ } else if (FIXNUM_P(arg)) {
543
+ mpz_make_struct_init(res, res_val);
544
+ if (FIX2INT(arg) > 0)
545
+ mpz_sub_ui (res_val, self_val, FIX2INT(arg));
546
+ else
547
+ mpz_add_ui (res_val, self_val, -FIX2INT(arg));
548
+ } else if (GMPQ_P(arg)) {
549
+ mpq_make_struct_init(res, res_val_q);
550
+ mpq_get_struct(arg,arg_val_q);
551
+ mpz_set (mpq_denref(res_val_q), mpq_denref(arg_val_q));
552
+ mpz_mul (mpq_numref(res_val_q), mpq_denref(arg_val_q), self_val);
553
+ mpz_sub (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_numref(arg_val_q));
554
+ } else if (GMPF_P(arg)) {
555
+ mpf_get_struct_prec (arg, arg_val_f, prec);
556
+ mpf_make_struct_init(res, res_val_f, prec);
557
+ mpf_set_z (res_val_f, self_val);
558
+ mpf_sub (res_val_f, res_val_f, arg_val_f);
559
+ } else if (BIGNUM_P(arg)) {
560
+ mpz_make_struct_init(res, res_val);
561
+ mpz_set_bignum (res_val, arg);
562
+ mpz_sub (res_val, self_val, res_val);
563
+ } else {
564
+ typeerror (ZQFXB);
565
+ }
566
+ return res;
567
+ }
568
+
569
+ /*
570
+ * call-seq:
571
+ * sub!(other)
572
+ *
573
+ * Subtracts other from this GMP::Z, and sets this GMP::Z's value to the
574
+ * result. Other can be
575
+ * * GMP::Z
576
+ * * Fixnum
577
+ * * GMP::Q
578
+ * * GMP::F
579
+ * * Bignum
580
+ */
581
+ VALUE r_gmpz_sub_self(VALUE self, VALUE arg)
582
+ {
583
+ MP_INT *self_val, *arg_val;
584
+
585
+ mpz_get_struct(self,self_val);
586
+
587
+ if (GMPZ_P(arg)) {
588
+ mpz_get_struct(arg, arg_val);
589
+ mpz_sub (self_val, self_val, arg_val);
590
+ } else if (FIXNUM_P(arg)) {
591
+ if (FIX2INT(arg) > 0)
592
+ mpz_sub_ui (self_val, self_val, FIX2INT(arg));
593
+ else
594
+ mpz_add_ui (self_val, self_val, -FIX2INT(arg));
595
+ } else if (BIGNUM_P(arg)) {
596
+ mpz_temp_from_bignum(arg_val, arg);
597
+ mpz_sub (self_val, self_val, arg_val);
598
+ mpz_temp_free (arg_val);
599
+ } else {
600
+ typeerror (ZXB);
601
+ }
602
+ return Qnil;
603
+ }
604
+
605
+ /*
606
+ * call-seq:
607
+ * *(other)
608
+ *
609
+ * Multiplies this GMP::Z with other. Other can be
610
+ * * GMP::Z
611
+ * * Fixnum
612
+ * * GMP::Q
613
+ * * GMP::F
614
+ * * Bignum
615
+ */
616
+ VALUE r_gmpz_mul(VALUE self, VALUE arg)
617
+ {
618
+ MP_INT *self_val, *arg_val, *res_val;
619
+ VALUE res;
620
+
621
+ mpz_get_struct(self,self_val);
622
+
623
+ if (GMPZ_P(arg)) {
624
+ mpz_make_struct_init(res, res_val);
625
+ mpz_get_struct(arg,arg_val);
626
+ mpz_mul(res_val, self_val, arg_val);
627
+ } else if (FIXNUM_P(arg)) {
628
+ mpz_make_struct_init(res, res_val);
629
+ mpz_mul_si(res_val, self_val, FIX2INT(arg));
630
+ } else if (GMPQ_P(arg)) {
631
+ return r_gmpq_mul(arg, self);
632
+ } else if (GMPF_P(arg)) {
633
+ return r_gmpf_mul(arg, self);
634
+ } else if (BIGNUM_P(arg)) {
635
+ mpz_make_struct_init(res, res_val);
636
+ mpz_set_bignum(res_val, arg);
637
+ mpz_mul(res_val, res_val, self_val);
638
+ } else {
639
+ typeerror(ZQFXB);
640
+ }
641
+ return res;
642
+ }
643
+
644
+ /*
645
+ * Document-method: neg
646
+ *
647
+ * call-seq:
648
+ * integer.neg
649
+ * -integer
650
+ *
651
+ * From the GMP Manual:
652
+ *
653
+ * Returns -+integer+.
654
+ */
655
+ /*
656
+ * Document-method: neg!
657
+ *
658
+ * call-seq:
659
+ * integer.neg!
660
+ *
661
+ * From the GMP Manual:
662
+ *
663
+ * Sets +integer+ to -+integer+.
664
+ */
665
+ DEFUN_INT2INT(neg, mpz_neg)
666
+ /*
667
+ * Document-method: abs
668
+ *
669
+ * call-seq:
670
+ * integer.abs
671
+ *
672
+ * From the GMP Manual:
673
+ *
674
+ * Returns the absolute value of +integer+.
675
+ */
676
+ /*
677
+ * Document-method: abs!
678
+ *
679
+ * call-seq:
680
+ * integer.abs!
681
+ *
682
+ * From the GMP Manual:
683
+ *
684
+ * Sets +integer+ to its absolute value.
685
+ */
686
+ DEFUN_INT2INT(abs, mpz_abs)
687
+
688
+
689
+ /**********************************************************************
690
+ * Integer Division *
691
+ **********************************************************************/
692
+
693
+ /*
694
+ * call-seq:
695
+ * /(other)
696
+ *
697
+ * Divides this GMP::Z by other. Other can be
698
+ * * GMP::Z
699
+ * * Fixnum
700
+ * * GMP::Q
701
+ * * GMP::F
702
+ * * Bignum
703
+ */
704
+ VALUE r_gmpz_div(VALUE self, VALUE arg)
705
+ {
706
+ MP_INT *self_val, *arg_val_z, *tmp_z;
707
+ MP_RAT *arg_val_q, *res_val_q;
708
+ MP_FLOAT *arg_val_f, *res_val_f;
709
+ VALUE res;
710
+ unsigned int prec;
711
+
712
+ mpz_get_struct(self,self_val);
713
+
714
+ if (GMPZ_P(arg)) {
715
+ mpz_get_struct(arg, arg_val_z);
716
+ if (mpz_cmp_ui(arg_val_z, 0) == 0)
717
+ rb_raise(rb_eZeroDivError, "divided by 0");
718
+ mpq_make_struct_init(res, res_val_q);
719
+ mpq_set_num(res_val_q, self_val);
720
+ mpq_set_den(res_val_q, arg_val_z);
721
+ mpq_canonicalize (res_val_q);
722
+ } else if (FIXNUM_P(arg)) {
723
+ if (FIX2INT(arg) == 0)
724
+ rb_raise(rb_eZeroDivError, "divided by 0");
725
+ mpq_make_struct_init(res, res_val_q);
726
+ mpq_set_num(res_val_q, self_val);
727
+ mpz_set_ui(mpq_denref(res_val_q), FIX2INT(arg));
728
+ mpq_canonicalize (res_val_q);
729
+ } else if (GMPQ_P(arg)) {
730
+ mpq_get_struct(arg, arg_val_q);
731
+ if (mpz_cmp_ui(mpq_numref(arg_val_q), 0) == 0)
732
+ rb_raise(rb_eZeroDivError, "divided by 0");
733
+ mpz_temp_init(tmp_z);
734
+ mpq_make_struct_init(res, res_val_q);
735
+ mpz_gcd(tmp_z, mpq_numref(arg_val_q), self_val);
736
+ mpz_divexact(mpq_numref(res_val_q), self_val, tmp_z);
737
+ mpz_divexact(mpq_denref(res_val_q), mpq_numref(arg_val_q), tmp_z);
738
+ mpz_mul(mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_denref(arg_val_q));
739
+ mpz_temp_free(tmp_z);
740
+ } else if (GMPF_P(arg)) {
741
+ mpf_get_struct_prec(arg, arg_val_f, prec);
742
+ mpf_make_struct_init(res, res_val_f, prec);
743
+ mpf_set_z(res_val_f, self_val);
744
+ mpf_div(res_val_f, res_val_f, arg_val_f);
745
+ } else if (BIGNUM_P(arg)) {
746
+ mpq_make_struct_init(res, res_val_q);
747
+ mpz_set_bignum(mpq_denref(res_val_q), arg);
748
+ if (mpz_cmp_ui(mpq_denref(res_val_q), 0) == 0)
749
+ rb_raise(rb_eZeroDivError, "divided by 0");
750
+ mpq_set_num(res_val_q, self_val);
751
+ mpq_canonicalize(res_val_q);
752
+ } else {
753
+ typeerror(ZQFXB);
754
+ }
755
+ return res;
756
+ }
757
+
758
+ /*
759
+ * Document-method: tdiv
760
+ *
761
+ * call-seq:
762
+ * n.tdiv d
763
+ *
764
+ * From the GMP Manual:
765
+ *
766
+ * Divides +n+ by +d+, forming a quotient +q+. tdiv rounds +q+ towards zero.
767
+ * The +t+ stands for "truncate".
768
+ *
769
+ * +q+ will satisfy <tt>n=q*d+r</tt>, and +r+ will satisfy
770
+ * <tt>0<=abs(r)<abs(d)</tt>.
771
+ *
772
+ * This function calculates only the quotient.
773
+ */
774
+ DEFUN_INT_DIV(tdiv, mpz_tdiv_q)
775
+ /*
776
+ * Document-method: tmod
777
+ *
778
+ * call-seq:
779
+ * n.tmod d
780
+ *
781
+ * From the GMP Manual:
782
+ *
783
+ * Divides +n+ by +d+, forming a remainder +r+. +r+ will have the same sign as
784
+ * +n+. The +t+ stands for �truncate�.
785
+ *
786
+ * +r+ will satisfy <tt>n=q*d+r</tt>, and +r+ will satisfy
787
+ * <tt>0<=abs(r)<abs(d)</tt>.
788
+ *
789
+ * This function calculates only the remainder.
790
+ *
791
+ * The remainder can be negative, so the return value is the absolute value of
792
+ * the remainder.
793
+ */
794
+ DEFUN_INT_DIV(tmod, mpz_tdiv_r)
795
+ /*
796
+ * Document-method: fdiv
797
+ *
798
+ * call-seq:
799
+ * n.fdiv d
800
+ *
801
+ * From the GMP Manual:
802
+ *
803
+ * Divide n by d, forming a quotient q. fdiv rounds q down towards -infinity.
804
+ * The f stands for �floor�.
805
+ *
806
+ * q will satisfy n=q*d+r.
807
+ *
808
+ * This function calculates only the quotient.
809
+ */
810
+ DEFUN_INT_DIV(fdiv, mpz_fdiv_q)
811
+ /*
812
+ * Document-method: fmod
813
+ *
814
+ * call-seq:
815
+ * n.fmod d
816
+ *
817
+ * From the GMP Manual:
818
+ *
819
+ * Divides n by d, forming a remainder r. r will have the same sign as d. The f
820
+ * stands for �floor�.
821
+ *
822
+ * r will satisfy n=q*d+r, and r will satisfy 0<=abs(r)<abs(d).
823
+ *
824
+ * This function calculates only the remainder.
825
+ *
826
+ * The remainder can be negative, so the return value is the absolute value of
827
+ * the remainder.
828
+ */
829
+ DEFUN_INT_DIV(fmod, mpz_fdiv_r)
830
+ /*
831
+ * Document-method: cdiv
832
+ *
833
+ * call-seq:
834
+ * n.cdiv d
835
+ *
836
+ * From the GMP Manual:
837
+ *
838
+ * Divide +n+ by +d+, forming a quotient +q+. +cdiv+ rounds +q+ up towards
839
+ * <tt>+infinity</tt>. The c stands for �ceil�.
840
+ *
841
+ * +q+ will satisfy <tt>n=q*d+r</tt>.
842
+ *
843
+ * This function calculates only the quotient.
844
+ */
845
+ DEFUN_INT_DIV(cdiv, mpz_cdiv_q)
846
+ /*
847
+ * Document-method: cmod
848
+ *
849
+ * call-seq:
850
+ * n.cmod d
851
+ *
852
+ * From the GMP Manual:
853
+ *
854
+ * Divides +n+ by +d+, forming a remainder +r+. +r+ will have the opposite sign
855
+ * as +d+. The c stands for �ceil�.
856
+ *
857
+ * +r+ will satisfy <tt>n=q*d+r</tt>, and +r+ will satisfy
858
+ * <tt>0<=abs(r)<abs(d)</tt>.
859
+ *
860
+ * This function calculates only the remainder.
861
+ */
862
+ DEFUN_INT_DIV(cmod, mpz_cdiv_r)
863
+
864
+
865
+ /**********************************************************************
866
+ * Integer Exponentiation *
867
+ **********************************************************************/
868
+
869
+ /**********************************************************************
870
+ * Integer Roots *
871
+ **********************************************************************/
872
+
873
+ /*
874
+ * Document-method: root
875
+ *
876
+ * call-seq:
877
+ * GMP::Z.root(m, n)
878
+ *
879
+ * From the GMP Manual:
880
+ *
881
+ * Returns the truncated integer part of the +n+th root of +m+.
882
+ */
883
+ DEFUN_INT_F_UL(root,mpz_root,"root number")
884
+
885
+ /*
886
+ * Document-method: sqrt
887
+ *
888
+ * call-seq:
889
+ * integer.sqrt
890
+ *
891
+ * From the GMP Manual:
892
+ *
893
+ * Returns the truncated integer part of the square root of +integer+.
894
+ */
895
+ /*
896
+ * Document-method: sqrt!
897
+ *
898
+ * call-seq:
899
+ * integer.sqrt!
900
+ *
901
+ * From the GMP Manual:
902
+ *
903
+ * Sets +integer+ to the truncated integer part of its square root.
904
+ */
905
+ DEFUN_INT2INT(sqrt, mpz_sqrt)
906
+
907
+ /*
908
+ * Document-method: sqrtrem
909
+ *
910
+ * call-seq:
911
+ * integer.sqrtrem #=> sqrt, rem
912
+ *
913
+ * From the GMP Manual:
914
+ *
915
+ * Returns the truncated integer part of the square root of +integer+ as
916
+ * +sqrt+ and the remainder <tt>integer - sqrt * sqrt</tt> as +rem+, which will
917
+ * be zero if +integer+ is a perfect square.
918
+ */
919
+ static VALUE r_gmpz_sqrtrem(VALUE self)
920
+ {
921
+ MP_INT *self_val, *sqrt_val, *rem_val;
922
+ VALUE sqrt, rem;
923
+
924
+ mpz_get_struct(self, self_val);
925
+ mpz_make_struct_init(sqrt, sqrt_val);
926
+ mpz_make_struct_init(rem, rem_val);
927
+ mpz_sqrtrem(sqrt_val, rem_val, self_val);
928
+ return rb_assoc_new(sqrt, rem);
929
+ }
930
+
931
+
932
+ /**********************************************************************
933
+ * Number Theoretic Functions *
934
+ **********************************************************************/
935
+
936
+ /*
937
+ * Document-method: remove
938
+ *
939
+ * call-seq:
940
+ * integer.remove(factor)
941
+ *
942
+ * From the GMP Manual:
943
+ *
944
+ * Remove all occurrences of the factor +factor+ from +integer+. The return
945
+ * value is how many such occurrences were removed.
946
+ */
947
+ VALUE r_gmpz_remove(VALUE self, VALUE arg)
948
+ {
949
+ MP_INT *self_val, *arg_val, *res_val;
950
+ VALUE res;
951
+ int free_arg_val = 0;
952
+
953
+ mpz_get_struct(self,self_val);
954
+
955
+ if (GMPZ_P(arg)) {
956
+ mpz_get_struct(arg,arg_val);
957
+ if (mpz_sgn(arg_val) != 1)
958
+ rb_raise(rb_eRangeError, "argument must be positive");
959
+ } else if (FIXNUM_P(arg)) {
960
+ if (FIX2INT(arg) <= 0)
961
+ rb_raise(rb_eRangeError, "argument must be positive");
962
+ mpz_temp_alloc(arg_val);
963
+ mpz_init_set_ui(arg_val, FIX2INT(arg));
964
+ } else if (BIGNUM_P(arg)) {
965
+ mpz_temp_from_bignum(arg_val, arg);
966
+ if (mpz_sgn(arg_val) != 1) {
967
+ mpz_temp_free (arg_val);
968
+ rb_raise(rb_eRangeError, "argument must be positive");
969
+ }
970
+ } else {
971
+ typeerror(ZXB);
972
+ }
973
+
974
+ mpz_make_struct_init (res, res_val);
975
+ mpz_remove (res_val, self_val, arg_val);
976
+
977
+ if (free_arg_val)
978
+ mpz_temp_free(arg_val);
979
+
980
+ return res;
981
+ }
982
+
983
+ /*
984
+ * Document-method: GMP::Z.fac
985
+ *
986
+ * call-seq:
987
+ * GMP::Z.fac(n)
988
+ *
989
+ * From the GMP Manual:
990
+ *
991
+ * Returns <tt>n!</tt>, the factorial of +n+.
992
+ *
993
+ * Examples:
994
+ *
995
+ * GMP::Z.fac(0) #=> 1
996
+ * GMP::Z.fac(1) #=> 1
997
+ * GMP::Z.fac(2) #=> 2
998
+ * GMP::Z.fac(3) #=> 6
999
+ * GMP::Z.fac(4) #=> 24
1000
+ */
1001
+ DEFUN_INT_SINGLETON_UI(fac,mpz_fac_ui)
1002
+ /*
1003
+ * Document-method: GMP::Z.fib
1004
+ *
1005
+ * call-seq:
1006
+ * GMP::Z.fib(n)
1007
+ *
1008
+ * From the GMP Manual:
1009
+ *
1010
+ * Returns <tt>F[n]</tt>, the +n+th Fibonacci number.
1011
+ *
1012
+ * Examples:
1013
+ *
1014
+ * GMP::Z.fib(1) #=> 1
1015
+ * GMP::Z.fib(2) #=> 1
1016
+ * GMP::Z.fib(3) #=> 2
1017
+ * GMP::Z.fac(4) #=> 3
1018
+ * GMP::Z.fac(5) #=> 5
1019
+ * GMP::Z.fac(6) #=> 8
1020
+ * GMP::Z.fac(7) #=> 13
1021
+ */
1022
+ DEFUN_INT_SINGLETON_UI(fib,mpz_fib_ui)
1023
+
1024
+
1025
+ /**********************************************************************
1026
+ * Integer Comparisons *
1027
+ **********************************************************************/
1028
+
1029
+ VALUE r_gmpz_eq(VALUE self, VALUE arg)
1030
+ {
1031
+ MP_INT *self_val, *arg_val_z;
1032
+ MP_RAT *arg_val_q;
1033
+
1034
+ mpz_get_struct (self, self_val);
1035
+ if (GMPZ_P(arg)) {
1036
+ mpz_get_struct(arg, arg_val_z);
1037
+ return (mpz_cmp (self_val, arg_val_z)==0) ? Qtrue : Qfalse;
1038
+ } else if (FIXNUM_P(arg)) {
1039
+ return (mpz_cmp_si (self_val, FIX2INT(arg))==0) ? Qtrue : Qfalse;
1040
+ } else if (GMPQ_P(arg)) {
1041
+ mpq_get_struct(arg, arg_val_q);
1042
+ if (mpz_cmp_ui(mpq_denref(arg_val_q), 1)==0)
1043
+ return Qfalse;
1044
+ return (mpz_cmp (self_val, mpq_numref(arg_val_q))==0) ? Qtrue : Qfalse;
1045
+ } else if (BIGNUM_P(arg)) {
1046
+ mpz_temp_from_bignum(arg_val_z, arg);
1047
+ if (mpz_cmp (self_val, arg_val_z)==0) {
1048
+ mpz_temp_free(arg_val_z);
1049
+ return Qtrue;
1050
+ } else {
1051
+ mpz_temp_free(arg_val_z);
1052
+ return Qfalse;
1053
+ }
1054
+ } else {
1055
+ return Qfalse;
1056
+ }
1057
+ }
1058
+
1059
+ VALUE r_gmpz_cmpabs(VALUE self, VALUE arg)
1060
+ {
1061
+ MP_INT *arg_val_z, *self_val;
1062
+ MP_RAT *arg_val_q;
1063
+ int res;
1064
+
1065
+ mpz_get_struct(self, self_val);
1066
+
1067
+ if (GMPZ_P(arg)) {
1068
+ mpz_get_struct(arg,arg_val_z);
1069
+ return INT2FIX(mpz_cmpabs(self_val, arg_val_z));
1070
+ } else if (FIXNUM_P(arg)) {
1071
+ if (FIX2INT(arg) >= 0)
1072
+ return INT2FIX(mpz_cmpabs_ui(self_val, FIX2INT(arg)));
1073
+ else
1074
+ return INT2FIX(mpz_cmpabs_ui(self_val, -FIX2INT(arg)));
1075
+ } else if (GMPQ_P(arg)) {
1076
+ mpq_get_struct(arg,arg_val_q);
1077
+ mpz_temp_alloc(arg_val_z);
1078
+ mpz_init(arg_val_z);
1079
+ mpz_mul(arg_val_z, self_val, mpq_denref(arg_val_q));
1080
+ res = mpz_cmpabs(arg_val_z, mpq_numref(arg_val_q));
1081
+ mpz_temp_free(arg_val_z);
1082
+ return INT2FIX(res);
1083
+ } else if (GMPF_P(arg)) {
1084
+ not_yet;
1085
+ } else if (BIGNUM_P(arg)) {
1086
+ mpz_temp_from_bignum(arg_val_z, arg);
1087
+ res = mpz_cmpabs(self_val, arg_val_z);
1088
+ mpz_temp_free(arg_val_z);
1089
+ return INT2FIX(res);
1090
+ } else {
1091
+ typeerror(ZQFXB);
1092
+ }
1093
+ }
1094
+
1095
+
1096
+ /**********************************************************************
1097
+ * Integer Logic and Bit Fiddling *
1098
+ **********************************************************************/
1099
+
1100
+ /*
1101
+ * Document-method: &
1102
+ *
1103
+ * call-seq:
1104
+ * integer & other
1105
+ *
1106
+ * From the GMP Manual:
1107
+ *
1108
+ * Returns +integer+ bitwise-and +other+.
1109
+ */
1110
+ DEFUN_INT_LOGIC(and, mpz_and)
1111
+ /*
1112
+ * Document-method: |
1113
+ *
1114
+ * call-seq:
1115
+ * integer | other
1116
+ *
1117
+ * From the GMP Manual:
1118
+ *
1119
+ * Returns +integer+ bitwise inclusive-or +other+.
1120
+ */
1121
+ DEFUN_INT_LOGIC(or, mpz_ior)
1122
+ /*
1123
+ * Document-method: ^
1124
+ *
1125
+ * call-seq:
1126
+ * integer ^ other
1127
+ *
1128
+ * From the GMP Manual:
1129
+ *
1130
+ * Returns +integer+ bitwise exclusive-or +other+.
1131
+ */
1132
+ DEFUN_INT_LOGIC(xor, mpz_xor)
1133
+
1134
+ /*
1135
+ * call-seq:
1136
+ * integer.scan0(starting_bit)
1137
+ *
1138
+ * From the GMP Manual:
1139
+ *
1140
+ * Scan integer, starting from bit starting_bit, towards more significant bits,
1141
+ * until the first 0 bit is found. Return the index of the found bit.
1142
+ *
1143
+ * If the bit at starting_bit is already what's sought, then starting_bit is
1144
+ * returned.
1145
+ *
1146
+ * If there's no bit found, then INT2FIX(ULONG_MAX) is returned. This will
1147
+ * happen in scan0 past the end of a negative number.
1148
+ */
1149
+ VALUE r_gmpz_scan0(VALUE self, VALUE bitnr)
1150
+ {
1151
+ MP_INT *self_val;
1152
+ int bitnr_val;
1153
+ mpz_get_struct(self, self_val);
1154
+ if (FIXNUM_P(bitnr)) {
1155
+ bitnr_val = FIX2INT (bitnr);
1156
+ } else {
1157
+ typeerror_as(X, "index");
1158
+ }
1159
+ return INT2FIX(mpz_scan0(self_val, bitnr_val));
1160
+ }
1161
+
1162
+ /*
1163
+ * call-seq:
1164
+ * integer.scan1(starting_bit)
1165
+ *
1166
+ * From the GMP Manual:
1167
+ *
1168
+ * Scan integer, starting from bit starting_bit, towards more significant bits,
1169
+ * until the first 1 bit is found. Return the index of the found bit.
1170
+ *
1171
+ * If the bit at starting_bit is already what's sought, then starting_bit is
1172
+ * returned.
1173
+ *
1174
+ * If there's no bit found, then INT2FIX(ULONG_MAX) is returned. This will
1175
+ * happen in mpz_scan1 past the end of a nonnegative number.
1176
+ */
1177
+ VALUE r_gmpz_scan1(VALUE self, VALUE bitnr)
1178
+ {
1179
+ MP_INT *self_val;
1180
+ int bitnr_val;
1181
+
1182
+ mpz_get_struct(self, self_val);
1183
+
1184
+ if (FIXNUM_P(bitnr)) {
1185
+ bitnr_val = FIX2INT (bitnr);
1186
+ } else {
1187
+ typeerror_as(X, "index");
1188
+ }
1189
+
1190
+ return INT2FIX(mpz_scan1(self_val, bitnr_val));
1191
+ }
1192
+
1193
+
1194
+ /**********************************************************************
1195
+ * Integer Random Numbers *
1196
+ **********************************************************************/
1197
+
1198
+ /**********************************************************************
1199
+ * Miscellaneous Integer Functions *
1200
+ **********************************************************************/
1201
+
1202
+ /**********************************************************************
1203
+ * Integer Special Functions *
1204
+ **********************************************************************/
1205
+
1206
+
1207
+ /**********************************************************************
1208
+ * _unsorted_ *
1209
+ **********************************************************************/
1210
+
1211
+ /*
1212
+ * Document-method: com
1213
+ *
1214
+ * call-seq:
1215
+ * integer.com
1216
+ *
1217
+ * From the GMP Manual:
1218
+ *
1219
+ * Returns the one's complement of +integer+.
1220
+ */
1221
+ /*
1222
+ * Document-method: com!
1223
+ *
1224
+ * call-seq:
1225
+ * integer.com!
1226
+ *
1227
+ * From the GMP Manual:
1228
+ *
1229
+ * Sets +integer+ to its one's complement.
1230
+ */
1231
+ DEFUN_INT2INT(com, mpz_com)
1232
+ /*
1233
+ * Document-method: nextprime
1234
+ *
1235
+ * call-seq:
1236
+ * integer.nextprime
1237
+ *
1238
+ * From the GMP Manual:
1239
+ *
1240
+ * Returns the next prime greater than +integer+.
1241
+ *
1242
+ * This function uses a probabilistic algorithm to identify primes. For
1243
+ * practical purposes it's adequate, the chance of a composite passing will be
1244
+ * extremely small.
1245
+ */
1246
+ /*
1247
+ * Document-method: nextprime!
1248
+ *
1249
+ * call-seq:
1250
+ * integer.nextprime!
1251
+ *
1252
+ * From the GMP Manual:
1253
+ *
1254
+ * Sets +integer+ to the next prime greater than +integer+.
1255
+ *
1256
+ * This function uses a probabilistic algorithm to identify primes. For
1257
+ * practical purposes it's adequate, the chance of a composite passing will be
1258
+ * extremely small.
1259
+ */
1260
+ DEFUN_INT2INT(nextprime, mpz_nextprime)
1261
+
1262
+ /*
1263
+ * call-seq: probab_prime?([reps])
1264
+ *
1265
+ * Determine whether +n+ is prime. Returns 2 if +n+ is definitely prime,
1266
+ * returns 1 if +n+ is probably prime (without being certain), or return 0 if
1267
+ * +n+ is definitely composite.
1268
+ *
1269
+ * This function does some trial divisions, then some Miller-Rabin
1270
+ * probabilistic primality tests. +reps+ controls how many such tests are done,
1271
+ * 5 to 10 is a reasonable number, more will reduce the chances of a composite
1272
+ * being returned as �probably prime�.
1273
+ *
1274
+ * Miller-Rabin and similar tests can be more properly called compositeness
1275
+ * tests. Numbers which fail are known to be composite but those which pass
1276
+ * might be prime or might be composite. Only a few composites pass, hence
1277
+ * those which pass are considered probably prime.
1278
+ */
1279
+ VALUE r_gmpz_is_probab_prime(int argc, VALUE* argv, VALUE self)
1280
+ {
1281
+ MP_INT *self_val;
1282
+ int reps_val;
1283
+ VALUE reps;
1284
+ mpz_get_struct(self, self_val);
1285
+ rb_scan_args(argc, argv, "01", &reps);
1286
+ if(NIL_P(reps)){
1287
+ reps = INT2FIX(5);
1288
+ }
1289
+ if (FIXNUM_P(reps)) {
1290
+ reps_val = FIX2INT (reps);
1291
+ } else {
1292
+ typeerror_as(X, "reps");
1293
+ }
1294
+ return INT2FIX(mpz_probab_prime_p(self_val, reps_val));
1295
+ }
1296
+
1297
+ /*
1298
+ * Document-method: popcount
1299
+ *
1300
+ * call-seq:
1301
+ * integer.popcount
1302
+ *
1303
+ * From the GMP Manual:
1304
+ *
1305
+ * If <tt>integer>=0</tt>, return the population count of <tt>integer</tt>,
1306
+ * which is the number of 1 bits in the binary representation. If
1307
+ * <tt>op<0</tt>, the number of 1s is infinite, and the return value is
1308
+ * INT2FIX(ULONG_MAX), the largest possible unsigned long.
1309
+ */
1310
+ VALUE r_gmpz_popcount(VALUE self)
1311
+ {
1312
+ MP_INT *self_val;
1313
+ mpz_get_struct(self, self_val);
1314
+ return INT2FIX(mpz_popcount(self_val));
1315
+ }
1316
+
1317
+ /*
1318
+ * Document-method: jacobi
1319
+ *
1320
+ * call-seq:
1321
+ * a.jacobi
1322
+ *
1323
+ * <b>90% sure this is incorrectly implemented. Todo.</b>
1324
+ *
1325
+ * From the GMP Manual:
1326
+ *
1327
+ * Calculate the Jacobi symbol <tt>(a/b)</tt>. This is defined only for +b+
1328
+ * odd.
1329
+ */
1330
+ VALUE r_gmpz_jacobi(VALUE self)
1331
+ {
1332
+ MP_INT *self_val, *res_val;
1333
+ VALUE res;
1334
+ mpz_get_struct(self, self_val);
1335
+ if (mpz_sgn(self_val) != 1)
1336
+ rb_raise(rb_eRangeError, "you can take jacobi symbol only of positive value");
1337
+ if (mpz_even_p(self_val))
1338
+ rb_raise(rb_eRangeError, "you can't take jacobi symbol of even value");
1339
+ mpz_make_struct_init(res, res_val);
1340
+ mpz_jacobi(res_val, self_val);
1341
+ return res;
1342
+ }
1343
+
1344
+ /*
1345
+ * Document-method: legendre
1346
+ *
1347
+ * call-seq:
1348
+ * a.legendre
1349
+ *
1350
+ * <b>90% sure this is incorrectly implemented. Todo.</b>
1351
+ *
1352
+ * From the GMP Manual:
1353
+ *
1354
+ * Calculate the Legendre symbol <tt>(a/p)</tt>. This is defined only for +p+
1355
+ * an odd positive prime, and for such +p+ it's identical to the Jacobi symbol.
1356
+ */
1357
+ VALUE r_gmpz_legendre(VALUE self)
1358
+ {
1359
+ MP_INT *self_val, *res_val;
1360
+ VALUE res;
1361
+ mpz_get_struct(self, self_val);
1362
+ if (mpz_sgn(self_val) != 1)
1363
+ rb_raise(rb_eRangeError, "you can take legendre symbol only of positive value");
1364
+ if (mpz_even_p(self_val))
1365
+ rb_raise(rb_eRangeError, "you can't take legendre symbol of even value");
1366
+ mpz_make_struct_init(res, res_val);
1367
+ mpz_legendre(res_val, self_val);
1368
+ return res;
1369
+ }
1370
+
1371
+ /*
1372
+ * call-seq:
1373
+ * integer[index] = x &rarr; nil
1374
+ *
1375
+ * Sets the bit at index to x.
1376
+ */
1377
+ VALUE r_gmpz_setbit(VALUE self, VALUE bitnr, VALUE set_to)
1378
+ {
1379
+ MP_INT *self_val;
1380
+ int bitnr_val;
1381
+
1382
+ mpz_get_struct(self, self_val);
1383
+
1384
+ if (FIXNUM_P(bitnr)) {
1385
+ bitnr_val = FIX2INT (bitnr);
1386
+ } else {
1387
+ typeerror_as(X, "index");
1388
+ }
1389
+ if (RTEST(set_to)) {
1390
+ mpz_setbit(self_val, bitnr_val);
1391
+ } else {
1392
+ mpz_clrbit(self_val, bitnr_val);
1393
+ }
1394
+ return Qnil;
1395
+ }
1396
+
1397
+ /*
1398
+ * call-seq:
1399
+ * integer[index] &rarr; boolean
1400
+ *
1401
+ * Gets the bit at index, returned as either true or false.
1402
+ */
1403
+ VALUE r_gmpz_getbit(VALUE self, VALUE bitnr)
1404
+ {
1405
+ MP_INT *self_val;
1406
+ int bitnr_val;
1407
+ mpz_get_struct(self, self_val);
1408
+ if (FIXNUM_P(bitnr)) {
1409
+ bitnr_val = FIX2INT (bitnr);
1410
+ } else {
1411
+ typeerror_as(X, "index");
1412
+ }
1413
+ return mpz_tstbit(self_val, bitnr_val)?Qtrue:Qfalse;
1414
+ }
1415
+
1416
+ /*
1417
+ * Document-method: even?
1418
+ *
1419
+ * call-seq:
1420
+ * integer.even?
1421
+ *
1422
+ * From the GMP Manual:
1423
+ *
1424
+ * Determines whether integer is even. Returns true or false.
1425
+ */
1426
+ DEFUN_INT_COND_P(is_even,mpz_even_p)
1427
+ /*
1428
+ * Document-method: odd?
1429
+ *
1430
+ * call-seq:
1431
+ * integer.odd?
1432
+ *
1433
+ * From the GMP Manual:
1434
+ *
1435
+ * Determines whether integer is odd. Returns true or false.
1436
+ */
1437
+ DEFUN_INT_COND_P(is_odd,mpz_odd_p)
1438
+ /*
1439
+ * Document-method: square?
1440
+ *
1441
+ * call-seq:
1442
+ * integer.square?
1443
+ *
1444
+ * From the GMP Manual:
1445
+ *
1446
+ * Returns true if integer is a perfect square, i.e., if the square root of
1447
+ * integer is an integer. Under this definition both 0 and 1 are considered to
1448
+ * be perfect squares.
1449
+ */
1450
+ DEFUN_INT_COND_P(is_square,mpz_perfect_square_p)
1451
+ /*
1452
+ * Document-method: power?
1453
+ *
1454
+ * call-seq:
1455
+ * integer.square?
1456
+ *
1457
+ * From the GMP Manual:
1458
+ *
1459
+ * Returns true if integer is a perfect power, i.e., if there exist integers a
1460
+ * and b, with b>1, such that integer equals a raised to the power b.
1461
+ *
1462
+ * Under this definition both 0 and 1 are considered to be perfect powers.
1463
+ * Negative values of integers are accepted, but of course can only be odd
1464
+ * perfect powers.
1465
+ */
1466
+ DEFUN_INT_COND_P(is_power,mpz_perfect_power_p)
1467
+
1468
+ /*
1469
+ * call-seq:
1470
+ * integer.sgn
1471
+ *
1472
+ * From the GMP Manual:
1473
+ *
1474
+ * Returns +1 if +integer+ > 0, 0 if +integer+ == 0, and -1 if +integer+ < 0.
1475
+ */
1476
+ VALUE r_gmpz_sgn(VALUE self)
1477
+ {
1478
+ MP_INT *self_val;
1479
+ mpz_get_struct(self, self_val);
1480
+ return INT2FIX(mpz_sgn(self_val));
1481
+ }
1482
+
1483
+ /*
1484
+ * call-seq:
1485
+ * integer.powmod(exp, mod)
1486
+ *
1487
+ * From the GMP Manual:
1488
+ *
1489
+ * Returns +integer+ raised to +exp+ modulo +mod+.
1490
+ *
1491
+ * Negative +exp+ is supported if an inverse <tt>integer^-1</tt> mod
1492
+ * <tt>mod</tt> exists. If an inverse doesn't exist then a divide by zero is
1493
+ * raised.
1494
+ */
1495
+ VALUE r_gmpz_powm(VALUE self, VALUE exp, VALUE mod)
1496
+ {
1497
+ MP_INT *self_val, *res_val, *mod_val, *exp_val;
1498
+ VALUE res;
1499
+ int free_mod_val = 0;
1500
+
1501
+ if (GMPZ_P(mod)) {
1502
+ mpz_get_struct(mod, mod_val);
1503
+ if (mpz_sgn(mod_val) <= 0) {
1504
+ rb_raise (rb_eRangeError, "modulus must be positive");
1505
+ }
1506
+ } else if (FIXNUM_P(mod)) {
1507
+ if (FIX2INT(mod) <= 0) {
1508
+ rb_raise (rb_eRangeError, "modulus must be positive");
1509
+ }
1510
+ mpz_temp_alloc (mod_val);
1511
+ mpz_init_set_ui(mod_val, FIX2INT(mod));
1512
+ free_mod_val = 1;
1513
+ } else if (BIGNUM_P(mod)) {
1514
+ mpz_temp_from_bignum (mod_val, mod);
1515
+ if (mpz_sgn(mod_val) <= 0) {
1516
+ mpz_temp_free(mod_val);
1517
+ rb_raise (rb_eRangeError, "modulus must be positive");
1518
+ }
1519
+ free_mod_val = 1;
1520
+ } else {
1521
+ typeerror_as (ZXB, "modulus");
1522
+ }
1523
+ mpz_make_struct_init(res, res_val);
1524
+ mpz_get_struct(self, self_val);
1525
+
1526
+ if (GMPZ_P(exp)) {
1527
+ mpz_get_struct(exp, exp_val);
1528
+ if (mpz_sgn(mod_val) < 0) {
1529
+ rb_raise (rb_eRangeError, "exponent must be nonnegative");
1530
+ }
1531
+ mpz_powm (res_val, self_val, exp_val, mod_val);
1532
+ } else if (FIXNUM_P(exp)) {
1533
+ if (FIX2INT(exp) < 0)
1534
+ {
1535
+ if (free_mod_val)
1536
+ mpz_temp_free(mod_val);
1537
+ rb_raise (rb_eRangeError, "exponent must be nonnegative");
1538
+ }
1539
+ mpz_powm_ui (res_val, self_val, FIX2INT(exp), mod_val);
1540
+ } else if (BIGNUM_P(exp)) {
1541
+ mpz_temp_from_bignum (exp_val, exp);
1542
+ mpz_powm (res_val, self_val, exp_val, mod_val);
1543
+ mpz_temp_free (exp_val);
1544
+ } else {
1545
+ if (free_mod_val)
1546
+ mpz_temp_free(mod_val);
1547
+ typeerror_as (ZXB, "exponent");
1548
+ }
1549
+ if (free_mod_val)
1550
+ mpz_temp_free(mod_val);
1551
+ return res;
1552
+ }
1553
+
1554
+ /*
1555
+ * Document-method: **
1556
+ *
1557
+ * call-seq:
1558
+ * integer ** exp
1559
+ *
1560
+ * From the GMP Manual:
1561
+ *
1562
+ * Returns +integer+ raised to +exp+. The case 0^0 yields 1.
1563
+ */
1564
+ DEFUN_INT_F_UL(pow,mpz_pow_ui,"exponent")
1565
+ /*
1566
+ * Document-method: <<
1567
+ *
1568
+ * call-seq:
1569
+ * integer << n
1570
+ *
1571
+ * From the GMP Manual:
1572
+ *
1573
+ * Returns +integer+ times 2 raised to +n+. This operation can also be defined
1574
+ * as a left shift by +n+ bits.
1575
+ */
1576
+ DEFUN_INT_F_UL(shl,mpz_mul_2exp,"shift size")
1577
+ DEFUN_INT_F_UL(fshr,mpz_fdiv_q_2exp,"shift size")
1578
+ DEFUN_INT_F_UL(tshr,mpz_tdiv_q_2exp,"shift size")
1579
+ DEFUN_INT_F_UL(fshrm,mpz_fdiv_r_2exp,"mark size")
1580
+ DEFUN_INT_F_UL(tshrm,mpz_tdiv_r_2exp,"mark size")
1581
+
1582
+ int mpz_cmp_value(MP_INT *OP, VALUE arg)
1583
+ {
1584
+ MP_RAT *arg_val_q;
1585
+ MP_INT *arg_val_z;
1586
+ int res;
1587
+
1588
+ if (GMPZ_P(arg)) {
1589
+ mpz_get_struct(arg,arg_val_z);
1590
+ return mpz_cmp(OP,arg_val_z);
1591
+ } else if (FIXNUM_P(arg)) {
1592
+ return mpz_cmp_si(OP, FIX2INT(arg));
1593
+ } else if (GMPQ_P(arg)) {
1594
+ mpq_get_struct(arg,arg_val_q);
1595
+ mpz_temp_alloc(arg_val_z);
1596
+ mpz_init(arg_val_z);
1597
+ mpz_mul(arg_val_z, OP, mpq_denref(arg_val_q));
1598
+ res = mpz_cmp(arg_val_z, mpq_numref(arg_val_q));
1599
+ mpz_temp_free(arg_val_z);
1600
+ return res;
1601
+ } else if (GMPF_P(arg)) {
1602
+ not_yet;
1603
+ } else if (BIGNUM_P(arg)) {
1604
+ mpz_temp_from_bignum(arg_val_z, arg);
1605
+ res = mpz_cmp(OP, arg_val_z);
1606
+ mpz_temp_free(arg_val_z);
1607
+ return res;
1608
+ } else {
1609
+ typeerror_as(ZQFXB, "exponent");
1610
+ }
1611
+ }
1612
+
1613
+ VALUE r_gmpz_cmp(VALUE self, VALUE arg)
1614
+ {
1615
+ MP_INT *self_val;
1616
+ int res;
1617
+ mpz_get_struct(self,self_val);
1618
+ res = mpz_cmp_value(self_val, arg);
1619
+ if (res > 0)
1620
+ return INT2FIX(1);
1621
+ else if (res == 0)
1622
+ return INT2FIX(0);
1623
+ else
1624
+ return INT2FIX(-1);
1625
+ }
1626
+
1627
+ /*
1628
+ * Document-method: <
1629
+ *
1630
+ * call-seq:
1631
+ * int1 < int2
1632
+ *
1633
+ * Returns whether +int1+ is strictly less than +int2+.
1634
+ */
1635
+ DEFUN_INT_CMP(lt,<)
1636
+ /*
1637
+ * Document-method: <=
1638
+ *
1639
+ * call-seq:
1640
+ * int1 <= int2
1641
+ *
1642
+ * Returns whether +int1+ is less than or equal to +int2+.
1643
+ */
1644
+ DEFUN_INT_CMP(le,<=)
1645
+ /*
1646
+ * Document-method: >
1647
+ *
1648
+ * call-seq:
1649
+ * int1 > int2
1650
+ *
1651
+ * Returns whether +int1+ is strictly greater than +int2+.
1652
+ */
1653
+ DEFUN_INT_CMP(gt,>)
1654
+ /*
1655
+ * Document-method: >=
1656
+ *
1657
+ * call-seq:
1658
+ * int1 >= int2
1659
+ *
1660
+ * Returns whether +int1+ is greater than or equal to +int2+.
1661
+ */
1662
+ DEFUN_INT_CMP(ge,>=)
1663
+
1664
+ VALUE r_gmpzsg_pow(VALUE klass, VALUE base, VALUE exp)
1665
+ {
1666
+ MP_INT *res_val;
1667
+ VALUE res;
1668
+
1669
+ if (FIXNUM_P(base) && FIXNUM_P(exp))
1670
+ {
1671
+ if (FIX2INT(base) < 0)
1672
+ rb_raise (rb_eRangeError, "base must not be negative");
1673
+ if (FIX2INT(exp) < 0)
1674
+ rb_raise (rb_eRangeError, "exponent must not be negative");
1675
+ mpz_make_struct_init (res, res_val);
1676
+ mpz_ui_pow_ui (res_val, base, exp);
1677
+ return res;
1678
+ }
1679
+ return r_gmpz_pow (r_gmpzsg_new(1, &base, klass), exp);
1680
+ }
1681
+
1682
+ void init_gmpz()
1683
+ {
1684
+ mGMP = rb_define_module("GMP");
1685
+ rb_define_module_function(mGMP, "Z", r_gmpmod_z, -1);
1686
+
1687
+ cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
1688
+
1689
+ // Initializing, Assigning Integers
1690
+ rb_define_singleton_method(cGMP_Z, "new", r_gmpzsg_new, -1);
1691
+ rb_define_method(cGMP_Z, "initialize", r_gmpz_initialize, -1);
1692
+ rb_define_method(cGMP_Z, "swap", r_gmpz_swap, 1);
1693
+
1694
+ // Converting Integers
1695
+ rb_define_method(cGMP_Z, "to_i", r_gmpz_to_i, 0);
1696
+ rb_define_method(cGMP_Z, "to_d", r_gmpz_to_d, 0);
1697
+ rb_define_method(cGMP_Z, "to_s", r_gmpz_to_s, -1);
1698
+
1699
+ // Integer Arithmetic
1700
+ rb_define_method(cGMP_Z, "+", r_gmpz_add, 1);
1701
+ rb_define_method(cGMP_Z, "add!", r_gmpz_add_self, 1);
1702
+ rb_define_method(cGMP_Z, "-", r_gmpz_sub, 1);
1703
+ rb_define_method(cGMP_Z, "sub!", r_gmpz_sub_self, 1);
1704
+ rb_define_method(cGMP_Z, "*", r_gmpz_mul, 1);
1705
+ rb_define_method(cGMP_Z, "neg", r_gmpz_neg, 0);
1706
+ rb_define_method(cGMP_Z, "neg!", r_gmpz_neg_self, 0);
1707
+
1708
+ // Integer Division
1709
+ rb_define_method(cGMP_Z, "/", r_gmpz_div, 1);
1710
+ rb_define_method(cGMP_Z, "tdiv", r_gmpz_tdiv, 1);
1711
+ rb_define_method(cGMP_Z, "tmod", r_gmpz_tmod, 1);
1712
+ rb_define_method(cGMP_Z, "fdiv", r_gmpz_fdiv, 1);
1713
+ rb_define_method(cGMP_Z, "fmod", r_gmpz_fmod, 1);
1714
+ rb_define_method(cGMP_Z, "cdiv", r_gmpz_cdiv, 1);
1715
+ rb_define_method(cGMP_Z, "cmod", r_gmpz_cmod, 1);
1716
+
1717
+ // Integer Exponentiation
1718
+ rb_define_singleton_method(cGMP_Z, "pow", r_gmpzsg_pow, 2);
1719
+
1720
+ // Integer Roots
1721
+ rb_define_method(cGMP_Z, "root", r_gmpz_root, 1);
1722
+
1723
+ // Number Theoretic Functions
1724
+ rb_define_method(cGMP_Z, "remove", r_gmpz_remove, 1);
1725
+ rb_define_singleton_method(cGMP_Z, "fac", r_gmpzsg_fac, 1);
1726
+ rb_define_singleton_method(cGMP_Z, "fib", r_gmpzsg_fib, 1);
1727
+
1728
+ // Integer Comparisons
1729
+ rb_define_method(cGMP_Z, "<=>", r_gmpz_cmp, 1);
1730
+ rb_define_method(cGMP_Z, ">", r_gmpz_cmp_gt, 1);
1731
+ rb_define_method(cGMP_Z, ">=", r_gmpz_cmp_ge, 1);
1732
+ rb_define_method(cGMP_Z, "<", r_gmpz_cmp_lt, 1);
1733
+ rb_define_method(cGMP_Z, "<=", r_gmpz_cmp_le, 1);
1734
+ rb_define_method(cGMP_Z, "cmpabs", r_gmpz_cmpabs, 1);
1735
+
1736
+ // _unsorted_
1737
+ rb_define_method(cGMP_Z, "-@", r_gmpz_neg, 0);
1738
+ rb_define_method(cGMP_Z, "abs", r_gmpz_abs, 0);
1739
+ rb_define_method(cGMP_Z, "abs!", r_gmpz_abs_self, 0);
1740
+ rb_define_method(cGMP_Z, "com", r_gmpz_com, 0);
1741
+ rb_define_method(cGMP_Z, "com!", r_gmpz_com_self, 0);
1742
+ rb_define_method(cGMP_Z, "&", r_gmpz_and, 1);
1743
+ rb_define_method(cGMP_Z, "|", r_gmpz_or, 1);
1744
+ rb_define_method(cGMP_Z, "^", r_gmpz_xor, 1);
1745
+ rb_define_method(cGMP_Z, "[]=", r_gmpz_setbit, 2);
1746
+ rb_define_method(cGMP_Z, "[]", r_gmpz_getbit, 1);
1747
+ rb_define_method(cGMP_Z, "scan0", r_gmpz_scan0, 1);
1748
+ rb_define_method(cGMP_Z, "scan1", r_gmpz_scan1, 1);
1749
+ rb_define_method(cGMP_Z, "even?", r_gmpz_is_even, 0);
1750
+ rb_define_method(cGMP_Z, "odd?", r_gmpz_is_odd, 0);
1751
+ rb_define_method(cGMP_Z, "sgn", r_gmpz_sgn, 0);
1752
+
1753
+ rb_define_method(cGMP_Z, "**", r_gmpz_pow, 1);
1754
+ rb_define_method(cGMP_Z, "powmod", r_gmpz_powm, 2);
1755
+
1756
+ rb_define_method(cGMP_Z, "==", r_gmpz_eq, 1);
1757
+ rb_define_method(cGMP_Z, ">>", r_gmpz_fshr, 1);
1758
+ rb_define_method(cGMP_Z, "<<", r_gmpz_shl, 1);
1759
+ rb_define_method(cGMP_Z, "tshr", r_gmpz_tshr, 1);
1760
+ rb_define_method(cGMP_Z, "lastbits_sgn", r_gmpz_tshrm, 1);
1761
+ rb_define_method(cGMP_Z, "lastbits_pos", r_gmpz_fshrm, 1);
1762
+ rb_define_method(cGMP_Z, "square?", r_gmpz_is_square, 0);
1763
+ rb_define_method(cGMP_Z, "power?", r_gmpz_is_power, 0);
1764
+ rb_define_method(cGMP_Z, "sqrt", r_gmpz_sqrt, 0);
1765
+ rb_define_method(cGMP_Z, "sqrt!", r_gmpz_sqrt_self, 0);
1766
+ rb_define_method(cGMP_Z, "sqrtrem", r_gmpz_sqrtrem, 0);
1767
+ rb_define_method(cGMP_Z, "jacobi", r_gmpz_jacobi, 0);
1768
+ rb_define_method(cGMP_Z, "legendre", r_gmpz_legendre, 0);
1769
+ rb_define_method(cGMP_Z, "probab_prime?", r_gmpz_is_probab_prime, -1);
1770
+ rb_define_method(cGMP_Z, "nextprime", r_gmpz_nextprime, 0);
1771
+ rb_define_method(cGMP_Z, "nextprime!", r_gmpz_nextprime_self, 0);
1772
+ rb_define_method(cGMP_Z, "popcount", r_gmpz_popcount, 0);
1773
+
1774
+ }