gmp 0.4.7 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/CHANGELOG +31 -0
  2. data/README.rdoc +16 -8
  3. data/benchmark/multiply +1 -1
  4. data/benchmark/multiply.gc +57 -0
  5. data/benchmark/pi +126 -0
  6. data/benchmark/srb.sh +21 -0
  7. data/ext/extconf.rb +3 -0
  8. data/ext/gmp.c +16 -7
  9. data/ext/gmpbench_timing.c +1 -1
  10. data/ext/gmpf.c +445 -104
  11. data/ext/gmpq.c +25 -17
  12. data/ext/gmpz.c +232 -120
  13. data/ext/mprnd.c +23 -5
  14. data/ext/ruby_gmp.h +75 -9
  15. data/lib/gmp.rb +9 -0
  16. data/manual.pdf +0 -0
  17. data/manual.tex +494 -60
  18. data/test/README +1 -0
  19. data/test/mpfr_tcbrt.rb +95 -0
  20. data/test/mpfr_tisnan.rb +70 -0
  21. data/test/mpfr_trec_sqrt.rb +62 -0
  22. data/test/mpfr_tsqrt.rb +142 -6
  23. data/test/tc_cmp.rb +4 -4
  24. data/test/tc_constants.rb +10 -0
  25. data/test/tc_division.rb +13 -2
  26. data/test/tc_f_arithmetics_coersion.rb +2 -2
  27. data/test/tc_f_precision.rb +4 -3
  28. data/test/tc_fib_fac_nextprime.rb +2 -2
  29. data/test/tc_floor_ceil_truncate.rb +2 -2
  30. data/test/tc_hashes.rb +0 -2
  31. data/test/tc_logical_roots.rb +1 -3
  32. data/test/tc_mpfr_constants.rb +11 -0
  33. data/test/tc_mpfr_functions.rb +22 -9
  34. data/test/tc_mpfr_random.rb +1 -3
  35. data/test/tc_mpfr_rounding.rb +10 -7
  36. data/test/tc_q.rb +1 -3
  37. data/test/tc_q_basic.rb +3 -5
  38. data/test/tc_random.rb +1 -3
  39. data/test/tc_sgn_neg_abs.rb +1 -3
  40. data/test/tc_swap.rb +1 -3
  41. data/test/tc_z.rb +3 -3
  42. data/test/tc_z_addmul.rb +92 -0
  43. data/test/tc_z_basic.rb +6 -8
  44. data/test/tc_z_exponentiation.rb +1 -3
  45. data/test/tc_z_gcd_lcm_invert.rb +1 -3
  46. data/test/tc_z_jac_leg_rem.rb +1 -3
  47. data/test/tc_z_logic.rb +2 -2
  48. data/test/tc_z_shifts_last_bits.rb +2 -2
  49. data/test/tc_z_to_d_to_i.rb +2 -2
  50. data/test/test_helper.rb +1 -1
  51. data/test/test_unit/assertions.rb +31 -0
  52. data/test/unit_tests.rb +33 -27
  53. metadata +31 -6
data/CHANGELOG CHANGED
@@ -1,3 +1,34 @@
1
+ 0.5.3:
2
+ * Now supporting GMP 5.0.1 (I now test with GMP 4.3.2 and 5.0.1).
3
+ * Now supporting MPFR 3.0.0 (I now test with MPFR 2.4.2 and 3.0.0).
4
+ * Now supporting Ruby 1.9.2. A few changes had to be made.
5
+ * Added MPFR method GMP::F.zero? (mpfr_zero_p) with tests.
6
+ * Added MPFR method GMP::F.regular? (mpfr_regular_p) with tests (MPFR 3.0.0
7
+ only).
8
+ * Added MPFR methods GMP::F.rec_sqrt (mpfr_rec_sqrt) and GMP::F.cbrt
9
+ (mpfr_rec_cbrt), both heavily tested.
10
+ * Added MPFR method GMP::F.digamma (mpfr_digamma), not tested.
11
+ * Added GMP::F.prec= (mpf_set_prec) and GMP::F.prec_raw= (mpf_set_prec_raw),
12
+ neither tested yet.
13
+ * Added a dramatic amount of content to the manual. 26 pages.
14
+ * Unit test results: 98 tests, 11974 assertions, 0 failures, 0 errors
15
+ * Unit test results: 98 tests, 11961 assertions, 0 failures, 0 errors (MPFR 2.4.2)
16
+ * Unit test results: 79 tests, 742 assertions, 0 failures, 0 errors (w/o MPFR)
17
+
18
+ 0.4.19:
19
+ * Added FIX2NUM macro to help support x86_64.
20
+ * Fixed bug in MPRF functions; they were not using specified rounding modes.
21
+ * Added ** (pow) to GMP::F (when not using MPFR)
22
+ * Fixed add'l bug in MPFR functions, when specifying a rounding mode.
23
+ * Fixed memory bug when specifying an invalid precision, or base range.
24
+ * Fixed GMP::Z#pow (note that GMP::Z.pow has always worked.)
25
+ * Added many tests from MPFR's tsqrt.c. This actually exposed a lot of bugs in
26
+ the gem.
27
+ * Added GMP::Z.size (mpz_size). Not tested yet.
28
+ * Added GMP::Z.addmul! (mpz_addmul) with tests.
29
+ * Unit test results: 90 tests, 1500 assertions, 0 failures, 0 errors
30
+ * Unit test results: 79 tests, 742 assertions, 0 failures, 0 errors (w/o MPFR)
31
+
1
32
  0.4.7:
2
33
  * Added 6 MPFR trig methods, plus eint, li2, gamma, lngamma, zeta, erf, erfc,
3
34
  j0, j1, jn, y0, y1, and yn.
@@ -87,6 +87,12 @@ as pi, are defined under class methods of GMP::F, listed below.
87
87
  GMP::GMP_RNDZ #=> The constant representing "round toward zero"
88
88
  GMP::GMP_RNDU #=> The constant representing "round toward plus infinity"
89
89
  GMP::GMP_RNDD #=> The constant representing "round toward minus infinity"
90
+ New in MPFR 3.0.0:
91
+ GMP::MPFR_RNDN
92
+ GMP::MPFR_RNDZ
93
+ GMP::MPFR_RNDU
94
+ GMP::MPFR_RNDD
95
+ GMP::MPFR_RNDA #=> The constant representing "round away from zero"
90
96
 
91
97
  =Classes
92
98
 
@@ -192,6 +198,7 @@ You can also call them as:
192
198
  popcount the number of bits equal to 1
193
199
  sizeinbase(b) digits in base b
194
200
  size_in_bin digits in binary
201
+ size number of limbs
195
202
  to_i convert to Fixnum or Bignum
196
203
  GMP::Q and GMP::F
197
204
  / division
@@ -226,6 +233,8 @@ You can also call them as:
226
233
  const_catalan returns catalan
227
234
  GMP::F
228
235
  sqrt square root of the object
236
+ rec_sqrt square root of the recprical of the object
237
+ cbrt cube root of the object
229
238
  ** power
230
239
  log natural logarithm of object
231
240
  log2 binary logarithm of object
@@ -241,6 +250,7 @@ You can also call them as:
241
250
  li2 real part of the dilogarithm of object
242
251
  gamma Gamma fucntion of object
243
252
  lngamma logarithm of the Gamma function of object
253
+ digamma Digamma function of object (MPFR_VERSION >= "3.0.0")
244
254
  zeta Reimann Zeta function of object
245
255
  erf error function of object
246
256
  erfc complementary error function of object
@@ -265,13 +275,14 @@ You can also call them as:
265
275
  sec |
266
276
  csc |
267
277
  cot |
268
- aconh |
278
+ acosh |
269
279
  asinh |
270
280
  atanh /
271
281
  nan? \
272
282
  infinite? | type of floating point number
273
283
  finite? |
274
- number? /
284
+ number? |
285
+ regular? / (MPFR_VERSION >= "3.0.0")
275
286
  GMP::RandState
276
287
  mpfr_urandomb(fixnum) get uniformly distributed random floating-point
277
288
  number within 0 <= rop < 1
@@ -290,8 +301,6 @@ that is fixed with the unit_test gem.
290
301
 
