gmp 0.4.0-x86-mingw32

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.
Files changed (59) hide show
  1. data/CHANGELOG +109 -0
  2. data/INSTALL +4 -0
  3. data/README.rdoc +357 -0
  4. data/benchmark/COPYING +674 -0
  5. data/benchmark/README +75 -0
  6. data/benchmark/divide +34 -0
  7. data/benchmark/gcd +38 -0
  8. data/benchmark/gexpr +0 -0
  9. data/benchmark/gexpr.c +359 -0
  10. data/benchmark/multiply +44 -0
  11. data/benchmark/rsa +93 -0
  12. data/benchmark/runbench +147 -0
  13. data/benchmark/version +1 -0
  14. data/ext/extconf.rb +30 -0
  15. data/ext/gmp.c +197 -0
  16. data/ext/gmpbench_timing.c +80 -0
  17. data/ext/gmpf.c +595 -0
  18. data/ext/gmpf.h +144 -0
  19. data/ext/gmpq.c +780 -0
  20. data/ext/gmpq.h +12 -0
  21. data/ext/gmprandstate.c +224 -0
  22. data/ext/gmpz.c +1968 -0
  23. data/ext/gmpz.h +20 -0
  24. data/ext/libgmp-10.dll +0 -0
  25. data/ext/ruby_gmp.h +243 -0
  26. data/ext/takeover.h +36 -0
  27. data/manual.pdf +0 -0
  28. data/manual.tex +804 -0
  29. data/test/README +34 -0
  30. data/test/tc_cmp.rb +74 -0
  31. data/test/tc_division.rb +109 -0
  32. data/test/tc_f_arithmetics_coersion.rb +71 -0
  33. data/test/tc_f_precision.rb +48 -0
  34. data/test/tc_fib_fac_nextprime.rb +51 -0
  35. data/test/tc_floor_ceil_truncate.rb +21 -0
  36. data/test/tc_logical_roots.rb +48 -0
  37. data/test/tc_q.rb +27 -0
  38. data/test/tc_q_basic.rb +41 -0
  39. data/test/tc_random.rb +54 -0
  40. data/test/tc_sgn_neg_abs.rb +47 -0
  41. data/test/tc_swap.rb +19 -0
  42. data/test/tc_z.rb +71 -0
  43. data/test/tc_z_basic.rb +35 -0
  44. data/test/tc_z_exponentiation.rb +22 -0
  45. data/test/tc_z_gcd_lcm_invert.rb +57 -0
  46. data/test/tc_z_jac_leg_rem.rb +73 -0
  47. data/test/tc_z_logic.rb +54 -0
  48. data/test/tc_z_shifts_last_bits.rb +22 -0
  49. data/test/tc_z_to_d_to_i.rb +24 -0
  50. data/test/tc_zerodivisionexceptions.rb +17 -0
  51. data/test/test-12.rb +14 -0
  52. data/test/test-19.rb +13 -0
  53. data/test/test-20.rb +29 -0
  54. data/test/test-21.rb +37 -0
  55. data/test/test-22.rb +12 -0
  56. data/test/test-23.rb +11 -0
  57. data/test/test_helper.rb +8 -0
  58. data/test/unit_tests.rb +39 -0
  59. metadata +115 -0
