gmp 0.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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,80 @@
1
+ #include <ruby_gmp.h>
2
+
3
+ /*
4
+ * Taken directly from GMPbench.
5
+ */
6
+
7
+ #define TIME(t,func) \
8
+ do { \
9
+ long int __t0, __times, __t, __tmp; \
10
+ __times = 1; \
11
+ {func;} \
12
+ do { \
13
+ __times <<= 1; \
14
+ __t0 = FIX2INT(r_gmpmod_cputime ()); \
15
+ for (__t = 0; __t < __times; __t++) \
16
+ {func;} \
17
+ __tmp = FIX2INT(r_gmpmod_cputime ()) - __t0; \
18
+ } while (__tmp < 250); \
19
+ (t) = (double) __tmp / __times; \
20
+ } while (0)
21
+
22
+ /* Return user CPU time measured in milliseconds. */
23
+ #if !defined (__sun) \
24
+ && (defined (USG) || defined (__SVR4) || defined (_UNICOS) \
25
+ || defined (__hpux) || defined (_WIN32))
26
+ #include <time.h>
27
+
28
+ int
29
+ cputime ()
30
+ {
31
+ return (int) ((double) clock () * 1000 / CLOCKS_PER_SEC);
32
+ }
33
+ #else
34
+ #include <sys/types.h>
35
+ #include <sys/time.h>
36
+ #include <sys/resource.h>
37
+
38
+ int
39
+ cputime ()
40
+ {
41
+ struct rusage rus;
42
+
43
+ getrusage (0, &rus);
44
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
45
+ }
46
+ #endif
47
+
48
+ VALUE
49
+ r_gmpmod_cputime (VALUE self)
50
+ {
51
+ (void)self;
52
+ return INT2FIX (cputime ());
53
+ }
54
+
55
+ VALUE
56
+ r_gmpmod_time (VALUE self)
57
+ {
58
+ (void)self;
59
+ long int __t0, __times, __t, __tmp;
60
+ __times = 1;
61
+
62
+ rb_need_block();
63
+
64
+ rb_yield (Qnil);
65
+ do {
66
+ __times <<= 1;
67
+ __t0 = cputime ();
68
+ for (__t = 0; __t < __times; __t++)
69
+ {rb_yield (Qnil);}
70
+ __tmp = cputime () - __t0;
71
+ } while (__tmp < 250);
72
+ return rb_float_new ((double) __tmp / __times);
73
+ }
74
+
75
+ void init_gmpbench_timing()
76
+ {
77
+ mGMP = rb_define_module("GMP");
78
+ rb_define_module_function(mGMP, "cputime", r_gmpmod_cputime, 0);
79
+ rb_define_module_function(mGMP, "time", r_gmpmod_time, 0);
80
+ }
@@ -0,0 +1,595 @@
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
+ * 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_gmpf_to_d mpf_get_d
19
+ * to_s r_gmpf_to_s mpf_get_s
20
+ * + r_gmpf_add mpf_add
21
+ * - r_gmpf_sub mpf_sub
22
+ * * r_gmpf_mul mpf_mul
23
+ * / r_gmpf_div mpf_div
24
+ */
25
+
26
+ /**********************************************************************
27
+ * Macros *
28
+ **********************************************************************/
29
+
30
+ #define DEFUN_FLOAT2FLOAT(fname,mpf_fname) \
31
+ static VALUE r_gmpf_##fname(VALUE self) \
32
+ { \
33
+ MP_FLOAT *self_val, *res_val; \
34
+ VALUE res; \
35
+ mpf_get_struct(self, self_val); \
36
+ mpf_make_struct_init(res, res_val, mpf_get_prec(self_val)); \
37
+ mpf_fname(res_val, self_val); \
38
+ return res; \
39
+ } \
40
+ \
41
+ static VALUE r_gmpf_##fname##_self(VALUE self) \
42
+ { \
43
+ MP_FLOAT *self_val; \
44
+ mpf_get_struct(self, self_val); \
45
+ mpf_fname(self_val, self_val); \
46
+ return Qnil; \
47
+ }
48
+
49
+ #define DEFUN_FLOAT_CMP(name,CMP_OP) \
50
+ static VALUE r_gmpf_cmp_##name(VALUE self, VALUE arg) \
51
+ { \
52
+ MP_FLOAT *self_val; \
53
+ mpf_get_struct(self,self_val); \
54
+ return (mpf_cmp_value(self_val, arg) CMP_OP 0)?Qtrue:Qfalse; \
55
+ }
56
+
57
+
58
+ /**********************************************************************
59
+ * Initializing, Assigning Floats *
60
+ **********************************************************************/
61
+
62
+ /*
63
+ * call-seq:
64
+ * GMP::R.new(arg)
65
+ *
66
+ * Creates a new GMP::R float, with arg as its value, converting where
67
+ * necessary.
68
+ */
69
+ VALUE r_gmpfsg_new(int argc, VALUE *argv, VALUE klass)
70
+ {
71
+ MP_FLOAT *res_val;
72
+ VALUE res;
73
+
74
+ (void)klass;
75
+
76
+ if (argc > 2)
77
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0, 1 or 2)", argc);
78
+
79
+ mpf_make_struct (res, res_val);
80
+ rb_obj_call_init(res, argc, argv);
81
+
82
+ return res;
83
+ }
84
+
85
+ VALUE r_gmpf_initialize(int argc, VALUE *argv, VALUE self)
86
+ {
87
+ MP_FLOAT *self_val, *arg_val_f;
88
+ unsigned long prec = 0;
89
+ VALUE arg;
90
+
91
+ mpf_get_struct (self, self_val);
92
+
93
+ if (argc==0) {
94
+ mpf_init(self_val);
95
+ mpf_set_si(self_val, 0);
96
+ return Qnil;
97
+ }
98
+
99
+ arg = argv[0];
100
+
101
+ if (argc == 2) {
102
+ if (FIXNUM_P(argv[1])) {
103
+ if (FIX2INT(argv[1]) >= 0)
104
+ prec = FIX2INT(argv[1]);
105
+ else
106
+ rb_raise(rb_eRangeError, "prec must be non-negative");
107
+ } else {
108
+ rb_raise(rb_eTypeError, "prec must be FixNum");
109
+ }
110
+ } else if (GMPF_P(arg)) {
111
+ mpf_get_struct (arg, arg_val_f);
112
+ prec = mpf_get_prec (arg_val_f);
113
+ }
114
+ if (prec == 0)
115
+ mpf_init (self_val);
116
+ else
117
+ mpf_init2 (self_val, prec);
118
+
119
+ if (GMPF_P(arg)) {
120
+ mpf_get_struct (arg, arg_val_f);
121
+ mpf_set(self_val, arg_val_f);
122
+ } else {
123
+ mpf_set_value(self_val, arg);
124
+ }
125
+
126
+ return Qnil;
127
+ }
128
+
129
+ /*
130
+ * call-seq:
131
+ * GMP::F(arg)
132
+ *
133
+ * A convenience method for +GMP::F.new(arg)+.
134
+ */
135
+ VALUE r_gmpmod_f(int argc, VALUE *argv, VALUE module)
136
+ {
137
+ (void)module;
138
+ return r_gmpfsg_new(argc, argv, cGMP_F);
139
+ }
140
+
141
+
142
+ /**********************************************************************
143
+ * Converting Floats *
144
+ **********************************************************************/
145
+
146
+ VALUE r_gmpf_to_d(VALUE self)
147
+ {
148
+ MP_FLOAT *self_val;
149
+ mpf_get_struct(self, self_val);
150
+
151
+ return rb_float_new(mpf_get_d(self_val));
152
+ }
153
+
154
+ /*
155
+ * Document-method: to_s
156
+ *
157
+ * call-seq:
158
+ * float.to_s
159
+ *
160
+ * Returns the decimal representation of +float+, as a string.
161
+ */
162
+ VALUE r_gmpf_to_s(VALUE self)
163
+ {
164
+ MP_FLOAT *self_val;
165
+ char *str, *str2;
166
+ VALUE res;
167
+ mp_exp_t exponent;
168
+
169
+ mpf_get_struct(self, self_val);
170
+
171
+ str = mpf_get_str(NULL, &exponent, 10, 0, self_val);
172
+ if ((strcmp(str, "NaN") == 0) ||
173
+ (strcmp(str, "Inf") == 0) ||
174
+ (strcmp(str, "-Inf") == 0))
175
+ {
176
+ res = rb_str_new2(str);
177
+ }
178
+ else
179
+ {
180
+ if (str[0] == '-')
181
+ __gmp_asprintf(&str2, "-0.%se%+ld", str+1, exponent);
182
+ else
183
+ __gmp_asprintf(&str2, "0.%se%+ld", str, exponent);
184
+ res = rb_str_new2(str2);
185
+ free(str2);
186
+ }
187
+ free(str);
188
+ return res;
189
+ }
190
+
191
+
192
+ /**********************************************************************
193
+ * Float Arithmetic *
194
+ **********************************************************************/
195
+
196
+ /*
197
+ * call-seq:
198
+ * float + other
199
+ *
200
+ * Returns the sum of +float+ and +other+. +other+ can be
201
+ * * GMP::Z
202
+ * * Fixnum
203
+ * * GMP::Q
204
+ * * GMP::F
205
+ * * Bignum
206
+ * * Float
207
+ */
208
+ VALUE r_gmpf_add(VALUE self, VALUE arg)
209
+ {
210
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
211
+ MP_RAT *arg_val_q;
212
+ MP_INT *arg_val_z;
213
+ VALUE res;
214
+ unsigned long prec;
215
+
216
+ mpf_get_struct_prec (self, self_val, prec);
217
+
218
+ if (GMPF_P(arg)) {
219
+ mpf_get_struct (arg, arg_val_f);
220
+ prec_max(prec, arg_val_f);
221
+ mpf_make_struct_init(res, res_val, prec);
222
+ mpf_add(res_val, self_val, arg_val_f);
223
+ } else if (GMPQ_P(arg)) {
224
+ mpq_get_struct (arg, arg_val_q);
225
+ mpf_make_struct_init(res, res_val, prec);
226
+ mpf_set_q (res_val, arg_val_q);
227
+ mpf_add (res_val, res_val, self_val);
228
+ } else if (GMPZ_P(arg)) {
229
+ mpz_get_struct (arg, arg_val_z);
230
+ mpf_make_struct_init(res, res_val, prec);
231
+ mpf_set_z (res_val, arg_val_z);
232
+ mpf_add (res_val, res_val, self_val);
233
+ } else if (FLOAT_P(arg)) {
234
+ mpf_make_struct_init(res, res_val, prec);
235
+ mpf_set_d (res_val, NUM2DBL(arg));
236
+ mpf_add (res_val, res_val, self_val);
237
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
238
+ mpf_make_struct_init(res, res_val, prec);
239
+ mpf_set_si (res_val, FIX2INT(arg));
240
+ mpf_add (res_val, res_val, self_val);
241
+ } else if (BIGNUM_P(arg)) {
242
+ mpz_temp_from_bignum(arg_val_z, arg);
243
+ mpf_make_struct_init(res, res_val, prec);
244
+ mpf_set_z (res_val, arg_val_z);
245
+ mpf_add (res_val, res_val, self_val);
246
+ mpz_temp_free(arg_val_z);
247
+ } else {
248
+ typeerror(ZQFXBD);
249
+ }
250
+
251
+ return res;
252
+ }
253
+
254
+ /*
255
+ * call-seq:
256
+ * float1 - float2
257
+ *
258
+ * Subtracts +float2+ from +float1+. +float2+ can be
259
+ * * GMP::Z
260
+ * * Fixnum
261
+ * * GMP::Q
262
+ * * GMP::F
263
+ * * Bignum
264
+ * * Float
265
+ */
266
+ VALUE r_gmpf_sub(VALUE self, VALUE arg)
267
+ {
268
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
269
+ MP_RAT *arg_val_q;
270
+ MP_INT *arg_val_z;
271
+ VALUE res;
272
+ unsigned long prec;
273
+
274
+ mpf_get_struct_prec (self, self_val, prec);
275
+
276
+ if (GMPF_P(arg)) {
277
+ mpf_get_struct(arg, arg_val_f);
278
+ prec_max(prec, arg_val_f);
279
+ mpf_make_struct_init(res, res_val, prec);
280
+ mpf_sub(res_val, self_val, arg_val_f);
281
+ } else if (GMPQ_P(arg)) {
282
+ mpq_get_struct(arg, arg_val_q);
283
+ mpf_make_struct_init(res, res_val, prec);
284
+ mpf_set_q(res_val, arg_val_q);
285
+ mpf_sub(res_val, self_val, res_val);
286
+ } else if (GMPZ_P(arg)) {
287
+ mpz_get_struct(arg, arg_val_z);
288
+ mpf_make_struct_init(res, res_val, prec);
289
+ mpf_set_z(res_val, arg_val_z);
290
+ mpf_sub(res_val, self_val, res_val);
291
+ } else if (FLOAT_P(arg)) {
292
+ mpf_make_struct_init(res, res_val, prec);
293
+ mpf_set_d(res_val, NUM2DBL(arg));
294
+ mpf_sub(res_val, self_val, res_val);
295
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
296
+ mpf_make_struct_init(res, res_val, prec);
297
+ mpf_set_si(res_val, FIX2INT(arg));
298
+ mpf_sub(res_val, self_val, res_val);
299
+ } else if (BIGNUM_P(arg)) {
300
+ mpz_temp_from_bignum(arg_val_z, arg);
301
+ mpf_make_struct_init(res, res_val, prec);
302
+ mpf_set_z(res_val, arg_val_z);
303
+ mpf_sub(res_val, self_val, res_val);
304
+ mpz_temp_free(arg_val_z);
305
+ } else {
306
+ typeerror(ZQFXBD);
307
+ }
308
+
309
+ return res;
310
+ }
311
+
312
+ /*
313
+ * call-seq:
314
+ * float * other
315
+ *
316
+ * Returns the product of +float+ and +other+. +other+ can be
317
+ * * GMP::Z
318
+ * * Fixnum
319
+ * * GMP::Q
320
+ * * GMP::F
321
+ * * Bignum
322
+ * * Float
323
+ */
324
+ VALUE r_gmpf_mul(VALUE self, VALUE arg)
325
+ {
326
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
327
+ MP_RAT *arg_val_q;
328
+ MP_INT *arg_val_z;
329
+ VALUE res;
330
+ unsigned long prec;
331
+
332
+ mpf_get_struct_prec (self, self_val, prec);
333
+
334
+ if (GMPF_P(arg)) {
335
+ mpf_get_struct(arg, arg_val_f);
336
+ prec_max(prec, arg_val_f);
337
+ mpf_make_struct_init(res, res_val, prec);
338
+ mpf_mul(res_val, self_val, arg_val_f);
339
+ } else if (GMPQ_P(arg)) {
340
+ mpq_get_struct(arg, arg_val_q);
341
+ mpf_make_struct_init(res, res_val, prec);
342
+ mpf_set_q(res_val, arg_val_q);
343
+ mpf_mul(res_val, self_val, res_val);
344
+ } else if (GMPZ_P(arg)) {
345
+ mpz_get_struct(arg, arg_val_z);
346
+ mpf_make_struct_init(res, res_val, prec);
347
+ mpf_set_z(res_val, arg_val_z);
348
+ mpf_mul(res_val, self_val, res_val);
349
+ } else if (FLOAT_P(arg)) {
350
+ mpf_make_struct_init(res, res_val, prec);
351
+ mpf_set_d(res_val, NUM2DBL(arg));
352
+ mpf_mul(res_val, self_val, res_val);
353
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
354
+ mpf_make_struct_init(res, res_val, prec);
355
+ mpf_set_si(res_val, FIX2INT(arg));
356
+ mpf_mul(res_val, self_val, res_val);
357
+ } else if (BIGNUM_P(arg)) {
358
+ mpz_temp_from_bignum(arg_val_z, arg);
359
+ mpf_make_struct_init(res, res_val, prec);
360
+ mpf_set_z(res_val, arg_val_z);
361
+ mpf_mul(res_val, res_val, self_val);
362
+ mpz_temp_free(arg_val_z);
363
+ } else {
364
+ typeerror(ZQFXBD);
365
+ }
366
+
367
+ return res;
368
+ }
369
+
370
+ /*
371
+ * call-seq:
372
+ * float1 / float2
373
+ *
374
+ * Divides +float1+ by +float2+. +float2+ can be
375
+ * * GMP::Z
376
+ * * Fixnum
377
+ * * GMP::Q
378
+ * * GMP::F
379
+ * * Bignum
380
+ * * Float
381
+ */
382
+ VALUE r_gmpf_div(VALUE self, VALUE arg)
383
+ {
384
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
385
+ MP_RAT *arg_val_q;
386
+ MP_INT *arg_val_z;
387
+ VALUE res;
388
+ unsigned long prec;
389
+
390
+ mpf_get_struct_prec (self, self_val, prec);
391
+
392
+ if (GMPF_P(arg)) {
393
+ mpf_get_struct(arg, arg_val_f);
394
+ prec_max(prec, arg_val_f);
395
+ mpf_make_struct_init(res, res_val, prec);
396
+ mpf_div(res_val, self_val, arg_val_f);
397
+ } else if (GMPQ_P(arg)) {
398
+ mpq_get_struct(arg, arg_val_q);
399
+ mpf_make_struct_init(res, res_val, prec);
400
+ mpf_set_q(res_val, arg_val_q);
401
+ mpf_div(res_val, self_val, res_val);
402
+ } else if (GMPZ_P(arg)) {
403
+ mpz_get_struct(arg, arg_val_z);
404
+ mpf_make_struct_init(res, res_val, prec);
405
+ mpf_set_z(res_val, arg_val_z);
406
+ mpf_div(res_val, self_val, res_val);
407
+ } else if (FLOAT_P(arg)) {
408
+ mpf_make_struct_init(res, res_val, prec);
409
+ mpf_set_d(res_val, NUM2DBL(arg));
410
+ mpf_div(res_val, self_val, res_val);
411
+ } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
412
+ mpf_make_struct_init(res, res_val, prec);
413
+ mpf_set_si(res_val, FIX2INT(arg));
414
+ mpf_div(res_val, self_val, res_val);
415
+ } else if (BIGNUM_P(arg)) {
416
+ mpz_temp_from_bignum(arg_val_z, arg);
417
+ mpf_make_struct_init(res, res_val, prec);
418
+ mpf_set_z(res_val, arg_val_z);
419
+ mpf_div(res_val, self_val, res_val);
420
+ mpz_temp_free(arg_val_z);
421
+ } else {
422
+ typeerror(ZQFXBD);
423
+ }
424
+
425
+ return res;
426
+ }
427
+
428
+ /*
429
+ * Document-method: neg
430
+ *
431
+ * call-seq:
432
+ * float.neg
433
+ * -float
434
+ *
435
+ * From the GMP Manual:
436
+ *
437
+ * Returns -+float+.
438
+ */
439
+ /*
440
+ * Document-method: neg!
441
+ *
442
+ * call-seq:
443
+ * float.neg!
444
+ *
445
+ * Sets +float+ to -+float+.
446
+ */
447
+ DEFUN_FLOAT2FLOAT(neg,mpf_neg)
448
+ /*
449
+ * Document-method: abs
450
+ *
451
+ * call-seq:
452
+ * float.abs
453
+ *
454
+ * From the GMP Manual:
455
+ *
456
+ * Returns the absolute value of +float+.
457
+ */
458
+ /*
459
+ * Document-method: abs!
460
+ *
461
+ * call-seq:
462
+ * float.abs!
463
+ *
464
+ * Sets +float+ to the absolute value of +float+.
465
+ */
466
+ DEFUN_FLOAT2FLOAT(abs,mpf_abs)
467
+
468
+
469
+ /**********************************************************************
470
+ * Float Comparison *
471
+ **********************************************************************/
472
+
473
+ int mpf_cmp_value(MP_FLOAT *self_val, VALUE arg)
474
+ {
475
+ MP_FLOAT *arg_val;
476
+ int result;
477
+
478
+ if (GMPF_P(arg)) {
479
+ mpf_get_struct(arg,arg_val);
480
+ return mpf_cmp (self_val, arg_val);
481
+ } else {
482
+ mpf_temp_init(arg_val, mpf_get_prec (self_val));
483
+ mpf_set_value (arg_val, arg);
484
+ result = mpf_cmp (self_val, arg_val);
485
+ mpf_temp_free(arg_val);
486
+ return result;
487
+ }
488
+ }
489
+
490
+ /* what does really "equal" mean ? it's not obvious */
491
+ VALUE r_gmpf_eq(VALUE self, VALUE arg)
492
+ {
493
+ MP_FLOAT *self_val;
494
+ mpf_get_struct (self,self_val);
495
+ return (mpf_cmp_value(self_val, arg) == 0) ? Qtrue : Qfalse;
496
+ }
497
+
498
+ VALUE r_gmpf_cmp(VALUE self, VALUE arg)
499
+ {
500
+ MP_FLOAT *self_val;
501
+ int res;
502
+ mpf_get_struct(self,self_val);
503
+ res = mpf_cmp_value(self_val, arg);
504
+ if (res > 0)
505
+ return INT2FIX(1);
506
+ else if (res == 0)
507
+ return INT2FIX(0);
508
+ else
509
+ return INT2FIX(-1);
510
+ }
511
+
512
+ DEFUN_FLOAT_CMP(lt,<)
513
+ DEFUN_FLOAT_CMP(le,<=)
514
+ DEFUN_FLOAT_CMP(gt,>)
515
+ DEFUN_FLOAT_CMP(ge,>=)
516
+
517
+
518
+ /**********************************************************************
519
+ * _unsorted_ *
520
+ **********************************************************************/
521
+
522
+ DEFUN_FLOAT2FLOAT(floor,mpf_floor)
523
+ DEFUN_FLOAT2FLOAT(trunc,mpf_trunc)
524
+ DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
525
+
526
+ /*
527
+ * call-seq:
528
+ * float.sgn
529
+ *
530
+ * From the GMP Manual:
531
+ *
532
+ * Returns +1 if +float+ > 0, 0 if +float+ == 0, and -1 if +float+ < 0.
533
+ */
534
+ VALUE r_gmpf_sgn(VALUE self)
535
+ {
536
+ MP_FLOAT *self_val;
537
+ mpf_get_struct(self, self_val);
538
+ return INT2FIX(mpf_sgn(self_val));
539
+ }
540
+
541
+ VALUE r_gmpf_get_prec(VALUE self)
542
+ {
543
+ MP_FLOAT *self_val;
544
+ mpf_get_struct(self, self_val);
545
+ return INT2NUM(mpf_get_prec(self_val));
546
+ }
547
+
548
+
549
+ void init_gmpf()
550
+ {
551
+ mGMP = rb_define_module("GMP");
552
+ // rb_define_module_function(mGMP, "Z", r_gmpmod_z, -1);
553
+ // rb_define_module_function(mGMP, "Q", r_gmpmod_q, -1);
554
+ rb_define_module_function(mGMP, "F", r_gmpmod_f, -1);
555
+
556
+ cGMP_F = rb_define_class_under (mGMP, "F", rb_cNumeric);
557
+
558
+
559
+ // Initializing, Assigning Floats
560
+ rb_define_singleton_method(cGMP_F, "new", r_gmpfsg_new, -1);
561
+ rb_define_method(cGMP_F, "initialize", r_gmpf_initialize, -1);
562
+
563
+ // Converting Floats
564
+ rb_define_method(cGMP_F, "to_s", r_gmpf_to_s, 0);
565
+ rb_define_method(cGMP_F, "to_d", r_gmpf_to_d, 0);
566
+ rb_define_alias(cGMP_F, "to_f", "to_d");
567
+
568
+ // Float Arithmetic
569
+ rb_define_method(cGMP_F, "+", r_gmpf_add, 1);
570
+ rb_define_method(cGMP_F, "-", r_gmpf_sub, 1);
571
+ rb_define_method(cGMP_F, "*", r_gmpf_mul, 1);
572
+ rb_define_method(cGMP_F, "/", r_gmpf_div, 1);
573
+ rb_define_method(cGMP_F, "-@", r_gmpf_neg, 0);
574
+ rb_define_method(cGMP_F, "neg!", r_gmpf_neg_self, 0);
575
+ rb_define_method(cGMP_F, "abs", r_gmpf_abs, 0);
576
+ rb_define_method(cGMP_F, "abs!", r_gmpf_abs_self, 0);
577
+
578
+ // Float Comparison
579
+ rb_define_method(cGMP_F, "<=>", r_gmpf_cmp, 1);
580
+ rb_define_method(cGMP_F, ">", r_gmpf_cmp_gt, 1);
581
+ rb_define_method(cGMP_F, ">=", r_gmpf_cmp_ge, 1);
582
+ rb_define_method(cGMP_F, "<", r_gmpf_cmp_lt, 1);
583
+ rb_define_method(cGMP_F, "<=", r_gmpf_cmp_le, 1);
584
+ rb_define_method(cGMP_F, "==", r_gmpf_eq, 1);
585
+
586
+ // _unsorted_
587
+ rb_define_method(cGMP_F, "floor", r_gmpf_floor, 0);
588
+ rb_define_method(cGMP_F, "floor!", r_gmpf_floor_self, 0);
589
+ rb_define_method(cGMP_F, "ceil", r_gmpf_ceil, 0);
590
+ rb_define_method(cGMP_F, "ceil!", r_gmpf_ceil_self, 0);
591
+ rb_define_method(cGMP_F, "trunc", r_gmpf_trunc, 0);
592
+ rb_define_method(cGMP_F, "trunc!", r_gmpf_trunc_self, 0);
593
+ rb_define_method(cGMP_F, "sgn", r_gmpf_sgn, 0);
594
+ rb_define_method(cGMP_F, "prec", r_gmpf_get_prec, 0);
595
+ }