291
302
  =Known Issues
292
303
 
293
- * GMP::Z#pow does not appear to be working at all. Looking at the code, I don't
294
- think it ever did.
295
304
  * Don't call GMP::RandState(:lc_2exp_size). Give a 2nd arg.
296
305
 
297
306
  =Precision
@@ -380,11 +389,10 @@ efficiency in GMP; the inefficiencies of the gmp gem are relatively greater.
380
389
  =Todo
381
390
 
382
391
  These are inherited from Tomasz. I will go through these and see which are
383
- still relevant.
392
+ still relevant, and which I understand.
384
393
 
385
394
  * mpz_fits_* and 31 vs. 32 integer variables
386
395
  * fix all sign issues (don't know what these are)
387
- * floats with precision control
388
396
  * to_s vs. inspect
389
397
  * check if mpz_addmul_ui would optimize some statements
390
398
  * some system that allows using denref and numref as normal ruby objects (?)
@@ -404,5 +412,5 @@ still relevant.
404
412
  * check if different sorting of operatations gives better cache usage
405
413
  * GMP::* op RubyFloat and RubyFloat op GMP::*
406
414
  * sort checks
407
- * GMP::Q.to_s(base), GMP::F.to_s(base)
408
- * benchmark gcdext, pi
415
+ * GMP::Q.to_s(base), GMP::F.to_s(base) (test it!)
416
+ * benchmark gcdext, pi
@@ -41,4 +41,4 @@ while true
41
41
  f = f * 0.1
42
42
  end
43
43
 
44
- puts "RESULT: %#{decimals}f operations per second\n" % ops_per_sec
44
+ puts "RESULT: %#{decimals}f operations per second\n" % ops_per_sec
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '../ext/gmp'
4
+
5
+ multiplicands = ARGV
6
+ random_state = GMP::RandState.new
7
+
8
+ if multiplicands.size > 1
9
+ m, n = multiplicands[0].to_i, multiplicands[1].to_i
10
+ x = random_state.urandomb(m)
11
+ y = random_state.urandomb(n)
12
+ else
13
+ m = multiplicands[0].to_i
14
+ x = random_state.urandomb(m)
15
+ y = x
16
+ end
17
+
18
+ t = GMP::time { z = x * y }
19
+ iterations = (1 + (1e4 / t)).to_i
20
+
21
+ if multiplicands.size > 1
22
+ print "Multiplying %i-bit number with %i-bit number %i times..." % [m, n, iterations]
23
+ else
24
+ print "Squaring a %i-bit number %i times..." % [m, iterations]
25
+ end
26
+ STDOUT.flush
27
+
28
+ t0 = GMP::cputime
29
+ #iterations.times do
30
+ # z = x * y
31
+ #end
32
+ parts = 512
33
+ foo = iterations / parts
34
+ bar = iterations % parts
35
+ foo.times do
36
+ parts.times do
37
+ z = x * y
38
+ end
39
+ GC.start
40
+ end
41
+ bar.times do
42
+ z = x * y
43
+ end
44
+
45
+ ti = GMP::cputime - t0
46
+
47
+ puts "done!"
48
+ ops_per_sec = 1000.0 * iterations / ti
49
+ f = 100.0
50
+ decimals = 0
51
+ while true
52
+ decimals += 1
53
+ break if ops_per_sec > f
54
+ f = f * 0.1
55
+ end
56
+
57
+ puts "RESULT: %#{decimals}f operations per second\n" % ops_per_sec
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '../ext/gmp'
4
+
5
+ A = 13591409
6
+ B = 545140134
7
+ C = 640320
8
+ D = 12
9
+
10
+ BITS_PER_DIGIT = 3.32192809488736234787
11
+ DIGITS_PER_ITER = 14.1816474627254776555
12
+ DOUBLE_PREC = 53
13
+ INIT_FACS = 32
14
+
15
+ def my_sqrt_ui(r, x)
16
+ prec0 = r.prec
17
+ if prec0 < DOUBLE_PREC
18
+ r = GMP::F(Math.sqrt(x))
19
+ return
20
+ end
21
+
22
+ bits = 0
23
+ prec = prec0
24
+ while prec > DOUBLE_PREC
25
+ bit = prec & 1
26
+ prec = (prec+bit)/2
27
+ bits = bits*2 + bit
28
+ end
29
+
30
+ @t1.prec_raw=DOUBLE_PREC
31
+ @t1 = GMP::F(1/Math.sqrt(x))
32
+
33
+ while prec < prec0
34
+ prec *= 2
35
+ break if prec >= prec0
36
+ @t2.prec_raw=prec
37
+ @t2 = @t1 * @t1 # half x half -> full
38
+ @t2 *= x
39
+ @t2 = 1 - @t2
40
+ @t2.prec_raw=prec/2
41
+ @t2.div_2exp(@t2, 1)
42
+ @t2 *= @t1 # half x half -> half
43
+ @t1.prec_raw=prec
44
+ @t1 += @t2
45
+
46
+ prec -= bits & 1
47
+ bits /= 2
48
+ end
49
+
50
+ @t2.prec_raw=prec0/2
51
+ @t2 = @t1 * x
52
+ r = @t2 * @t2 # half * half -> full
53
+ r = x - r
54
+ @t1 *= r # half * half -> half
55
+ @t1.div_2exp(@t1, 1)
56
+ r = @t1+@t2
57
+ end
58
+
59
+ def my_div(r, y, x)
60
+ prec0 = r.prec
61
+ if prec0 <= DOUBLE_PREC
62
+ r = GMP::F(y.to_f / x.to_f)
63
+ return
64
+ end
65
+
66
+ bits = 0
67
+ prec = prec0
68
+ while prec > DOUBLE_PREC
69
+ bit = prec & 1
70
+ prec = (prec+bit)/2
71
+ bits = bits*2 + bit
72
+ end
73
+
74
+ @t1.prec_raw=DOUBLE_PREC
75
+ @t1 = 1 / x
76
+
77
+ while prec < prec0
78
+ prec *= 2
79
+ if prec < prec0
80
+ @t2.prec_raw=prec
81
+ @t2 = x * @t1 # full x half -> full
82
+ @t2 = 1 - @t2
83
+ @t2.prec_raw=prec/2
84
+ @t2 *= @t1 # half * half -> half
85
+ @t1.prec_raw=prec
86
+ @t1 += @t2
87
+ else
88
+ prec = prec0
89
+ @t2.prec_raw=prec/2
90
+ @t2 = @t1 * y # half * half -> half
91
+ r = x * @t2 # full * half -> full
92
+ r = y - r
93
+ t1 *= r # half * half -> half
94
+ r = t1 + t2
95
+ break
96
+ end
97
+
98
+ prec -= bits & 1
99
+ bits /= 2
100
+ end
101
+ end
102
+
103
+ def min(x,y); x < y ? x : y; end
104
+ def max(x,y); x > y ? x : y; end
105
+
106
+ Fac_t = Struct.new(max_facs, num_facs, fac, pow)
107
+ Sieve_t = Struct.new(fac, pow, nxt);
108
+
109
+ sieve = Sieve_t.new
110
+ ftmp = Fac_t.new
111
+ fmul = Fac_t.new
112
+
113
+ def fac_show(f)
114
+ (0...(f.num_facs)).each do |f|
115
+ if f.pow[i] == 1
116
+ print "#{f.fac[i]} "
117
+ else
118
+ print "#{f.fac[i]}^#{f.pow[i]} "
119
+ end
120
+ end
121
+ puts ""
122
+ end
123
+
124
+ def fac_reset(f)
125
+ f.num_facs = 0
126
+ end
@@ -0,0 +1,21 @@
1
+ #! /bin/bash
2
+ source ~/.rvm/scripts/rvm
3
+
4
+ if [ $# -gt 0 ]; then
5
+ rvm use $1
6
+ if [ $? -ne 0 ]; then
7
+ echo "ERROR: rvm doesn't like \"$1\". Quitting."
8
+ exit 1
9
+ fi
10
+ fi
11
+
12
+ LIBS=-lgmp ./runbench -n
13
+ if [ $? -ne 0 ]; then
14
+ echo "ERROR: ruby extconf.rb didn't work so hot. Quitting."
15
+ exit 2
16
+ fi
17
+
18
+ echo "RUBY: `ruby -v`"
19
+ echo "GMP: `ruby -r '../lib/gmp' -e \"puts GMP::GMP_VERSION\"`"
20
+ echo "GMP_CC: `ruby -r '../lib/gmp' -e \"puts GMP::GMP_CC\"`"
21
+
@@ -5,6 +5,7 @@ require 'mkmf'
5
5
  dir_config('gmp')
6
6
  dir_config('mpfr')
7
7
 
8
+ use_if_mpfr = ! ARGV.include?('--no-mpfr')
8
9
  ok = true
9
10
  unless have_header('gmp.h')
10
11
  $stderr.puts "can't find gmp.h, try --with-gmp-include=<path>"
@@ -16,11 +17,13 @@ unless have_library('gmp', '__gmpz_init')
16
17
  ok = false
17
18
  end
18
19
 
20
+ if use_if_mpfr
19
21
  if (have_header('mpfr.h') and
20
22
  have_header('mpf2mpfr.h') and
21
23
  have_library('mpfr', 'mpfr_init'))
22
24
  $CFLAGS += ' -DMPFR'
23
25
  end
26
+ end
24
27
 
25
28
  $CFLAGS += ' -Wall -W -O6 -g'
26
29
  if ok
data/ext/gmp.c CHANGED
@@ -13,7 +13,11 @@ VALUE cGMP_Rnd;
13
13
 
14
14
  void r_gmpz_free(void *ptr) { mpz_clear (ptr); free (ptr); }
15
15
  void r_gmpq_free(void *ptr) { mpq_clear (ptr); free (ptr); }
16
+ #ifdef MPFR
17
+ void r_gmpf_free(void *ptr) { mpfr_clear (ptr); free (ptr); }
18
+ #else
16
19
  void r_gmpf_free(void *ptr) { mpf_clear (ptr); free (ptr); }
20
+ #endif
17
21
  void r_gmprandstate_free(void *ptr) { gmp_randclear (ptr); free (ptr); }
18
22
 
19
23
  static void mpq_str_set(MP_RAT *ROP, char *str)
@@ -46,7 +50,7 @@ static VALUE r_gmpq_initialize(int argc, VALUE *argv, VALUE self)
46
50
  mpq_get_struct(argv[0], arg_val);
47
51
  mpq_set (self_val, arg_val);
48
52
  } else if (argc == 1 && STRING_P(argv[0])) {
49
- mpq_str_set (self_val, STR2CSTR(argv[0]));
53
+ mpq_str_set (self_val, StringValuePtr(argv[0]));
50
54
  } else {
51
55
  mpz_set_value (mpq_numref(self_val), argv[0]);
52
56
  if (argc == 2) {
@@ -83,10 +87,10 @@ static VALUE r_gmpfsg_set_default_prec(VALUE klass, VALUE arg)
83
87
  {
84
88
  (void)klass;
85
89
  if (FIXNUM_P(arg)) {
86
- if (FIX2INT(arg) <= 0) {
90
+ if (FIX2NUM(arg) <= 0) {
87
91
  rb_raise(rb_eRangeError, "prec must be positive");
88
92
  }
89
- mpf_set_default_prec (FIX2INT(arg));
93
+ mpf_set_default_prec (FIX2NUM(arg));
90
94
  } else {
91
95
  rb_raise(rb_eTypeError, "prec must be FixNum");
92
96
  }
@@ -133,6 +137,11 @@ static VALUE r_gmpfsg_set_default_rounding_mode(VALUE klass, VALUE arg)
133
137
  case 3:
134
138
  mpfr_set_default_rounding_mode (GMP_RNDD);
135
139
  break;
140
+ #if MPFR_VERSION_MAJOR>2
141
+ case 4:
142
+ mpfr_set_default_rounding_mode (MPFR_RNDA);
143
+ break;
144
+ #endif
136
145
  }
137
146
 
138
147
  return Qnil;
@@ -160,6 +169,10 @@ mp_rnd_t r_get_rounding_mode(VALUE rnd)
160
169
  return GMP_RNDU;
161
170
  case 3:
162
171
  return GMP_RNDD;
172
+ #if MPFR_VERSION_MAJOR>2
173
+ case 4:
174
+ return MPFR_RNDA;
175
+ #endif
163
176
  default:
164
177
  return GMP_RNDN;
165
178
  }
@@ -188,10 +201,6 @@ void Init_gmp() {
188
201
  rb_define_const(mGMP, "MPFR_VERSION", rb_str_new2(MPFR_VERSION_STRING));
189
202
  rb_define_const(mGMP, "MPFR_PREC_MIN", INT2FIX(MPFR_PREC_MIN));
190
203
  rb_define_const(mGMP, "MPFR_PREC_MAX", INT2FIX(MPFR_PREC_MAX));
191
- // rb_define_const(mGMP, "GMP_RNDN", INT2FIX(0));
192
- // rb_define_const(mGMP, "GMP_RNDZ", INT2FIX(1));
193
- // rb_define_const(mGMP, "GMP_RNDU", INT2FIX(2));
194
- // rb_define_const(mGMP, "GMP_RNDD", INT2FIX(3));
195
204
  #endif /* MPFR */
196
205
 
197
206
  cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
@@ -41,7 +41,7 @@ cputime ()
41
41
  struct rusage rus;
42
42
 
43
43
  getrusage (0, &rus);
44
- return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
44
+ return (int) (rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000);
45
45
  }
46
46
  #endif
47
47
 
data/ext/gmpf.c CHANGED
@@ -72,8 +72,8 @@ VALUE r_gmpfsg_new(int argc, VALUE *argv, VALUE klass)
72
72
  VALUE res;
73
73
  (void)klass;
74
74
 
75
- if (argc > 2)
76
- rb_raise(rb_eArgError, "wrong # of arguments(%d for 0, 1 or 2)", argc);
75
+ if (argc > 4)
76
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0, 1 2, 3, or 4)", argc);
77
77
 
78
78
  mpf_make_struct (res, res_val);
79
79
  rb_obj_call_init(res, argc, argv);
@@ -90,30 +90,68 @@ VALUE r_gmpf_initialize(int argc, VALUE *argv, VALUE self)
90
90
  mpf_get_struct (self, self_val);
91
91
 
92
92
  if (argc==0) {
93
- mpf_init(self_val);
94
- mpf_set_si(self_val, 0);
93
+ #ifdef MPFR
94
+ mpfr_init (self_val);
95
+ mpfr_set_si (self_val, 0, __gmp_default_rounding_mode);
96
+ #else
97
+ r_mpf_init (self_val);
98
+ mpf_set_si (self_val, 0);
99
+ #endif
95
100
  return Qnil;
96
101
  }
97
102
 
98
103
  arg = argv[0];
99
104
 
100
- if (argc == 2) {
105
+ //argc >= 2 ==> argv[0] is value, argv[1] is prec
106
+ if (argc >= 2) {
101
107
  if (FIXNUM_P(argv[1])) {
102
108
  if (FIX2INT(argv[1]) >= 0)
103
109
  prec = FIX2INT(argv[1]);
104
- else
110
+ else {
111
+ r_mpf_init (self_val);
105
112
  rb_raise(rb_eRangeError, "prec must be non-negative");
113
+ }
106
114
  } else {
115
+ r_mpf_init (self_val);
107
116
  rb_raise(rb_eTypeError, "prec must be a Fixnum");
108
117
  }
109
118
  } else if (GMPF_P(arg)) {
110
119
  mpf_get_struct (arg, arg_val_f);
111
120
  prec = mpf_get_prec (arg_val_f);
112
121
  }
122
+ #ifdef MPFR
123
+ int base = 10;
113
124
  if (prec == 0)
114
- mpf_init (self_val);
125
+ mpfr_init (self_val);
115
126
  else
116
- mpf_init2 (self_val, prec);
127
+ mpfr_init2 (self_val, prec);
128
+
129
+ if (STRING_P(argv[0])) {
130
+ if (argc >= 3) {
131
+ if (FIXNUM_P(argv[2])) {
132
+ if (FIX2INT(argv[2]) >= 2 && FIX2INT(argv[2]) <= 36)
133
+ base = FIX2INT(argv[2]);
134
+ else
135
+ rb_raise(rb_eRangeError, "base must be between 2 and 36");
136
+ }
137
+ else {
138
+ rb_raise(rb_eTypeError, "base must be a Fixnum");
139
+ }
140
+ }
141
+ if (argc == 4) {
142
+ // FIGURE IT OUT. ACCEPT A ROUNDING MODE!
143
+ }
144
+
145
+ mpf_set_value2 (self_val, arg, base);
146
+ return Qnil;
147
+ }
148
+
149
+ #else
150
+ if (prec == 0)
151
+ r_mpf_init (self_val);
152
+ else
153
+ r_mpf_init2 (self_val, prec);
154
+ #endif
117
155
 
118
156
  if (GMPF_P(arg)) {
119
157
  mpf_get_struct (arg, arg_val_f);
@@ -130,32 +168,71 @@ void mpf_set_value(MP_FLOAT *self_val, VALUE arg)
130
168
  {
131
169
  MP_RAT *arg_val_q;
132
170
  MP_INT *arg_val_z;
171
+ int result;
133
172
 
173
+ #ifdef MPFR
174
+ if (GMPQ_P(arg)) {
175
+ mpq_get_struct(arg, arg_val_q);
176
+ r_mpf_set_q(self_val, arg_val_q);
177
+ } else if (GMPZ_P(arg)) {
178
+ mpz_get_struct(arg, arg_val_z);
179
+ r_mpf_set_z(self_val, arg_val_z);
180
+ } else if (FLOAT_P(arg)) {
181
+ mpfr_set_d(self_val, NUM2DBL(arg), __gmp_default_rounding_mode);
182
+ } else if (FIXNUM_P(arg)) {
183
+ mpf_set_si(self_val, FIX2NUM(arg));
184
+ } else if (STRING_P(arg)) {
185
+ result = mpfr_set_str(self_val, StringValuePtr(arg), 10, __gmp_default_rounding_mode);
186
+ if (result == -1) {
187
+ rb_raise(rb_eRuntimeError, "Badly formatted string");
188
+ }
189
+ } else if (BIGNUM_P(arg)) {
190
+ #if 1 /* GMP3 code */
191
+ mpz_temp_from_bignum(arg_val_z, arg);
192
+ r_mpf_set_z(self_val, arg_val_z);
193
+ mpz_temp_free(arg_val_z);
194
+ #endif
195
+ #else
134
196
  if (GMPQ_P(arg)) {
135
197
  mpq_get_struct(arg, arg_val_q);
136
- mpf_set_q(self_val, arg_val_q);
198
+ r_mpf_set_q(self_val, arg_val_q);
137
199
  } else if (GMPZ_P(arg)) {
138
200
  mpz_get_struct(arg, arg_val_z);
139
- mpf_set_z(self_val, arg_val_z);
201
+ r_mpf_set_z(self_val, arg_val_z);
140
202
  } else if (FLOAT_P(arg)) {
141
- mpf_set_d(self_val, NUM2DBL(arg));
203
+ r_mpf_set_d(self_val, NUM2DBL(arg));
142
204
  } else if (FIXNUM_P(arg)) {
143
- mpf_set_si(self_val, FIX2INT(arg));
205
+ mpf_set_si(self_val, FIX2NUM(arg));
144
206
  } else if (STRING_P(arg)) {
145
- if (mpf_set_str(self_val, STR2CSTR(arg), 10) == -1) {
207
+ result = r_mpf_set_str(self_val, StringValuePtr(arg), 10);
208
+ if (result == -1) {
146
209
  rb_raise(rb_eRuntimeError, "Badly formatted string");
147
210
  }
148
211
  } else if (BIGNUM_P(arg)) {
149
212
  #if 1 /* GMP3 code */
150
213
  mpz_temp_from_bignum(arg_val_z, arg);
151
- mpf_set_z(self_val, arg_val_z);
214
+ r_mpf_set_z(self_val, arg_val_z);
152
215
  mpz_temp_free(arg_val_z);
216
+ #endif
153
217
  #endif
154
218
  } else {
155
219
  rb_raise(rb_eTypeError, "Don't know how to convert %s into GMP::F", rb_class2name(rb_class_of(arg)));
156
220
  }
157
221
  }
158
222
 
223
+ #ifdef MPFR
224
+ void mpf_set_value2(MP_FLOAT *self_val, VALUE arg, int base)
225
+ {
226
+ int result;
227
+
228
+ result = mpfr_set_str(self_val, StringValuePtr(arg), base, __gmp_default_rounding_mode);
229
+
230
+ if (result == -1) {
231
+ rb_raise(rb_eRuntimeError, "Badly formatted string");
232
+ }
233
+ }
234
+ #endif
235
+
159
236
  /*
160
237
  * call-seq:
161
238
  * GMP::F(arg)
@@ -181,6 +258,48 @@ VALUE r_gmpf_to_d(VALUE self)
181
258
  return rb_float_new(mpf_get_d(self_val));
182
259
  }
183
260
 
261
+ #ifdef MPFR
262
+ /*
263
+ * Document-method: to_s
264
+ *
265
+ * call-seq:
266
+ * float.to_s
267
+ *
268
+ * Returns the decimal representation of +float+, as a string.
269
+ */
270
+ VALUE r_gmpf_to_s(VALUE self)
271
+ {
272
+ MP_FLOAT *self_val;
273
+ char *str, *str2;
274
+ VALUE res;
275
+ mp_exp_t exponent;
276
+
277
+ mpf_get_struct(self, self_val);
278
+
279
+ //mpfr_sprintf(str, "%Rf", self_val);
280
+ //res = rb_str_new2(str);
281
+
282
+ str = mpfr_get_str(NULL, &exponent, 10, 0, self_val, __gmp_default_rounding_mode);
283
+ if ((strcmp(str, "NaN") == 0) ||
284
+ (strcmp(str, "Inf") == 0) ||
285
+ (strcmp(str, "-Inf") == 0))
286
+ {
287
+ res = rb_str_new2(str);
288
+ }
289
+ else
290
+ {
291
+ if (str[0] == '-')
292
+ __gmp_asprintf(&str2, "-0.%se%+ld", str+1, exponent);
293
+ else
294
+ __gmp_asprintf(&str2, "0.%se%+ld", str, exponent);
295
+ res = rb_str_new2(str2);
296
+ mpfr_free_str(str2);
297
+ }
298
+
299
+ mpfr_free_str(str);
300
+ return res;
301
+ }
302
+ #else
184
303
  /*
185
304
  * Document-method: to_s
186
305
  *
@@ -217,12 +336,14 @@ VALUE r_gmpf_to_s(VALUE self)
217
336
  free(str);
218
337
  return res;
219
338
  }
339
+ #endif
220
340
 
221
341
 
222
342
  /**********************************************************************
223
343
  * Float Arithmetic *
224
344
  **********************************************************************/
225
345
 
346
+ #ifndef MPFR
226
347
  /*
227
348
  * call-seq:
228
349
  * float + other
@@ -241,7 +362,7 @@ VALUE r_gmpf_add(VALUE self, VALUE arg)
241
362
  MP_RAT *arg_val_q;
242
363
  MP_INT *arg_val_z;
243
364
  VALUE res;
244
- unsigned long prec;
365
+ mpfr_prec_t prec;
245
366
 
246
367
  mpf_get_struct_prec (self, self_val, prec);
247
368
 
@@ -266,7 +387,7 @@ VALUE r_gmpf_add(VALUE self, VALUE arg)
266
387
  mpf_add (res_val, res_val, self_val);
267
388
  } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
268
389
  mpf_make_struct_init(res, res_val, prec);
269
- mpf_set_si (res_val, FIX2INT(arg));
390
+ mpf_set_si (res_val, FIX2NUM(arg));
270
391
  mpf_add (res_val, res_val, self_val);
271
392
  } else if (BIGNUM_P(arg)) {
272
393
  mpz_temp_from_bignum(arg_val_z, arg);
@@ -280,6 +401,72 @@ VALUE r_gmpf_add(VALUE self, VALUE arg)
280
401
 
281
402
  return res;
282
403
  }
404
+ #else
405
+ /*
406
+ * call-seq:
407
+ * float + other
408
+ *
409
+ * Returns the sum of +float+ and +other+. +other+ can be
410
+ * * GMP::Z
411
+ * * Fixnum
412
+ * * GMP::Q
413
+ * * GMP::F
414
+ * * Bignum
415
+ * * Float
416
+ */
417
+ #define DEFUN_F_ZQXFBD2F(fname) \
418
+ VALUE r_gmpfr_##fname(int argc, VALUE *argv, VALUE self) \
419
+ { \
420
+ MP_FLOAT *self_val, *res_val, *arg_val_f; \
421
+ MP_RAT *arg_val_q; \
422
+ MP_INT *arg_val_z; \
423
+ VALUE arg, res, res_prec, rnd_mode; \
424
+ mpfr_prec_t prec, res_prec_val; \
425
+ mp_rnd_t rnd_mode_val; \
426
+ \
427
+ rb_scan_args (argc, argv, "12", &arg, &rnd_mode, &res_prec); \
428
+ \
429
+ mpf_get_struct_prec (self, self_val, prec); \
430
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
431
+ else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
432
+ if (NIL_P (res_prec)) { res_prec_val = prec; } \
433
+ else { res_prec_val = FIX2INT (res_prec); } \
434
+ mpf_make_struct_init (res, res_val, res_prec_val); \
435
+ \
436
+ if (GMPF_P (arg)) { \
437
+ mpf_get_struct (arg, arg_val_f); \
438
+ prec_max (prec, arg_val_f); \
439
+ mpf_make_struct_init (res, res_val, prec); \
440
+ mpfr_##fname (res_val, self_val, arg_val_f, rnd_mode_val); \
441
+ } else if (GMPQ_P (arg)) { \
442
+ mpq_get_struct (arg, arg_val_q); \
443
+ mpf_make_struct_init (res, res_val, prec); \
444
+ mpfr_##fname##_q (res_val, self_val, arg_val_q, rnd_mode_val); \
445
+ } else if (GMPZ_P (arg)) { \
446
+ mpz_get_struct (arg, arg_val_z); \
447
+ mpf_make_struct_init (res, res_val, prec); \
448
+ mpfr_##fname##_z (res_val, self_val, arg_val_z, rnd_mode_val); \
449
+ } else if (FLOAT_P (arg)) { \
450
+ mpf_make_struct_init (res, res_val, prec); \
451
+ mpfr_##fname##_d (res_val, self_val, NUM2DBL (arg), rnd_mode_val); \
452
+ } else if (FIXNUM_P (arg)) { \
453
+ mpf_make_struct_init(res, res_val, prec); \
454
+ mpfr_##fname##_si (res_val, self_val, FIX2NUM (arg), rnd_mode_val); \
455
+ } else if (BIGNUM_P (arg)) { \
456
+ mpz_temp_from_bignum(arg_val_z, arg); \
457
+ mpf_make_struct_init(res, res_val, prec); \
458
+ mpfr_##fname##_z (res_val, self_val, arg_val_z, rnd_mode_val); \
459
+ mpz_temp_free (arg_val_z); \
460
+ } else { \
461
+ typeerror(ZQFXBD); \
462
+ } \
463
+ \
464
+ return res; \
465
+ }
466
+
467
+ DEFUN_F_ZQXFBD2F(add)
468
+ DEFUN_F_ZQXFBD2F(mul)
469
+ #endif
283
470
 
284
471
  /*
285
472
  * call-seq:
@@ -299,7 +486,7 @@ VALUE r_gmpf_sub(VALUE self, VALUE arg)
299
486
  MP_RAT *arg_val_q;
300
487
  MP_INT *arg_val_z;
301
488
  VALUE res;
302
- unsigned long prec;
489
+ mpfr_prec_t prec;
303
490
 
304
491
  mpf_get_struct_prec (self, self_val, prec);
305
492
 
@@ -324,7 +511,7 @@ VALUE r_gmpf_sub(VALUE self, VALUE arg)
324
511
  mpf_sub(res_val, self_val, res_val);
325
512
  } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
326
513
  mpf_make_struct_init(res, res_val, prec);
327
- mpf_set_si(res_val, FIX2INT(arg));
514
+ mpf_set_si(res_val, FIX2NUM(arg));
328
515
  mpf_sub(res_val, self_val, res_val);
329
516
  } else if (BIGNUM_P(arg)) {
330
517
  mpz_temp_from_bignum(arg_val_z, arg);
@@ -357,7 +544,8 @@ VALUE r_gmpf_mul(VALUE self, VALUE arg)
357
544
  MP_RAT *arg_val_q;
358
545
  MP_INT *arg_val_z;
359
546
  VALUE res;
360
- unsigned long prec;
547
+ //unsigned long prec;
548
+ mpfr_prec_t prec;
361
549
 
362
550
  mpf_get_struct_prec (self, self_val, prec);
363
551
 
@@ -382,7 +570,7 @@ VALUE r_gmpf_mul(VALUE self, VALUE arg)
382
570
  mpf_mul(res_val, self_val, res_val);
383
571
  } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
384
572
  mpf_make_struct_init(res, res_val, prec);
385
- mpf_set_si(res_val, FIX2INT(arg));
573
+ mpf_set_si(res_val, FIX2NUM(arg));
386
574
  mpf_mul(res_val, self_val, res_val);
387
575
  } else if (BIGNUM_P(arg)) {
388
576
  mpz_temp_from_bignum(arg_val_z, arg);
@@ -397,6 +585,92 @@ VALUE r_gmpf_mul(VALUE self, VALUE arg)
397
585
  return res;
398
586
  }
399
587
 
588
+ /*
589
+ * call-seq:
590
+ * float ** integer
591
+ *
592
+ * Returns +float+ raised to the +integer+ power. +integer+ must be
593
+ * * Fixnum or Bignum
594
+ * * non-negative
595
+ */
596
+ VALUE r_gmpf_pow(VALUE self, VALUE arg)
597
+ {
598
+ MP_FLOAT *self_val, *res_val;
599
+ VALUE res;
600
+
601
+ //unsigned long prec;
602
+ mpfr_prec_t prec;
603
+
604
+ mpf_get_struct_prec (self, self_val, prec);
605
+
606
+ if (FIXNUM_P(arg)) {
607
+ if (FIX2NUM(arg) >= 0) {
608
+ mpf_make_struct_init(res, res_val, prec);
609
+ mpf_pow_ui(res_val, self_val, FIX2NUM(arg));
610
+ } else {
611
+ rb_raise(rb_eRangeError, "power must be non-negative");
612
+ }
613
+ } else {
614
+ typeerror(X);
615
+ }
616
+
617
+ return res;
618
+ }
619
+
620
+ #ifdef MPFR
621
+ /*
622
+ * call-seq:
623
+ * float ** other
624
+ *
625
+ * Returns +float+ raised to the +other+ power. +other+ must be an instance of
626
+ * * Fixnum
627
+ * * Bignum
628
+ * * Float
629
+ * * GMP::Z
630
+ * * GMP::F
631
+ */
632
+ /*VALUE r_gmpfr_pow(int argc, VALUE *argv, VALUE self)
633
+ {
634
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
635
+ VALUE arg, rnd_mode, res_prec;
636
+ unsigned long arg_val, prec, res_prec_value;
637
+ mp_rnd_t rnd_mode_value;
638
+ MP_INT *arg_val_z;
639
+ VALUE res;
640
+
641
+ rb_scan_args (argc, argv, "12", &arg, &rnd_mode, &res_prec);
642
+
643
+ mpf_get_struct_prec (self, self_val, prec);
644
+
645
+ if (NIL_P (rnd_mode)) { rnd_mode_value = __gmp_default_rounding_mode; }
646
+ else { rnd_mode_value = r_get_rounding_mode(rnd_mode); }
647
+ if (NIL_P (res_prec)) { res_prec_value = prec; }
648
+ else { res_prec_value = FIX2INT (res_prec); }
649
+ mpf_make_struct_init (res, res_val, res_prec_value);
650
+
651
+ if (FIXNUM_P(arg)) {
652
+ mpfr_pow_ui(res_val, self_val, FIX2NUM(arg), rnd_mode_value);
653
+ } else if (BIGNUM_P(arg)) {
654
+ mpz_temp_from_bignum(arg_val_z, arg);
655
+ mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
656
+ mpz_temp_free(arg_val_z);
657
+ } else if (FLOAT_P(arg)) {
658
+ r_mpf_set_d (res_val, NUM2DBL(arg));
659
+ mpfr_pow (res_val, self_val, res_val, rnd_mode_value);
660
+ } else if (GMPZ_P(arg)) {
661
+ mpz_get_struct (arg, arg_val_z);
662
+ mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
663
+ } else if (GMPF_P(arg)) {
664
+ mpf_get_struct (arg, arg_val_f);
665
+ mpfr_pow (res_val, self_val, arg_val_f, rnd_mode_value);
666
+ } else {
667
+ typeerror(ZFXBD);
668
+ }
669
+
670
+ return res;
671
+ }*/
672
+ #endif
673
+
400
674
  /*
401
675
  * call-seq:
402
676
  * float1 / float2
@@ -415,7 +689,7 @@ VALUE r_gmpf_div(VALUE self, VALUE arg)
415
689
  MP_RAT *arg_val_q;
416
690
  MP_INT *arg_val_z;
417
691
  VALUE res;
418
- unsigned long prec;
692
+ mpfr_prec_t prec;
419
693
 
420
694
  mpf_get_struct_prec (self, self_val, prec);
421
695
 
@@ -440,7 +714,7 @@ VALUE r_gmpf_div(VALUE self, VALUE arg)
440
714
  mpf_div(res_val, self_val, res_val);
441
715
  } else if (FIXNUM_P(arg)) { // _ui with sign control instead ?
442
716
  mpf_make_struct_init(res, res_val, prec);
443
- mpf_set_si(res_val, FIX2INT(arg));
717
+ mpf_set_si(res_val, FIX2NUM(arg));
444
718
  mpf_div(res_val, self_val, res_val);
445
719
  } else if (BIGNUM_P(arg)) {
446
720
  mpz_temp_from_bignum(arg_val_z, arg);
@@ -455,6 +729,8 @@ VALUE r_gmpf_div(VALUE self, VALUE arg)
455
729
  return res;
456
730
  }
457
731
 
732
+
733
+
458
734
  /*
459
735
  * Document-method: neg
460
736
  *
@@ -507,11 +783,11 @@ int mpf_cmp_value(MP_FLOAT *self_val, VALUE arg)
507
783
 
508
784
  if (GMPF_P(arg)) {
509
785
  mpf_get_struct(arg,arg_val);
510
- return mpf_cmp (self_val, arg_val);
786
+ return r_mpf_cmp (self_val, arg_val);
511
787
  } else {
512
788
  mpf_temp_init(arg_val, mpf_get_prec (self_val));
513
789
  mpf_set_value (arg_val, arg);
514
- result = mpf_cmp (self_val, arg_val);
790
+ result = r_mpf_cmp (self_val, arg_val);
515
791
  mpf_temp_free(arg_val);
516
792
  return result;
517
793
  }
@@ -529,8 +805,8 @@ VALUE r_gmpf_cmp(VALUE self, VALUE arg)
529
805
  {
530
806
  MP_FLOAT *self_val;
531
807
  int res;
532
- mpf_get_struct(self,self_val);
533
- res = mpf_cmp_value(self_val, arg);
808
+ mpf_get_struct (self, self_val);
809
+ res = mpf_cmp_value (self_val, arg);
534
810
  if (res > 0)
535
811
  return INT2FIX(1);
536
812
  else if (res == 0)
@@ -547,26 +823,26 @@ DEFUN_FLOAT_CMP(ge,>=)
547
823
 
548
824
  #ifdef MPFR
549
825
 
550
- #define MPFR_SINGLE_FUNCTION(name) \
551
- VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
552
- { \
553
- MP_FLOAT *self_val, *res_val; \
554
- VALUE rnd_mode, res_prec; \
555
- unsigned long prec, res_prec_value; \
556
- mp_rnd_t rnd_mode_value; \
557
- VALUE res; \
558
- \
559
- rb_scan_args (argc, argv, "02", &rnd_mode, &res_prec); \
560
- \
561
- mpf_get_struct_prec (self, self_val, prec); \
562
- if (NIL_P (rnd_mode)) { rnd_mode_value = __gmp_default_rounding_mode; } \
563
- else { rnd_mode_value = r_get_rounding_mode(rnd_mode); } \
564
- if (NIL_P (res_prec)) { res_prec_value = prec; } \
565
- else { res_prec_value = FIX2INT (res_prec); } \
566
- mpf_make_struct_init (res, res_val, res_prec_value); \
567
- mpfr_##name (res_val, self_val, __gmp_default_rounding_mode); \
568
- \
569
- return res; \
826
+ #define MPFR_SINGLE_FUNCTION(name) \
827
+ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
828
+ { \
829
+ MP_FLOAT *self_val, *res_val; \
830
+ VALUE rnd_mode, res_prec; \
831
+ mpfr_prec_t prec, res_prec_value; \
832
+ mp_rnd_t rnd_mode_val; \
833
+ VALUE res; \
834
+ \
835
+ rb_scan_args (argc, argv, "02", &rnd_mode, &res_prec); \
836
+ \
837
+ mpf_get_struct_prec (self, self_val, prec); \
838
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
839
+ else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
840
+ if (NIL_P (res_prec)) { res_prec_value = prec; } \
841
+ else { res_prec_value = FIX2INT (res_prec); } \
842
+ mpf_make_struct_init (res, res_val, res_prec_value); \
843
+ mpfr_##name (res_val, self_val, rnd_mode_val); \
844
+ \
845
+ return res; \
570
846
  }
571
847
 
572
848
  #define MPFR_SINGLE_1ARG_FUNCTION(name) \
@@ -574,7 +850,7 @@ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
574
850
  { \
575
851
  MP_FLOAT *self_val, *res_val; \
576
852
  VALUE arg1, res_prec; \
577
- unsigned long prec, arg1_val, res_prec_value; \
853
+ mpfr_prec_t prec, arg1_val, res_prec_value; \
578
854
  VALUE res; \
579
855
  \
580
856
  rb_scan_args (argc, argv, "11", &arg1, &res_prec); \
@@ -590,6 +866,19 @@ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
590
866
  return res; \
591
867
  }
592
868
 
869
+ #define MPFR_SINGLE_BOOLEAN_FUNCTION(name) \
870
+ static VALUE r_gmpfr_##name(VALUE self) \
871
+ { \
872
+ MP_FLOAT *self_val; \
873
+ \
874
+ mpf_get_struct(self, self_val); \
875
+ if (mpfr_##name (self_val)) \
876
+ return Qtrue; \
877
+ else \
878
+ return Qfalse; \
879
+ }
880
+
881
+
593
882
  #define MPFR_CONST_FUNCTION(name) \
594
883
  VALUE r_gmpfrsg_##name() \
595
884
  { \
@@ -604,6 +893,8 @@ VALUE r_gmpfrsg_##name() \
604
893
  }
605
894
 
606
895
  MPFR_SINGLE_FUNCTION(sqrt)
896
+ MPFR_SINGLE_FUNCTION(rec_sqrt)
897
+ MPFR_SINGLE_FUNCTION(cbrt)
607
898
 
608
899
  MPFR_SINGLE_FUNCTION(log)
609
900
  MPFR_SINGLE_FUNCTION(log2)
@@ -640,6 +931,9 @@ MPFR_SINGLE_FUNCTION(li2)
640
931
  MPFR_SINGLE_FUNCTION(gamma)
641
932
  MPFR_SINGLE_FUNCTION(lngamma)
642
933
  /*MPFR_SINGLE_FUNCTION(lgamma)*/
934
+ #if MPFR_VERSION_MAJOR > 2
935
+ MPFR_SINGLE_FUNCTION(digamma)
936
+ #endif
643
937
  MPFR_SINGLE_FUNCTION(zeta)
644
938
  MPFR_SINGLE_FUNCTION(erf)
645
939
  MPFR_SINGLE_FUNCTION(erfc)
@@ -655,32 +949,8 @@ MPFR_CONST_FUNCTION(const_pi)
655
949
  MPFR_CONST_FUNCTION(const_euler)
656
950
  MPFR_CONST_FUNCTION(const_catalan)
657
951
 
658
- static VALUE r_gmpfr_nan_p(VALUE self)
659
- {
660
- MP_FLOAT *self_val;
661
-
662
- mpf_get_struct(self, self_val);
663
- if (mpfr_nan_p(self_val)) {
664
- return Qtrue;
665
- }
666
- else {
667
- return Qfalse;
668
- }
669
- }
670
-
671
- static VALUE r_gmpfr_inf_p(VALUE self)
672
- {
673
- MP_FLOAT *self_val;
674
-
675
- mpf_get_struct(self, self_val);
676
- if (mpfr_inf_p(self_val)) {
677
- return Qtrue;
678
- }
679
- else {
680
- return Qfalse;
681
- }
682
- }
683
-
952
+ MPFR_SINGLE_BOOLEAN_FUNCTION(nan_p)
953
+ MPFR_SINGLE_BOOLEAN_FUNCTION(inf_p)
684
954
  static VALUE r_gmpfr_fin_p(VALUE self)
685
955
  {
686
956
  if (r_gmpfr_inf_p(self)) {
@@ -690,26 +960,18 @@ static VALUE r_gmpfr_fin_p(VALUE self)
690
960
  return Qtrue;
691
961
  }
692
962
  }
693
-
694
- static VALUE r_gmpfr_number_p(VALUE self)
695
- {
696
- MP_FLOAT *self_val;
697
-
698
- mpf_get_struct(self, self_val);
699
- if (mpfr_number_p(self_val)) {
700
- return Qtrue;
701
- }
702
- else {
703
- return Qfalse;
704
- }
705
- }
963
+ MPFR_SINGLE_BOOLEAN_FUNCTION(number_p)
964
+ MPFR_SINGLE_BOOLEAN_FUNCTION(zero_p)
965
+ #if MPFR_VERSION_MAJOR > 2
966
+ MPFR_SINGLE_BOOLEAN_FUNCTION(regular_p)
967
+ #endif
706
968
 
707
969
  static VALUE r_gmpfr_pow(VALUE self, VALUE arg)
708
970
  {
709
971
  MP_FLOAT *self_val, *res_val, *arg_val_f;
710
972
  MP_RAT *arg_val_q;
711
973
  MP_INT *arg_val_z;
712
- unsigned long prec;
974
+ mpfr_prec_t prec;
713
975
  VALUE res;
714
976
 
715
977
  mpf_get_struct_prec(self, self_val, prec);
@@ -743,7 +1005,6 @@ static VALUE r_gmpfr_pow(VALUE self, VALUE arg)
743
1005
  } else {
744
1006
  typeerror(ZQFXBD);
745
1007
  }
746
-
747
1008
  }
748
1009
 
749
1010
  return res;
@@ -771,15 +1032,39 @@ DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
771
1032
  VALUE r_gmpf_sgn(VALUE self)
772
1033
  {
773
1034
  MP_FLOAT *self_val;
774
- mpf_get_struct(self, self_val);
775
- return INT2FIX(mpf_sgn(self_val));
1035
+ mpf_get_struct (self, self_val);
1036
+ return INT2FIX (mpf_sgn (self_val));
776
1037
  }
777
1038
 
778
1039
  VALUE r_gmpf_get_prec(VALUE self)
779
1040
  {
780
1041
  MP_FLOAT *self_val;
781
- mpf_get_struct(self, self_val);
782
- return INT2NUM(mpf_get_prec(self_val));
1042
+ mpf_get_struct (self, self_val);
1043
+ return INT2NUM (mpf_get_prec (self_val));
1044
+ }
1045
+
1046
+ VALUE r_gmpf_set_prec(VALUE self, VALUE arg)
1047
+ {
1048
+ MP_FLOAT *self_val;
1049
+ if (FIXNUM_P(arg)) {
1050
+ mpf_get_struct (self, self_val);
1051
+ mpf_set_prec (self_val, FIX2NUM (arg));
1052
+ return Qnil;
1053
+ } else {
1054
+ typeerror(X);
1055
+ }
1056
+ }
1057
+
1058
+ VALUE r_gmpf_set_prec_raw(VALUE self, VALUE arg)
1059
+ {
1060
+ MP_FLOAT *self_val;
1061
+ if (FIXNUM_P(arg)) {
1062
+ mpf_get_struct (self, self_val);
1063
+ mpf_set_prec_raw (self_val, FIX2NUM (arg));
1064
+ return Qnil;
1065
+ } else {
1066
+ typeerror(X);
1067
+ }
783
1068
  }
784
1069
 
785
1070
 
@@ -794,6 +1079,9 @@ void init_gmpf()
794
1079
  // Initializing, Assigning Floats
795
1080
  rb_define_singleton_method(cGMP_F, "new", r_gmpfsg_new, -1);
796
1081
  rb_define_method(cGMP_F, "initialize", r_gmpf_initialize, -1);
1082
+ rb_define_method(cGMP_F, "prec", r_gmpf_get_prec, 0);
1083
+ rb_define_method(cGMP_F, "prec=", r_gmpf_set_prec, 1);
1084
+ rb_define_method(cGMP_F, "prec_raw=", r_gmpf_set_prec_raw, 1);
797
1085
 
798
1086
  // Converting Floats
799
1087
  rb_define_method(cGMP_F, "to_s", r_gmpf_to_s, 0);
@@ -801,10 +1089,18 @@ void init_gmpf()
801
1089
  rb_define_alias(cGMP_F, "to_f", "to_d");
802
1090
 
803
1091
  // Float Arithmetic
804
- rb_define_method(cGMP_F, "+", r_gmpf_add, 1);
805
1092
  rb_define_method(cGMP_F, "-", r_gmpf_sub, 1);
806
- rb_define_method(cGMP_F, "*", r_gmpf_mul, 1);
807
1093
  rb_define_method(cGMP_F, "/", r_gmpf_div, 1);
1094
+ #ifndef MPFR
1095
+ rb_define_method(cGMP_F, "+", r_gmpf_add, 1);
1096
+ rb_define_method(cGMP_F, "*", r_gmpf_mul, 1);
1097
+ rb_define_method(cGMP_F, "**", r_gmpf_pow, 1);
1098
+ rb_define_alias(cGMP_F, "pow", "**");
1099
+ #else
1100
+ rb_define_method(cGMP_F, "+", r_gmpfr_add, -1);
1101
+ rb_define_method(cGMP_F, "*", r_gmpfr_mul, -1);
1102
+ rb_define_method(cGMP_F, "**", r_gmpfr_pow, 1);
1103
+ #endif
808
1104
  rb_define_method(cGMP_F, "-@", r_gmpf_neg, 0);
809
1105
  rb_define_method(cGMP_F, "neg!", r_gmpf_neg_self, 0);
810
1106
  rb_define_method(cGMP_F, "abs", r_gmpf_abs, 0);
@@ -817,18 +1113,53 @@ void init_gmpf()
817
1113
  rb_define_method(cGMP_F, "<", r_gmpf_cmp_lt, 1);
818
1114
  rb_define_method(cGMP_F, "<=", r_gmpf_cmp_le, 1);
819
1115
  rb_define_method(cGMP_F, "==", r_gmpf_eq, 1);
1116
+ rb_define_method(cGMP_F, "sgn", r_gmpf_sgn, 0);
1117
+
1118
+ // Miscellaneous Functions
1119
+ rb_define_method(cGMP_F, "ceil", r_gmpf_ceil, 0);
1120
+ rb_define_method(cGMP_F, "ceil!", r_gmpf_ceil_self, 0);
1121
+ rb_define_method(cGMP_F, "floor", r_gmpf_floor, 0);
1122
+ rb_define_method(cGMP_F, "floor!", r_gmpf_floor_self, 0);rb_define_method(cGMP_F, "trunc", r_gmpf_trunc, 0);
1123
+ rb_define_method(cGMP_F, "trunc!", r_gmpf_trunc_self, 0);
1124
+
820
1125
 
821
1126
  #ifdef MPFR
1127
+ /* To implement; new in MPFR 3.0.0:
1128
+ *
1129
+ * mpfr_buildopt_tls_p
1130
+ * mpfr_buildopt_decimal_p
1131
+ * mpfr_set_zero
1132
+ * mpfr_ai
1133
+ * mpfr_set_flt
1134
+ * mpfr_get_flt
1135
+ * mpfr_urandom
1136
+ * mpfr_set_z_2exp
1137
+ */
822
1138
  // Basic Arithmetic Functions
823
- rb_define_method(cGMP_F, "sqrt", r_gmpfr_sqrt, -1);
1139
+ rb_define_method(cGMP_F, "sqrt", r_gmpfr_sqrt, -1);
1140
+ rb_define_method(cGMP_F, "rec_sqrt", r_gmpfr_rec_sqrt, -1);
1141
+ rb_define_method(cGMP_F, "cbrt", r_gmpfr_cbrt, -1);
1142
+ // "root", r_gmpfr_root
1143
+ // "neg", r_gmpfr_neg
1144
+ // "abs", r_gmpfr_abs
1145
+ // "dim", r_gmpfr_dim
1146
+ // "mul_2", r_gmpfr_mul_2
1147
+ // "div_2", r_gmpfr_div_2
824
1148
 
825
- rb_define_method(cGMP_F, "**", r_gmpfr_pow, 1);
1149
+ //rb_define_method(cGMP_F, "**", r_gmpfr_pow, 1);
826
1150
 
827
1151
  // Comparison Functions
828
1152
  rb_define_method(cGMP_F, "nan?", r_gmpfr_nan_p, 0);
829
1153
  rb_define_method(cGMP_F, "infinite?", r_gmpfr_inf_p, 0);
830
1154
  rb_define_method(cGMP_F, "finite?", r_gmpfr_fin_p, 0);
831
1155
  rb_define_method(cGMP_F, "number?", r_gmpfr_number_p, 0);
1156
+ rb_define_method(cGMP_F, "zero?", r_gmpfr_zero_p, 0);
1157
+ #if MPFR_VERSION_MAJOR > 2
1158
+ rb_define_method(cGMP_F, "regular?", r_gmpfr_regular_p, 0);
1159
+ #endif
1160
+ //"sgn", r_gmpfr_sgn
1161
+ //"lessgreater", r_gmpfr_lessgreater_p
1162
+ //"unordered", r_gmpfr_unordered_p
832
1163
 
833
1164
  // Special Functions
834
1165
  rb_define_method(cGMP_F, "log", r_gmpfr_log, -1);
@@ -840,6 +1171,7 @@ void init_gmpf()
840
1171
  rb_define_method(cGMP_F, "cos", r_gmpfr_cos, -1);
841
1172
  rb_define_method(cGMP_F, "sin", r_gmpfr_sin, -1);
842
1173
  rb_define_method(cGMP_F, "tan", r_gmpfr_tan, -1);
1174
+ // "sin_cos", r_gmpfr_sin_cos
843
1175
  rb_define_method(cGMP_F, "sec", r_gmpfr_sec, -1);
844
1176
  rb_define_method(cGMP_F, "csc", r_gmpfr_csc, -1);
845
1177
  rb_define_method(cGMP_F, "cot", r_gmpfr_cot, -1);
@@ -847,10 +1179,13 @@ void init_gmpf()
847
1179
  rb_define_method(cGMP_F, "acos", r_gmpfr_acos, -1);
848
1180
  rb_define_method(cGMP_F, "asin", r_gmpfr_asin, -1);
849
1181
  rb_define_method(cGMP_F, "atan", r_gmpfr_atan, -1);
1182
+ // "atan2", r_gmpfr_atan2
850
1183
 
851
1184
  rb_define_method(cGMP_F, "cosh", r_gmpfr_cosh, -1);
852
1185
  rb_define_method(cGMP_F, "sinh", r_gmpfr_sinh, -1);
853
1186
  rb_define_method(cGMP_F, "tanh", r_gmpfr_tanh, -1);
1187
+
1188
+ // "sinh_cosh", r_gmpfr_sinh_cosh
854
1189
 
855
1190
  rb_define_method(cGMP_F, "sech", r_gmpfr_sech, -1);
856
1191
  rb_define_method(cGMP_F, "csch", r_gmpfr_csch, -1);
@@ -859,6 +1194,8 @@ void init_gmpf()
859
1194
  rb_define_method(cGMP_F, "asinh", r_gmpfr_asinh, -1);
860
1195
  rb_define_method(cGMP_F, "atanh", r_gmpfr_atanh, -1);
861
1196
 
1197
+ // "fac", r_gmpfr_fac
1198
+
862
1199
  rb_define_method(cGMP_F, "log1p", r_gmpfr_log1p, -1);
863
1200
  rb_define_method(cGMP_F, "expm1", r_gmpfr_expm1, -1);
864
1201
  rb_define_method(cGMP_F, "eint", r_gmpfr_eint, -1);
@@ -866,6 +1203,9 @@ void init_gmpf()
866
1203
  rb_define_method(cGMP_F, "gamma", r_gmpfr_gamma, -1);
867
1204
  rb_define_method(cGMP_F, "lngamma", r_gmpfr_lngamma, -1);
868
1205
  /*rb_define_method(cGMP_F, "lgamma", r_gmpfr_lgamma, -1);*/
1206
+ #if MPFR_VERSION_MAJOR > 2
1207
+ rb_define_method(cGMP_F, "digamma", r_gmpfr_digamma, -1);
1208
+ #endif
869
1209
  rb_define_method(cGMP_F, "zeta", r_gmpfr_zeta, -1);
870
1210
  rb_define_method(cGMP_F, "erf", r_gmpfr_erf, -1);
871
1211
  rb_define_method(cGMP_F, "erfc", r_gmpfr_erfc, -1);
@@ -875,20 +1215,21 @@ void init_gmpf()
875
1215
  rb_define_method(cGMP_F, "y0", r_gmpfr_y0, -1);
876
1216
  rb_define_method(cGMP_F, "y1", r_gmpfr_y1, -1);
877
1217
  rb_define_method(cGMP_F, "yn", r_gmpfr_yn, -1);
1218
+
1219
+ // "fma", r_gmpfr_fma
1220
+ // "fms", r_gmpfr_fms
1221
+ // "agm", r_gmpfr_agm
1222
+ // "hypot", r_gmpfr_hypot
1223
+ // "ai", r_gmpfr_ai !! 3.0.0
878
1224
 
879
1225
  rb_define_singleton_method(cGMP_F, "const_log2", r_gmpfrsg_const_log2, 0);
880
1226
  rb_define_singleton_method(cGMP_F, "const_pi", r_gmpfrsg_const_pi, 0);
881
1227
  rb_define_singleton_method(cGMP_F, "const_euler", r_gmpfrsg_const_euler, 0);
882
1228
  rb_define_singleton_method(cGMP_F, "const_catalan", r_gmpfrsg_const_catalan, 0);
1229
+
1230
+ // Integer and Remainder Related Functions
1231
+ // "integer?", r_gmpfr_integer_p
883
1232
  #endif /* MPFR */
884
1233
 
885
1234
  // _unsorted_
886
- rb_define_method(cGMP_F, "floor", r_gmpf_floor, 0);
887
- rb_define_method(cGMP_F, "floor!", r_gmpf_floor_self, 0);
888
- rb_define_method(cGMP_F, "ceil", r_gmpf_ceil, 0);
889
- rb_define_method(cGMP_F, "ceil!", r_gmpf_ceil_self, 0);
890
- rb_define_method(cGMP_F, "trunc", r_gmpf_trunc, 0);
891
- rb_define_method(cGMP_F, "trunc!", r_gmpf_trunc_self, 0);
892
- rb_define_method(cGMP_F, "sgn", r_gmpf_sgn, 0);
893
- rb_define_method(cGMP_F, "prec", r_gmpf_get_prec, 0);
894
1235
  }