@@ -0,0 +1,144 @@
1
+ #ifndef _GMPF_H_
2
+ #define _GMPF_H_
3
+
4
+ /*
5
+ * gmpf.h
6
+ *
7
+ * This file contains GMP::F stuff.
8
+ */
9
+
10
+ #include <ruby_gmp.h>
11
+
12
+ #ifdef MPFR
13
+ #define MPFR_SINGLE_FUNCTION(name) \
14
+ static VALUE r_gmpfr_##name(VALUE self) \
15
+ { \
16
+ MP_FLOAT *self_val, *res_val; \
17
+ unsigned long prec; \
18
+ VALUE res; \
19
+ \
20
+ mpf_get_struct_prec(self, self_val, prec); \
21
+ mpf_make_struct_init(res, res_val, prec); \
22
+ mpfr_##name(res_val, self_val, __gmp_default_rounding_mode); \
23
+ \
24
+ return res; \
25
+ }
26
+
27
+ MPFR_SINGLE_FUNCTION(log)
28
+ MPFR_SINGLE_FUNCTION(exp)
29
+ MPFR_SINGLE_FUNCTION(sqrt)
30
+ MPFR_SINGLE_FUNCTION(cos)
31
+ MPFR_SINGLE_FUNCTION(sin)
32
+ MPFR_SINGLE_FUNCTION(tan)
33
+ MPFR_SINGLE_FUNCTION(acos)
34
+ MPFR_SINGLE_FUNCTION(asin)
35
+ MPFR_SINGLE_FUNCTION(atan)
36
+ MPFR_SINGLE_FUNCTION(cosh)
37
+ MPFR_SINGLE_FUNCTION(sinh)
38
+ MPFR_SINGLE_FUNCTION(tanh)
39
+ MPFR_SINGLE_FUNCTION(acosh)
40
+ MPFR_SINGLE_FUNCTION(asinh)
41
+ MPFR_SINGLE_FUNCTION(atanh)
42
+ MPFR_SINGLE_FUNCTION(log1p)
43
+ MPFR_SINGLE_FUNCTION(expm1)
44
+ MPFR_SINGLE_FUNCTION(log2)
45
+ MPFR_SINGLE_FUNCTION(log10)
46
+
47
+ static VALUE r_gmpfr_nan_p(VALUE self)
48
+ {
49
+ MP_FLOAT *self_val;
50
+
51
+ mpf_get_struct(self, self_val);
52
+ if (mpfr_nan_p(self_val)) {
53
+ return Qtrue;
54
+ }
55
+ else {
56
+ return Qfalse;
57
+ }
58
+ }
59
+
60
+ static VALUE r_gmpfr_inf_p(VALUE self)
61
+ {
62
+ MP_FLOAT *self_val;
63
+
64
+ mpf_get_struct(self, self_val);
65
+ if (mpfr_inf_p(self_val)) {
66
+ return Qtrue;
67
+ }
68
+ else {
69
+ return Qfalse;
70
+ }
71
+ }
72
+
73
+ static VALUE r_gmpfr_fin_p(VALUE self)
74
+ {
75
+ if (r_gmpfr_inf_p(self)) {
76
+ return Qfalse;
77
+ }
78
+ else {
79
+ return Qtrue;
80
+ }
81
+ }
82
+
83
+ static VALUE r_gmpfr_number_p(VALUE self)
84
+ {
85
+ MP_FLOAT *self_val;
86
+
87
+ mpf_get_struct(self, self_val);
88
+ if (mpfr_number_p(self_val)) {
89
+ return Qtrue;
90
+ }
91
+ else {
92
+ return Qfalse;
93
+ }
94
+ }
95
+
96
+ static VALUE r_gmpfr_pow(VALUE self, VALUE arg)
97
+ {
98
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
99
+ MP_RAT *arg_val_q;
100
+ MP_INT *arg_val_z;
101
+ unsigned long prec;
102
+ VALUE res;
103
+
104
+ mpf_get_struct_prec(self, self_val, prec);
105
+
106
+ if (GMPF_P(arg)) {
107
+ mpf_get_struct(arg, arg_val_f);
108
+ prec_max(prec, arg_val_f);
109
+ mpf_make_struct_init(res, res_val, prec);
110
+ mpfr_pow(res_val, self_val, arg_val_f, __gmp_default_rounding_mode);
111
+ } else {
112
+ mpf_make_struct_init(res, res_val, prec);
113
+
114
+ if (GMPZ_P(arg)) {
115
+ mpz_get_struct(arg, arg_val_z);
116
+ mpf_set_z(res_val, arg_val_z);
117
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
118
+ } else if (GMPQ_P(arg)) {
119
+ mpq_get_struct(arg, arg_val_q);
120
+ mpf_set_q(res_val, arg_val_q);
121
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
122
+ } else if (FLOAT_P(arg)) {
123
+ mpf_set_d(res_val, FLT2DBL(arg));
124
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
125
+ } else if (FIXNUM_P(arg)) {
126
+ mpfr_pow_si(res_val, self_val, FIX2INT(arg), __gmp_default_rounding_mode);
127
+ } else if (BIGNUM_P(arg)) {
128
+ mpz_temp_from_bignum(arg_val_z, arg);
129
+ mpf_set_z(res_val, arg_val_z);
130
+ mpz_temp_free(arg_val_z);
131
+ mpfr_pow(res_val, self_val, res_val, __gmp_default_rounding_mode);
132
+ } else {
133
+ typeerror(ZQFXBD);
134
+ }
135
+
136
+ }
137
+
138
+ return res;
139
+ }
140
+
141
+ #endif
142
+
143
+
144
+ #endif
@@ -0,0 +1,780 @@
1
+ #include <gmpz.h>
2
+ #include <gmpq.h>
3
+ #include <gmpf.h>
4
+
5
+ /*
6
+ * Document-class: GMP::Q
7
+ *
8
+ * GMP Multiple Precision Rational Number.
9
+ *
10
+ * Instances of this class can store variables of the type mpq_t. This class
11
+ * also contains many methods that act as the functions for mpq_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_gmpq_to_d mpq_get_d
19
+ * to_s r_gmpq_to_s ?
20
+ * add r_gmpq_add mpq_add
21
+ * sub r_gmpq_sub mpq_sub
22
+ * mul r_gmpq_mul mpq_mul
23
+ * div r_gmpq_div mpq_div
24
+ * -@ r_gmpq_neg mpq_neg
25
+ * neg r_gmpq_neg mpq_neg
26
+ * neg! r_gmpq_neg_self mpq_neg
27
+ * abs r_gmpq_abs mpq_abs
28
+ * abs! r_gmpq_abs_self mpq_abs
29
+ */
30
+
31
+ /**********************************************************************
32
+ * Macros *
33
+ **********************************************************************/
34
+
35
+ #define DEFUN_RAT_CMP(name,CMP_OP) \
36
+ static VALUE r_gmpq_cmp_##name(VALUE self, VALUE arg) \
37
+ { \
38
+ MP_RAT *self_val; \
39
+ mpq_get_struct(self,self_val); \
40
+ return (mpq_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
41
+ }
42
+
43
+ #define DEFUN_RAT2INT(fname,mpz_fname) \
44
+ static VALUE r_gmpq_##fname(VALUE self) \
45
+ { \
46
+ MP_RAT *self_val; \
47
+ MP_INT *res_val; \
48
+ VALUE res; \
49
+ \
50
+ mpq_get_struct(self, self_val); \
51
+ mpz_make_struct_init(res, res_val) \
52
+ mpz_fname(res_val, mpq_numref(self_val), mpq_denref(self_val)); \
53
+ return res; \
54
+ }
55
+
56
+
57
+ /**********************************************************************
58
+ * Initializing Rationals *
59
+ **********************************************************************/
60
+
61
+ /*
62
+ * call-seq:
63
+ * GMP::Q.new(arg)
64
+ *
65
+ * Creates a new GMP::Q rational, with arg as its value, converting where
66
+ * necessary.
67
+ */
68
+ VALUE r_gmpqsg_new(int argc, VALUE *argv, VALUE klass)
69
+ {
70
+ MP_RAT *res_val;
71
+ VALUE res;
72
+
73
+ (void)klass;
74
+
75
+ if (argc > 2)
76
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0, 1 or 2)", argc);
77
+
78
+ mpq_make_struct (res, res_val);
79
+ mpq_init (res_val);
80
+ rb_obj_call_init(res, argc, argv);
81
+
82
+ return res;
83
+ }
84
+
85
+ /*
86
+ * call-seq:
87
+ * GMP::Q(arg)
88
+ *
89
+ * A convenience method for +GMP::Q.new(arg)+.
90
+ */
91
+ VALUE r_gmpmod_q(int argc, VALUE *argv, VALUE module)
92
+ {
93
+ (void)module;
94
+ return r_gmpqsg_new(argc, argv, cGMP_Q);
95
+ }
96
+
97
+ /*
98
+ * call-seq:
99
+ * rat1.swap rat2
100
+ *
101
+ * Efficiently swaps the contents of +rat1+ with +rat2+.
102
+ */
103
+ VALUE r_gmpq_swap(VALUE self, VALUE arg)
104
+ {
105
+ MP_RAT *self_val, *arg_val;
106
+
107
+ if (!GMPQ_P(arg)) {
108
+ rb_raise(rb_eTypeError, "Can't swap GMP::Q with object of other class");
109
+ }
110
+
111
+ mpq_get_struct(self, self_val);
112
+ mpq_get_struct(arg, arg_val);
113
+ mpq_swap(self_val,arg_val);
114
+
115
+ return Qnil;
116
+ }
117
+
118
+
119
+ /**********************************************************************
120
+ * Rational Conversions *
121
+ **********************************************************************/
122
+
123
+ /*
124
+ * call-seq:
125
+ * rational.to_d
126
+ *
127
+ * Returns +rational+ as an Float if +rational+ fits in a Float.
128
+ *
129
+ * Otherwise returns the least significant part of +rational+, with the same
130
+ * sign as +rational+.
131
+ *
132
+ * If the exponent from the conversion is too big or too small to fit a double
133
+ * then the result is system dependent. For too big an infinity is returned
134
+ * when available. For too small 0.0 is normally returned. Hardware overflow,
135
+ * underflow and denorm traps may or may not occur.
136
+ */
137
+ VALUE r_gmpq_to_d(VALUE self)
138
+ {
139
+ MP_RAT *self_val;
140
+ mpq_get_struct(self, self_val);
141
+
142
+ return rb_float_new(mpq_get_d(self_val));
143
+ }
144
+
145
+ /*
146
+ * Document-method: to_s
147
+ *
148
+ * call-seq:
149
+ * rational.to_s
150
+ *
151
+ * Returns the decimal representation of +rational+, as a Ruby string.
152
+ */
153
+ VALUE r_gmpq_to_s(VALUE self)
154
+ {
155
+ MP_RAT *self_val;
156
+ MP_INT *self_val_num, *self_val_den;
157
+ char *str;
158
+ VALUE res;
159
+ int sizeinbase;
160
+ int offset;
161
+
162
+ Data_Get_Struct(self, MP_RAT, self_val);
163
+
164
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) == 0) {
165
+ str = mpz_get_str(NULL, 10, mpq_numref (self_val));
166
+ res = rb_str_new2(str);
167
+ free (str);
168
+ return res;
169
+ }
170
+
171
+ self_val_num = mpq_numref(self_val);
172
+ self_val_den = mpq_denref(self_val);
173
+
174
+ sizeinbase = mpz_sizeinbase (self_val_num, 10) + mpz_sizeinbase (self_val_den, 10) + 3;
175
+ str = malloc (sizeinbase);
176
+
177
+ mpz_get_str (str, 10, self_val_num);
178
+ offset = strlen (str);
179
+ str[offset] = '/';
180
+ mpz_get_str (str + offset + 1, 10, self_val_den);
181
+ res = rb_str_new2(str);
182
+ free (str);
183
+
184
+ return res;
185
+ }
186
+
187
+
188
+ /**********************************************************************
189
+ * Rational Arithmetic *
190
+ **********************************************************************/
191
+
192
+ /*
193
+ * call-seq:
194
+ * rat1 + rat2
195
+ *
196
+ * Adds +rat1+ to +rat2+. +rat2+ can be
197
+ * * GMP::Z
198
+ * * Fixnum
199
+ * * GMP::Q
200
+ * * GMP::F
201
+ * * Bignum
202
+ */
203
+ VALUE r_gmpq_add(VALUE self, VALUE arg)
204
+ {
205
+ MP_RAT *self_val, *arg_val_q, *res_val;
206
+ MP_INT *arg_val_z, *res_val_num;
207
+ VALUE res;
208
+
209
+ mpq_get_struct(self, self_val);
210
+ mpq_make_struct_init(res, res_val);
211
+
212
+ if (GMPQ_P(arg)) {
213
+ mpq_get_struct(arg,arg_val_q);
214
+ mpq_add(res_val, self_val, arg_val_q);
215
+ } else if (GMPZ_P(arg)) {
216
+ res_val_num = mpq_numref(res_val);
217
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
218
+ mpz_get_struct(arg, arg_val_z);
219
+ mpz_mul(res_val_num, mpq_denref(self_val), arg_val_z);
220
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
221
+ } else if (FIXNUM_P(arg)) {
222
+ res_val_num = mpq_numref(res_val);
223
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
224
+ mpz_mul_si(res_val_num, mpq_denref(self_val), FIX2INT(arg));
225
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
226
+ } else if (GMPF_P(arg)) {
227
+ return r_gmpf_add(arg,self);
228
+ } else if (BIGNUM_P(arg)) {
229
+ res_val_num = mpq_numref(res_val);
230
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
231
+ mpz_set_bignum(res_val_num, arg);
232
+ mpz_mul(res_val_num, res_val_num, mpq_denref(self_val));
233
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
234
+ } else {
235
+ typeerror(ZQFXB);
236
+ }
237
+ return res;
238
+ }
239
+
240
+ /*
241
+ * call-seq:
242
+ * rat1 - rat2
243
+ *
244
+ * Subtracts +rat2+ from +rat1+. +rat2+ can be
245
+ * * GMP::Z
246
+ * * Fixnum
247
+ * * GMP::Q
248
+ * * GMP::F
249
+ * * Bignum
250
+ */
251
+ VALUE r_gmpq_sub(VALUE self, VALUE arg)
252
+ {
253
+ MP_RAT *self_val, *arg_val_q, *res_val;
254
+ MP_INT *arg_val_z, *res_val_num;
255
+ MP_FLOAT *arg_val_f, *res_val_f;
256
+ VALUE res;
257
+ unsigned int prec;
258
+
259
+ mpq_get_struct(self, self_val);
260
+ mpq_make_struct_init(res, res_val);
261
+
262
+ if (GMPQ_P(arg)) {
263
+ mpq_get_struct(arg,arg_val_q);
264
+ mpq_sub (res_val, self_val, arg_val_q);
265
+ } else if (GMPZ_P(arg)) {
266
+ res_val_num = mpq_numref(res_val);
267
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
268
+ mpz_get_struct(arg, arg_val_z);
269
+ mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
270
+ mpz_neg (res_val_num, res_val_num);
271
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
272
+ } else if (FIXNUM_P(arg)) {
273
+ res_val_num = mpq_numref(res_val);
274
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
275
+ mpz_mul_si (res_val_num, mpq_denref(self_val), -FIX2INT(arg));
276
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
277
+ } else if (GMPF_P(arg)) {
278
+ mpf_get_struct_prec (arg, arg_val_f, prec);
279
+ mpf_make_struct_init(res, res_val_f, prec);
280
+ mpf_set_q (res_val_f, self_val);
281
+ mpf_sub (res_val_f, res_val_f, arg_val_f);
282
+ } else if (BIGNUM_P(arg)) {
283
+ res_val_num = mpq_numref(res_val);
284
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
285
+ mpz_set_bignum (res_val_num, arg);
286
+ mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
287
+ mpz_neg (res_val_num, res_val_num);
288
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
289
+ } else {
290
+ typeerror (ZQFXB);
291
+ }
292
+ return res;
293
+ }
294
+
295
+ /*
296
+ * call-seq:
297
+ * rat1 * rat2
298
+ *
299
+ * Multiplies +rat1+ with +rat2+. +rat2+ can be
300
+ * * GMP::Z
301
+ * * Fixnum
302
+ * * GMP::Q
303
+ * * GMP::F
304
+ * * Bignum
305
+ */
306
+ VALUE r_gmpq_mul(VALUE self, VALUE arg)
307
+ {
308
+ MP_RAT *self_val, *arg_val_q, *res_val;
309
+ MP_INT *arg_val_z, *tmp_z;
310
+ VALUE res;
311
+ #if GMP >= 4
312
+ unsigned long tmp_ui;
313
+ #endif
314
+
315
+ mpq_get_struct(self, self_val);
316
+ mpq_make_struct_init(res, res_val);
317
+
318
+ if (GMPQ_P(arg)) {
319
+ mpq_get_struct(arg,arg_val_q);
320
+ mpq_mul(res_val, self_val, arg_val_q);
321
+ } else if (GMPZ_P(arg)) {
322
+ mpz_get_struct(arg,arg_val_z);
323
+ mpz_temp_init(tmp_z);
324
+ mpz_gcd(tmp_z, mpq_denref(self_val), arg_val_z);
325
+ mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
326
+ mpz_divexact(mpq_numref(res_val), arg_val_z, tmp_z);
327
+ mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
328
+ mpz_temp_free(tmp_z);
329
+ } else if (FIXNUM_P(arg)) {
330
+ #if GMP >= 4
331
+ if (FIX2INT(arg) > 0) {
332
+ tmp_ui = mpz_gcd_ui(0, mpq_denref(self_val), FIX2INT(arg));
333
+ } else if (FIX2INT(arg) < 0) {
334
+ tmp_ui = mpz_gcd_ui(0, mpq_denref(self_val), -FIX2INT(arg));
335
+ } else {
336
+ mpz_set_ui(mpq_numref(res_val), 0);
337
+ mpz_set_ui(mpq_denref(res_val), 1);
338
+ return res;
339
+ }
340
+ mpz_divexact_ui(mpq_denref(res_val), mpq_denref(self_val), tmp_ui);
341
+ mpz_mul_ui(mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg)/tmp_ui);
342
+ #else
343
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
344
+ mpz_mul_si(mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg));
345
+ mpq_canonicalize(res_val);
346
+ #endif
347
+ } else if (GMPF_P(arg)) {
348
+ return r_gmpf_mul(arg, self);
349
+ } else if (BIGNUM_P(arg)) {
350
+ mpz_temp_alloc(tmp_z);
351
+ mpz_set_bignum(tmp_z, arg);
352
+ mpz_gcd(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
353
+ mpz_divexact(mpq_numref(res_val), tmp_z, mpq_denref(res_val));
354
+ mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), mpq_denref(res_val));
355
+ mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
356
+ mpz_temp_free(tmp_z);
357
+ } else {
358
+ typeerror(ZQFXB);
359
+ }
360
+ return res;
361
+ }
362
+
363
+ /*
364
+ * call-seq:
365
+ * rat1 / rat2
366
+ *
367
+ * Divides +rat1+ by +rat2+. +rat2+ can be
368
+ * * GMP::Z
369
+ * * Fixnum
370
+ * * GMP::Q
371
+ * * GMP::F
372
+ * * Bignum
373
+ */
374
+ VALUE r_gmpq_div(VALUE self, VALUE arg)
375
+ {
376
+ MP_RAT *self_val, *arg_val_q, *res_val;
377
+ MP_INT *arg_val_z, *tmp_z;
378
+ MP_FLOAT *arg_val_f, *res_val_f;
379
+ VALUE res;
380
+ unsigned long tmp_ui, prec;
381
+
382
+ mpq_get_struct(self, self_val);
383
+ mpq_make_struct_init(res, res_val);
384
+
385
+ if (GMPQ_P(arg)) {
386
+ mpq_get_struct(arg,arg_val_q);
387
+ if (mpz_sgn(mpq_numref(arg_val_q)) == 0)
388
+ rb_raise(rb_eZeroDivError, "divided by 0");
389
+ mpq_div(res_val, self_val, arg_val_q);
390
+ } else if (GMPZ_P(arg)) {
391
+ mpz_get_struct(arg,arg_val_z);
392
+ mpz_temp_init(tmp_z);
393
+ mpz_gcd(tmp_z, mpq_numref(self_val), arg_val_z);
394
+ mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
395
+ mpz_divexact(mpq_denref(res_val), arg_val_z, tmp_z);
396
+ mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
397
+ mpz_temp_free(tmp_z);
398
+ } else if (FIXNUM_P(arg)) {
399
+ if (FIX2INT(arg) == 0)
400
+ rb_raise(rb_eZeroDivError, "divided by 0");
401
+ if (FIX2INT(arg) > 0) {
402
+ tmp_ui = mpz_gcd_ui(0, mpq_numref(self_val), FIX2INT(arg));
403
+ } else {
404
+ tmp_ui = mpz_gcd_ui(0, mpq_numref(self_val), -FIX2INT(arg));
405
+ }
406
+ mpz_divexact_ui(mpq_numref(res_val), mpq_numref(self_val), tmp_ui);
407
+ mpz_mul_ui(mpq_denref(res_val), mpq_denref(self_val), FIX2INT(arg)/tmp_ui);
408
+ } else if (GMPF_P(arg)) {
409
+ mpf_get_struct_prec(arg, arg_val_f, prec);
410
+ mpf_make_struct_init(res, res_val_f, prec);
411
+ mpf_set_q(res_val_f, self_val);
412
+ mpf_div(res_val_f, res_val_f, arg_val_f);
413
+ } else if (BIGNUM_P(arg)) {
414
+ mpz_temp_alloc(tmp_z);
415
+ mpz_set_bignum(tmp_z, arg);
416
+ mpz_gcd(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
417
+ mpz_divexact(mpq_denref(res_val), tmp_z, mpq_numref(res_val));
418
+ mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), mpq_numref(res_val));
419
+ mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
420
+ mpz_temp_free(tmp_z);
421
+ } else {
422
+ typeerror(ZQFXB);
423
+ }
424
+ return res;
425
+ }
426
+
427
+ DEFUN_RAT2INT(floor,mpz_fdiv_q)
428
+ DEFUN_RAT2INT(trunc,mpz_tdiv_q)
429
+ DEFUN_RAT2INT(ceil,mpz_cdiv_q)
430
+
431
+ /*
432
+ * Document-method: neg
433
+ *
434
+ * call-seq:
435
+ * -rational
436
+ * rational.neg
437
+ *
438
+ * From the GMP Manual:
439
+ *
440
+ * Returns -+rational+.
441
+ */
442
+ VALUE r_gmpq_neg(VALUE self)
443
+ {
444
+ MP_RAT *self_val, *res_val;
445
+ VALUE res;
446
+ mpq_get_struct(self, self_val);
447
+ mpq_make_struct_init(res, res_val);
448
+ mpq_neg (res_val, self_val);
449
+ return res;
450
+ }
451
+
452
+ /*
453
+ * Document-method: neg!
454
+ *
455
+ * call-seq:
456
+ * rational.neg!
457
+ *
458
+ * From the GMP Manual:
459
+ *
460
+ * Sets +rational+ to -+rational+.
461
+ */
462
+ VALUE r_gmpq_neg_self(VALUE self)
463
+ {
464
+ MP_RAT *self_val;
465
+ mpq_get_struct(self, self_val);
466
+ mpz_neg (mpq_numref(self_val), mpq_numref(self_val));
467
+ return Qnil;
468
+ }
469
+
470
+ /*
471
+ * Document-method: abs
472
+ *
473
+ * call-seq:
474
+ * rational.abs
475
+ *
476
+ * From the GMP Manual:
477
+ *
478
+ * Returns the absolute value of +rational+.
479
+ */
480
+ VALUE r_gmpq_abs(VALUE self)
481
+ {
482
+ MP_RAT *self_val, *res_val;
483
+ VALUE res;
484
+ mpq_get_struct(self, self_val);
485
+ mpq_make_struct_init(res, res_val);
486
+ mpz_abs (mpq_numref(res_val), mpq_numref(self_val));
487
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
488
+
489
+ return res;
490
+ }
491
+
492
+ /*
493
+ * Document-method: abs!
494
+ *
495
+ * call-seq:
496
+ * rational.abs!
497
+ *
498
+ * From the GMP Manual:
499
+ *
500
+ * Sets +rational+ to its absolute value.
501
+ */
502
+ VALUE r_gmpq_abs_self(VALUE self)
503
+ {
504
+ MP_RAT *self_val;
505
+ mpq_get_struct(self, self_val);
506
+ mpz_abs (mpq_numref(self_val), mpq_numref(self_val));
507
+ return Qnil;
508
+ }
509
+
510
+ VALUE r_gmpq_inv(VALUE self)
511
+ {
512
+ MP_RAT *self_val, *res_val;
513
+ VALUE res;
514
+
515
+ mpq_get_struct(self, self_val);
516
+ if (mpq_sgn(self_val) == 0)
517
+ rb_raise (rb_eZeroDivError, "divided by 0");
518
+ mpq_make_struct_init(res, res_val);
519
+ mpq_inv (res_val, self_val);
520
+
521
+ return res;
522
+ }
523
+
524
+ VALUE r_gmpq_inv_self(VALUE self)
525
+ {
526
+ MP_RAT *self_val;
527
+ mpq_get_struct(self, self_val);
528
+ if (mpq_sgn(self_val) == 0)
529
+ rb_raise (rb_eZeroDivError, "divided by 0");
530
+ mpq_inv (self_val, self_val);
531
+ return Qnil;
532
+ }
533
+
534
+
535
+ /**********************************************************************
536
+ * Comparing Rationals *
537
+ **********************************************************************/
538
+
539
+ int mpq_cmp_value(MP_RAT *OP, VALUE arg)
540
+ {
541
+ MP_INT *arg_val_z, *tmp_z;
542
+ MP_RAT *arg_val_q;
543
+ int res;
544
+
545
+ if (GMPQ_P(arg)) {
546
+ mpq_get_struct(arg,arg_val_q);
547
+ return mpq_cmp(OP,arg_val_q);
548
+ } else if (GMPZ_P(arg)) {
549
+ mpz_get_struct(arg, arg_val_z);
550
+ mpz_temp_alloc(tmp_z);
551
+ mpz_init(tmp_z);
552
+ mpz_mul(tmp_z, mpq_denref(OP), arg_val_z);
553
+ res = mpz_cmp(mpq_numref(OP),tmp_z);
554
+ mpz_temp_free(tmp_z);
555
+ return res;
556
+ } else if (FIXNUM_P(arg)) {
557
+ mpz_temp_alloc(tmp_z);
558
+ mpz_init(tmp_z);
559
+ mpz_mul_si(tmp_z, mpq_denref(OP), FIX2INT(arg));
560
+ res = mpz_cmp(mpq_numref(OP), tmp_z);
561
+ mpz_temp_free(tmp_z);
562
+ return res;
563
+ } else if (GMPF_P(arg)) {
564
+ not_yet;
565
+ } else if (BIGNUM_P(arg)) {
566
+ mpz_temp_from_bignum(tmp_z, arg);
567
+ mpz_mul(tmp_z, tmp_z, mpq_denref(OP));
568
+ res = mpz_cmp(mpq_numref(OP), tmp_z);
569
+ mpz_temp_free(tmp_z);
570
+ return res;
571
+ } else {
572
+ typeerror(ZQFXB);
573
+ }
574
+ }
575
+
576
+ VALUE r_gmpq_eq(VALUE self, VALUE arg)
577
+ {
578
+ MP_RAT *self_val, *arg_val_q;
579
+ MP_INT *arg_val_z;
580
+
581
+ mpq_get_struct(self,self_val);
582
+ if (GMPQ_P(arg)) {
583
+ mpq_get_struct(arg,arg_val_q);
584
+ return mpq_equal(self_val,arg_val_q)?Qtrue:Qfalse;
585
+ } else if (GMPZ_P(arg)) {
586
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
587
+ return Qfalse;
588
+ mpz_get_struct (arg, arg_val_z);
589
+ return (mpz_cmp(mpq_numref(self_val),arg_val_z)==0)?Qtrue:Qfalse;
590
+ } else if (FIXNUM_P(arg)) {
591
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
592
+ return Qfalse;
593
+ return (mpz_cmp_ui(mpq_numref(self_val),FIX2INT(arg))==0)?Qtrue:Qfalse;
594
+ } else if (BIGNUM_P(arg)) {
595
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
596
+ return Qfalse;
597
+ mpz_temp_from_bignum(arg_val_z, arg);
598
+ if (mpz_cmp (mpq_numref(self_val),arg_val_z) == 0) {
599
+ mpz_temp_free (arg_val_z);
600
+ return Qtrue;
601
+ } else {
602
+ mpz_temp_free (arg_val_z);
603
+ return Qfalse;
604
+ }
605
+ } else {
606
+ return Qfalse;
607
+ }
608
+ }
609
+
610
+ VALUE r_gmpq_cmp(VALUE self, VALUE arg)
611
+ {
612
+ MP_RAT *self_val;
613
+ int res;
614
+ mpq_get_struct (self,self_val);
615
+ res = mpq_cmp_value(self_val, arg);
616
+ if (res > 0)
617
+ return INT2FIX(1);
618
+ else if (res == 0)
619
+ return INT2FIX(0);
620
+ else
621
+ return INT2FIX(-1);
622
+ }
623
+
624
+ DEFUN_RAT_CMP(lt,<)
625
+ DEFUN_RAT_CMP(le,<=)
626
+ DEFUN_RAT_CMP(gt,>)
627
+ DEFUN_RAT_CMP(ge,>=)
628
+
629
+ static VALUE r_gmpq_cmpabs(VALUE self, VALUE arg)
630
+ {
631
+ MP_RAT *arg_val_q, *self_val;
632
+ MP_INT *arg_val_z, *tmp_z;
633
+ int res;
634
+ int sgnt;
635
+
636
+ mpq_get_struct(self, self_val);
637
+
638
+ if (GMPQ_P(arg)) {
639
+ mpq_get_struct(arg,arg_val_q);
640
+ sgnt = 3*mpz_sgn(mpq_numref(self_val)) + mpz_sgn(mpq_numref(arg_val_q));
641
+ switch (sgnt)
642
+ {
643
+ default:
644
+ case 0:
645
+ return INT2FIX(0);
646
+ case 1:
647
+ case -1:
648
+ return INT2FIX(-1);
649
+ case 2:
650
+ tmp_z = mpq_numref(arg_val_q);
651
+ mpz_neg (tmp_z, tmp_z);
652
+ res = mpq_cmp (self_val, arg_val_q);
653
+ mpz_neg (tmp_z, tmp_z);
654
+ return res;
655
+ case -2:
656
+ tmp_z = mpq_numref(arg_val_q);
657
+ mpz_neg (tmp_z, tmp_z);
658
+ res = mpq_cmp (self_val, arg_val_q);
659
+ mpz_neg (tmp_z, tmp_z);
660
+ return res;
661
+ case 3:
662
+ case -3:
663
+ return INT2FIX(1);
664
+ case 4:
665
+ case -4:
666
+ return INT2FIX(mpq_cmp (self_val,arg_val_q));
667
+ }
668
+ } else if (GMPZ_P(arg)) {
669
+ mpz_get_struct(arg, arg_val_z);
670
+ mpz_temp_alloc (tmp_z);
671
+ mpz_init (tmp_z);
672
+ mpz_mul (tmp_z, mpq_denref(self_val), arg_val_z);
673
+ res = mpz_cmpabs (mpq_numref(self_val),tmp_z);
674
+ mpz_temp_free (tmp_z);
675
+ return res;
676
+ } else if (FIXNUM_P(arg)) {
677
+ mpz_temp_alloc (tmp_z);
678
+ mpz_init (tmp_z);
679
+ mpz_mul_si (tmp_z, mpq_denref(self_val), FIX2INT(arg));
680
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
681
+ mpz_temp_free (tmp_z);
682
+ return res;
683
+ } else if (GMPF_P(arg)) {
684
+ not_yet;
685
+ } else if (BIGNUM_P(arg)) {
686
+ mpz_temp_from_bignum (tmp_z, arg);
687
+ mpz_mul (tmp_z, tmp_z, mpq_denref(self_val));
688
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
689
+ mpz_temp_free (tmp_z);
690
+ return res;
691
+ } else {
692
+ typeerror (ZQFXB);
693
+ }
694
+ }
695
+
696
+ /*
697
+ * call-seq:
698
+ * rational.sgn
699
+ *
700
+ * From the GMP Manual:
701
+ *
702
+ * Returns +1 if +rational+ > 0, 0 if +rational+ == 0, and -1 if +rational+ < 0.
703
+ */
704
+ VALUE r_gmpq_sgn(VALUE self)
705
+ {
706
+ MP_RAT *self_val;
707
+ mpq_get_struct(self, self_val);
708
+ return INT2FIX(mpq_sgn(self_val));
709
+ }
710
+
711
+ /**********************************************************************
712
+ * Applying Integer Functions *
713
+ **********************************************************************/
714
+
715
+ VALUE r_gmpq_num(VALUE self)
716
+ {
717
+ MP_RAT *self_val;
718
+ MP_INT *res_val;
719
+ VALUE res;
720
+ mpq_get_struct(self,self_val);
721
+ mpz_make_struct(res, res_val);
722
+ mpz_init_set (res_val, mpq_numref (self_val));
723
+ return res;
724
+ }
725
+
726
+ VALUE r_gmpq_den(VALUE self)
727
+ {
728
+ MP_RAT *self_val;
729
+ MP_INT *res_val;
730
+ VALUE res;
731
+ mpq_get_struct(self,self_val);
732
+ mpz_make_struct(res, res_val);
733
+ mpz_init_set (res_val, mpq_denref (self_val));
734
+ return res;
735
+ }
736
+
737
+
738
+ void init_gmpq()
739
+ {
740
+ mGMP = rb_define_module("GMP");
741
+ rb_define_module_function(mGMP, "Q", r_gmpmod_q, -1);
742
+
743
+ cGMP_Q = rb_define_class_under (mGMP, "Q", rb_cNumeric);
744
+
745
+ // Initializing Rationals
746
+ rb_define_singleton_method(cGMP_Q, "new", r_gmpqsg_new, -1);
747
+ rb_define_method(cGMP_Q, "swap", r_gmpq_swap, 1);
748
+
749
+ // Rational Conversions
750
+ rb_define_method(cGMP_Q, "to_d", r_gmpq_to_d, 0);
751
+ rb_define_alias(cGMP_Q, "to_f", "to_d");
752
+ rb_define_method(cGMP_Q, "to_s", r_gmpq_to_s, 0);
753
+
754
+ // Rational Arithmetic
755
+ rb_define_method(cGMP_Q, "+", r_gmpq_add, 1);
756
+ rb_define_method(cGMP_Q, "-", r_gmpq_sub, 1);
757
+ rb_define_method(cGMP_Q, "*", r_gmpq_mul, 1);
758
+ rb_define_method(cGMP_Q, "/", r_gmpq_div, 1);
759
+ rb_define_method(cGMP_Q, "-@", r_gmpq_neg, 0);
760
+ rb_define_method(cGMP_Q, "neg!", r_gmpq_neg_self, 0);
761
+ rb_define_method(cGMP_Q, "inv", r_gmpq_inv, 0);
762
+ rb_define_method(cGMP_Q, "inv!", r_gmpq_inv_self, 0);
763
+ rb_define_method(cGMP_Q, "abs", r_gmpq_abs, 0);
764
+ rb_define_method(cGMP_Q, "abs!", r_gmpq_abs_self, 0);
765
+
766
+ // Comparing Rationals
767
+ rb_define_method(cGMP_Q, "<=>", r_gmpq_cmp, 1);
768
+ rb_define_method(cGMP_Q, ">", r_gmpq_cmp_gt, 1);
769
+ rb_define_method(cGMP_Q, ">=", r_gmpq_cmp_ge, 1);
770
+ rb_define_method(cGMP_Q, "<", r_gmpq_cmp_lt, 1);
771
+ rb_define_method(cGMP_Q, "<=", r_gmpq_cmp_le, 1);
772
+ rb_define_method(cGMP_Q, "==", r_gmpq_eq, 1);
773
+ rb_define_method(cGMP_Q, "sgn", r_gmpq_sgn, 0);
774
+ rb_define_method(cGMP_Q, "cmpabs", r_gmpq_cmpabs, 1);
775
+
776
+ // _unsorted_
777
+ rb_define_method(cGMP_Q, "floor", r_gmpq_floor, 0);
778
+ rb_define_method(cGMP_Q, "ceil", r_gmpq_ceil, 0);
779
+ rb_define_method(cGMP_Q, "trunc", r_gmpq_trunc, 0);
780
+ }