gmp 0.4.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +109 -0
- data/INSTALL +4 -0
- data/README.rdoc +357 -0
- data/benchmark/COPYING +674 -0
- data/benchmark/README +75 -0
- data/benchmark/divide +34 -0
- data/benchmark/gcd +38 -0
- data/benchmark/gexpr +0 -0
- data/benchmark/gexpr.c +359 -0
- data/benchmark/multiply +44 -0
- data/benchmark/rsa +93 -0
- data/benchmark/runbench +147 -0
- data/benchmark/version +1 -0
- data/ext/extconf.rb +30 -0
- data/ext/gmp.c +197 -0
- data/ext/gmpbench_timing.c +80 -0
- data/ext/gmpf.c +595 -0
- data/ext/gmpf.h +144 -0
- data/ext/gmpq.c +780 -0
- data/ext/gmpq.h +12 -0
- data/ext/gmprandstate.c +224 -0
- data/ext/gmpz.c +1968 -0
- data/ext/gmpz.h +20 -0
- data/ext/libgmp-10.dll +0 -0
- data/ext/ruby_gmp.h +243 -0
- data/ext/takeover.h +36 -0
- data/manual.pdf +0 -0
- data/manual.tex +804 -0
- data/test/README +34 -0
- data/test/tc_cmp.rb +74 -0
- data/test/tc_division.rb +109 -0
- data/test/tc_f_arithmetics_coersion.rb +71 -0
- data/test/tc_f_precision.rb +48 -0
- data/test/tc_fib_fac_nextprime.rb +51 -0
- data/test/tc_floor_ceil_truncate.rb +21 -0
- data/test/tc_logical_roots.rb +48 -0
- data/test/tc_q.rb +27 -0
- data/test/tc_q_basic.rb +41 -0
- data/test/tc_random.rb +54 -0
- data/test/tc_sgn_neg_abs.rb +47 -0
- data/test/tc_swap.rb +19 -0
- data/test/tc_z.rb +71 -0
- data/test/tc_z_basic.rb +35 -0
- data/test/tc_z_exponentiation.rb +22 -0
- data/test/tc_z_gcd_lcm_invert.rb +57 -0
- data/test/tc_z_jac_leg_rem.rb +73 -0
- data/test/tc_z_logic.rb +54 -0
- data/test/tc_z_shifts_last_bits.rb +22 -0
- data/test/tc_z_to_d_to_i.rb +24 -0
- data/test/tc_zerodivisionexceptions.rb +17 -0
- data/test/test-12.rb +14 -0
- data/test/test-19.rb +13 -0
- data/test/test-20.rb +29 -0
- data/test/test-21.rb +37 -0
- data/test/test-22.rb +12 -0
- data/test/test-23.rb +11 -0
- data/test/test_helper.rb +8 -0
- data/test/unit_tests.rb +39 -0
- 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
|
+
}
|
data/ext/gmpf.c
ADDED
@@ -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
|
+
}
|