srawlins-gmp 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/gmpf.h ADDED
@@ -0,0 +1,442 @@
1
+ static VALUE r_gmpf_to_d(VALUE self)
2
+ {
3
+ MP_FLOAT *self_val;
4
+ mpf_get_struct (self, self_val);
5
+
6
+ return rb_float_new(mpf_get_d(self_val));
7
+ }
8
+
9
+ static VALUE r_gmpf_to_s(VALUE self)
10
+ {
11
+ MP_FLOAT *self_val;
12
+ char *str, *str2;
13
+ VALUE res;
14
+ mp_exp_t exponent;
15
+
16
+ mpf_get_struct(self, self_val);
17
+
18
+ str = mpf_get_str(NULL, &exponent, 10, 0, self_val);
19
+ if ((strcmp (str, "NaN") == 0) ||
20
+ (strcmp (str, "Inf") == 0) ||
21
+ (strcmp (str, "-Inf") == 0))
22
+ {
23
+ res = rb_str_new2(str);
24
+ }
25
+ else
26
+ {
27
+ if (str[0] == '-')
28
+ __gmp_asprintf (&str2, "-0.%se%+ld", str+1, exponent);
29
+ else
30
+ __gmp_asprintf (&str2, "0.%se%+ld", str, exponent);
31
+ res = rb_str_new2(str2);
32
+ free (str2);
33
+ }
34
+ free (str);
35
+ return res;
36
+ }
37
+
38
+ static VALUE r_gmpf_add(VALUE self, VALUE arg)
39
+ {
40
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
41
+ MP_RAT *arg_val_q;
42
+ MP_INT *arg_val_z;
43
+ VALUE res;
44
+ unsigned long prec;
45
+
46
+ mpf_get_struct_prec (self, self_val, prec);
47
+
48
+ if (GMPF_P(arg)) {
49
+ mpf_get_struct (arg, arg_val_f);
50
+ prec_max(prec, arg_val_f);
51
+ mpf_make_struct_init(res, res_val, prec);
52
+ mpf_add(res_val, self_val, arg_val_f);
53
+ } else if (GMPQ_P(arg)) {
54
+ mpq_get_struct (arg, arg_val_q);
55
+ mpf_make_struct_init(res, res_val, prec);
56
+ mpf_set_q (res_val, arg_val_q);
57
+ mpf_add (res_val, res_val, self_val);
58
+ } else if (GMPZ_P(arg)) {
59
+ mpz_get_struct (arg, arg_val_z);
60
+ mpf_make_struct_init(res, res_val, prec);
61
+ mpf_set_z (res_val, arg_val_z);
62
+ mpf_add (res_val, res_val, self_val);
63
+ } else if (FLOAT_P(arg)) {
64
+ mpf_make_struct_init(res, res_val, prec);
65
+ mpf_set_d (res_val, FLT2DBL(arg));
66
+ mpf_add (res_val, res_val, self_val);
67
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
68
+ mpf_make_struct_init(res, res_val, prec);
69
+ mpf_set_si (res_val, FIX2INT(arg));
70
+ mpf_add (res_val, res_val, self_val);
71
+ } else if (BIGNUM_P(arg)) {
72
+ mpz_temp_from_bignum(arg_val_z, arg);
73
+ mpf_make_struct_init(res, res_val, prec);
74
+ mpf_set_z (res_val, arg_val_z);
75
+ mpf_add (res_val, res_val, self_val);
76
+ mpz_temp_free(arg_val_z);
77
+ } else {
78
+ typeerror(ZQFXBD);
79
+ }
80
+
81
+ return res;
82
+ }
83
+
84
+ static VALUE r_gmpf_sub(VALUE self, VALUE arg)
85
+ {
86
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
87
+ MP_RAT *arg_val_q;
88
+ MP_INT *arg_val_z;
89
+ VALUE res;
90
+ unsigned long prec;
91
+
92
+ mpf_get_struct_prec (self, self_val, prec);
93
+
94
+ if (GMPF_P(arg)) {
95
+ mpf_get_struct (arg, arg_val_f);
96
+ prec_max(prec, arg_val_f);
97
+ mpf_make_struct_init(res, res_val, prec);
98
+ mpf_sub(res_val, self_val, arg_val_f);
99
+ } else if (GMPQ_P(arg)) {
100
+ mpq_get_struct (arg, arg_val_q);
101
+ mpf_make_struct_init(res, res_val, prec);
102
+ mpf_set_q (res_val, arg_val_q);
103
+ mpf_sub (res_val, self_val, res_val);
104
+ } else if (GMPZ_P(arg)) {
105
+ mpz_get_struct (arg, arg_val_z);
106
+ mpf_make_struct_init(res, res_val, prec);
107
+ mpf_set_z (res_val, arg_val_z);
108
+ mpf_sub (res_val, self_val, res_val);
109
+ } else if (FLOAT_P(arg)) {
110
+ mpf_make_struct_init(res, res_val, prec);
111
+ mpf_set_d (res_val, FLT2DBL(arg));
112
+ mpf_sub (res_val, self_val, res_val);
113
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
114
+ mpf_make_struct_init(res, res_val, prec);
115
+ mpf_set_si (res_val, FIX2INT(arg));
116
+ mpf_sub (res_val, self_val, res_val);
117
+ } else if (BIGNUM_P(arg)) {
118
+ mpz_temp_from_bignum(arg_val_z, arg);
119
+ mpf_make_struct_init(res, res_val, prec);
120
+ mpf_set_z (res_val, arg_val_z);
121
+ mpf_sub (res_val, res_val, self_val);
122
+ mpz_temp_free(arg_val_z);
123
+ } else {
124
+ typeerror(ZQFXBD);
125
+ }
126
+
127
+ return res;
128
+ }
129
+
130
+ static VALUE r_gmpf_mul(VALUE self, VALUE arg)
131
+ {
132
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
133
+ MP_RAT *arg_val_q;
134
+ MP_INT *arg_val_z;
135
+ VALUE res;
136
+ unsigned long prec;
137
+
138
+ mpf_get_struct_prec (self, self_val, prec);
139
+
140
+ if (GMPF_P(arg)) {
141
+ mpf_get_struct (arg, arg_val_f);
142
+ prec_max(prec, arg_val_f);
143
+ mpf_make_struct_init(res, res_val, prec);
144
+ mpf_mul(res_val, self_val, arg_val_f);
145
+ } else if (GMPQ_P(arg)) {
146
+ mpq_get_struct (arg, arg_val_q);
147
+ mpf_make_struct_init(res, res_val, prec);
148
+ mpf_set_q (res_val, arg_val_q);
149
+ mpf_mul (res_val, self_val, res_val);
150
+ } else if (GMPZ_P(arg)) {
151
+ mpz_get_struct (arg, arg_val_z);
152
+ mpf_make_struct_init(res, res_val, prec);
153
+ mpf_set_z (res_val, arg_val_z);
154
+ mpf_mul (res_val, self_val, res_val);
155
+ } else if (FLOAT_P(arg)) {
156
+ mpf_make_struct_init(res, res_val, prec);
157
+ mpf_set_d (res_val, FLT2DBL(arg));
158
+ mpf_mul (res_val, self_val, res_val);
159
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
160
+ mpf_make_struct_init(res, res_val, prec);
161
+ mpf_set_si (res_val, FIX2INT(arg));
162
+ mpf_mul (res_val, self_val, res_val);
163
+ } else if (BIGNUM_P(arg)) {
164
+ mpz_temp_from_bignum(arg_val_z, arg);
165
+ mpf_make_struct_init(res, res_val, prec);
166
+ mpf_set_z (res_val, arg_val_z);
167
+ mpf_mul (res_val, res_val, self_val);
168
+ mpz_temp_free(arg_val_z);
169
+ } else {
170
+ typeerror(ZQFXBD);
171
+ }
172
+
173
+ return res;
174
+ }
175
+
176
+ static VALUE r_gmpf_div(VALUE self, VALUE arg)
177
+ {
178
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
179
+ MP_RAT *arg_val_q;
180
+ MP_INT *arg_val_z;
181
+ VALUE res;
182
+ unsigned long prec;
183
+
184
+ mpf_get_struct_prec (self, self_val, prec);
185
+
186
+ if (GMPF_P(arg)) {
187
+ mpf_get_struct (arg, arg_val_f);
188
+ prec_max(prec, arg_val_f);
189
+ mpf_make_struct_init(res, res_val, prec);
190
+ mpf_div(res_val, self_val, arg_val_f);
191
+ } else if (GMPQ_P(arg)) {
192
+ mpq_get_struct (arg, arg_val_q);
193
+ mpf_make_struct_init(res, res_val, prec);
194
+ mpf_set_q (res_val, arg_val_q);
195
+ mpf_div (res_val, self_val, res_val);
196
+ } else if (GMPZ_P(arg)) {
197
+ mpz_get_struct (arg, arg_val_z);
198
+ mpf_make_struct_init(res, res_val, prec);
199
+ mpf_set_z (res_val, arg_val_z);
200
+ mpf_div (res_val, self_val, res_val);
201
+ } else if (FLOAT_P(arg)) {
202
+ mpf_make_struct_init(res, res_val, prec);
203
+ mpf_set_d (res_val, FLT2DBL(arg));
204
+ mpf_div (res_val, self_val, res_val);
205
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
206
+ mpf_make_struct_init(res, res_val, prec);
207
+ mpf_set_si (res_val, FIX2INT(arg));
208
+ mpf_div (res_val, self_val, res_val);
209
+ } else if (BIGNUM_P(arg)) {
210
+ mpz_temp_from_bignum(arg_val_z, arg);
211
+ mpf_make_struct_init(res, res_val, prec);
212
+ mpf_set_z (res_val, arg_val_z);
213
+ mpf_div (res_val, res_val, self_val);
214
+ mpz_temp_free(arg_val_z);
215
+ } else {
216
+ typeerror(ZQFXBD);
217
+ }
218
+
219
+ return res;
220
+ }
221
+
222
+ #define DEFUN_FLOAT2FLOAT(fname,mpf_fname) \
223
+ static VALUE r_gmpf_##fname(VALUE self) \
224
+ {\
225
+ MP_FLOAT *self_val, *res_val; \
226
+ VALUE res; \
227
+ mpf_get_struct(self, self_val); \
228
+ mpf_make_struct_init(res, res_val, mpf_get_prec(self_val)); \
229
+ mpf_fname(res_val, self_val); \
230
+ return res; \
231
+ }\
232
+ \
233
+ static VALUE r_gmpf_##fname##_self(VALUE self) \
234
+ {\
235
+ MP_FLOAT *self_val; \
236
+ mpf_get_struct(self, self_val); \
237
+ mpf_fname(self_val, self_val); \
238
+ return Qnil; \
239
+ }
240
+
241
+ DEFUN_FLOAT2FLOAT(abs,mpf_abs)
242
+ DEFUN_FLOAT2FLOAT(neg,mpf_neg)
243
+ DEFUN_FLOAT2FLOAT(floor,mpf_floor)
244
+ DEFUN_FLOAT2FLOAT(trunc,mpf_trunc)
245
+ DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
246
+
247
+ int mpf_cmp_value(MP_FLOAT *self_val, VALUE arg)
248
+ {
249
+ MP_FLOAT *arg_val;
250
+ int result;
251
+
252
+ if (GMPF_P(arg)) {
253
+ mpf_get_struct(arg,arg_val);
254
+ return mpf_cmp (self_val, arg_val);
255
+ } else {
256
+ mpf_temp_init(arg_val, mpf_get_prec (self_val));
257
+ mpf_set_value (arg_val, arg);
258
+ result = mpf_cmp (self_val, arg_val);
259
+ mpf_temp_free(arg_val);
260
+ return result;
261
+ }
262
+ }
263
+
264
+ /* what does really "equal" mean ? it's not obvious */
265
+ VALUE r_gmpf_eq(VALUE self, VALUE arg)
266
+ {
267
+ MP_FLOAT *self_val;
268
+ mpf_get_struct (self,self_val);
269
+ return (mpf_cmp_value(self_val, arg) == 0) ? Qtrue : Qfalse;
270
+ }
271
+
272
+ VALUE r_gmpf_cmp (VALUE self, VALUE arg)
273
+ {
274
+ MP_FLOAT *self_val;
275
+ int res;
276
+ mpf_get_struct (self,self_val);
277
+ res = mpf_cmp_value(self_val, arg);
278
+ if (res > 0)
279
+ return INT2FIX(1);
280
+ else if (res == 0)
281
+ return INT2FIX(0);
282
+ else
283
+ return INT2FIX(-1);
284
+ }
285
+
286
+ #define DEFUN_FLOAT_CMP(name,CMP_OP) \
287
+ static VALUE r_gmpf_cmp_##name(VALUE self, VALUE arg) \
288
+ { \
289
+ MP_FLOAT *self_val; \
290
+ mpf_get_struct (self,self_val); \
291
+ return (mpf_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
292
+ }
293
+
294
+ DEFUN_FLOAT_CMP(lt,<)
295
+ DEFUN_FLOAT_CMP(le,<=)
296
+ DEFUN_FLOAT_CMP(gt,>)
297
+ DEFUN_FLOAT_CMP(ge,>=)
298
+
299
+ static VALUE r_gmpf_sgn(VALUE self)
300
+ {
301
+ MP_FLOAT *self_val;
302
+ mpf_get_struct(self, self_val);
303
+ return INT2FIX(mpf_sgn(self_val));
304
+ }
305
+
306
+ static VALUE r_gmpf_get_prec(VALUE self)
307
+ {
308
+ MP_FLOAT *self_val;
309
+ mpf_get_struct(self, self_val);
310
+ return INT2NUM(mpf_get_prec(self_val));
311
+ }
312
+
313
+ #ifdef MPFR
314
+ #define MPFR_SINGLE_FUNCTION(name) \
315
+ static VALUE r_gmpfr_##name(VALUE self) \
316
+ { \
317
+ MP_FLOAT *self_val, *res_val; \
318
+ unsigned long prec; \
319
+ VALUE res; \
320
+ \
321
+ mpf_get_struct_prec(self, self_val, prec); \
322
+ mpf_make_struct_init(res, res_val, prec); \
323
+ mpfr_##name(res_val, self_val, __gmp_default_rounding_mode); \
324
+ \
325
+ return res; \
326
+ }
327
+
328
+ MPFR_SINGLE_FUNCTION(log)
329
+ MPFR_SINGLE_FUNCTION(exp)
330
+ MPFR_SINGLE_FUNCTION(sqrt)
331
+ MPFR_SINGLE_FUNCTION(cos)
332
+ MPFR_SINGLE_FUNCTION(sin)
333
+ MPFR_SINGLE_FUNCTION(tan)
334
+ MPFR_SINGLE_FUNCTION(acos)
335
+ MPFR_SINGLE_FUNCTION(asin)
336
+ MPFR_SINGLE_FUNCTION(atan)
337
+ MPFR_SINGLE_FUNCTION(cosh)
338
+ MPFR_SINGLE_FUNCTION(sinh)
339
+ MPFR_SINGLE_FUNCTION(tanh)
340
+ MPFR_SINGLE_FUNCTION(acosh)
341
+ MPFR_SINGLE_FUNCTION(asinh)
342
+ MPFR_SINGLE_FUNCTION(atanh)
343
+ MPFR_SINGLE_FUNCTION(log1p)
344
+ MPFR_SINGLE_FUNCTION(expm1)
345
+ MPFR_SINGLE_FUNCTION(log2)
346
+ MPFR_SINGLE_FUNCTION(log10)
347
+
348
+ static VALUE r_gmpfr_nan_p(VALUE self)
349
+ {
350
+ MP_FLOAT *self_val;
351
+
352
+ mpf_get_struct(self, self_val);
353
+ if (mpfr_nan_p(self_val)) {
354
+ return Qtrue;
355
+ }
356
+ else {
357
+ return Qfalse;
358
+ }
359
+ }
360
+
361
+ static VALUE r_gmpfr_inf_p(VALUE self)
362
+ {
363
+ MP_FLOAT *self_val;
364
+
365
+ mpf_get_struct(self, self_val);
366
+ if (mpfr_inf_p(self_val)) {
367
+ return Qtrue;
368
+ }
369
+ else {
370
+ return Qfalse;
371
+ }
372
+ }
373
+
374
+ static VALUE r_gmpfr_fin_p(VALUE self)
375
+ {
376
+ if (r_gmpfr_inf_p(self)) {
377
+ return Qfalse;
378
+ }
379
+ else {
380
+ return Qtrue;
381
+ }
382
+ }
383
+
384
+ static VALUE r_gmpfr_number_p(VALUE self)
385
+ {
386
+ MP_FLOAT *self_val;
387
+
388
+ mpf_get_struct(self, self_val);
389
+ if (mpfr_number_p(self_val)) {
390
+ return Qtrue;
391
+ }
392
+ else {
393
+ return Qfalse;
394
+ }
395
+ }
396
+
397
+ static VALUE r_gmpfr_pow(VALUE self, VALUE arg)
398
+ {
399
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
400
+ MP_RAT *arg_val_q;
401
+ MP_INT *arg_val_z;
402
+ unsigned long prec;
403
+ VALUE res;
404
+
405
+ mpf_get_struct_prec(self, self_val, prec);
406
+
407
+ if (GMPF_P(arg)) {
408
+ mpf_get_struct(arg, arg_val_f);
409
+ prec_max(prec, arg_val_f);
410
+ mpf_make_struct_init(res, res_val, prec);
411
+ mpfr_pow(res_val, self_val, arg_val_f, __gmp_default_rounding_mode);
412
+ } else {
413
+ mpf_make_struct_init(res, res_val, prec);
414
+
415
+ if (GMPZ_P(arg)) {
416
+ mpz_get_struct(arg, arg_val_z);
417
+ mpf_set_z(res_val, arg_val_z);
418
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
419
+ } else if (GMPQ_P(arg)) {
420
+ mpq_get_struct(arg, arg_val_q);
421
+ mpf_set_q(res_val, arg_val_q);
422
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
423
+ } else if (FLOAT_P(arg)) {
424
+ mpf_set_d(res_val, FLT2DBL(arg));
425
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
426
+ } else if (FIXNUM_P(arg)) {
427
+ mpfr_pow_si(res_val, self_val, FIX2INT(arg), __gmp_default_rounding_mode);
428
+ } else if (BIGNUM_P(arg)) {
429
+ mpz_temp_from_bignum(arg_val_z, arg);
430
+ mpf_set_z(res_val, arg_val_z);
431
+ mpz_temp_free(arg_val_z);
432
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
433
+ } else {
434
+ typeerror(ZQFXBD);
435
+ }
436
+
437
+ }
438
+
439
+ return res;
440
+ }
441
+
442
+ #endif
data/ext/gmpq.h ADDED
@@ -0,0 +1,486 @@
1
+ static VALUE r_gmpq_add(VALUE self, VALUE arg)
2
+ {
3
+ MP_RAT *self_val, *arg_val_q, *res_val;
4
+ MP_INT *arg_val_z, *res_val_num;
5
+ VALUE res;
6
+
7
+ mpq_get_struct(self, self_val);
8
+ mpq_make_struct_init(res, res_val);
9
+
10
+ if (GMPQ_P(arg)) {
11
+ mpq_get_struct(arg,arg_val_q);
12
+ mpq_add (res_val, self_val, arg_val_q);
13
+ } else if (GMPZ_P(arg)) {
14
+ res_val_num = mpq_numref(res_val);
15
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
16
+ mpz_get_struct(arg, arg_val_z);
17
+ mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
18
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
19
+ } else if (FIXNUM_P(arg)) {
20
+ res_val_num = mpq_numref(res_val);
21
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
22
+ mpz_mul_si (res_val_num, mpq_denref(self_val), FIX2INT(arg));
23
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
24
+ } else if (GMPF_P(arg)) {
25
+ return r_gmpf_add(arg,self);
26
+ } else if (BIGNUM_P(arg)) {
27
+ res_val_num = mpq_numref(res_val);
28
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
29
+ mpz_set_bignum (res_val_num, arg);
30
+ mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
31
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
32
+ } else {
33
+ typeerror (ZQFXB);
34
+ }
35
+ return res;
36
+ }
37
+
38
+ static VALUE r_gmpq_sub(VALUE self, VALUE arg)
39
+ {
40
+ MP_RAT *self_val, *arg_val_q, *res_val;
41
+ MP_INT *arg_val_z, *res_val_num;
42
+ MP_FLOAT *arg_val_f, *res_val_f;
43
+ VALUE res;
44
+ unsigned int prec;
45
+
46
+ mpq_get_struct(self, self_val);
47
+ mpq_make_struct_init(res, res_val);
48
+
49
+ if (GMPQ_P(arg)) {
50
+ mpq_get_struct(arg,arg_val_q);
51
+ mpq_sub (res_val, self_val, arg_val_q);
52
+ } else if (GMPZ_P(arg)) {
53
+ res_val_num = mpq_numref(res_val);
54
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
55
+ mpz_get_struct(arg, arg_val_z);
56
+ mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
57
+ mpz_neg (res_val_num, res_val_num);
58
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
59
+ } else if (FIXNUM_P(arg)) {
60
+ res_val_num = mpq_numref(res_val);
61
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
62
+ mpz_mul_si (res_val_num, mpq_denref(self_val), -FIX2INT(arg));
63
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
64
+ } else if (GMPF_P(arg)) {
65
+ mpf_get_struct_prec (arg, arg_val_f, prec);
66
+ mpf_make_struct_init(res, res_val_f, prec);
67
+ mpf_set_q (res_val_f, self_val);
68
+ mpf_sub (res_val_f, res_val_f, arg_val_f);
69
+ } else if (BIGNUM_P(arg)) {
70
+ res_val_num = mpq_numref(res_val);
71
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
72
+ mpz_set_bignum (res_val_num, arg);
73
+ mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
74
+ mpz_neg (res_val_num, res_val_num);
75
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
76
+ } else {
77
+ typeerror (ZQFXB);
78
+ }
79
+ return res;
80
+ }
81
+
82
+ static VALUE r_gmpq_mul(VALUE self, VALUE arg)
83
+ {
84
+ MP_RAT *self_val, *arg_val_q, *res_val;
85
+ MP_INT *arg_val_z, *tmp_z;
86
+ VALUE res;
87
+ #if GMP >= 4
88
+ unsigned long tmp_ui;
89
+ #endif
90
+
91
+ mpq_get_struct(self, self_val);
92
+ mpq_make_struct_init(res, res_val);
93
+
94
+ if (GMPQ_P(arg)) {
95
+ mpq_get_struct(arg,arg_val_q);
96
+ mpq_mul (res_val, self_val, arg_val_q);
97
+ } else if (GMPZ_P(arg)) {
98
+ mpz_get_struct(arg,arg_val_z);
99
+ mpz_temp_init(tmp_z);
100
+ mpz_gcd (tmp_z, mpq_denref(self_val), arg_val_z);
101
+ mpz_divexact (mpq_denref(res_val), mpq_denref(self_val), tmp_z);
102
+ mpz_divexact (mpq_numref(res_val), arg_val_z, tmp_z);
103
+ mpz_mul (mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
104
+ mpz_temp_free(tmp_z);
105
+ } else if (FIXNUM_P(arg)) {
106
+ #if GMP >= 4
107
+ if (FIX2INT(arg) > 0) {
108
+ tmp_ui = mpz_gcd_ui (0, mpq_denref(self_val), FIX2INT(arg));
109
+ } else if (FIX2INT(arg) < 0) {
110
+ tmp_ui = mpz_gcd_ui (0, mpq_denref(self_val), -FIX2INT(arg));
111
+ } else {
112
+ mpz_set_ui(mpq_numref(res_val), 0);
113
+ mpz_set_ui(mpq_denref(res_val), 1);
114
+ return res;
115
+ }
116
+ mpz_divexact_ui (mpq_denref(res_val), mpq_denref(self_val), tmp_ui);
117
+ mpz_mul_ui (mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg)/tmp_ui);
118
+ #else
119
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
120
+ mpz_mul_si (mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg));
121
+ mpq_canonicalize (res_val);
122
+ #endif
123
+ } else if (GMPF_P(arg)) {
124
+ return r_gmpf_mul (arg, self);
125
+ } else if (BIGNUM_P(arg)) {
126
+ mpz_temp_alloc(tmp_z);
127
+ mpz_set_bignum(tmp_z, arg);
128
+ mpz_gcd(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
129
+ mpz_divexact(mpq_numref(res_val), tmp_z, mpq_denref(res_val));
130
+ mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), mpq_denref(res_val));
131
+ mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
132
+ mpz_temp_free(tmp_z);
133
+ } else {
134
+ typeerror (ZQFXB);
135
+ }
136
+ return res;
137
+ }
138
+
139
+ static VALUE r_gmpq_div(VALUE self, VALUE arg)
140
+ {
141
+ MP_RAT *self_val, *arg_val_q, *res_val;
142
+ MP_INT *arg_val_z, *tmp_z;
143
+ MP_FLOAT *arg_val_f, *res_val_f;
144
+ VALUE res;
145
+ unsigned long tmp_ui, prec;
146
+
147
+ mpq_get_struct(self, self_val);
148
+ mpq_make_struct_init(res, res_val);
149
+
150
+ if (GMPQ_P(arg)) {
151
+ mpq_get_struct(arg,arg_val_q);
152
+ if (mpz_sgn(mpq_numref(arg_val_q)) == 0)
153
+ rb_raise (rb_eZeroDivError, "divided by 0");
154
+ mpq_div (res_val, self_val, arg_val_q);
155
+ } else if (GMPZ_P(arg)) {
156
+ mpz_get_struct(arg,arg_val_z);
157
+ mpz_temp_init(tmp_z);
158
+ mpz_gcd (tmp_z, mpq_numref(self_val), arg_val_z);
159
+ mpz_divexact (mpq_numref(res_val), mpq_numref(self_val), tmp_z);
160
+ mpz_divexact (mpq_denref(res_val), arg_val_z, tmp_z);
161
+ mpz_mul (mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
162
+ mpz_temp_free(tmp_z);
163
+ } else if (FIXNUM_P(arg)) {
164
+ if (FIX2INT(arg) == 0)
165
+ rb_raise (rb_eZeroDivError, "divided by 0");
166
+ if (FIX2INT(arg) > 0) {
167
+ tmp_ui = mpz_gcd_ui (0, mpq_numref(self_val), FIX2INT(arg));
168
+ } else {
169
+ tmp_ui = mpz_gcd_ui (0, mpq_numref(self_val), -FIX2INT(arg));
170
+ }
171
+ mpz_divexact_ui (mpq_numref(res_val), mpq_numref(self_val), tmp_ui);
172
+ mpz_mul_ui (mpq_denref(res_val), mpq_denref(self_val), FIX2INT(arg)/tmp_ui);
173
+ } else if (GMPF_P(arg)) {
174
+ mpf_get_struct_prec (arg, arg_val_f, prec);
175
+ mpf_make_struct_init(res, res_val_f, prec);
176
+ mpf_set_q (res_val_f, self_val);
177
+ mpf_div (res_val_f, res_val_f, arg_val_f);
178
+ } else if (BIGNUM_P(arg)) {
179
+ mpz_temp_alloc(tmp_z);
180
+ mpz_set_bignum(tmp_z, arg);
181
+ mpz_gcd(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
182
+ mpz_divexact(mpq_denref(res_val), tmp_z, mpq_numref(res_val));
183
+ mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), mpq_numref(res_val));
184
+ mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
185
+ mpz_temp_free(tmp_z);
186
+ } else {
187
+ typeerror (ZQFXB);
188
+ }
189
+ return res;
190
+ }
191
+
192
+ static VALUE r_gmpq_neg(VALUE self)
193
+ {
194
+ MP_RAT *self_val, *res_val;
195
+ VALUE res;
196
+ mpq_get_struct(self, self_val);
197
+ mpq_make_struct_init(res, res_val);
198
+ mpq_neg (res_val, self_val);
199
+ return res;
200
+ }
201
+
202
+ static VALUE r_gmpq_neg_self(VALUE self)
203
+ {
204
+ MP_RAT *self_val;
205
+ mpq_get_struct(self, self_val);
206
+ mpz_neg (mpq_numref(self_val), mpq_numref(self_val));
207
+ return Qnil;
208
+ }
209
+
210
+ static VALUE r_gmpq_abs(VALUE self)
211
+ {
212
+ MP_RAT *self_val, *res_val;
213
+ VALUE res;
214
+ mpq_get_struct(self, self_val);
215
+ mpq_make_struct_init(res, res_val);
216
+ mpz_abs (mpq_numref(res_val), mpq_numref(self_val));
217
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
218
+
219
+ return res;
220
+ }
221
+
222
+ static VALUE r_gmpq_abs_self(VALUE self)
223
+ {
224
+ MP_RAT *self_val;
225
+ mpq_get_struct(self, self_val);
226
+ mpz_abs (mpq_numref(self_val), mpq_numref(self_val));
227
+ return Qnil;
228
+ }
229
+
230
+ static VALUE r_gmpq_inv(VALUE self)
231
+ {
232
+ MP_RAT *self_val, *res_val;
233
+ VALUE res;
234
+
235
+ mpq_get_struct(self, self_val);
236
+ if (mpq_sgn(self_val) == 0)
237
+ rb_raise (rb_eZeroDivError, "divided by 0");
238
+ mpq_make_struct_init(res, res_val);
239
+ mpq_inv (res_val, self_val);
240
+
241
+ return res;
242
+ }
243
+
244
+ static VALUE r_gmpq_inv_self(VALUE self)
245
+ {
246
+ MP_RAT *self_val;
247
+ mpq_get_struct(self, self_val);
248
+ if (mpq_sgn(self_val) == 0)
249
+ rb_raise (rb_eZeroDivError, "divided by 0");
250
+ mpq_inv (self_val, self_val);
251
+ return Qnil;
252
+ }
253
+
254
+ static VALUE r_gmpq_sgn(VALUE self)
255
+ {
256
+ MP_RAT *self_val;
257
+ mpq_get_struct(self, self_val);
258
+ return INT2FIX(mpq_sgn(self_val));
259
+ }
260
+
261
+ static int mpq_cmp_value (MP_RAT *OP, VALUE arg)
262
+ {
263
+ MP_INT *arg_val_z, *tmp_z;
264
+ MP_RAT *arg_val_q;
265
+ int res;
266
+
267
+ if (GMPQ_P(arg)) {
268
+ mpq_get_struct(arg,arg_val_q);
269
+ return mpq_cmp (OP,arg_val_q);
270
+ } else if (GMPZ_P(arg)) {
271
+ mpz_get_struct(arg, arg_val_z);
272
+ mpz_temp_alloc (tmp_z);
273
+ mpz_init (tmp_z);
274
+ mpz_mul (tmp_z, mpq_denref(OP), arg_val_z);
275
+ res = mpz_cmp (mpq_numref(OP),tmp_z);
276
+ mpz_temp_free (tmp_z);
277
+ return res;
278
+ } else if (FIXNUM_P(arg)) {
279
+ mpz_temp_alloc (tmp_z);
280
+ mpz_init (tmp_z);
281
+ mpz_mul_si (tmp_z, mpq_denref(OP), FIX2INT(arg));
282
+ res = mpz_cmp (mpq_numref(OP), tmp_z);
283
+ mpz_temp_free (tmp_z);
284
+ return res;
285
+ } else if (GMPF_P(arg)) {
286
+ not_yet;
287
+ } else if (BIGNUM_P(arg)) {
288
+ mpz_temp_from_bignum (tmp_z, arg);
289
+ mpz_mul (tmp_z, tmp_z, mpq_denref(OP));
290
+ res = mpz_cmp (mpq_numref(OP), tmp_z);
291
+ mpz_temp_free (tmp_z);
292
+ return res;
293
+ } else {
294
+ typeerror (ZQFXB);
295
+ }
296
+ }
297
+
298
+ static VALUE r_gmpq_eq(VALUE self, VALUE arg)
299
+ {
300
+ MP_RAT *self_val, *arg_val_q;
301
+ MP_INT *arg_val_z;
302
+
303
+ mpq_get_struct(self,self_val);
304
+ if (GMPQ_P(arg)) {
305
+ mpq_get_struct(arg,arg_val_q);
306
+ return mpq_equal(self_val,arg_val_q)?Qtrue:Qfalse;
307
+ } else if (GMPZ_P(arg)) {
308
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
309
+ return Qfalse;
310
+ mpz_get_struct (arg, arg_val_z);
311
+ return (mpz_cmp(mpq_numref(self_val),arg_val_z)==0)?Qtrue:Qfalse;
312
+ } else if (FIXNUM_P(arg)) {
313
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
314
+ return Qfalse;
315
+ return (mpz_cmp_ui(mpq_numref(self_val),FIX2INT(arg))==0)?Qtrue:Qfalse;
316
+ } else if (BIGNUM_P(arg)) {
317
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
318
+ return Qfalse;
319
+ mpz_temp_from_bignum(arg_val_z, arg);
320
+ if (mpz_cmp (mpq_numref(self_val),arg_val_z) == 0) {
321
+ mpz_temp_free (arg_val_z);
322
+ return Qtrue;
323
+ } else {
324
+ mpz_temp_free (arg_val_z);
325
+ return Qfalse;
326
+ }
327
+ } else {
328
+ return Qfalse;
329
+ }
330
+ }
331
+
332
+ static VALUE r_gmpq_cmp(VALUE self, VALUE arg)
333
+ {
334
+ MP_RAT *self_val;
335
+ int res;
336
+ mpq_get_struct (self,self_val);
337
+ res = mpq_cmp_value(self_val, arg);
338
+ if (res > 0)
339
+ return INT2FIX(1);
340
+ else if (res == 0)
341
+ return INT2FIX(0);
342
+ else
343
+ return INT2FIX(-1);
344
+ }
345
+
346
+ #define DEFUN_RAT_CMP(name,CMP_OP) \
347
+ static VALUE r_gmpq_cmp_##name(VALUE self, VALUE arg) \
348
+ { \
349
+ MP_RAT *self_val; \
350
+ mpq_get_struct (self,self_val); \
351
+ return (mpq_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
352
+ }
353
+
354
+ DEFUN_RAT_CMP(lt,<)
355
+ DEFUN_RAT_CMP(le,<=)
356
+ DEFUN_RAT_CMP(gt,>)
357
+ DEFUN_RAT_CMP(ge,>=)
358
+
359
+ static VALUE r_gmpq_swap(VALUE self, VALUE arg)
360
+ {
361
+ MP_RAT *self_val, *arg_val;
362
+
363
+ if (!GMPQ_P(arg)) {
364
+ rb_raise(rb_eTypeError, "Can't swap GMP::Q with object of other class");
365
+ }
366
+
367
+ mpq_get_struct(self, self_val);
368
+ mpq_get_struct(arg, arg_val);
369
+ mpq_swap(self_val,arg_val);
370
+
371
+ return Qnil;
372
+ }
373
+
374
+ #define DEFUN_RAT2INT(fname,mpz_fname) \
375
+ static VALUE r_gmpq_##fname(VALUE self) \
376
+ { \
377
+ MP_RAT *self_val; \
378
+ MP_INT *res_val; \
379
+ VALUE res; \
380
+ \
381
+ mpq_get_struct(self, self_val); \
382
+ mpz_make_struct_init (res, res_val) \
383
+ mpz_fname (res_val, mpq_numref(self_val), mpq_denref(self_val)); \
384
+ return res; \
385
+ }
386
+
387
+ DEFUN_RAT2INT(floor,mpz_fdiv_q)
388
+ DEFUN_RAT2INT(trunc,mpz_tdiv_q)
389
+ DEFUN_RAT2INT(ceil,mpz_cdiv_q)
390
+
391
+ static VALUE r_gmpq_to_d(VALUE self)
392
+ {
393
+ MP_RAT *self_val;
394
+ mpq_get_struct (self, self_val);
395
+
396
+ return rb_float_new(mpq_get_d(self_val));
397
+ }
398
+
399
+ static VALUE r_gmpq_cmpabs (VALUE self, VALUE arg)
400
+ {
401
+ MP_RAT *arg_val_q, *self_val;
402
+ MP_INT *arg_val_z, *tmp_z;
403
+ int res;
404
+ int sgnt;
405
+
406
+ mpq_get_struct(self, self_val);
407
+
408
+ if (GMPQ_P(arg)) {
409
+ mpq_get_struct(arg,arg_val_q);
410
+ sgnt = 3*mpz_sgn(mpq_numref(self_val)) + mpz_sgn(mpq_numref(arg_val_q));
411
+ switch (sgnt)
412
+ {
413
+ default:
414
+ case 0:
415
+ return INT2FIX(0);
416
+ case 1:
417
+ case -1:
418
+ return INT2FIX(-1);
419
+ case 2:
420
+ tmp_z = mpq_numref(arg_val_q);
421
+ mpz_neg (tmp_z, tmp_z);
422
+ res = mpq_cmp (self_val, arg_val_q);
423
+ mpz_neg (tmp_z, tmp_z);
424
+ return res;
425
+ case -2:
426
+ tmp_z = mpq_numref(arg_val_q);
427
+ mpz_neg (tmp_z, tmp_z);
428
+ res = mpq_cmp (self_val, arg_val_q);
429
+ mpz_neg (tmp_z, tmp_z);
430
+ return res;
431
+ case 3:
432
+ case -3:
433
+ return INT2FIX(1);
434
+ case 4:
435
+ case -4:
436
+ return INT2FIX(mpq_cmp (self_val,arg_val_q));
437
+ }
438
+ } else if (GMPZ_P(arg)) {
439
+ mpz_get_struct(arg, arg_val_z);
440
+ mpz_temp_alloc (tmp_z);
441
+ mpz_init (tmp_z);
442
+ mpz_mul (tmp_z, mpq_denref(self_val), arg_val_z);
443
+ res = mpz_cmpabs (mpq_numref(self_val),tmp_z);
444
+ mpz_temp_free (tmp_z);
445
+ return res;
446
+ } else if (FIXNUM_P(arg)) {
447
+ mpz_temp_alloc (tmp_z);
448
+ mpz_init (tmp_z);
449
+ mpz_mul_si (tmp_z, mpq_denref(self_val), FIX2INT(arg));
450
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
451
+ mpz_temp_free (tmp_z);
452
+ return res;
453
+ } else if (GMPF_P(arg)) {
454
+ not_yet;
455
+ } else if (BIGNUM_P(arg)) {
456
+ mpz_temp_from_bignum (tmp_z, arg);
457
+ mpz_mul (tmp_z, tmp_z, mpq_denref(self_val));
458
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
459
+ mpz_temp_free (tmp_z);
460
+ return res;
461
+ } else {
462
+ typeerror (ZQFXB);
463
+ }
464
+ }
465
+
466
+ static VALUE r_gmpq_num(VALUE self)
467
+ {
468
+ MP_RAT *self_val;
469
+ MP_INT *res_val;
470
+ VALUE res;
471
+ mpq_get_struct(self,self_val);
472
+ mpz_make_struct(res, res_val);
473
+ mpz_init_set (res_val, mpq_numref (self_val));
474
+ return res;
475
+ }
476
+
477
+ static VALUE r_gmpq_den(VALUE self)
478
+ {
479
+ MP_RAT *self_val;
480
+ MP_INT *res_val;
481
+ VALUE res;
482
+ mpq_get_struct(self,self_val);
483
+ mpz_make_struct(res, res_val);
484
+ mpz_init_set (res_val, mpq_denref (self_val));
485
+ return res;
486
+ }