srawlins-gmp 0.1.1

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.
data/ext/gmpz.h ADDED
@@ -0,0 +1,833 @@
1
+ /*
2
+ * gmpz.h
3
+ *
4
+ * This file contains GMP::Z method definitions.
5
+ */
6
+
7
+ /*
8
+ * call-seq: +(other)
9
+ *
10
+ * Adds this GMP::Z to other. Other can be
11
+ * * GMP::Z
12
+ * * Fixnum
13
+ * * GMP::Q
14
+ * * GMP::F
15
+ * * Bignum
16
+ */
17
+ static VALUE r_gmpz_add(VALUE self, VALUE arg)
18
+ {
19
+ MP_INT *self_val, *arg_val, *res_val;
20
+ VALUE res;
21
+
22
+ mpz_get_struct(self,self_val);
23
+
24
+ if (GMPZ_P(arg)) {
25
+ mpz_get_struct(arg,arg_val);
26
+ mpz_make_struct_init(res, res_val);
27
+ mpz_add (res_val, self_val, arg_val);
28
+ } else if (FIXNUM_P(arg)) {
29
+ mpz_make_struct_init(res, res_val);
30
+ if (FIX2INT(arg) > 0)
31
+ mpz_add_ui (res_val, self_val, FIX2INT(arg));
32
+ else
33
+ mpz_sub_ui (res_val, self_val, -FIX2INT(arg));
34
+ } else if (GMPQ_P(arg)) {
35
+ return r_gmpq_add(arg, self);
36
+ } else if (GMPF_P(arg)) {
37
+ return r_gmpf_add(arg, self);
38
+ } else if (BIGNUM_P(arg)) {
39
+ mpz_make_struct_init(res, res_val);
40
+ mpz_init (res_val);
41
+ mpz_set_bignum (res_val, arg);
42
+ mpz_add (res_val, res_val, self_val);
43
+ } else {
44
+ typeerror (ZQFXB);
45
+ }
46
+ return res;
47
+ }
48
+
49
+ static VALUE r_gmpz_add_self(VALUE self, VALUE arg)
50
+ {
51
+ MP_INT *self_val, *arg_val;
52
+
53
+ mpz_get_struct(self,self_val);
54
+
55
+ if (GMPZ_P(arg)) {
56
+ mpz_get_struct(arg,arg_val);
57
+ mpz_add (self_val, self_val, arg_val);
58
+ } else if (FIXNUM_P(arg)) {
59
+ if (FIX2INT(arg) > 0)
60
+ mpz_add_ui (self_val, self_val, FIX2INT(arg));
61
+ else
62
+ mpz_sub_ui (self_val, self_val, -FIX2INT(arg));
63
+ } else if (BIGNUM_P(arg)) {
64
+ mpz_temp_from_bignum (arg_val, arg);
65
+ mpz_add (self_val, self_val, arg_val);
66
+ mpz_temp_free (arg_val);
67
+ } else {
68
+ typeerror (ZXB);
69
+ }
70
+ return Qnil;
71
+ }
72
+
73
+ static VALUE r_gmpz_sub(VALUE self, VALUE arg)
74
+ {
75
+ MP_RAT *res_val_q, *arg_val_q;
76
+ MP_INT *self_val, *arg_val, *res_val;
77
+ MP_FLOAT *arg_val_f, *res_val_f;
78
+ VALUE res;
79
+ unsigned long prec;
80
+
81
+ mpz_get_struct(self,self_val);
82
+
83
+ if (GMPZ_P(arg)) {
84
+ mpz_make_struct_init(res, res_val);
85
+ mpz_get_struct(arg,arg_val);
86
+ mpz_sub (res_val, self_val, arg_val);
87
+ } else if (FIXNUM_P(arg)) {
88
+ mpz_make_struct_init(res, res_val);
89
+ if (FIX2INT(arg) > 0)
90
+ mpz_sub_ui (res_val, self_val, FIX2INT(arg));
91
+ else
92
+ mpz_add_ui (res_val, self_val, -FIX2INT(arg));
93
+ } else if (GMPQ_P(arg)) {
94
+ mpq_make_struct_init(res, res_val_q);
95
+ mpq_get_struct(arg,arg_val_q);
96
+ mpz_set (mpq_denref(res_val_q), mpq_denref(arg_val_q));
97
+ mpz_mul (mpq_numref(res_val_q), mpq_denref(arg_val_q), self_val);
98
+ mpz_sub (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_numref(arg_val_q));
99
+ } else if (GMPF_P(arg)) {
100
+ mpf_get_struct_prec (arg, arg_val_f, prec);
101
+ mpf_make_struct_init(res, res_val_f, prec);
102
+ mpf_set_z (res_val_f, self_val);
103
+ mpf_sub (res_val_f, res_val_f, arg_val_f);
104
+ } else if (BIGNUM_P(arg)) {
105
+ mpz_make_struct_init(res, res_val);
106
+ mpz_set_bignum (res_val, arg);
107
+ mpz_sub (res_val, self_val, res_val);
108
+ } else {
109
+ typeerror (ZQFXB);
110
+ }
111
+ return res;
112
+ }
113
+
114
+ static VALUE r_gmpz_sub_self(VALUE self, VALUE arg)
115
+ {
116
+ MP_INT *self_val, *arg_val;
117
+
118
+ mpz_get_struct(self,self_val);
119
+
120
+ if (GMPZ_P(arg)) {
121
+ mpz_get_struct(arg, arg_val);
122
+ mpz_sub (self_val, self_val, arg_val);
123
+ } else if (FIXNUM_P(arg)) {
124
+ if (FIX2INT(arg) > 0)
125
+ mpz_sub_ui (self_val, self_val, FIX2INT(arg));
126
+ else
127
+ mpz_add_ui (self_val, self_val, -FIX2INT(arg));
128
+ } else if (BIGNUM_P(arg)) {
129
+ mpz_temp_from_bignum(arg_val, arg);
130
+ mpz_sub (self_val, self_val, arg_val);
131
+ mpz_temp_free (arg_val);
132
+ } else {
133
+ typeerror (ZXB);
134
+ }
135
+ return Qnil;
136
+ }
137
+
138
+ static VALUE r_gmpz_mul(VALUE self, VALUE arg)
139
+ {
140
+ MP_INT *self_val, *arg_val, *res_val;
141
+ VALUE res;
142
+
143
+ mpz_get_struct(self,self_val);
144
+
145
+ if (GMPZ_P(arg)) {
146
+ mpz_make_struct_init(res, res_val);
147
+ mpz_get_struct(arg,arg_val);
148
+ mpz_mul (res_val, self_val, arg_val);
149
+ } else if (FIXNUM_P(arg)) {
150
+ mpz_make_struct_init(res, res_val);
151
+ mpz_mul_si (res_val, self_val, FIX2INT(arg));
152
+ } else if (GMPQ_P(arg)) {
153
+ return r_gmpq_mul(arg, self);
154
+ } else if (GMPF_P(arg)) {
155
+ return r_gmpf_mul(arg, self);
156
+ } else if (BIGNUM_P(arg)) {
157
+ mpz_make_struct_init(res, res_val);
158
+ mpz_set_bignum (res_val, arg);
159
+ mpz_mul (res_val, res_val, self_val);
160
+ } else {
161
+ typeerror (ZQFXB);
162
+ }
163
+ return res;
164
+ }
165
+
166
+ static VALUE r_gmpz_div(VALUE self, VALUE arg)
167
+ {
168
+ MP_INT *self_val, *arg_val_z, *tmp_z;
169
+ MP_RAT *arg_val_q, *res_val_q;
170
+ MP_FLOAT *arg_val_f, *res_val_f;
171
+ VALUE res;
172
+ unsigned int prec;
173
+
174
+ mpz_get_struct(self,self_val);
175
+
176
+ if (GMPZ_P(arg)) {
177
+ mpz_get_struct(arg, arg_val_z);
178
+ if (mpz_cmp_ui(arg_val_z, 0) == 0)
179
+ rb_raise (rb_eZeroDivError, "divided by 0");
180
+ mpq_make_struct_init(res, res_val_q);
181
+ mpq_set_num (res_val_q, self_val);
182
+ mpq_set_den (res_val_q, arg_val_z);
183
+ mpq_canonicalize (res_val_q);
184
+ } else if (FIXNUM_P(arg)) {
185
+ if (FIX2INT(arg) == 0)
186
+ rb_raise (rb_eZeroDivError, "divided by 0");
187
+ mpq_make_struct_init(res, res_val_q);
188
+ mpq_set_num (res_val_q, self_val);
189
+ mpz_set_ui (mpq_denref(res_val_q), FIX2INT(arg));
190
+ mpq_canonicalize (res_val_q);
191
+ } else if (GMPQ_P(arg)) {
192
+ mpq_get_struct(arg, arg_val_q);
193
+ if (mpz_cmp_ui(mpq_numref(arg_val_q), 0) == 0)
194
+ rb_raise (rb_eZeroDivError, "divided by 0");
195
+ mpz_temp_init(tmp_z);
196
+ mpq_make_struct_init(res, res_val_q);
197
+ mpz_gcd (tmp_z, mpq_numref(arg_val_q), self_val);
198
+ mpz_divexact (mpq_numref(res_val_q), self_val, tmp_z);
199
+ mpz_divexact (mpq_denref(res_val_q), mpq_numref(arg_val_q), tmp_z);
200
+ mpz_mul (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_denref(arg_val_q));
201
+ mpz_temp_free(tmp_z);
202
+ } else if (GMPF_P(arg)) {
203
+ mpf_get_struct_prec (arg, arg_val_f, prec);
204
+ mpf_make_struct_init(res, res_val_f, prec);
205
+ mpf_set_z (res_val_f, self_val);
206
+ mpf_div (res_val_f, res_val_f, arg_val_f);
207
+ } else if (BIGNUM_P(arg)) {
208
+ mpq_make_struct_init(res, res_val_q);
209
+ mpz_set_bignum (mpq_denref(res_val_q), arg);
210
+ if (mpz_cmp_ui(mpq_denref(res_val_q), 0) == 0)
211
+ rb_raise (rb_eZeroDivError, "divided by 0");
212
+ mpq_set_num (res_val_q, self_val);
213
+ mpq_canonicalize (res_val_q);
214
+ } else {
215
+ typeerror (ZQFXB);
216
+ }
217
+ return res;
218
+ }
219
+
220
+ static VALUE r_gmpz_setbit(VALUE self, VALUE bitnr, VALUE set_to)
221
+ {
222
+ MP_INT *self_val;
223
+ int bitnr_val;
224
+
225
+ mpz_get_struct(self, self_val);
226
+
227
+ if (FIXNUM_P(bitnr)) {
228
+ bitnr_val = FIX2INT (bitnr);
229
+ } else {
230
+ typeerror_as(X, "index");
231
+ }
232
+ if (RTEST(set_to)) {
233
+ mpz_setbit (self_val, bitnr_val);
234
+ } else {
235
+ mpz_clrbit (self_val, bitnr_val);
236
+ }
237
+ return Qnil;
238
+ }
239
+
240
+ static VALUE r_gmpz_getbit(VALUE self, VALUE bitnr)
241
+ {
242
+ MP_INT *self_val;
243
+ int bitnr_val;
244
+ mpz_get_struct(self, self_val);
245
+ if (FIXNUM_P(bitnr)) {
246
+ bitnr_val = FIX2INT (bitnr);
247
+ } else {
248
+ typeerror_as(X, "index");
249
+ }
250
+ return mpz_tstbit(self_val, bitnr_val)?Qtrue:Qfalse;
251
+ }
252
+
253
+ static VALUE r_gmpz_scan0(VALUE self, VALUE bitnr)
254
+ {
255
+ MP_INT *self_val;
256
+ int bitnr_val;
257
+ mpz_get_struct(self, self_val);
258
+ if (FIXNUM_P(bitnr)) {
259
+ bitnr_val = FIX2INT (bitnr);
260
+ } else {
261
+ typeerror_as(X, "index");
262
+ }
263
+ return INT2FIX(mpz_scan0(self_val, bitnr_val));
264
+ }
265
+
266
+ static VALUE r_gmpz_scan1(VALUE self, VALUE bitnr)
267
+ {
268
+ MP_INT *self_val;
269
+ int bitnr_val;
270
+
271
+ mpz_get_struct(self, self_val);
272
+
273
+ if (FIXNUM_P(bitnr)) {
274
+ bitnr_val = FIX2INT (bitnr);
275
+ } else {
276
+ typeerror_as(X, "index");
277
+ }
278
+
279
+ return INT2FIX(mpz_scan1(self_val, bitnr_val));
280
+ }
281
+
282
+ #define DEFUN_INT_COND_P(fname,mpz_fname) \
283
+ static VALUE r_gmpz_##fname(VALUE self) \
284
+ { \
285
+ MP_INT *self_val; \
286
+ mpz_get_struct(self, self_val); \
287
+ return mpz_fname(self_val)?Qtrue:Qfalse; \
288
+ }
289
+
290
+ DEFUN_INT_COND_P(is_even,mpz_even_p)
291
+ DEFUN_INT_COND_P(is_odd,mpz_odd_p)
292
+ DEFUN_INT_COND_P(is_square,mpz_perfect_square_p)
293
+ DEFUN_INT_COND_P(is_power,mpz_perfect_power_p)
294
+
295
+ static VALUE r_gmpz_sgn(VALUE self)
296
+ {
297
+ MP_INT *self_val;
298
+ mpz_get_struct(self, self_val);
299
+ return INT2FIX(mpz_sgn(self_val));
300
+ }
301
+
302
+ static VALUE r_gmpz_powm(VALUE self, VALUE exp, VALUE mod)
303
+ {
304
+ MP_INT *self_val, *res_val, *mod_val, *exp_val;
305
+ VALUE res;
306
+ int free_mod_val = 0;
307
+
308
+ if (GMPZ_P(mod)) {
309
+ mpz_get_struct(mod, mod_val);
310
+ if (mpz_sgn(mod_val) <= 0) {
311
+ rb_raise (rb_eRangeError, "modulus must be positive");
312
+ }
313
+ } else if (FIXNUM_P(mod)) {
314
+ if (FIX2INT(mod) <= 0) {
315
+ rb_raise (rb_eRangeError, "modulus must be positive");
316
+ }
317
+ mpz_temp_alloc (mod_val);
318
+ mpz_init_set_ui(mod_val, FIX2INT(mod));
319
+ free_mod_val = 1;
320
+ } else if (BIGNUM_P(mod)) {
321
+ mpz_temp_from_bignum (mod_val, mod);
322
+ if (mpz_sgn(mod_val) <= 0) {
323
+ mpz_temp_free(mod_val);
324
+ rb_raise (rb_eRangeError, "modulus must be positive");
325
+ }
326
+ free_mod_val = 1;
327
+ } else {
328
+ typeerror_as (ZXB, "modulus");
329
+ }
330
+ mpz_make_struct_init(res, res_val);
331
+ mpz_get_struct(self, self_val);
332
+
333
+ if (GMPZ_P(exp)) {
334
+ mpz_get_struct(exp, exp_val);
335
+ if (mpz_sgn(mod_val) < 0) {
336
+ rb_raise (rb_eRangeError, "exponent must be nonnegative");
337
+ }
338
+ mpz_powm (res_val, self_val, exp_val, mod_val);
339
+ } else if (FIXNUM_P(exp)) {
340
+ if (FIX2INT(exp) < 0)
341
+ {
342
+ if (free_mod_val)
343
+ mpz_temp_free(mod_val);
344
+ rb_raise (rb_eRangeError, "exponent must be nonnegative");
345
+ }
346
+ mpz_powm_ui (res_val, self_val, FIX2INT(exp), mod_val);
347
+ } else if (BIGNUM_P(exp)) {
348
+ mpz_temp_from_bignum (exp_val, exp);
349
+ mpz_powm (res_val, self_val, exp_val, mod_val);
350
+ mpz_temp_free (exp_val);
351
+ } else {
352
+ if (free_mod_val)
353
+ mpz_temp_free(mod_val);
354
+ typeerror_as (ZXB, "exponent");
355
+ }
356
+ if (free_mod_val)
357
+ mpz_temp_free(mod_val);
358
+ return res;
359
+ }
360
+
361
+ static VALUE r_gmpz_swap(VALUE self, VALUE arg)
362
+ {
363
+ MP_INT *self_val, *arg_val;
364
+ if (!GMPZ_P(arg)) {
365
+ rb_raise(rb_eTypeError, "Can't swap GMP::Z with object of other class");
366
+ }
367
+ mpz_get_struct(self, self_val);
368
+ mpz_get_struct(arg, arg_val);
369
+ mpz_swap(self_val,arg_val);
370
+ return Qnil;
371
+ }
372
+
373
+
374
+ #define DEFUN_INT_F_UL(fname,mpz_fname,argname) \
375
+ static VALUE r_gmpz_##fname(VALUE self, VALUE exp) \
376
+ { \
377
+ MP_INT *self_val, *res_val; \
378
+ VALUE res; \
379
+ unsigned long exp_val; \
380
+ \
381
+ if (FIXNUM_P(exp)) { \
382
+ if (FIX2INT (exp) < 0) \
383
+ rb_raise (rb_eRangeError, argname " out of range"); \
384
+ exp_val = FIX2INT (exp); \
385
+ } else if (GMPZ_P(exp)) {\
386
+ mpz_get_struct (exp, res_val); \
387
+ if (!mpz_fits_ulong_p (res_val)) \
388
+ rb_raise (rb_eRangeError, argname " out of range"); \
389
+ exp_val = mpz_get_ui (res_val); \
390
+ if (exp_val == 0) \
391
+ rb_raise (rb_eRangeError, argname " out of range"); \
392
+ } else { \
393
+ typeerror_as (ZX, argname); \
394
+ } \
395
+ \
396
+ mpz_make_struct_init(res, res_val); \
397
+ mpz_get_struct(self, self_val); \
398
+ mpz_fname(res_val, self_val, exp_val); \
399
+ \
400
+ return res; \
401
+ }
402
+
403
+ DEFUN_INT_F_UL(pow,mpz_pow_ui,"exponent")
404
+ DEFUN_INT_F_UL(shl,mpz_mul_2exp,"shift size")
405
+ DEFUN_INT_F_UL(fshr,mpz_fdiv_q_2exp,"shift size")
406
+ DEFUN_INT_F_UL(tshr,mpz_tdiv_q_2exp,"shift size")
407
+ DEFUN_INT_F_UL(fshrm,mpz_fdiv_r_2exp,"mark size")
408
+ DEFUN_INT_F_UL(tshrm,mpz_tdiv_r_2exp,"mark size")
409
+ DEFUN_INT_F_UL(root,mpz_root,"root number")
410
+
411
+ static int mpz_cmp_value (MP_INT *OP, VALUE arg)
412
+ {
413
+ MP_RAT *arg_val_q;
414
+ MP_INT *arg_val_z;
415
+ int res;
416
+
417
+ if (GMPZ_P(arg)) {
418
+ mpz_get_struct(arg,arg_val_z);
419
+ return mpz_cmp (OP,arg_val_z);
420
+ } else if (FIXNUM_P(arg)) {
421
+ return mpz_cmp_si (OP, FIX2INT(arg));
422
+ } else if (GMPQ_P(arg)) {
423
+ mpq_get_struct(arg,arg_val_q);
424
+ mpz_temp_alloc (arg_val_z);
425
+ mpz_init(arg_val_z);
426
+ mpz_mul(arg_val_z, OP, mpq_denref(arg_val_q));
427
+ res = mpz_cmp (arg_val_z, mpq_numref(arg_val_q));
428
+ mpz_temp_free(arg_val_z);
429
+ return res;
430
+ } else if (GMPF_P(arg)) {
431
+ not_yet;
432
+ } else if (BIGNUM_P(arg)) {
433
+ mpz_temp_from_bignum (arg_val_z, arg);
434
+ res = mpz_cmp (OP, arg_val_z);
435
+ mpz_temp_free(arg_val_z);
436
+ return res;
437
+ } else {
438
+ typeerror_as (ZQFXB, "exponent");
439
+ }
440
+ }
441
+
442
+ static VALUE r_gmpz_eq(VALUE self, VALUE arg)
443
+ {
444
+ MP_INT *self_val, *arg_val_z;
445
+ MP_RAT *arg_val_q;
446
+
447
+ mpz_get_struct (self, self_val);
448
+ if (GMPZ_P(arg)) {
449
+ mpz_get_struct(arg, arg_val_z);
450
+ return (mpz_cmp (self_val, arg_val_z)==0) ? Qtrue : Qfalse;
451
+ } else if (FIXNUM_P(arg)) {
452
+ return (mpz_cmp_si (self_val, FIX2INT(arg))==0) ? Qtrue : Qfalse;
453
+ } else if (GMPQ_P(arg)) {
454
+ mpq_get_struct(arg, arg_val_q);
455
+ if (mpz_cmp_ui(mpq_denref(arg_val_q), 1)==0)
456
+ return Qfalse;
457
+ return (mpz_cmp (self_val, mpq_numref(arg_val_q))==0) ? Qtrue : Qfalse;
458
+ } else if (BIGNUM_P(arg)) {
459
+ mpz_temp_from_bignum(arg_val_z, arg);
460
+ if (mpz_cmp (self_val, arg_val_z)==0) {
461
+ mpz_temp_free(arg_val_z);
462
+ return Qtrue;
463
+ } else {
464
+ mpz_temp_free(arg_val_z);
465
+ return Qfalse;
466
+ }
467
+ } else {
468
+ return Qfalse;
469
+ }
470
+ }
471
+
472
+ static VALUE r_gmpz_cmp(VALUE self, VALUE arg)
473
+ {
474
+ MP_INT *self_val;
475
+ int res;
476
+ mpz_get_struct (self,self_val);
477
+ res = mpz_cmp_value(self_val, arg);
478
+ if (res > 0)
479
+ return INT2FIX(1);
480
+ else if (res == 0)
481
+ return INT2FIX(0);
482
+ else
483
+ return INT2FIX(-1);
484
+ }
485
+
486
+ #define DEFUN_INT_CMP(name,CMP_OP) \
487
+ static VALUE r_gmpz_cmp_##name(VALUE self, VALUE arg) \
488
+ { \
489
+ MP_INT *self_val; \
490
+ mpz_get_struct (self,self_val); \
491
+ return (mpz_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
492
+ }
493
+
494
+ DEFUN_INT_CMP(lt,<)
495
+ DEFUN_INT_CMP(le,<=)
496
+ DEFUN_INT_CMP(gt,>)
497
+ DEFUN_INT_CMP(ge,>=)
498
+
499
+ #define DEFUN_INT_DIV(fname,gmp_fname) \
500
+ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \
501
+ { \
502
+ MP_INT *self_val, *arg_val, *res_val; \
503
+ VALUE res; \
504
+ int arg_val_i; \
505
+ \
506
+ mpz_get_struct(self, self_val); \
507
+ mpz_make_struct_init(res, res_val); \
508
+ \
509
+ if (GMPZ_P(arg)) { \
510
+ mpz_get_struct(arg,arg_val); \
511
+ if (mpz_cmp_ui(arg_val, 0) == 0) \
512
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
513
+ gmp_fname (res_val, self_val, arg_val); \
514
+ } else if (FIXNUM_P(arg)) { \
515
+ arg_val_i = FIX2INT(arg); \
516
+ if (arg_val_i > 0) { \
517
+ gmp_fname##_ui (res_val, self_val, arg_val_i); \
518
+ } else if (arg_val_i == 0) { \
519
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
520
+ } else { \
521
+ mpz_neg (res_val, self_val); \
522
+ gmp_fname##_ui (res_val, self_val, -arg_val_i); \
523
+ } \
524
+ } else if (BIGNUM_P(arg)) { \
525
+ mpz_set_bignum (res_val, arg); \
526
+ if (mpz_cmp_ui(res_val, 0) == 0) \
527
+ rb_raise (rb_eZeroDivError, "divided by 0"); \
528
+ gmp_fname (res_val, self_val, res_val); \
529
+ } else { \
530
+ typeerror(ZXB); \
531
+ } \
532
+ return res; \
533
+ }
534
+
535
+ DEFUN_INT_DIV(tdiv, mpz_tdiv_q)
536
+ DEFUN_INT_DIV(tmod, mpz_tdiv_r)
537
+ DEFUN_INT_DIV(fdiv, mpz_fdiv_q)
538
+ DEFUN_INT_DIV(fmod, mpz_fdiv_r)
539
+ DEFUN_INT_DIV(cdiv, mpz_cdiv_q)
540
+ DEFUN_INT_DIV(cmod, mpz_cdiv_r)
541
+
542
+ #define DEFUN_INT2INT(fname,mpz_fname) \
543
+ static VALUE r_gmpz_##fname(VALUE self) \
544
+ { \
545
+ MP_INT *self_val, *res_val; \
546
+ VALUE res; \
547
+ mpz_get_struct(self, self_val); \
548
+ mpz_make_struct_init(res, res_val); \
549
+ mpz_fname(res_val, self_val); \
550
+ return res; \
551
+ } \
552
+ \
553
+ static VALUE r_gmpz_##fname##_self(VALUE self) \
554
+ { \
555
+ MP_INT *self_val; \
556
+ mpz_get_struct(self, self_val); \
557
+ mpz_fname(self_val, self_val); \
558
+ return Qnil; \
559
+ }
560
+
561
+ DEFUN_INT2INT(abs, mpz_abs)
562
+ DEFUN_INT2INT(neg, mpz_neg)
563
+ DEFUN_INT2INT(com, mpz_com)
564
+ DEFUN_INT2INT(sqrt, mpz_sqrt)
565
+ DEFUN_INT2INT(nextprime, mpz_nextprime)
566
+
567
+ /*
568
+ * call-seq: probab_prime_p(reps)
569
+ *
570
+ * Determine whether n is prime. Return 2 if n is definitely prime, return 1 if
571
+ * n is probably prime (without being certain), or return 0 if n is definitely
572
+ * composite.
573
+ *
574
+ * This function does some trial divisions, then some Miller-Rabin
575
+ * probabilistic primality tests. reps controls how many such tests are done, 5
576
+ * to 10 is a reasonable number, more will reduce the chances of a composite
577
+ * being returned as �probably prime�.
578
+ *
579
+ * Miller-Rabin and similar tests can be more properly called compositeness
580
+ * tests. Numbers which fail are known to be composite but those which pass
581
+ * might be prime or might be composite. Only a few composites pass, hence
582
+ * those which pass are considered probably prime.
583
+ */
584
+ static VALUE r_gmpz_is_probab_prime(int argc, VALUE* argv, VALUE self)
585
+ {
586
+ MP_INT *self_val;
587
+ int reps_val;
588
+ VALUE reps;
589
+ mpz_get_struct(self, self_val);
590
+ rb_scan_args(argc, argv, "01", &reps);
591
+ if(NIL_P(reps)){
592
+ reps = INT2FIX(5);
593
+ }
594
+ if (FIXNUM_P(reps)) {
595
+ reps_val = FIX2INT (reps);
596
+ } else {
597
+ typeerror_as(X, "reps");
598
+ }
599
+ return INT2FIX(mpz_probab_prime_p(self_val, reps_val));
600
+ }
601
+
602
+ static VALUE r_gmpz_popcount(VALUE self)
603
+ {
604
+ MP_INT *self_val;
605
+ mpz_get_struct(self, self_val);
606
+ return INT2FIX(mpz_popcount(self_val));
607
+ }
608
+
609
+ static VALUE r_gmpz_jacobi(VALUE self)
610
+ {
611
+ MP_INT *self_val, *res_val;
612
+ VALUE res;
613
+ mpz_get_struct(self, self_val);
614
+ if (mpz_sgn(self_val) != 1)
615
+ rb_raise(rb_eRangeError, "you can take jacobi symbol only of positive value");
616
+ if (mpz_even_p(self_val))
617
+ rb_raise(rb_eRangeError, "you can't take jacobi symbol of even value");
618
+ mpz_make_struct_init(res, res_val);
619
+ mpz_jacobi(res_val, self_val);
620
+ return res;
621
+ }
622
+
623
+ static VALUE r_gmpz_legendre(VALUE self)
624
+ {
625
+ MP_INT *self_val, *res_val;
626
+ VALUE res;
627
+ mpz_get_struct(self, self_val);
628
+ if (mpz_sgn(self_val) != 1)
629
+ rb_raise(rb_eRangeError, "you can take legendre symbol only of positive value");
630
+ if (mpz_even_p(self_val))
631
+ rb_raise(rb_eRangeError, "you can't take legendre symbol of even value");
632
+ mpz_make_struct_init(res, res_val);
633
+ mpz_legendre(res_val, self_val);
634
+ return res;
635
+ }
636
+
637
+ #define DEFUN_INT_LOGIC(fname, mpz_fname) \
638
+ static VALUE r_gmpz_##fname(VALUE self, VALUE arg) \
639
+ { \
640
+ MP_INT *self_val, *arg_val, *res_val; \
641
+ VALUE res; \
642
+ \
643
+ mpz_get_struct(self, self_val); \
644
+ \
645
+ mpz_make_struct(res, res_val); \
646
+ if (GMPZ_P(arg)) { \
647
+ mpz_get_struct(arg,arg_val); \
648
+ mpz_init (res_val); \
649
+ mpz_fname (res_val, self_val, arg_val); \
650
+ } else if (FIXNUM_P(arg)) { \
651
+ mpz_init_set_si (res_val, FIX2INT(arg)); \
652
+ mpz_fname (res_val, self_val, res_val); \
653
+ } else if (BIGNUM_P(arg)) { \
654
+ mpz_init (res_val); \
655
+ mpz_set_bignum (res_val, arg); \
656
+ mpz_fname (res_val, self_val, res_val); \
657
+ } else { \
658
+ typeerror(ZXB); \
659
+ } \
660
+ return res; \
661
+ }
662
+
663
+ DEFUN_INT_LOGIC(and, mpz_and)
664
+ DEFUN_INT_LOGIC(xor, mpz_xor)
665
+ DEFUN_INT_LOGIC(or, mpz_ior)
666
+
667
+ static VALUE r_gmpz_sqrtrem(VALUE self)
668
+ {
669
+ MP_INT *self_val, *sqrt_val, *rem_val;
670
+ VALUE sqrt, rem;
671
+
672
+ mpz_get_struct (self, self_val);
673
+ mpz_make_struct_init(sqrt, sqrt_val);
674
+ mpz_make_struct_init(rem, rem_val);
675
+ mpz_sqrtrem (sqrt_val, rem_val, self_val);
676
+ return rb_assoc_new(sqrt, rem);
677
+ }
678
+
679
+ static VALUE r_gmpz_to_d(VALUE self)
680
+ {
681
+ MP_INT *self_val;
682
+ mpz_get_struct (self, self_val);
683
+
684
+ return rb_float_new(mpz_get_d(self_val));
685
+ }
686
+
687
+ #define DEFUN_INT_SINGLETON_UI(fname,mpz_fname) \
688
+ static VALUE r_gmpzsg_##fname(VALUE klass, VALUE arg) \
689
+ { \
690
+ MP_INT *arg_val_z, *res_val; \
691
+ unsigned long arg_val_ul; \
692
+ VALUE res; \
693
+ \
694
+ (void)klass; \
695
+ \
696
+ if (FIXNUM_P(arg)) { \
697
+ arg_val_ul = FIX2INT (arg); \
698
+ } else if (GMPZ_P(arg)) { \
699
+ mpz_get_struct (arg, arg_val_z); \
700
+ if (!mpz_fits_ulong_p (arg_val_z)) \
701
+ rb_raise (rb_eRangeError, "argument out of range"); \
702
+ arg_val_ul = mpz_get_ui (arg_val_z); \
703
+ if (arg_val_ul == 0) \
704
+ rb_raise (rb_eRangeError, "argument out of range"); \
705
+ } else { \
706
+ typeerror_as (ZX, "argument"); \
707
+ } \
708
+ mpz_make_struct_init(res, res_val); \
709
+ mpz_fname (res_val, arg_val_ul); \
710
+ return res; \
711
+ }
712
+
713
+ DEFUN_INT_SINGLETON_UI(fib,mpz_fib_ui)
714
+ DEFUN_INT_SINGLETON_UI(fac,mpz_fac_ui)
715
+
716
+ static VALUE r_gmpzsg_pow(VALUE klass, VALUE base, VALUE exp)
717
+ {
718
+ MP_INT *res_val;
719
+ VALUE res;
720
+
721
+ if (FIXNUM_P(base) && FIXNUM_P(exp))
722
+ {
723
+ if (FIX2INT(base) < 0)
724
+ rb_raise (rb_eRangeError, "base must not be negative");
725
+ if (FIX2INT(exp) < 0)
726
+ rb_raise (rb_eRangeError, "exponent must not be negative");
727
+ mpz_make_struct_init (res, res_val);
728
+ mpz_ui_pow_ui (res_val, base, exp);
729
+ return res;
730
+ }
731
+ return r_gmpz_pow (r_gmpzsg_new(1, &base, klass), exp);
732
+ }
733
+
734
+ static VALUE r_gmpz_remove(VALUE self, VALUE arg)
735
+ {
736
+ MP_INT *self_val, *arg_val, *res_val;
737
+ VALUE res;
738
+ int free_arg_val = 0;
739
+
740
+ mpz_get_struct(self,self_val);
741
+
742
+ if (GMPZ_P(arg)) {
743
+ mpz_get_struct(arg,arg_val);
744
+ if (mpz_sgn(arg_val) != 1)
745
+ rb_raise(rb_eRangeError, "argument must be positive");
746
+ } else if (FIXNUM_P(arg)) {
747
+ if (FIX2INT(arg) <= 0)
748
+ rb_raise(rb_eRangeError, "argument must be positive");
749
+ mpz_temp_alloc(arg_val);
750
+ mpz_init_set_ui(arg_val, FIX2INT(arg));
751
+ } else if (BIGNUM_P(arg)) {
752
+ mpz_temp_from_bignum(arg_val, arg);
753
+ if (mpz_sgn(arg_val) != 1) {
754
+ mpz_temp_free (arg_val);
755
+ rb_raise(rb_eRangeError, "argument must be positive");
756
+ }
757
+ } else {
758
+ typeerror(ZXB);
759
+ }
760
+
761
+ mpz_make_struct_init (res, res_val);
762
+ mpz_remove (res_val, self_val, arg_val);
763
+
764
+ if (free_arg_val)
765
+ mpz_temp_free(arg_val);
766
+
767
+ return res;
768
+ }
769
+
770
+ static VALUE r_gmpz_to_i(VALUE self)
771
+ {
772
+ MP_INT *self_val;
773
+ char *str;
774
+ VALUE res;
775
+
776
+ mpz_get_struct(self, self_val);
777
+ if (mpz_fits_slong_p(self_val))
778
+ return rb_int2inum(mpz_get_si(self_val));
779
+ str = mpz_get_str(NULL, 0, self_val);
780
+ res = rb_cstr2inum (str, 10);
781
+ free (str);
782
+ return res;
783
+ }
784
+
785
+ static VALUE r_gmpz_cmpabs(VALUE self, VALUE arg)
786
+ {
787
+ MP_INT *arg_val_z, *self_val;
788
+ MP_RAT *arg_val_q;
789
+ int res;
790
+
791
+ mpz_get_struct (self, self_val);
792
+
793
+ if (GMPZ_P(arg)) {
794
+ mpz_get_struct(arg,arg_val_z);
795
+ return INT2FIX(mpz_cmpabs (self_val, arg_val_z));
796
+ } else if (FIXNUM_P(arg)) {
797
+ if (FIX2INT(arg) >= 0)
798
+ return INT2FIX(mpz_cmpabs_ui (self_val, FIX2INT(arg)));
799
+ else
800
+ return INT2FIX(mpz_cmpabs_ui (self_val, -FIX2INT(arg)));
801
+ } else if (GMPQ_P(arg)) {
802
+ mpq_get_struct(arg,arg_val_q);
803
+ mpz_temp_alloc (arg_val_z);
804
+ mpz_init(arg_val_z);
805
+ mpz_mul(arg_val_z, self_val, mpq_denref(arg_val_q));
806
+ res = mpz_cmpabs (arg_val_z, mpq_numref(arg_val_q));
807
+ mpz_temp_free(arg_val_z);
808
+ return INT2FIX(res);
809
+ } else if (GMPF_P(arg)) {
810
+ not_yet;
811
+ } else if (BIGNUM_P(arg)) {
812
+ mpz_temp_from_bignum (arg_val_z, arg);
813
+ res = mpz_cmpabs (self_val, arg_val_z);
814
+ mpz_temp_free(arg_val_z);
815
+ return INT2FIX(res);
816
+ } else {
817
+ typeerror(ZQFXB);
818
+ }
819
+ }
820
+
821
+ static VALUE r_gmpz_to_s(VALUE self)
822
+ {
823
+ MP_INT *self_val;
824
+ char *str;
825
+ VALUE res;
826
+
827
+ Data_Get_Struct(self, MP_INT, self_val);
828
+ str = mpz_get_str(NULL, 10, self_val);
829
+ res = rb_str_new2(str);
830
+ free (str);
831
+
832
+ return res;
833
+ }