srawlins-gmp 0.1.5 → 0.1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/CHANGELOG +13 -1
  2. data/ext/gmpf.c +423 -0
  3. data/ext/gmpq.c +679 -0
  4. data/ext/gmpz.c +1598 -0
  5. data/ext/ruby_gmp.h +192 -0
  6. metadata +5 -1
data/CHANGELOG CHANGED
@@ -1,4 +1,16 @@
1
- 1.1.0:
1
+ 0.1.5:
2
+ * Merged in reorg changes: Files like gmpz.c allow for documenting the C
3
+ extension methods.
4
+ * A good portion of the documentation has been written, may not be included
5
+ yet, but can be generated with
6
+ rdoc README.rdoc ext/*.c ext/*.h
7
+
8
+ 0.1.4:
9
+ * Fixed a lot of gemspec problems
10
+ * Many more tests
11
+ * Tested on OS X 10.5.8
12
+
13
+ 0.1.1:
2
14
  * Attempting to revitalize through GitHub
3
15
  * no changes to code yet
4
16
  * modernizing files, eg with new ruby standards, towards a gem
@@ -0,0 +1,423 @@
1
+ #include <gmpz.h>
2
+ #include <gmpq.h>
3
+ #include <gmpf.h>
4
+
5
+ /*
6
+ * Document-class: GMP::F
7
+ *
8
+ * GMP Multiple Precision floating point numbers.
9
+ *
10
+ * Instances of this class can store variables of the type mpf_t. This class
11
+ * also contains many methods that act as the functions for mpf_t variables,
12
+ * as well as a few methods that attempt to make this library more Ruby-ish.
13
+ */
14
+
15
+ /**********************************************************************
16
+ * Macros *
17
+ **********************************************************************/
18
+
19
+ #define DEFUN_FLOAT2FLOAT(fname,mpf_fname) \
20
+ static VALUE r_gmpf_##fname(VALUE self) \
21
+ { \
22
+ MP_FLOAT *self_val, *res_val; \
23
+ VALUE res; \
24
+ mpf_get_struct(self, self_val); \
25
+ mpf_make_struct_init(res, res_val, mpf_get_prec(self_val)); \
26
+ mpf_fname(res_val, self_val); \
27
+ return res; \
28
+ } \
29
+ \
30
+ static VALUE r_gmpf_##fname##_self(VALUE self) \
31
+ { \
32
+ MP_FLOAT *self_val; \
33
+ mpf_get_struct(self, self_val); \
34
+ mpf_fname(self_val, self_val); \
35
+ return Qnil; \
36
+ }
37
+
38
+ #define DEFUN_FLOAT_CMP(name,CMP_OP) \
39
+ static VALUE r_gmpf_cmp_##name(VALUE self, VALUE arg) \
40
+ { \
41
+ MP_FLOAT *self_val; \
42
+ mpf_get_struct(self,self_val); \
43
+ return (mpf_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
44
+ }
45
+
46
+
47
+ /**********************************************************************
48
+ * Initializing, Assigning Floats *
49
+ **********************************************************************/
50
+
51
+
52
+ /**********************************************************************
53
+ * Converting Floats *
54
+ **********************************************************************/
55
+
56
+ VALUE r_gmpf_to_d(VALUE self)
57
+ {
58
+ MP_FLOAT *self_val;
59
+ mpf_get_struct (self, self_val);
60
+
61
+ return rb_float_new(mpf_get_d(self_val));
62
+ }
63
+
64
+ VALUE r_gmpf_to_s(VALUE self)
65
+ {
66
+ MP_FLOAT *self_val;
67
+ char *str, *str2;
68
+ VALUE res;
69
+ mp_exp_t exponent;
70
+
71
+ mpf_get_struct(self, self_val);
72
+
73
+ str = mpf_get_str(NULL, &exponent, 10, 0, self_val);
74
+ if ((strcmp (str, "NaN") == 0) ||
75
+ (strcmp (str, "Inf") == 0) ||
76
+ (strcmp (str, "-Inf") == 0))
77
+ {
78
+ res = rb_str_new2(str);
79
+ }
80
+ else
81
+ {
82
+ if (str[0] == '-')
83
+ __gmp_asprintf (&str2, "-0.%se%+ld", str+1, exponent);
84
+ else
85
+ __gmp_asprintf (&str2, "0.%se%+ld", str, exponent);
86
+ res = rb_str_new2(str2);
87
+ free (str2);
88
+ }
89
+ free (str);
90
+ return res;
91
+ }
92
+
93
+
94
+ /**********************************************************************
95
+ * Float Arithmetic *
96
+ **********************************************************************/
97
+
98
+ /*
99
+ * call-seq:
100
+ * float + other
101
+ *
102
+ * Returns the sum of +float+ and +other+. +other+ can be
103
+ * * GMP::Z
104
+ * * Fixnum
105
+ * * GMP::Q
106
+ * * GMP::F
107
+ * * Bignum
108
+ */
109
+ VALUE r_gmpf_add(VALUE self, VALUE arg)
110
+ {
111
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
112
+ MP_RAT *arg_val_q;
113
+ MP_INT *arg_val_z;
114
+ VALUE res;
115
+ unsigned long prec;
116
+
117
+ mpf_get_struct_prec (self, self_val, prec);
118
+
119
+ if (GMPF_P(arg)) {
120
+ mpf_get_struct (arg, arg_val_f);
121
+ prec_max(prec, arg_val_f);
122
+ mpf_make_struct_init(res, res_val, prec);
123
+ mpf_add(res_val, self_val, arg_val_f);
124
+ } else if (GMPQ_P(arg)) {
125
+ mpq_get_struct (arg, arg_val_q);
126
+ mpf_make_struct_init(res, res_val, prec);
127
+ mpf_set_q (res_val, arg_val_q);
128
+ mpf_add (res_val, res_val, self_val);
129
+ } else if (GMPZ_P(arg)) {
130
+ mpz_get_struct (arg, arg_val_z);
131
+ mpf_make_struct_init(res, res_val, prec);
132
+ mpf_set_z (res_val, arg_val_z);
133
+ mpf_add (res_val, res_val, self_val);
134
+ } else if (FLOAT_P(arg)) {
135
+ mpf_make_struct_init(res, res_val, prec);
136
+ mpf_set_d (res_val, FLT2DBL(arg));
137
+ mpf_add (res_val, res_val, self_val);
138
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
139
+ mpf_make_struct_init(res, res_val, prec);
140
+ mpf_set_si (res_val, FIX2INT(arg));
141
+ mpf_add (res_val, res_val, self_val);
142
+ } else if (BIGNUM_P(arg)) {
143
+ mpz_temp_from_bignum(arg_val_z, arg);
144
+ mpf_make_struct_init(res, res_val, prec);
145
+ mpf_set_z (res_val, arg_val_z);
146
+ mpf_add (res_val, res_val, self_val);
147
+ mpz_temp_free(arg_val_z);
148
+ } else {
149
+ typeerror(ZQFXBD);
150
+ }
151
+
152
+ return res;
153
+ }
154
+
155
+ VALUE r_gmpf_sub(VALUE self, VALUE arg)
156
+ {
157
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
158
+ MP_RAT *arg_val_q;
159
+ MP_INT *arg_val_z;
160
+ VALUE res;
161
+ unsigned long prec;
162
+
163
+ mpf_get_struct_prec (self, self_val, prec);
164
+
165
+ if (GMPF_P(arg)) {
166
+ mpf_get_struct (arg, arg_val_f);
167
+ prec_max(prec, arg_val_f);
168
+ mpf_make_struct_init(res, res_val, prec);
169
+ mpf_sub(res_val, self_val, arg_val_f);
170
+ } else if (GMPQ_P(arg)) {
171
+ mpq_get_struct (arg, arg_val_q);
172
+ mpf_make_struct_init(res, res_val, prec);
173
+ mpf_set_q (res_val, arg_val_q);
174
+ mpf_sub (res_val, self_val, res_val);
175
+ } else if (GMPZ_P(arg)) {
176
+ mpz_get_struct (arg, arg_val_z);
177
+ mpf_make_struct_init(res, res_val, prec);
178
+ mpf_set_z (res_val, arg_val_z);
179
+ mpf_sub (res_val, self_val, res_val);
180
+ } else if (FLOAT_P(arg)) {
181
+ mpf_make_struct_init(res, res_val, prec);
182
+ mpf_set_d (res_val, FLT2DBL(arg));
183
+ mpf_sub (res_val, self_val, res_val);
184
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
185
+ mpf_make_struct_init(res, res_val, prec);
186
+ mpf_set_si (res_val, FIX2INT(arg));
187
+ mpf_sub (res_val, self_val, res_val);
188
+ } else if (BIGNUM_P(arg)) {
189
+ mpz_temp_from_bignum(arg_val_z, arg);
190
+ mpf_make_struct_init(res, res_val, prec);
191
+ mpf_set_z (res_val, arg_val_z);
192
+ mpf_sub (res_val, res_val, self_val);
193
+ mpz_temp_free(arg_val_z);
194
+ } else {
195
+ typeerror(ZQFXBD);
196
+ }
197
+
198
+ return res;
199
+ }
200
+
201
+ /*
202
+ * call-seq:
203
+ * float * other
204
+ *
205
+ * Returns the product of +float+ and +other+. +other+ can be
206
+ * * GMP::Z
207
+ * * Fixnum
208
+ * * GMP::Q
209
+ * * GMP::F
210
+ * * Bignum
211
+ */
212
+ VALUE r_gmpf_mul(VALUE self, VALUE arg)
213
+ {
214
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
215
+ MP_RAT *arg_val_q;
216
+ MP_INT *arg_val_z;
217
+ VALUE res;
218
+ unsigned long prec;
219
+
220
+ mpf_get_struct_prec (self, self_val, prec);
221
+
222
+ if (GMPF_P(arg)) {
223
+ mpf_get_struct(arg, arg_val_f);
224
+ prec_max(prec, arg_val_f);
225
+ mpf_make_struct_init(res, res_val, prec);
226
+ mpf_mul(res_val, self_val, arg_val_f);
227
+ } else if (GMPQ_P(arg)) {
228
+ mpq_get_struct(arg, arg_val_q);
229
+ mpf_make_struct_init(res, res_val, prec);
230
+ mpf_set_q(res_val, arg_val_q);
231
+ mpf_mul(res_val, self_val, res_val);
232
+ } else if (GMPZ_P(arg)) {
233
+ mpz_get_struct(arg, arg_val_z);
234
+ mpf_make_struct_init(res, res_val, prec);
235
+ mpf_set_z(res_val, arg_val_z);
236
+ mpf_mul(res_val, self_val, res_val);
237
+ } else if (FLOAT_P(arg)) {
238
+ mpf_make_struct_init(res, res_val, prec);
239
+ mpf_set_d(res_val, FLT2DBL(arg));
240
+ mpf_mul(res_val, self_val, res_val);
241
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
242
+ mpf_make_struct_init(res, res_val, prec);
243
+ mpf_set_si(res_val, FIX2INT(arg));
244
+ mpf_mul(res_val, self_val, res_val);
245
+ } else if (BIGNUM_P(arg)) {
246
+ mpz_temp_from_bignum(arg_val_z, arg);
247
+ mpf_make_struct_init(res, res_val, prec);
248
+ mpf_set_z(res_val, arg_val_z);
249
+ mpf_mul(res_val, res_val, self_val);
250
+ mpz_temp_free(arg_val_z);
251
+ } else {
252
+ typeerror(ZQFXBD);
253
+ }
254
+
255
+ return res;
256
+ }
257
+
258
+ VALUE r_gmpf_div(VALUE self, VALUE arg)
259
+ {
260
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
261
+ MP_RAT *arg_val_q;
262
+ MP_INT *arg_val_z;
263
+ VALUE res;
264
+ unsigned long prec;
265
+
266
+ mpf_get_struct_prec (self, self_val, prec);
267
+
268
+ if (GMPF_P(arg)) {
269
+ mpf_get_struct (arg, arg_val_f);
270
+ prec_max(prec, arg_val_f);
271
+ mpf_make_struct_init(res, res_val, prec);
272
+ mpf_div(res_val, self_val, arg_val_f);
273
+ } else if (GMPQ_P(arg)) {
274
+ mpq_get_struct (arg, arg_val_q);
275
+ mpf_make_struct_init(res, res_val, prec);
276
+ mpf_set_q (res_val, arg_val_q);
277
+ mpf_div (res_val, self_val, res_val);
278
+ } else if (GMPZ_P(arg)) {
279
+ mpz_get_struct (arg, arg_val_z);
280
+ mpf_make_struct_init(res, res_val, prec);
281
+ mpf_set_z (res_val, arg_val_z);
282
+ mpf_div (res_val, self_val, res_val);
283
+ } else if (FLOAT_P(arg)) {
284
+ mpf_make_struct_init(res, res_val, prec);
285
+ mpf_set_d (res_val, FLT2DBL(arg));
286
+ mpf_div (res_val, self_val, res_val);
287
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
288
+ mpf_make_struct_init(res, res_val, prec);
289
+ mpf_set_si (res_val, FIX2INT(arg));
290
+ mpf_div (res_val, self_val, res_val);
291
+ } else if (BIGNUM_P(arg)) {
292
+ mpz_temp_from_bignum(arg_val_z, arg);
293
+ mpf_make_struct_init(res, res_val, prec);
294
+ mpf_set_z (res_val, arg_val_z);
295
+ mpf_div (res_val, res_val, self_val);
296
+ mpz_temp_free(arg_val_z);
297
+ } else {
298
+ typeerror(ZQFXBD);
299
+ }
300
+
301
+ return res;
302
+ }
303
+
304
+ DEFUN_FLOAT2FLOAT(abs,mpf_abs)
305
+ DEFUN_FLOAT2FLOAT(neg,mpf_neg)
306
+
307
+
308
+ /**********************************************************************
309
+ * Float Comparison *
310
+ **********************************************************************/
311
+
312
+ int mpf_cmp_value(MP_FLOAT *self_val, VALUE arg)
313
+ {
314
+ MP_FLOAT *arg_val;
315
+ int result;
316
+
317
+ if (GMPF_P(arg)) {
318
+ mpf_get_struct(arg,arg_val);
319
+ return mpf_cmp (self_val, arg_val);
320
+ } else {
321
+ mpf_temp_init(arg_val, mpf_get_prec (self_val));
322
+ mpf_set_value (arg_val, arg);
323
+ result = mpf_cmp (self_val, arg_val);
324
+ mpf_temp_free(arg_val);
325
+ return result;
326
+ }
327
+ }
328
+
329
+ /* what does really "equal" mean ? it's not obvious */
330
+ VALUE r_gmpf_eq(VALUE self, VALUE arg)
331
+ {
332
+ MP_FLOAT *self_val;
333
+ mpf_get_struct (self,self_val);
334
+ return (mpf_cmp_value(self_val, arg) == 0) ? Qtrue : Qfalse;
335
+ }
336
+
337
+ VALUE r_gmpf_cmp(VALUE self, VALUE arg)
338
+ {
339
+ MP_FLOAT *self_val;
340
+ int res;
341
+ mpf_get_struct(self,self_val);
342
+ res = mpf_cmp_value(self_val, arg);
343
+ if (res > 0)
344
+ return INT2FIX(1);
345
+ else if (res == 0)
346
+ return INT2FIX(0);
347
+ else
348
+ return INT2FIX(-1);
349
+ }
350
+
351
+ DEFUN_FLOAT_CMP(lt,<)
352
+ DEFUN_FLOAT_CMP(le,<=)
353
+ DEFUN_FLOAT_CMP(gt,>)
354
+ DEFUN_FLOAT_CMP(ge,>=)
355
+
356
+
357
+ /**********************************************************************
358
+ * _unsorted_ *
359
+ **********************************************************************/
360
+
361
+ DEFUN_FLOAT2FLOAT(floor,mpf_floor)
362
+ DEFUN_FLOAT2FLOAT(trunc,mpf_trunc)
363
+ DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
364
+
365
+ VALUE r_gmpf_sgn(VALUE self)
366
+ {
367
+ MP_FLOAT *self_val;
368
+ mpf_get_struct(self, self_val);
369
+ return INT2FIX(mpf_sgn(self_val));
370
+ }
371
+
372
+ VALUE r_gmpf_get_prec(VALUE self)
373
+ {
374
+ MP_FLOAT *self_val;
375
+ mpf_get_struct(self, self_val);
376
+ return INT2NUM(mpf_get_prec(self_val));
377
+ }
378
+
379
+
380
+ void init_gmpf()
381
+ {
382
+ mGMP = rb_define_module("GMP");
383
+ rb_define_module_function(mGMP, "Z", r_gmpmod_z, -1);
384
+ rb_define_module_function(mGMP, "Q", r_gmpmod_q, -1);
385
+ rb_define_module_function(mGMP, "F", r_gmpmod_f, -1);
386
+
387
+ cGMP_F = rb_define_class_under (mGMP, "F", rb_cNumeric);
388
+
389
+
390
+ // Initializin, Assigning Floats
391
+
392
+ // Converting Floats
393
+ rb_define_method(cGMP_F, "to_s", r_gmpf_to_s, 0);
394
+ rb_define_method(cGMP_F, "to_d", r_gmpf_to_d, 0);
395
+
396
+ // Float Arithmetic
397
+ rb_define_method(cGMP_F, "+", r_gmpf_add, 1);
398
+ rb_define_method(cGMP_F, "-", r_gmpf_sub, 1);
399
+ rb_define_method(cGMP_F, "*", r_gmpf_mul, 1);
400
+ rb_define_method(cGMP_F, "/", r_gmpf_div, 1);
401
+ rb_define_method(cGMP_F, "-@", r_gmpf_neg, 0);
402
+ rb_define_method(cGMP_F, "neg!", r_gmpf_neg_self, 0);
403
+ rb_define_method(cGMP_F, "abs", r_gmpf_abs, 0);
404
+ rb_define_method(cGMP_F, "abs!", r_gmpf_abs_self, 0);
405
+
406
+ // Float Comparison
407
+ rb_define_method(cGMP_F, "<=>", r_gmpf_cmp, 1);
408
+ rb_define_method(cGMP_F, ">", r_gmpf_cmp_gt, 1);
409
+ rb_define_method(cGMP_F, ">=", r_gmpf_cmp_ge, 1);
410
+ rb_define_method(cGMP_F, "<", r_gmpf_cmp_lt, 1);
411
+ rb_define_method(cGMP_F, "<=", r_gmpf_cmp_le, 1);
412
+ rb_define_method(cGMP_F, "==", r_gmpf_eq, 1);
413
+
414
+ // _unsorted_
415
+ rb_define_method(cGMP_F, "floor", r_gmpf_floor, 0);
416
+ rb_define_method(cGMP_F, "floor!", r_gmpf_floor_self, 0);
417
+ rb_define_method(cGMP_F, "ceil", r_gmpf_ceil, 0);
418
+ rb_define_method(cGMP_F, "ceil!", r_gmpf_ceil_self, 0);
419
+ rb_define_method(cGMP_F, "trunc", r_gmpf_trunc, 0);
420
+ rb_define_method(cGMP_F, "trunc!", r_gmpf_trunc_self, 0);
421
+ rb_define_method(cGMP_F, "sgn", r_gmpf_sgn, 0);
422
+ rb_define_method(cGMP_F, "prec", r_gmpf_get_prec, 0);
423
+ }
@@ -0,0 +1,679 @@
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
+
15
+ /**********************************************************************
16
+ * Macros *
17
+ **********************************************************************/
18
+
19
+ #define DEFUN_RAT_CMP(name,CMP_OP) \
20
+ static VALUE r_gmpq_cmp_##name(VALUE self, VALUE arg) \
21
+ { \
22
+ MP_RAT *self_val; \
23
+ mpq_get_struct(self,self_val); \
24
+ return (mpq_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
25
+ }
26
+
27
+ #define DEFUN_RAT2INT(fname,mpz_fname) \
28
+ static VALUE r_gmpq_##fname(VALUE self) \
29
+ { \
30
+ MP_RAT *self_val; \
31
+ MP_INT *res_val; \
32
+ VALUE res; \
33
+ \
34
+ mpq_get_struct(self, self_val); \
35
+ mpz_make_struct_init(res, res_val) \
36
+ mpz_fname(res_val, mpq_numref(self_val), mpq_denref(self_val)); \
37
+ return res; \
38
+ }
39
+
40
+
41
+ /**********************************************************************
42
+ * Initializing Rationals *
43
+ **********************************************************************/
44
+
45
+ VALUE r_gmpq_swap(VALUE self, VALUE arg)
46
+ {
47
+ MP_RAT *self_val, *arg_val;
48
+
49
+ if (!GMPQ_P(arg)) {
50
+ rb_raise(rb_eTypeError, "Can't swap GMP::Q with object of other class");
51
+ }
52
+
53
+ mpq_get_struct(self, self_val);
54
+ mpq_get_struct(arg, arg_val);
55
+ mpq_swap(self_val,arg_val);
56
+
57
+ return Qnil;
58
+ }
59
+
60
+
61
+ /**********************************************************************
62
+ * Rational Conversions *
63
+ **********************************************************************/
64
+
65
+ /*
66
+ * call-seq:
67
+ * rational.to_d
68
+ *
69
+ * Returns +rational+ as an Float if +rational+ fits in a Float.
70
+ *
71
+ * Otherwise returns the least significant part of +rational+, with the same
72
+ * sign as +rational+.
73
+ *
74
+ * If the exponent from the conversion is too big or too small to fit a double
75
+ * then the result is system dependent. For too big an infinity is returned
76
+ * when available. For too small 0.0 is normally returned. Hardware overflow,
77
+ * underflow and denorm traps may or may not occur.
78
+ */
79
+ VALUE r_gmpq_to_d(VALUE self)
80
+ {
81
+ MP_RAT *self_val;
82
+ mpq_get_struct(self, self_val);
83
+
84
+ return rb_float_new(mpq_get_d(self_val));
85
+ }
86
+
87
+
88
+ /**********************************************************************
89
+ * Rational Arithmetic *
90
+ **********************************************************************/
91
+
92
+ /*
93
+ * call-seq:
94
+ * rat1 + rat2
95
+ *
96
+ * Adds +rat1+ to +rat2+. +rat2+ can be
97
+ * * GMP::Z
98
+ * * Fixnum
99
+ * * GMP::Q
100
+ * * GMP::F
101
+ * * Bignum
102
+ */
103
+ VALUE r_gmpq_add(VALUE self, VALUE arg)
104
+ {
105
+ MP_RAT *self_val, *arg_val_q, *res_val;
106
+ MP_INT *arg_val_z, *res_val_num;
107
+ VALUE res;
108
+
109
+ mpq_get_struct(self, self_val);
110
+ mpq_make_struct_init(res, res_val);
111
+
112
+ if (GMPQ_P(arg)) {
113
+ mpq_get_struct(arg,arg_val_q);
114
+ mpq_add(res_val, self_val, arg_val_q);
115
+ } else if (GMPZ_P(arg)) {
116
+ res_val_num = mpq_numref(res_val);
117
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
118
+ mpz_get_struct(arg, arg_val_z);
119
+ mpz_mul(res_val_num, mpq_denref(self_val), arg_val_z);
120
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
121
+ } else if (FIXNUM_P(arg)) {
122
+ res_val_num = mpq_numref(res_val);
123
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
124
+ mpz_mul_si(res_val_num, mpq_denref(self_val), FIX2INT(arg));
125
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
126
+ } else if (GMPF_P(arg)) {
127
+ return r_gmpf_add(arg,self);
128
+ } else if (BIGNUM_P(arg)) {
129
+ res_val_num = mpq_numref(res_val);
130
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
131
+ mpz_set_bignum(res_val_num, arg);
132
+ mpz_mul(res_val_num, res_val_num, mpq_denref(self_val));
133
+ mpz_add(res_val_num, res_val_num, mpq_numref(self_val));
134
+ } else {
135
+ typeerror(ZQFXB);
136
+ }
137
+ return res;
138
+ }
139
+
140
+ /*
141
+ * call-seq:
142
+ * rat1 - rat2
143
+ *
144
+ * Subtracts +rat2+ from +rat1+. +rat2+ can be
145
+ * * GMP::Z
146
+ * * Fixnum
147
+ * * GMP::Q
148
+ * * GMP::F
149
+ * * Bignum
150
+ */
151
+ VALUE r_gmpq_sub(VALUE self, VALUE arg)
152
+ {
153
+ MP_RAT *self_val, *arg_val_q, *res_val;
154
+ MP_INT *arg_val_z, *res_val_num;
155
+ MP_FLOAT *arg_val_f, *res_val_f;
156
+ VALUE res;
157
+ unsigned int prec;
158
+
159
+ mpq_get_struct(self, self_val);
160
+ mpq_make_struct_init(res, res_val);
161
+
162
+ if (GMPQ_P(arg)) {
163
+ mpq_get_struct(arg,arg_val_q);
164
+ mpq_sub (res_val, self_val, arg_val_q);
165
+ } else if (GMPZ_P(arg)) {
166
+ res_val_num = mpq_numref(res_val);
167
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
168
+ mpz_get_struct(arg, arg_val_z);
169
+ mpz_mul (res_val_num, mpq_denref(self_val), arg_val_z);
170
+ mpz_neg (res_val_num, res_val_num);
171
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
172
+ } else if (FIXNUM_P(arg)) {
173
+ res_val_num = mpq_numref(res_val);
174
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
175
+ mpz_mul_si (res_val_num, mpq_denref(self_val), -FIX2INT(arg));
176
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
177
+ } else if (GMPF_P(arg)) {
178
+ mpf_get_struct_prec (arg, arg_val_f, prec);
179
+ mpf_make_struct_init(res, res_val_f, prec);
180
+ mpf_set_q (res_val_f, self_val);
181
+ mpf_sub (res_val_f, res_val_f, arg_val_f);
182
+ } else if (BIGNUM_P(arg)) {
183
+ res_val_num = mpq_numref(res_val);
184
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
185
+ mpz_set_bignum (res_val_num, arg);
186
+ mpz_mul (res_val_num, res_val_num, mpq_denref(self_val));
187
+ mpz_neg (res_val_num, res_val_num);
188
+ mpz_add (res_val_num, res_val_num, mpq_numref(self_val));
189
+ } else {
190
+ typeerror (ZQFXB);
191
+ }
192
+ return res;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * rat1 * rat2
198
+ *
199
+ * Multiplies +rat1+ with +rat2+. +rat2+ can be
200
+ * * GMP::Z
201
+ * * Fixnum
202
+ * * GMP::Q
203
+ * * GMP::F
204
+ * * Bignum
205
+ */
206
+ VALUE r_gmpq_mul(VALUE self, VALUE arg)
207
+ {
208
+ MP_RAT *self_val, *arg_val_q, *res_val;
209
+ MP_INT *arg_val_z, *tmp_z;
210
+ VALUE res;
211
+ #if GMP >= 4
212
+ unsigned long tmp_ui;
213
+ #endif
214
+
215
+ mpq_get_struct(self, self_val);
216
+ mpq_make_struct_init(res, res_val);
217
+
218
+ if (GMPQ_P(arg)) {
219
+ mpq_get_struct(arg,arg_val_q);
220
+ mpq_mul(res_val, self_val, arg_val_q);
221
+ } else if (GMPZ_P(arg)) {
222
+ mpz_get_struct(arg,arg_val_z);
223
+ mpz_temp_init(tmp_z);
224
+ mpz_gcd(tmp_z, mpq_denref(self_val), arg_val_z);
225
+ mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
226
+ mpz_divexact(mpq_numref(res_val), arg_val_z, tmp_z);
227
+ mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
228
+ mpz_temp_free(tmp_z);
229
+ } else if (FIXNUM_P(arg)) {
230
+ #if GMP >= 4
231
+ if (FIX2INT(arg) > 0) {
232
+ tmp_ui = mpz_gcd_ui(0, mpq_denref(self_val), FIX2INT(arg));
233
+ } else if (FIX2INT(arg) < 0) {
234
+ tmp_ui = mpz_gcd_ui(0, mpq_denref(self_val), -FIX2INT(arg));
235
+ } else {
236
+ mpz_set_ui(mpq_numref(res_val), 0);
237
+ mpz_set_ui(mpq_denref(res_val), 1);
238
+ return res;
239
+ }
240
+ mpz_divexact_ui(mpq_denref(res_val), mpq_denref(self_val), tmp_ui);
241
+ mpz_mul_ui(mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg)/tmp_ui);
242
+ #else
243
+ mpz_set(mpq_denref(res_val), mpq_denref(self_val));
244
+ mpz_mul_si(mpq_numref(res_val), mpq_numref(self_val), FIX2INT(arg));
245
+ mpq_canonicalize(res_val);
246
+ #endif
247
+ } else if (GMPF_P(arg)) {
248
+ return r_gmpf_mul(arg, self);
249
+ } else if (BIGNUM_P(arg)) {
250
+ mpz_temp_alloc(tmp_z);
251
+ mpz_set_bignum(tmp_z, arg);
252
+ mpz_gcd(mpq_denref(res_val), mpq_denref(self_val), tmp_z);
253
+ mpz_divexact(mpq_numref(res_val), tmp_z, mpq_denref(res_val));
254
+ mpz_divexact(mpq_denref(res_val), mpq_denref(self_val), mpq_denref(res_val));
255
+ mpz_mul(mpq_numref(res_val), mpq_numref(res_val), mpq_numref(self_val));
256
+ mpz_temp_free(tmp_z);
257
+ } else {
258
+ typeerror(ZQFXB);
259
+ }
260
+ return res;
261
+ }
262
+
263
+ /*
264
+ * call-seq:
265
+ * rat1 / rat2
266
+ *
267
+ * Divides +rat1+ by +rat2+. +rat2+ can be
268
+ * * GMP::Z
269
+ * * Fixnum
270
+ * * GMP::Q
271
+ * * GMP::F
272
+ * * Bignum
273
+ */
274
+ VALUE r_gmpq_div(VALUE self, VALUE arg)
275
+ {
276
+ MP_RAT *self_val, *arg_val_q, *res_val;
277
+ MP_INT *arg_val_z, *tmp_z;
278
+ MP_FLOAT *arg_val_f, *res_val_f;
279
+ VALUE res;
280
+ unsigned long tmp_ui, prec;
281
+
282
+ mpq_get_struct(self, self_val);
283
+ mpq_make_struct_init(res, res_val);
284
+
285
+ if (GMPQ_P(arg)) {
286
+ mpq_get_struct(arg,arg_val_q);
287
+ if (mpz_sgn(mpq_numref(arg_val_q)) == 0)
288
+ rb_raise(rb_eZeroDivError, "divided by 0");
289
+ mpq_div(res_val, self_val, arg_val_q);
290
+ } else if (GMPZ_P(arg)) {
291
+ mpz_get_struct(arg,arg_val_z);
292
+ mpz_temp_init(tmp_z);
293
+ mpz_gcd(tmp_z, mpq_numref(self_val), arg_val_z);
294
+ mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
295
+ mpz_divexact(mpq_denref(res_val), arg_val_z, tmp_z);
296
+ mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
297
+ mpz_temp_free(tmp_z);
298
+ } else if (FIXNUM_P(arg)) {
299
+ if (FIX2INT(arg) == 0)
300
+ rb_raise(rb_eZeroDivError, "divided by 0");
301
+ if (FIX2INT(arg) > 0) {
302
+ tmp_ui = mpz_gcd_ui(0, mpq_numref(self_val), FIX2INT(arg));
303
+ } else {
304
+ tmp_ui = mpz_gcd_ui(0, mpq_numref(self_val), -FIX2INT(arg));
305
+ }
306
+ mpz_divexact_ui(mpq_numref(res_val), mpq_numref(self_val), tmp_ui);
307
+ mpz_mul_ui(mpq_denref(res_val), mpq_denref(self_val), FIX2INT(arg)/tmp_ui);
308
+ } else if (GMPF_P(arg)) {
309
+ mpf_get_struct_prec(arg, arg_val_f, prec);
310
+ mpf_make_struct_init(res, res_val_f, prec);
311
+ mpf_set_q(res_val_f, self_val);
312
+ mpf_div(res_val_f, res_val_f, arg_val_f);
313
+ } else if (BIGNUM_P(arg)) {
314
+ mpz_temp_alloc(tmp_z);
315
+ mpz_set_bignum(tmp_z, arg);
316
+ mpz_gcd(mpq_numref(res_val), mpq_numref(self_val), tmp_z);
317
+ mpz_divexact(mpq_denref(res_val), tmp_z, mpq_numref(res_val));
318
+ mpz_divexact(mpq_numref(res_val), mpq_numref(self_val), mpq_numref(res_val));
319
+ mpz_mul(mpq_denref(res_val), mpq_denref(res_val), mpq_denref(self_val));
320
+ mpz_temp_free(tmp_z);
321
+ } else {
322
+ typeerror(ZQFXB);
323
+ }
324
+ return res;
325
+ }
326
+
327
+ DEFUN_RAT2INT(floor,mpz_fdiv_q)
328
+ DEFUN_RAT2INT(trunc,mpz_tdiv_q)
329
+ DEFUN_RAT2INT(ceil,mpz_cdiv_q)
330
+
331
+ /*
332
+ * Document-method: neg
333
+ *
334
+ * call-seq:
335
+ * -rational
336
+ * rational.neg
337
+ *
338
+ * From the GMP Manual:
339
+ *
340
+ * Returns -+rational+.
341
+ */
342
+ VALUE r_gmpq_neg(VALUE self)
343
+ {
344
+ MP_RAT *self_val, *res_val;
345
+ VALUE res;
346
+ mpq_get_struct(self, self_val);
347
+ mpq_make_struct_init(res, res_val);
348
+ mpq_neg (res_val, self_val);
349
+ return res;
350
+ }
351
+
352
+ /*
353
+ * Document-method: neg!
354
+ *
355
+ * call-seq:
356
+ * rational.neg!
357
+ *
358
+ * From the GMP Manual:
359
+ *
360
+ * Sets +rational+ to -+rational+.
361
+ */
362
+ VALUE r_gmpq_neg_self(VALUE self)
363
+ {
364
+ MP_RAT *self_val;
365
+ mpq_get_struct(self, self_val);
366
+ mpz_neg (mpq_numref(self_val), mpq_numref(self_val));
367
+ return Qnil;
368
+ }
369
+
370
+ /*
371
+ * Document-method: abs
372
+ *
373
+ * call-seq:
374
+ * rational.abs
375
+ *
376
+ * From the GMP Manual:
377
+ *
378
+ * Returns the absolute value of +rational+.
379
+ */
380
+ VALUE r_gmpq_abs(VALUE self)
381
+ {
382
+ MP_RAT *self_val, *res_val;
383
+ VALUE res;
384
+ mpq_get_struct(self, self_val);
385
+ mpq_make_struct_init(res, res_val);
386
+ mpz_abs (mpq_numref(res_val), mpq_numref(self_val));
387
+ mpz_set (mpq_denref(res_val), mpq_denref(self_val));
388
+
389
+ return res;
390
+ }
391
+
392
+ /*
393
+ * Document-method: abs!
394
+ *
395
+ * call-seq:
396
+ * rational.abs!
397
+ *
398
+ * From the GMP Manual:
399
+ *
400
+ * Sets +rational+ to its absolute value.
401
+ */
402
+ VALUE r_gmpq_abs_self(VALUE self)
403
+ {
404
+ MP_RAT *self_val;
405
+ mpq_get_struct(self, self_val);
406
+ mpz_abs (mpq_numref(self_val), mpq_numref(self_val));
407
+ return Qnil;
408
+ }
409
+
410
+ VALUE r_gmpq_inv(VALUE self)
411
+ {
412
+ MP_RAT *self_val, *res_val;
413
+ VALUE res;
414
+
415
+ mpq_get_struct(self, self_val);
416
+ if (mpq_sgn(self_val) == 0)
417
+ rb_raise (rb_eZeroDivError, "divided by 0");
418
+ mpq_make_struct_init(res, res_val);
419
+ mpq_inv (res_val, self_val);
420
+
421
+ return res;
422
+ }
423
+
424
+ VALUE r_gmpq_inv_self(VALUE self)
425
+ {
426
+ MP_RAT *self_val;
427
+ mpq_get_struct(self, self_val);
428
+ if (mpq_sgn(self_val) == 0)
429
+ rb_raise (rb_eZeroDivError, "divided by 0");
430
+ mpq_inv (self_val, self_val);
431
+ return Qnil;
432
+ }
433
+
434
+
435
+ /**********************************************************************
436
+ * Comparing Rationals *
437
+ **********************************************************************/
438
+
439
+ int mpq_cmp_value(MP_RAT *OP, VALUE arg)
440
+ {
441
+ MP_INT *arg_val_z, *tmp_z;
442
+ MP_RAT *arg_val_q;
443
+ int res;
444
+
445
+ if (GMPQ_P(arg)) {
446
+ mpq_get_struct(arg,arg_val_q);
447
+ return mpq_cmp(OP,arg_val_q);
448
+ } else if (GMPZ_P(arg)) {
449
+ mpz_get_struct(arg, arg_val_z);
450
+ mpz_temp_alloc(tmp_z);
451
+ mpz_init(tmp_z);
452
+ mpz_mul(tmp_z, mpq_denref(OP), arg_val_z);
453
+ res = mpz_cmp(mpq_numref(OP),tmp_z);
454
+ mpz_temp_free(tmp_z);
455
+ return res;
456
+ } else if (FIXNUM_P(arg)) {
457
+ mpz_temp_alloc(tmp_z);
458
+ mpz_init(tmp_z);
459
+ mpz_mul_si(tmp_z, mpq_denref(OP), FIX2INT(arg));
460
+ res = mpz_cmp(mpq_numref(OP), tmp_z);
461
+ mpz_temp_free(tmp_z);
462
+ return res;
463
+ } else if (GMPF_P(arg)) {
464
+ not_yet;
465
+ } else if (BIGNUM_P(arg)) {
466
+ mpz_temp_from_bignum(tmp_z, arg);
467
+ mpz_mul(tmp_z, tmp_z, mpq_denref(OP));
468
+ res = mpz_cmp(mpq_numref(OP), tmp_z);
469
+ mpz_temp_free(tmp_z);
470
+ return res;
471
+ } else {
472
+ typeerror(ZQFXB);
473
+ }
474
+ }
475
+
476
+ VALUE r_gmpq_eq(VALUE self, VALUE arg)
477
+ {
478
+ MP_RAT *self_val, *arg_val_q;
479
+ MP_INT *arg_val_z;
480
+
481
+ mpq_get_struct(self,self_val);
482
+ if (GMPQ_P(arg)) {
483
+ mpq_get_struct(arg,arg_val_q);
484
+ return mpq_equal(self_val,arg_val_q)?Qtrue:Qfalse;
485
+ } else if (GMPZ_P(arg)) {
486
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
487
+ return Qfalse;
488
+ mpz_get_struct (arg, arg_val_z);
489
+ return (mpz_cmp(mpq_numref(self_val),arg_val_z)==0)?Qtrue:Qfalse;
490
+ } else if (FIXNUM_P(arg)) {
491
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
492
+ return Qfalse;
493
+ return (mpz_cmp_ui(mpq_numref(self_val),FIX2INT(arg))==0)?Qtrue:Qfalse;
494
+ } else if (BIGNUM_P(arg)) {
495
+ if (mpz_cmp_ui(mpq_denref(self_val), 1) != 0)
496
+ return Qfalse;
497
+ mpz_temp_from_bignum(arg_val_z, arg);
498
+ if (mpz_cmp (mpq_numref(self_val),arg_val_z) == 0) {
499
+ mpz_temp_free (arg_val_z);
500
+ return Qtrue;
501
+ } else {
502
+ mpz_temp_free (arg_val_z);
503
+ return Qfalse;
504
+ }
505
+ } else {
506
+ return Qfalse;
507
+ }
508
+ }
509
+
510
+ VALUE r_gmpq_cmp(VALUE self, VALUE arg)
511
+ {
512
+ MP_RAT *self_val;
513
+ int res;
514
+ mpq_get_struct (self,self_val);
515
+ res = mpq_cmp_value(self_val, arg);
516
+ if (res > 0)
517
+ return INT2FIX(1);
518
+ else if (res == 0)
519
+ return INT2FIX(0);
520
+ else
521
+ return INT2FIX(-1);
522
+ }
523
+
524
+ DEFUN_RAT_CMP(lt,<)
525
+ DEFUN_RAT_CMP(le,<=)
526
+ DEFUN_RAT_CMP(gt,>)
527
+ DEFUN_RAT_CMP(ge,>=)
528
+
529
+ static VALUE r_gmpq_cmpabs(VALUE self, VALUE arg)
530
+ {
531
+ MP_RAT *arg_val_q, *self_val;
532
+ MP_INT *arg_val_z, *tmp_z;
533
+ int res;
534
+ int sgnt;
535
+
536
+ mpq_get_struct(self, self_val);
537
+
538
+ if (GMPQ_P(arg)) {
539
+ mpq_get_struct(arg,arg_val_q);
540
+ sgnt = 3*mpz_sgn(mpq_numref(self_val)) + mpz_sgn(mpq_numref(arg_val_q));
541
+ switch (sgnt)
542
+ {
543
+ default:
544
+ case 0:
545
+ return INT2FIX(0);
546
+ case 1:
547
+ case -1:
548
+ return INT2FIX(-1);
549
+ case 2:
550
+ tmp_z = mpq_numref(arg_val_q);
551
+ mpz_neg (tmp_z, tmp_z);
552
+ res = mpq_cmp (self_val, arg_val_q);
553
+ mpz_neg (tmp_z, tmp_z);
554
+ return res;
555
+ case -2:
556
+ tmp_z = mpq_numref(arg_val_q);
557
+ mpz_neg (tmp_z, tmp_z);
558
+ res = mpq_cmp (self_val, arg_val_q);
559
+ mpz_neg (tmp_z, tmp_z);
560
+ return res;
561
+ case 3:
562
+ case -3:
563
+ return INT2FIX(1);
564
+ case 4:
565
+ case -4:
566
+ return INT2FIX(mpq_cmp (self_val,arg_val_q));
567
+ }
568
+ } else if (GMPZ_P(arg)) {
569
+ mpz_get_struct(arg, arg_val_z);
570
+ mpz_temp_alloc (tmp_z);
571
+ mpz_init (tmp_z);
572
+ mpz_mul (tmp_z, mpq_denref(self_val), arg_val_z);
573
+ res = mpz_cmpabs (mpq_numref(self_val),tmp_z);
574
+ mpz_temp_free (tmp_z);
575
+ return res;
576
+ } else if (FIXNUM_P(arg)) {
577
+ mpz_temp_alloc (tmp_z);
578
+ mpz_init (tmp_z);
579
+ mpz_mul_si (tmp_z, mpq_denref(self_val), FIX2INT(arg));
580
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
581
+ mpz_temp_free (tmp_z);
582
+ return res;
583
+ } else if (GMPF_P(arg)) {
584
+ not_yet;
585
+ } else if (BIGNUM_P(arg)) {
586
+ mpz_temp_from_bignum (tmp_z, arg);
587
+ mpz_mul (tmp_z, tmp_z, mpq_denref(self_val));
588
+ res = mpz_cmpabs (mpq_numref(self_val), tmp_z);
589
+ mpz_temp_free (tmp_z);
590
+ return res;
591
+ } else {
592
+ typeerror (ZQFXB);
593
+ }
594
+ }
595
+
596
+ /*
597
+ * call-seq:
598
+ * rational.sgn
599
+ *
600
+ * From the GMP Manual:
601
+ *
602
+ * Returns +1 if +rational+ > 0, 0 if +rational+ == 0, and -1 if +rational+ < 0.
603
+ */
604
+ VALUE r_gmpq_sgn(VALUE self)
605
+ {
606
+ MP_RAT *self_val;
607
+ mpq_get_struct(self, self_val);
608
+ return INT2FIX(mpq_sgn(self_val));
609
+ }
610
+
611
+ /**********************************************************************
612
+ * Applying Integer Functions *
613
+ **********************************************************************/
614
+
615
+ VALUE r_gmpq_num(VALUE self)
616
+ {
617
+ MP_RAT *self_val;
618
+ MP_INT *res_val;
619
+ VALUE res;
620
+ mpq_get_struct(self,self_val);
621
+ mpz_make_struct(res, res_val);
622
+ mpz_init_set (res_val, mpq_numref (self_val));
623
+ return res;
624
+ }
625
+
626
+ VALUE r_gmpq_den(VALUE self)
627
+ {
628
+ MP_RAT *self_val;
629
+ MP_INT *res_val;
630
+ VALUE res;
631
+ mpq_get_struct(self,self_val);
632
+ mpz_make_struct(res, res_val);
633
+ mpz_init_set (res_val, mpq_denref (self_val));
634
+ return res;
635
+ }
636
+
637
+
638
+ void init_gmpq()
639
+ {
640
+ mGMP = rb_define_module("GMP");
641
+ rb_define_module_function(mGMP, "Z", r_gmpmod_z, -1);
642
+ rb_define_module_function(mGMP, "Q", r_gmpmod_q, -1);
643
+ rb_define_module_function(mGMP, "F", r_gmpmod_f, -1);
644
+
645
+ cGMP_Q = rb_define_class_under (mGMP, "Q", rb_cNumeric);
646
+
647
+ // Initializing Rationals
648
+ rb_define_method(cGMP_Q, "swap", r_gmpq_swap, 1);
649
+
650
+ // Rational Conversions
651
+ rb_define_method(cGMP_Q, "to_d", r_gmpq_to_d, 0);
652
+
653
+ // Rational Arithmetic
654
+ rb_define_method(cGMP_Q, "+", r_gmpq_add, 1);
655
+ rb_define_method(cGMP_Q, "-", r_gmpq_sub, 1);
656
+ rb_define_method(cGMP_Q, "*", r_gmpq_mul, 1);
657
+ rb_define_method(cGMP_Q, "/", r_gmpq_div, 1);
658
+ rb_define_method(cGMP_Q, "-@", r_gmpq_neg, 0);
659
+ rb_define_method(cGMP_Q, "neg!", r_gmpq_neg_self, 0);
660
+ rb_define_method(cGMP_Q, "inv", r_gmpq_inv, 0);
661
+ rb_define_method(cGMP_Q, "inv!", r_gmpq_inv_self, 0);
662
+ rb_define_method(cGMP_Q, "abs", r_gmpq_abs, 0);
663
+ rb_define_method(cGMP_Q, "abs!", r_gmpq_abs_self, 0);
664
+
665
+ // Comparing Rationals
666
+ rb_define_method(cGMP_Q, "<=>", r_gmpq_cmp, 1);
667
+ rb_define_method(cGMP_Q, ">", r_gmpq_cmp_gt, 1);
668
+ rb_define_method(cGMP_Q, ">=", r_gmpq_cmp_ge, 1);
669
+ rb_define_method(cGMP_Q, "<", r_gmpq_cmp_lt, 1);
670
+ rb_define_method(cGMP_Q, "<=", r_gmpq_cmp_le, 1);
671
+ rb_define_method(cGMP_Q, "==", r_gmpq_eq, 1);
672
+ rb_define_method(cGMP_Q, "sgn", r_gmpq_sgn, 0);
673
+ rb_define_method(cGMP_Q, "cmpabs", r_gmpq_cmpabs, 1);
674
+
675
+ // _unsorted_
676
+ rb_define_method(cGMP_Q, "floor", r_gmpq_floor, 0);
677
+ rb_define_method(cGMP_Q, "ceil", r_gmpq_ceil, 0);
678
+ rb_define_method(cGMP_Q, "trunc", r_gmpq_trunc, 0);
679
+ }