gmp 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }