ruby-mpfr 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ #define DEFUN_TAKEOVER_LOGIC(fname, mpz_fname, old_fname) \
2
+ static VALUE takeover_fixnum_##fname(int argc, VALUE *argv, VALUE self) \
3
+ { \
4
+ MP_INT *res_val, *arg_val; \
5
+ VALUE res; \
6
+ \
7
+ if (argc != 1 || !GMPZ_P(argv[0])) { \
8
+ return rb_funcall2 (self, rb_intern (old_fname), argc, argv); \
9
+ } else { \
10
+ mpz_make_struct(res, res_val); \
11
+ mpz_get_struct(argv[0], arg_val); \
12
+ mpz_init_set_si (res_val, FIX2INT(self)); \
13
+ mpz_fname (res_val, res_val, arg_val); \
14
+ return res; \
15
+ } \
16
+ } \
17
+ \
18
+ static VALUE takeover_bignum_##fname(int argc, VALUE *argv, VALUE self) \
19
+ {\
20
+ MP_INT *res_val, *arg_val; \
21
+ VALUE res; \
22
+ \
23
+ if (argc != 1 || !GMPZ_P(argv[0])) { \
24
+ return rb_funcall2 (self, rb_intern (old_fname), argc, argv); \
25
+ } else { \
26
+ mpz_get_struct(argv[0], arg_val); \
27
+ mpz_make_struct_init(res, res_val); \
28
+ mpz_set_bignum (res_val, self); \
29
+ mpz_fname (res_val, res_val, arg_val); \
30
+ return res; \
31
+ } \
32
+ }
33
+
34
+ DEFUN_TAKEOVER_LOGIC(and, mpz_and, "old_and")
35
+ DEFUN_TAKEOVER_LOGIC(or, mpz_ior, "old_or")
36
+ DEFUN_TAKEOVER_LOGIC(xor, mpz_xor, "old_xor")
@@ -0,0 +1,161 @@
1
+ #include "ruby_mpfr_gmp.h"
2
+
3
+ #if defined(MPFR) && defined(HAVE_MPFR_H)
4
+ #define R_MPF_GET_PREC(mpf) mpfr_get_prec(mpf)
5
+ #else
6
+ #define R_MPF_GET_PREC(mpf) mpf_get_prec(mpf)
7
+ #endif
8
+
9
+ static VALUE r_mpfr_to_mpf(int argc, VALUE *argv, VALUE self)
10
+ {
11
+ VALUE ptr_return;
12
+ MPFR *ptr_self;
13
+ MP_FLOAT *ptr_mpf;
14
+ mp_rnd_t rnd;
15
+ rnd = r_mpfr_rnd_from_optional_argument(0, 1, argc, argv);
16
+ r_mpfr_get_struct(ptr_self, self);
17
+ mpf_make_struct_init(ptr_return, ptr_mpf, mpfr_get_prec(ptr_self));
18
+ #if defined(MPFR) && defined(HAVE_MPFR_H)
19
+ mpfr_set(ptr_mpf, ptr_self, rnd);
20
+ #else
21
+ mpfr_get_f(ptr_mpf, ptr_self, rnd);
22
+ #endif
23
+ return ptr_return;
24
+ }
25
+
26
+ static VALUE r_mpfr_to_mpz(int argc, VALUE *argv, VALUE self)
27
+ {
28
+ VALUE ptr_return;
29
+ MPFR *ptr_self;
30
+ MP_INT *ptr_mpz;
31
+ mp_rnd_t rnd;
32
+ rnd = r_mpfr_rnd_from_optional_argument(0, 1, argc, argv);
33
+ r_mpfr_get_struct(ptr_self, self);
34
+ mpz_make_struct_init(ptr_return, ptr_mpz);
35
+ mpfr_get_z(ptr_mpz, ptr_self, rnd);
36
+ return ptr_return;
37
+ }
38
+
39
+ static VALUE r_mpfr_get_z_2exp(VALUE self)
40
+ {
41
+ VALUE ptr_return;
42
+ MPFR *ptr_self;
43
+ MP_INT *ptr_mpz;
44
+ long int exp;
45
+ r_mpfr_get_struct(ptr_self, self);
46
+ mpz_make_struct_init(ptr_return, ptr_mpz);
47
+ exp = mpfr_get_z_2exp(ptr_mpz, ptr_self);
48
+ return rb_ary_new3(2, ptr_return, INT2NUM(exp));
49
+ }
50
+
51
+ static VALUE r_gmpf_to_fr(int argc, VALUE *argv, VALUE self)
52
+ {
53
+ VALUE ptr_return;
54
+ MP_FLOAT *ptr_self;
55
+ MPFR *ptr_mpfr;
56
+ mp_rnd_t rnd;
57
+ mp_prec_t prec;
58
+ mpf_get_struct(self, ptr_self);
59
+ switch(argc) {
60
+ case 2:
61
+ switch(TYPE(argv[0])){
62
+ case T_SYMBOL:
63
+ rnd = r_mpfr_rnd_from_value(argv[0]);
64
+ if (FIXNUM_P(argv[1])) {
65
+ prec = NUM2INT(argv[1]);
66
+ } else {
67
+ rb_raise(rb_eArgError, "Invalid arguments for GMP::F#to_fr; argc=%d\n", argc);
68
+ }
69
+ break;
70
+ case T_FIXNUM:
71
+ prec = NUM2INT(argv[0]);
72
+ if (SYMBOL_P(argv[1])) {
73
+ rnd = r_mpfr_rnd_from_value(argv[1]);
74
+ } else {
75
+ rb_raise(rb_eArgError, "Invalid arguments for GMP::F#to_fr; argc=%d\n", argc);
76
+ }
77
+ break;
78
+ default:
79
+ rb_raise(rb_eArgError, "Invalid arguments for GMP::F#to_fr; argc=%d\n", argc);
80
+ }
81
+ break;
82
+ case 1:
83
+ switch(TYPE(argv[0])){
84
+ case T_SYMBOL:
85
+ prec = R_MPF_GET_PREC(ptr_self);
86
+ rnd = r_mpfr_rnd_from_value(argv[0]);
87
+ break;
88
+ case T_FIXNUM:
89
+ prec = NUM2INT(argv[0]);
90
+ rnd = mpfr_get_default_rounding_mode();
91
+ break;
92
+ default:
93
+ rb_raise(rb_eArgError, "Invalid arguments for GMP::F#to_fr; argc=%d\n", argc);
94
+ }
95
+ break;
96
+ case 0:
97
+ prec = R_MPF_GET_PREC(ptr_self);
98
+ rnd = mpfr_get_default_rounding_mode();
99
+ break;
100
+ default:
101
+ rb_raise(rb_eArgError, "Invalid number of arguments for GMP::F#to_fr; argc=%d\n", argc);
102
+ }
103
+ r_mpfr_make_struct_init2(ptr_return, ptr_mpfr, prec);
104
+ mpfr_set(ptr_mpfr, ptr_self, rnd);
105
+ return ptr_return;
106
+ }
107
+
108
+ static VALUE r_gmpz_to_fr(int argc, VALUE *argv, VALUE self)
109
+ {
110
+ mp_rnd_t rnd;
111
+ mp_prec_t prec;
112
+ MP_INT *ptr_self;
113
+ VALUE ptr_return;
114
+ MPFR *ptr_mpfr;
115
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
116
+ mpz_get_struct(self, ptr_self);
117
+ r_mpfr_make_struct_init2(ptr_return, ptr_mpfr, prec);
118
+ mpfr_set_z(ptr_mpfr, ptr_self, rnd);
119
+ return ptr_return;
120
+ }
121
+
122
+ static VALUE r_gmpq_to_fr(int argc, VALUE *argv, VALUE self)
123
+ {
124
+ mp_rnd_t rnd;
125
+ mp_prec_t prec;
126
+ MP_RAT *ptr_self;
127
+ VALUE ptr_return;
128
+ MPFR *ptr_mpfr;
129
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
130
+ mpq_get_struct(self, ptr_self);
131
+ r_mpfr_make_struct_init2(ptr_return, ptr_mpfr, prec);
132
+ mpfr_set_q(ptr_mpfr, ptr_self, rnd);
133
+ return ptr_return;
134
+ }
135
+
136
+ /* Return a random number of MPFR object. */
137
+ static VALUE r_gmprandstate_mpfr_urandomb2(int argc, VALUE *argv, VALUE self)
138
+ {
139
+ MP_RANDSTATE *ptr_self;
140
+ MPFR *ptr_return;
141
+ VALUE val_ret;
142
+ mp_prec_t prec;
143
+ prec = r_mpfr_prec_from_optional_argument(0, 1, argc, argv);
144
+ mprandstate_get_struct(self, ptr_self);
145
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
146
+ mpfr_urandomb(ptr_return, ptr_self);
147
+ return val_ret;
148
+ }
149
+
150
+ void Init_mpfr_gmp()
151
+ {
152
+ rb_define_method(r_mpfr_class, "to_mpf", r_mpfr_to_mpf, -1);
153
+ rb_define_method(r_mpfr_class, "to_mpz", r_mpfr_to_mpz, -1);
154
+ rb_define_method(r_mpfr_class, "get_z_2exp", r_mpfr_get_z_2exp, 0);
155
+
156
+ rb_define_method(cGMP_F, "to_fr", r_gmpf_to_fr, -1);
157
+ rb_define_method(cGMP_Z, "to_fr", r_gmpz_to_fr, -1);
158
+ rb_define_method(cGMP_Q, "to_fr", r_gmpq_to_fr, -1);
159
+
160
+ rb_define_method(cGMP_RandState, "mpfr_urandomb2", r_gmprandstate_mpfr_urandomb2, -1);
161
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef _RUBY_MPFR_GMP_H_
2
+ #define _RUBY_MPFR_GMP_H_
3
+
4
+ /*
5
+ In ruby_mpfr.h we set 'typedef __mpfr_struct MPFR' and
6
+ in ruby_gmp.h MPFR is a flag meaning the existence of mpfr.h.
7
+ So, we must define the following.
8
+ */
9
+ #define MPFR MPFR
10
+
11
+ #include "gmp_header/ruby_gmp.h"
12
+ #include "../../mpfr/ruby_mpfr.h"
13
+
14
+ #endif /* _RUBY_MPFR_GMP_H_ */
data/ext/mpfr/ruby_mpfr.c CHANGED
@@ -1,4 +1,5 @@
1
1
  #include "ruby_mpfr.h"
2
+ #include <stdbool.h>
2
3
 
3
4
  #define MPFR_DUMP_NUMBER 'A'
4
5
  #define MPFR_DUMP_PZERO 'B'
@@ -7,7 +8,10 @@
7
8
  #define MPFR_DUMP_MINF 'E'
8
9
  #define MPFR_DUMP_NAN 'F'
9
10
 
10
- static ID eqq, to_s, new, class, method_defined, object_id;
11
+ #define MPFR_P(obj) RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))
12
+
13
+ static ID eqq, to_s, new, class, method_defined, object_id, to_fr,
14
+ id_rndn, id_rndz, id_rndu, id_rndd, id_rnda;
11
15
  static VALUE __mpfr_class__, __sym_to_s__, __sym_to_str__;
12
16
 
13
17
  /* ------------------------------ Precision and Rounding Mode Start ------------------------------ */
@@ -18,45 +22,46 @@ static VALUE __mpfr_class__, __sym_to_s__, __sym_to_str__;
18
22
  /* return it if it is valid as rounding mode number. */
19
23
  mp_rnd_t r_mpfr_rnd_from_value(VALUE rnd)
20
24
  {
21
- mp_rnd_t r = (mp_rnd_t)NUM2INT(rnd);
22
- if(!VALID_RND(r)){
23
- rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
25
+ ID rnd_id = SYM2ID(rnd);
26
+ if (rnd_id == id_rndn) {
27
+ return MPFR_RNDN;
28
+ } else if (rnd_id == id_rndz) {
29
+ return MPFR_RNDZ;
30
+ } else if (rnd_id == id_rndu) {
31
+ return MPFR_RNDU;
32
+ } else if (rnd_id == id_rndd) {
33
+ return MPFR_RNDD;
34
+ } else if (rnd_id == id_rnda) {
35
+ return MPFR_RNDA;
24
36
  }
25
- return r;
37
+ rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
38
+ /* rb_raise(rb_eArgError, "Argument must be Rounding Mode: %s", rb_class2name(rnd)); */
26
39
  }
27
40
 
28
41
  /* If argc equals max, convert last argument to rounding mode number. */
29
42
  /* Otherwise, return defoult rounding mode number. */
30
43
  mp_rnd_t r_mpfr_rnd_from_optional_argument(int min, int max, int argc, VALUE *argv)
31
44
  {
32
- mp_rnd_t rnd;
33
45
  if(argc >= min && argc <= max){
34
46
  if(argc == max){
35
- rnd = r_mpfr_rnd_from_value(argv[max-1]);
36
- }else{
37
- rnd = mpfr_get_default_rounding_mode();
47
+ return r_mpfr_rnd_from_value(argv[max-1]);
38
48
  }
39
- }else{
40
- rb_raise(rb_eArgError, "Invalid number of arguments.");
49
+ return mpfr_get_default_rounding_mode();
41
50
  }
42
- return rnd;
51
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
43
52
  }
44
53
 
45
54
  /* If argc equals max, convert last argument to precision number. */
46
55
  /* Otherwise, return defoult precision number. */
47
56
  mp_rnd_t r_mpfr_prec_from_optional_argument(int min, int max, int argc, VALUE *argv)
48
57
  {
49
- mp_prec_t prec;
50
58
  if(argc >= min && argc <= max){
51
59
  if(argc == max){
52
- prec = NUM2INT(argv[max - 1]);
53
- }else{
54
- prec = mpfr_get_default_prec();
60
+ return NUM2INT(argv[max - 1]);
55
61
  }
56
- }else{
57
- rb_raise(rb_eArgError, "Invalid number of arguments.");
62
+ return mpfr_get_default_prec();
58
63
  }
59
- return prec;
64
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
60
65
  }
61
66
 
62
67
  /* min is a minimum number of arguments. */
@@ -65,22 +70,41 @@ void r_mpfr_get_rnd_prec_from_optional_arguments(mp_rnd_t *rnd, mp_prec_t *prec,
65
70
  int argc, VALUE *argv)
66
71
  {
67
72
  if(argc >= min && argc <= max){
68
- if(argc >= max - 1){
69
- *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
70
- }else{
71
- *rnd = mpfr_get_default_rounding_mode();
72
- }
73
- if(argc == max){
74
- *prec = NUM2INT(argv[max - 1]);
75
- }else{
73
+ if (argc == max - 1) {
74
+ switch(TYPE(argv[max - 2])){
75
+ case T_SYMBOL:
76
+ *prec = mpfr_get_default_prec();
77
+ *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
78
+ return;
79
+ case T_FIXNUM:
80
+ *prec = NUM2INT(argv[max - 2]);
81
+ *rnd = mpfr_get_default_rounding_mode();
82
+ return;
83
+ }
84
+ } else if (argc == max) {
85
+ switch(TYPE(argv[max - 2])){
86
+ case T_SYMBOL:
87
+ *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
88
+ if (FIXNUM_P(argv[max - 1])) {
89
+ *prec = NUM2INT(argv[max - 1]);
90
+ return;
91
+ }
92
+ case T_FIXNUM:
93
+ *prec = NUM2INT(argv[max - 2]);
94
+ if (SYMBOL_P(argv[max - 1])) {
95
+ *rnd = r_mpfr_rnd_from_value(argv[max - 1]);
96
+ return;
97
+ }
98
+ }
99
+ } else {
76
100
  *prec = mpfr_get_default_prec();
101
+ *rnd = mpfr_get_default_rounding_mode();
102
+ return;
77
103
  }
78
- }else{
79
- rb_raise(rb_eArgError, "Invalid number of arguments.");
80
104
  }
105
+ rb_raise(rb_eArgError, "Invalid number of arguments or invalid type of an argument.");
81
106
  }
82
107
 
83
-
84
108
  /* Set the default MPFR precision in bits. */
85
109
  static VALUE r_mpfr_set_default_prec(VALUE self, VALUE prec)
86
110
  {
@@ -101,19 +125,40 @@ static VALUE r_mpfr_get_default_prec(VALUE self)
101
125
  /* Set the default rounding mode. The default rounding mode is MPFR::RNDN. */
102
126
  static VALUE r_mpfr_set_default_rounding_mode(VALUE self, VALUE rnd)
103
127
  {
104
- mp_rnd_t a = NUM2INT(rnd);
105
- if(VALID_RND(a)){
106
- mpfr_set_default_rounding_mode(a);
107
- }else{
108
- rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
128
+ ID rnd_id = SYM2ID(rnd);
129
+ if (rnd_id == id_rndn) {
130
+ mpfr_set_default_rounding_mode(MPFR_RNDN);
131
+ } else if (rnd_id == id_rndz) {
132
+ mpfr_set_default_rounding_mode(MPFR_RNDZ);
133
+ } else if (rnd_id == id_rndu) {
134
+ mpfr_set_default_rounding_mode(MPFR_RNDU);
135
+ } else if (rnd_id == id_rndd) {
136
+ mpfr_set_default_rounding_mode(MPFR_RNDD);
137
+ } else if (rnd_id == id_rnda) {
138
+ mpfr_set_default_rounding_mode(MPFR_RNDA);
109
139
  }
110
- return INT2FIX(mpfr_get_default_rounding_mode());
140
+ return rnd;
111
141
  }
112
142
 
113
143
  /* Get the default rounding mode. */
114
144
  static VALUE r_mpfr_get_default_rounding_mode(VALUE self)
115
145
  {
116
- return INT2NUM(mpfr_get_default_rounding_mode());
146
+ switch (mpfr_get_default_rounding_mode()) {
147
+ case MPFR_RNDN:
148
+ return ID2SYM(id_rndn);
149
+ case MPFR_RNDZ:
150
+ return ID2SYM(id_rndz);
151
+ case MPFR_RNDU:
152
+ return ID2SYM(id_rndu);
153
+ case MPFR_RNDD:
154
+ return ID2SYM(id_rndd);
155
+ case MPFR_RNDA:
156
+ return ID2SYM(id_rnda);
157
+ case MPFR_RNDF:
158
+ case MPFR_RNDNA:
159
+ rb_raise(rb_eStandardError, "Unsupported rounding mode.");
160
+ }
161
+ rb_raise(rb_eStandardError, "Invalid rounding mode.");
117
162
  }
118
163
 
119
164
  /* ------------------------------ Precision and Rounding Mode End ------------------------------ */
@@ -337,7 +382,7 @@ static void r_mpfr_convert_to_str_set(MPFR *ptr, VALUE obj, mp_rnd_t rnd)
337
382
 
338
383
  void r_mpfr_set_robj(MPFR *ptr, VALUE obj, mp_rnd_t rnd)
339
384
  {
340
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))){
385
+ if(MPFR_P(obj)){
341
386
  MPFR *ptr_obj;
342
387
  r_mpfr_get_struct(ptr_obj, obj);
343
388
  mpfr_set(ptr, ptr_obj, rnd);
@@ -356,18 +401,35 @@ void r_mpfr_set_robj(MPFR *ptr, VALUE obj, mp_rnd_t rnd)
356
401
  r_mpfr_convert_to_str_set(ptr, obj, rnd);
357
402
  break;
358
403
  default:
359
- rb_raise(rb_eArgError, "Invalid class %s for making MPFR.", rb_class2name(obj));
404
+ if(rb_respond_to(obj, to_fr)){
405
+ MPFR *ptr_obj;
406
+ volatile VALUE tmp = rb_funcall(obj, to_fr, 0);
407
+ r_mpfr_get_struct(ptr_obj, tmp);
408
+ mpfr_set(ptr, ptr_obj, rnd);
409
+ } else {
410
+ rb_raise(rb_eArgError, "Invalid class %s for making MPFR.", rb_class2name(obj));
411
+ }
360
412
  break;
361
413
  }
362
414
  }
363
415
  }
364
416
 
417
+ VALUE r_mpfr_robj_to_mpfr(VALUE obj, int argc, VALUE *argv)
418
+ {
419
+ if (rb_respond_to(obj, to_fr)) {
420
+ return rb_funcall2(obj, to_fr, argc, argv);
421
+ }
422
+ rb_raise(rb_eArgError, "The object of %s can not been converted to MPFR.", rb_class2name(obj));
423
+ }
424
+
365
425
  /* If obj is MPFR instance, then this method returns obj. */
366
426
  /* Otherwise it returns MPFR.new(obj). */
367
427
  VALUE r_mpfr_new_fr_obj(VALUE obj)
368
428
  {
369
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))){
429
+ if(MPFR_P(obj)){
370
430
  return obj;
431
+ }else if (rb_respond_to(obj, to_fr)) {
432
+ return rb_funcall(obj, to_fr, 0);
371
433
  }else{
372
434
  return rb_funcall(__mpfr_class__, new, 1, obj);
373
435
  }
@@ -380,39 +442,68 @@ static VALUE r_mpfr_alloc(VALUE self)
380
442
  return self;
381
443
  }
382
444
 
383
- static void r_mpfr_set_initial_value(MPFR *ptr, int argc, VALUE *argv)
445
+ /* Return new MPFR instance. The same arguments as MPFR.new is acceptable. */
446
+ static VALUE r_mpfr_global_new(int argc, VALUE *argv, VALUE self)
384
447
  {
448
+ MPFR *ptr;
449
+ VALUE val;
450
+ mp_prec_t prec;
451
+ mp_rnd_t rnd;
385
452
  switch(argc){
386
453
  case 0:
387
- mpfr_init(ptr);
454
+ r_mpfr_make_struct_init(val, ptr);
388
455
  mpfr_set_nan(ptr);
389
- break;
456
+ return val;
390
457
  case 1:
391
- mpfr_init(ptr);
392
- r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
458
+ prec = mpfr_get_default_prec();
459
+ rnd = mpfr_get_default_rounding_mode();
393
460
  break;
394
461
  case 2:
395
- case 3:
396
- if(argc == 2){
397
- mpfr_init(ptr);
398
- }else{
399
- mpfr_init2(ptr, NUM2INT(argv[2]));
462
+ if (SYMBOL_P(argv[1])) {
463
+ rnd = r_mpfr_rnd_from_value(argv[1]);
464
+ prec = mpfr_get_default_prec();
465
+ } else if (FIXNUM_P(argv[1])) {
466
+ prec = NUM2INT(argv[1]);
467
+ rnd = mpfr_get_default_rounding_mode();
468
+ } else {
469
+ rb_raise(rb_eArgError, "Invalid argument.");
400
470
  }
401
- r_mpfr_set_robj(ptr, argv[0], r_mpfr_rnd_from_value(argv[1]));
471
+ break;
472
+ case 3:
473
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
402
474
  break;
403
475
  default:
404
476
  rb_raise(rb_eArgError, "Invalid number of arguments.");
405
477
  break;
406
478
  }
407
- }
408
-
409
- /* Return new MPFR instance. The same arguments as MPFR.new is acceptable. */
410
- static VALUE r_mpfr_global_new(int argc, VALUE *argv, VALUE self)
411
- {
412
- MPFR *ptr;
413
- VALUE val;
414
- r_mpfr_make_struct(val, ptr);
415
- r_mpfr_set_initial_value(ptr, argc, argv);
479
+ if(MPFR_P(argv[0])){
480
+ MPFR *ptr_obj;
481
+ r_mpfr_get_struct(ptr_obj, argv[0]);
482
+ r_mpfr_make_struct_init2(val, ptr, prec);
483
+ mpfr_set(ptr, ptr_obj, rnd);
484
+ }else{
485
+ switch(TYPE(argv[0])){
486
+ case T_STRING:
487
+ r_mpfr_make_struct_init2(val, ptr, prec);
488
+ mpfr_set_str(ptr, StringValuePtr(argv[0]), 10, rnd);
489
+ break;
490
+ case T_FLOAT:
491
+ r_mpfr_make_struct_init2(val, ptr, prec);
492
+ mpfr_set_d(ptr, NUM2DBL(argv[0]), rnd);
493
+ break;
494
+ case T_FIXNUM:
495
+ r_mpfr_make_struct_init2(val, ptr, prec);
496
+ mpfr_set_si(ptr, FIX2LONG(argv[0]), rnd);
497
+ break;
498
+ case T_BIGNUM:
499
+ r_mpfr_make_struct_init2(val, ptr, prec);
500
+ r_mpfr_convert_to_str_set(ptr, argv[0], rnd);
501
+ break;
502
+ default:
503
+ val = r_mpfr_robj_to_mpfr(argv[0], argc - 1, argv + 1);
504
+ break;
505
+ }
506
+ }
416
507
  return val;
417
508
  }
418
509
 
@@ -426,7 +517,37 @@ static VALUE r_mpfr_initialize(int argc, VALUE *argv, VALUE self)
426
517
  {
427
518
  MPFR *ptr;
428
519
  r_mpfr_get_struct(ptr, self);
429
- r_mpfr_set_initial_value(ptr, argc, argv);
520
+ switch(argc){
521
+ case 0:
522
+ mpfr_init(ptr);
523
+ mpfr_set_nan(ptr);
524
+ break;
525
+ case 1:
526
+ mpfr_init(ptr);
527
+ r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
528
+ break;
529
+ case 2:
530
+ if (SYMBOL_P(argv[1])) {
531
+ mpfr_init(ptr);
532
+ r_mpfr_set_robj(ptr, argv[0], r_mpfr_rnd_from_value(argv[1]));
533
+ } else if (FIXNUM_P(argv[1])) {
534
+ mpfr_init2(ptr, NUM2INT(argv[1]));
535
+ r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
536
+ }
537
+ break;
538
+ case 3:
539
+ {
540
+ mp_prec_t prec;
541
+ mp_rnd_t rnd;
542
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
543
+ mpfr_init2(ptr, prec);
544
+ r_mpfr_set_robj(ptr, argv[0], rnd);
545
+ }
546
+ break;
547
+ default:
548
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
549
+ break;
550
+ }
430
551
  return Qtrue;
431
552
  }
432
553
 
@@ -444,12 +565,7 @@ static VALUE r_mpfr_initialize_copy(VALUE self, VALUE other)
444
565
  /* Return array which have MPFR instance converted to from p1 and self. */
445
566
  static VALUE r_mpfr_coerce(VALUE self, VALUE other)
446
567
  {
447
- VALUE val_other;
448
- MPFR *ptr_self, *ptr_other;
449
- r_mpfr_get_struct(ptr_self, self);
450
- r_mpfr_make_struct_init2(val_other, ptr_other, mpfr_get_prec(ptr_self));
451
- r_mpfr_set_robj(ptr_other, other, mpfr_get_default_rounding_mode());
452
- return rb_ary_new3(2, val_other, self);
568
+ return rb_ary_new3(2, r_mpfr_global_new(1, &other, r_mpfr_class), self);
453
569
  }
454
570
 
455
571
  /* Return NaN. This method takes one optional argument meaning precision. */
@@ -585,7 +701,7 @@ static VALUE r_mpfr_swap(VALUE self, VALUE other)
585
701
  {
586
702
  MPFR *ptr_self, *ptr_other;
587
703
  r_mpfr_get_struct(ptr_self, self);
588
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
704
+ if(MPFR_P(other)){
589
705
  r_mpfr_get_struct(ptr_other, other);
590
706
  }else{
591
707
  rb_raise(rb_eArgError, "Argument must be MPFR object.");
@@ -722,7 +838,7 @@ static VALUE r_mpfr_add(VALUE self, VALUE other)
722
838
  r_mpfr_get_struct(ptr_self, self);
723
839
  r_mpfr_make_struct_init(val_ret, ptr_return);
724
840
 
725
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
841
+ if(MPFR_P(other)){
726
842
  r_mpfr_get_struct(ptr_other, other);
727
843
  mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
728
844
  }else if(TYPE(other) == T_FIXNUM){
@@ -733,6 +849,10 @@ static VALUE r_mpfr_add(VALUE self, VALUE other)
733
849
  volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
734
850
  r_mpfr_get_struct(ptr_other, tmp);
735
851
  mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
852
+ }else if(rb_respond_to(other, to_fr)){
853
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
854
+ r_mpfr_get_struct(ptr_other, tmp);
855
+ mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
736
856
  }else{
737
857
  rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
738
858
  }
@@ -747,7 +867,7 @@ static VALUE r_mpfr_sub(VALUE self, VALUE other)
747
867
  r_mpfr_get_struct(ptr_self, self);
748
868
  r_mpfr_make_struct_init(val_ret, ptr_return);
749
869
 
750
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
870
+ if(MPFR_P(other)){
751
871
  r_mpfr_get_struct(ptr_other, other);
752
872
  mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
753
873
  }else if(TYPE(other) == T_FIXNUM){
@@ -758,6 +878,10 @@ static VALUE r_mpfr_sub(VALUE self, VALUE other)
758
878
  volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
759
879
  r_mpfr_get_struct(ptr_other, tmp);
760
880
  mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
881
+ }else if(rb_respond_to(other, to_fr)){
882
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
883
+ r_mpfr_get_struct(ptr_other, tmp);
884
+ mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
761
885
  }else{
762
886
  rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
763
887
  }
@@ -772,7 +896,7 @@ static VALUE r_mpfr_mul(VALUE self, VALUE other)
772
896
  r_mpfr_get_struct(ptr_self, self);
773
897
  r_mpfr_make_struct_init(val_ret, ptr_return);
774
898
 
775
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
899
+ if(MPFR_P(other)){
776
900
  r_mpfr_get_struct(ptr_other, other);
777
901
  mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
778
902
  }else if(TYPE(other) == T_FIXNUM){
@@ -783,6 +907,10 @@ static VALUE r_mpfr_mul(VALUE self, VALUE other)
783
907
  volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
784
908
  r_mpfr_get_struct(ptr_other, tmp);
785
909
  mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
910
+ }else if(rb_respond_to(other, to_fr)){
911
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
912
+ r_mpfr_get_struct(ptr_other, tmp);
913
+ mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
786
914
  }else{
787
915
  rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
788
916
  }
@@ -797,7 +925,7 @@ static VALUE r_mpfr_div(VALUE self, VALUE other)
797
925
  r_mpfr_get_struct(ptr_self, self);
798
926
  r_mpfr_make_struct_init(val_ret, ptr_return);
799
927
 
800
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
928
+ if(MPFR_P(other)){
801
929
  r_mpfr_get_struct(ptr_other, other);
802
930
  mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
803
931
  }else if(TYPE(other) == T_FIXNUM){
@@ -808,6 +936,10 @@ static VALUE r_mpfr_div(VALUE self, VALUE other)
808
936
  volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
809
937
  r_mpfr_get_struct(ptr_other, tmp);
810
938
  mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
939
+ }else if(rb_respond_to(other, to_fr)){
940
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
941
+ r_mpfr_get_struct(ptr_other, tmp);
942
+ mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
811
943
  }else{
812
944
  rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
813
945
  }
@@ -875,7 +1007,7 @@ static VALUE r_mpfr_math_add(int argc, VALUE *argv, VALUE self)
875
1007
  r_mpfr_get_struct(ptr_arg1, tmp_argv0);
876
1008
  r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
877
1009
 
878
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
1010
+ if(MPFR_P(argv[1])){
879
1011
  r_mpfr_get_struct(ptr_arg2, argv[1]);
880
1012
  mpfr_add(ptr_return, ptr_arg1, ptr_arg2, rnd);
881
1013
  }else if(TYPE(argv[1]) == T_FIXNUM){
@@ -899,7 +1031,7 @@ static VALUE r_mpfr_math_sub(int argc, VALUE *argv, VALUE self)
899
1031
  r_mpfr_get_struct(ptr_arg1, tmp_argv0);
900
1032
  r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
901
1033
 
902
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
1034
+ if(MPFR_P(argv[1])){
903
1035
  r_mpfr_get_struct(ptr_arg2, argv[1]);
904
1036
  mpfr_sub(ptr_return, ptr_arg1, ptr_arg2, rnd);
905
1037
  }else if(TYPE(argv[1]) == T_FIXNUM){
@@ -923,7 +1055,7 @@ static VALUE r_mpfr_math_mul(int argc, VALUE *argv, VALUE self)
923
1055
  r_mpfr_get_struct(ptr_arg1, tmp_argv0);
924
1056
  r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
925
1057
 
926
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
1058
+ if(MPFR_P(argv[1])){
927
1059
  r_mpfr_get_struct(ptr_arg2, argv[1]);
928
1060
  mpfr_mul(ptr_return, ptr_arg1, ptr_arg2, rnd);
929
1061
  }else if(TYPE(argv[1]) == T_FIXNUM){
@@ -947,7 +1079,7 @@ static VALUE r_mpfr_math_div(int argc, VALUE *argv, VALUE self)
947
1079
  r_mpfr_get_struct(ptr_arg1, tmp_argv0);
948
1080
  r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
949
1081
 
950
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
1082
+ if(MPFR_P(argv[1])){
951
1083
  r_mpfr_get_struct(ptr_arg2, argv[1]);
952
1084
  mpfr_div(ptr_return, ptr_arg1, ptr_arg2, rnd);
953
1085
  }else if(TYPE(argv[1]) == T_FIXNUM){
@@ -1128,7 +1260,7 @@ static VALUE r_mpfr_cmp(VALUE self, VALUE other)
1128
1260
  r_mpfr_get_struct(ptr_self, self);
1129
1261
  int val_ret;
1130
1262
 
1131
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
1263
+ if(MPFR_P(other)){
1132
1264
  r_mpfr_get_struct(ptr_other, other);
1133
1265
  val_ret = mpfr_cmp(ptr_self, ptr_other);
1134
1266
  }else if(TYPE(other) == T_FIXNUM){
@@ -1891,7 +2023,7 @@ static VALUE r_mpfr_math_sin_cos(int argc, VALUE *argv, VALUE self)
1891
2023
  {
1892
2024
  mp_rnd_t rnd;
1893
2025
  mp_prec_t prec;
1894
- r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 2, 4, argc, argv);
2026
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
1895
2027
  MPFR *ptr_arg1, *ptr_return1, *ptr_return2;
1896
2028
  VALUE val_ret1, val_ret2;
1897
2029
  volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
@@ -2549,7 +2681,7 @@ static VALUE r_mpfr_math_free_cache(VALUE self)
2549
2681
  static VALUE r_mpfr_math_sum(int argc, VALUE *argv, VALUE self){
2550
2682
  int num;
2551
2683
  for (num = 0; num < argc; num += 1) {
2552
- if(!RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[num]))){ break; }
2684
+ if(!MPFR_P(argv[num])){ break; }
2553
2685
  }
2554
2686
 
2555
2687
  mp_rnd_t rnd;
@@ -2710,6 +2842,45 @@ static VALUE r_mpfr_marshal_load(VALUE self, VALUE dump_string)
2710
2842
  return self;
2711
2843
  }
2712
2844
 
2845
+ /* Conversion to MPFR. */
2846
+
2847
+ /* Convert to MPFR. */
2848
+ static VALUE r_mpfr_float_to_fr (int argc, VALUE *argv, VALUE self)
2849
+ {
2850
+ MPFR *ptr_return;
2851
+ VALUE val_ret;
2852
+ mp_rnd_t rnd;
2853
+ mp_prec_t prec;
2854
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 0, 2, argc, argv);
2855
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
2856
+ mpfr_set_d(ptr_return, NUM2DBL(self), rnd);
2857
+ return val_ret;
2858
+ }
2859
+
2860
+ /* Convert to MPFR. */
2861
+ static VALUE r_mpfr_fixnum_to_fr (int argc, VALUE *argv, VALUE self)
2862
+ {
2863
+ MPFR *ptr_return;
2864
+ VALUE val_ret;
2865
+ mp_prec_t prec;
2866
+ prec = r_mpfr_prec_from_optional_argument(0, 1, argc, argv);
2867
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
2868
+ mpfr_set_si(ptr_return, NUM2INT(self), MPFR_RNDN);
2869
+ return val_ret;
2870
+ }
2871
+
2872
+ /* Convert to MPFR. */
2873
+ static VALUE r_mpfr_bignum_to_fr (int argc, VALUE *argv, VALUE self)
2874
+ {
2875
+ MPFR *ptr_return;
2876
+ VALUE val_ret;
2877
+ mp_prec_t prec;
2878
+ prec = r_mpfr_prec_from_optional_argument(0, 1, argc, argv);
2879
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
2880
+ r_mpfr_convert_to_str_set(ptr_return, self, MPFR_RNDN);
2881
+ return val_ret;
2882
+ }
2883
+
2713
2884
  void Init_mpfr()
2714
2885
  {
2715
2886
  /* ------------------------------ Class MPFR Start ------------------------------ */
@@ -2770,6 +2941,21 @@ void Init_mpfr()
2770
2941
  MPFR#to_s makes a string corresponding to mpfr_printf("%.Re", fr).
2771
2942
  If you want to adjust format of string, you can MPFR#to_strf.
2772
2943
  MPFR#to_strf(format) returns a string corresponding to mpfr_printf(format, fr).
2944
+
2945
+ == Conversion to MPFR
2946
+
2947
+ ruby-mpfr defines methods 'to_fr' for Float, Fixnum, and Bignum and
2948
+ uses these methods to convert an object of MPFR.
2949
+ In particular, MPFR() uses method 'to_fr'.
2950
+ The method 'to_fr' must accept two optional arguments that are rounding mode and precision
2951
+ if you want to define a method 'to_fr' for your class.
2952
+
2953
+ == Conversion between MPFR and GMP (experimental)
2954
+
2955
+ We can use ruby-mpfr with gmp bindings of ruby (https://github.com/srawlins/gmp).
2956
+ If we add require 'mpfr/gmp' in ruby code,
2957
+ some conversion methods between MPFR and GMP are added.
2958
+
2773
2959
  */
2774
2960
  r_mpfr_class = rb_define_class("MPFR", rb_cNumeric);
2775
2961
  rb_include_module(r_mpfr_class, rb_mComparable);
@@ -2798,16 +2984,22 @@ void Init_mpfr()
2798
2984
  /* Integer whichi is MPFR_EMIN_DEFAULT. */
2799
2985
  rb_define_const(r_mpfr_class, "EMIN_DEFAULT", INT2NUM(MPFR_EMIN_DEFAULT));
2800
2986
 
2987
+ id_rndn = rb_intern("RNDN");
2988
+ id_rndz = rb_intern("RNDZ");
2989
+ id_rndu = rb_intern("RNDU");
2990
+ id_rndd = rb_intern("RNDD");
2991
+ id_rnda = rb_intern("RNDA");
2992
+
2801
2993
  /* Integer that is macro MPFR_RNDN. */
2802
- rb_define_const(r_mpfr_class, "RNDN", INT2NUM(MPFR_RNDN));
2994
+ rb_define_const(r_mpfr_class, "RNDN", ID2SYM(id_rndn));
2803
2995
  /* Integer that is macro MPFR_RNDZ. */
2804
- rb_define_const(r_mpfr_class, "RNDZ", INT2NUM(MPFR_RNDZ));
2996
+ rb_define_const(r_mpfr_class, "RNDZ", ID2SYM(id_rndz));
2805
2997
  /* Integer that is macro MPFR_RNDU. */
2806
- rb_define_const(r_mpfr_class, "RNDU", INT2NUM(MPFR_RNDU));
2998
+ rb_define_const(r_mpfr_class, "RNDU", ID2SYM(id_rndu));
2807
2999
  /* Integer that is macro MPFR_RNDD. */
2808
- rb_define_const(r_mpfr_class, "RNDD", INT2NUM(MPFR_RNDD));
3000
+ rb_define_const(r_mpfr_class, "RNDD", ID2SYM(id_rndd));
2809
3001
  /* Integer that is macro MPFR_RNDD. */
2810
- rb_define_const(r_mpfr_class, "RNDA", INT2NUM(MPFR_RNDA));
3002
+ rb_define_const(r_mpfr_class, "RNDA", ID2SYM(id_rnda));
2811
3003
 
2812
3004
  /* ------------------------------ Constants End ------------------------------ */
2813
3005
 
@@ -3114,12 +3306,21 @@ void Init_mpfr()
3114
3306
 
3115
3307
  /* ------------------------------ Module MPFR::Math End ------------------------------ */
3116
3308
 
3309
+ /* ------------------------------ Conversion to MPFR Start ------------------------------ */
3310
+
3311
+ rb_define_method(rb_cFloat, "to_fr", r_mpfr_float_to_fr, -1);
3312
+ rb_define_method(rb_cFixnum, "to_fr", r_mpfr_fixnum_to_fr, -1);
3313
+ rb_define_method(rb_cBignum, "to_fr", r_mpfr_bignum_to_fr, -1);
3314
+
3315
+ /* ------------------------------ Conversion to MPFR End ------------------------------ */
3316
+
3117
3317
  eqq = rb_intern("===");
3118
3318
  to_s = rb_intern("to_s");
3119
3319
  new = rb_intern("new");
3120
3320
  class = rb_intern("class");
3121
3321
  method_defined = rb_intern("method_defined?");
3122
3322
  object_id = rb_intern("object_id");
3323
+ to_fr = rb_intern("to_fr");
3123
3324
 
3124
3325
  __mpfr_class__ = rb_eval_string("MPFR");
3125
3326
  __sym_to_s__ = rb_eval_string(":to_s");