ext/mpfr/ruby_mpfr.c in ruby-mpfr-0.0.9 vs ext/mpfr/ruby_mpfr.c in ruby-mpfr-0.0.10
- old
+ new
@@ -1,88 +1,112 @@
#include "ruby_mpfr.h"
+#include <stdbool.h>
#define MPFR_DUMP_NUMBER 'A'
#define MPFR_DUMP_PZERO 'B'
#define MPFR_DUMP_MZERO 'C'
#define MPFR_DUMP_PINF 'D'
#define MPFR_DUMP_MINF 'E'
#define MPFR_DUMP_NAN 'F'
-static ID eqq, to_s, new, class, method_defined, object_id;
+#define MPFR_P(obj) RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))
+
+static ID eqq, to_s, new, class, method_defined, object_id, to_fr,
+ id_rndn, id_rndz, id_rndu, id_rndd, id_rnda;
static VALUE __mpfr_class__, __sym_to_s__, __sym_to_str__;
/* ------------------------------ Precision and Rounding Mode Start ------------------------------ */
#define VALID_RND(rnd_mode) (rnd_mode >= MPFR_RNDN && rnd_mode < ((MPFR_RNDA)+1))
#define SPECIAL_FUNC_STATE "@@special_func_state"
/* Convert VALUE rnd (rounding mode number) to C integer and */
/* return it if it is valid as rounding mode number. */
mp_rnd_t r_mpfr_rnd_from_value(VALUE rnd)
{
- mp_rnd_t r = (mp_rnd_t)NUM2INT(rnd);
- if(!VALID_RND(r)){
- rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
+ ID rnd_id = SYM2ID(rnd);
+ if (rnd_id == id_rndn) {
+ return MPFR_RNDN;
+ } else if (rnd_id == id_rndz) {
+ return MPFR_RNDZ;
+ } else if (rnd_id == id_rndu) {
+ return MPFR_RNDU;
+ } else if (rnd_id == id_rndd) {
+ return MPFR_RNDD;
+ } else if (rnd_id == id_rnda) {
+ return MPFR_RNDA;
}
- return r;
+ rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
+ /* rb_raise(rb_eArgError, "Argument must be Rounding Mode: %s", rb_class2name(rnd)); */
}
/* If argc equals max, convert last argument to rounding mode number. */
/* Otherwise, return defoult rounding mode number. */
mp_rnd_t r_mpfr_rnd_from_optional_argument(int min, int max, int argc, VALUE *argv)
{
- mp_rnd_t rnd;
if(argc >= min && argc <= max){
if(argc == max){
- rnd = r_mpfr_rnd_from_value(argv[max-1]);
- }else{
- rnd = mpfr_get_default_rounding_mode();
+ return r_mpfr_rnd_from_value(argv[max-1]);
}
- }else{
- rb_raise(rb_eArgError, "Invalid number of arguments.");
+ return mpfr_get_default_rounding_mode();
}
- return rnd;
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
}
/* If argc equals max, convert last argument to precision number. */
/* Otherwise, return defoult precision number. */
mp_rnd_t r_mpfr_prec_from_optional_argument(int min, int max, int argc, VALUE *argv)
{
- mp_prec_t prec;
if(argc >= min && argc <= max){
if(argc == max){
- prec = NUM2INT(argv[max - 1]);
- }else{
- prec = mpfr_get_default_prec();
+ return NUM2INT(argv[max - 1]);
}
- }else{
- rb_raise(rb_eArgError, "Invalid number of arguments.");
+ return mpfr_get_default_prec();
}
- return prec;
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
}
/* min is a minimum number of arguments. */
/* max is a maximum number of arguments. */
void r_mpfr_get_rnd_prec_from_optional_arguments(mp_rnd_t *rnd, mp_prec_t *prec, int min, int max,
int argc, VALUE *argv)
{
if(argc >= min && argc <= max){
- if(argc >= max - 1){
- *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
- }else{
+ if (argc == max - 1) {
+ switch(TYPE(argv[max - 2])){
+ case T_SYMBOL:
+ *prec = mpfr_get_default_prec();
+ *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
+ return;
+ case T_FIXNUM:
+ *prec = NUM2INT(argv[max - 2]);
+ *rnd = mpfr_get_default_rounding_mode();
+ return;
+ }
+ } else if (argc == max) {
+ switch(TYPE(argv[max - 2])){
+ case T_SYMBOL:
+ *rnd = r_mpfr_rnd_from_value(argv[max - 2]);
+ if (FIXNUM_P(argv[max - 1])) {
+ *prec = NUM2INT(argv[max - 1]);
+ return;
+ }
+ case T_FIXNUM:
+ *prec = NUM2INT(argv[max - 2]);
+ if (SYMBOL_P(argv[max - 1])) {
+ *rnd = r_mpfr_rnd_from_value(argv[max - 1]);
+ return;
+ }
+ }
+ } else {
+ *prec = mpfr_get_default_prec();
*rnd = mpfr_get_default_rounding_mode();
+ return;
}
- if(argc == max){
- *prec = NUM2INT(argv[max - 1]);
- }else{
- *prec = mpfr_get_default_prec();
- }
- }else{
- rb_raise(rb_eArgError, "Invalid number of arguments.");
}
+ rb_raise(rb_eArgError, "Invalid number of arguments or invalid type of an argument.");
}
-
/* Set the default MPFR precision in bits. */
static VALUE r_mpfr_set_default_prec(VALUE self, VALUE prec)
{
int set_prec = NUM2INT(prec);
if(set_prec <= 0){
@@ -99,23 +123,44 @@
}
/* Set the default rounding mode. The default rounding mode is MPFR::RNDN. */
static VALUE r_mpfr_set_default_rounding_mode(VALUE self, VALUE rnd)
{
- mp_rnd_t a = NUM2INT(rnd);
- if(VALID_RND(a)){
- mpfr_set_default_rounding_mode(a);
- }else{
- rb_raise(rb_eArgError, "Argument must be Rounding Mode.");
+ ID rnd_id = SYM2ID(rnd);
+ if (rnd_id == id_rndn) {
+ mpfr_set_default_rounding_mode(MPFR_RNDN);
+ } else if (rnd_id == id_rndz) {
+ mpfr_set_default_rounding_mode(MPFR_RNDZ);
+ } else if (rnd_id == id_rndu) {
+ mpfr_set_default_rounding_mode(MPFR_RNDU);
+ } else if (rnd_id == id_rndd) {
+ mpfr_set_default_rounding_mode(MPFR_RNDD);
+ } else if (rnd_id == id_rnda) {
+ mpfr_set_default_rounding_mode(MPFR_RNDA);
}
- return INT2FIX(mpfr_get_default_rounding_mode());
+ return rnd;
}
/* Get the default rounding mode. */
static VALUE r_mpfr_get_default_rounding_mode(VALUE self)
{
- return INT2NUM(mpfr_get_default_rounding_mode());
+ switch (mpfr_get_default_rounding_mode()) {
+ case MPFR_RNDN:
+ return ID2SYM(id_rndn);
+ case MPFR_RNDZ:
+ return ID2SYM(id_rndz);
+ case MPFR_RNDU:
+ return ID2SYM(id_rndu);
+ case MPFR_RNDD:
+ return ID2SYM(id_rndd);
+ case MPFR_RNDA:
+ return ID2SYM(id_rnda);
+ case MPFR_RNDF:
+ case MPFR_RNDNA:
+ rb_raise(rb_eStandardError, "Unsupported rounding mode.");
+ }
+ rb_raise(rb_eStandardError, "Invalid rounding mode.");
}
/* ------------------------------ Precision and Rounding Mode End ------------------------------ */
/* ------------------------------ Exception Related Functions Start ------------------------------ */
@@ -335,11 +380,11 @@
}
}
void r_mpfr_set_robj(MPFR *ptr, VALUE obj, mp_rnd_t rnd)
{
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))){
+ if(MPFR_P(obj)){
MPFR *ptr_obj;
r_mpfr_get_struct(ptr_obj, obj);
mpfr_set(ptr, ptr_obj, rnd);
}else{
switch(TYPE(obj)){
@@ -354,22 +399,39 @@
break;
case T_BIGNUM:
r_mpfr_convert_to_str_set(ptr, obj, rnd);
break;
default:
- rb_raise(rb_eArgError, "Invalid class %s for making MPFR.", rb_class2name(obj));
+ if(rb_respond_to(obj, to_fr)){
+ MPFR *ptr_obj;
+ volatile VALUE tmp = rb_funcall(obj, to_fr, 0);
+ r_mpfr_get_struct(ptr_obj, tmp);
+ mpfr_set(ptr, ptr_obj, rnd);
+ } else {
+ rb_raise(rb_eArgError, "Invalid class %s for making MPFR.", rb_class2name(obj));
+ }
break;
}
}
}
+VALUE r_mpfr_robj_to_mpfr(VALUE obj, int argc, VALUE *argv)
+{
+ if (rb_respond_to(obj, to_fr)) {
+ return rb_funcall2(obj, to_fr, argc, argv);
+ }
+ rb_raise(rb_eArgError, "The object of %s can not been converted to MPFR.", rb_class2name(obj));
+}
+
/* If obj is MPFR instance, then this method returns obj. */
/* Otherwise it returns MPFR.new(obj). */
VALUE r_mpfr_new_fr_obj(VALUE obj)
{
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, obj))){
+ if(MPFR_P(obj)){
return obj;
+ }else if (rb_respond_to(obj, to_fr)) {
+ return rb_funcall(obj, to_fr, 0);
}else{
return rb_funcall(__mpfr_class__, new, 1, obj);
}
}
@@ -378,43 +440,72 @@
MPFR *ptr;
r_mpfr_make_struct(self, ptr);
return self;
}
-static void r_mpfr_set_initial_value(MPFR *ptr, int argc, VALUE *argv)
+/* Return new MPFR instance. The same arguments as MPFR.new is acceptable. */
+static VALUE r_mpfr_global_new(int argc, VALUE *argv, VALUE self)
{
+ MPFR *ptr;
+ VALUE val;
+ mp_prec_t prec;
+ mp_rnd_t rnd;
switch(argc){
case 0:
- mpfr_init(ptr);
+ r_mpfr_make_struct_init(val, ptr);
mpfr_set_nan(ptr);
- break;
+ return val;
case 1:
- mpfr_init(ptr);
- r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
+ prec = mpfr_get_default_prec();
+ rnd = mpfr_get_default_rounding_mode();
break;
case 2:
- case 3:
- if(argc == 2){
- mpfr_init(ptr);
- }else{
- mpfr_init2(ptr, NUM2INT(argv[2]));
+ if (SYMBOL_P(argv[1])) {
+ rnd = r_mpfr_rnd_from_value(argv[1]);
+ prec = mpfr_get_default_prec();
+ } else if (FIXNUM_P(argv[1])) {
+ prec = NUM2INT(argv[1]);
+ rnd = mpfr_get_default_rounding_mode();
+ } else {
+ rb_raise(rb_eArgError, "Invalid argument.");
}
- r_mpfr_set_robj(ptr, argv[0], r_mpfr_rnd_from_value(argv[1]));
break;
+ case 3:
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
+ break;
default:
rb_raise(rb_eArgError, "Invalid number of arguments.");
break;
}
-}
-
-/* Return new MPFR instance. The same arguments as MPFR.new is acceptable. */
-static VALUE r_mpfr_global_new(int argc, VALUE *argv, VALUE self)
-{
- MPFR *ptr;
- VALUE val;
- r_mpfr_make_struct(val, ptr);
- r_mpfr_set_initial_value(ptr, argc, argv);
+ if(MPFR_P(argv[0])){
+ MPFR *ptr_obj;
+ r_mpfr_get_struct(ptr_obj, argv[0]);
+ r_mpfr_make_struct_init2(val, ptr, prec);
+ mpfr_set(ptr, ptr_obj, rnd);
+ }else{
+ switch(TYPE(argv[0])){
+ case T_STRING:
+ r_mpfr_make_struct_init2(val, ptr, prec);
+ mpfr_set_str(ptr, StringValuePtr(argv[0]), 10, rnd);
+ break;
+ case T_FLOAT:
+ r_mpfr_make_struct_init2(val, ptr, prec);
+ mpfr_set_d(ptr, NUM2DBL(argv[0]), rnd);
+ break;
+ case T_FIXNUM:
+ r_mpfr_make_struct_init2(val, ptr, prec);
+ mpfr_set_si(ptr, FIX2LONG(argv[0]), rnd);
+ break;
+ case T_BIGNUM:
+ r_mpfr_make_struct_init2(val, ptr, prec);
+ r_mpfr_convert_to_str_set(ptr, argv[0], rnd);
+ break;
+ default:
+ val = r_mpfr_robj_to_mpfr(argv[0], argc - 1, argv + 1);
+ break;
+ }
+ }
return val;
}
/*
This method returns MPFR instance.
@@ -424,11 +515,41 @@
*/
static VALUE r_mpfr_initialize(int argc, VALUE *argv, VALUE self)
{
MPFR *ptr;
r_mpfr_get_struct(ptr, self);
- r_mpfr_set_initial_value(ptr, argc, argv);
+ switch(argc){
+ case 0:
+ mpfr_init(ptr);
+ mpfr_set_nan(ptr);
+ break;
+ case 1:
+ mpfr_init(ptr);
+ r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
+ break;
+ case 2:
+ if (SYMBOL_P(argv[1])) {
+ mpfr_init(ptr);
+ r_mpfr_set_robj(ptr, argv[0], r_mpfr_rnd_from_value(argv[1]));
+ } else if (FIXNUM_P(argv[1])) {
+ mpfr_init2(ptr, NUM2INT(argv[1]));
+ r_mpfr_set_robj(ptr, argv[0], mpfr_get_default_rounding_mode());
+ }
+ break;
+ case 3:
+ {
+ mp_prec_t prec;
+ mp_rnd_t rnd;
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
+ mpfr_init2(ptr, prec);
+ r_mpfr_set_robj(ptr, argv[0], rnd);
+ }
+ break;
+ default:
+ rb_raise(rb_eArgError, "Invalid number of arguments.");
+ break;
+ }
return Qtrue;
}
/* This method is the method of initialization for copying object. */
static VALUE r_mpfr_initialize_copy(VALUE self, VALUE other)
@@ -442,16 +563,11 @@
}
/* Return array which have MPFR instance converted to from p1 and self. */
static VALUE r_mpfr_coerce(VALUE self, VALUE other)
{
- VALUE val_other;
- MPFR *ptr_self, *ptr_other;
- r_mpfr_get_struct(ptr_self, self);
- r_mpfr_make_struct_init2(val_other, ptr_other, mpfr_get_prec(ptr_self));
- r_mpfr_set_robj(ptr_other, other, mpfr_get_default_rounding_mode());
- return rb_ary_new3(2, val_other, self);
+ return rb_ary_new3(2, r_mpfr_global_new(1, &other, r_mpfr_class), self);
}
/* Return NaN. This method takes one optional argument meaning precision. */
static VALUE r_mpfr_nan(int argc, VALUE *argv, VALUE self)
{
@@ -583,11 +699,11 @@
/* Swap the values self and p1 efficiently. p1 must be MPFR object. */
static VALUE r_mpfr_swap(VALUE self, VALUE other)
{
MPFR *ptr_self, *ptr_other;
r_mpfr_get_struct(ptr_self, self);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
}else{
rb_raise(rb_eArgError, "Argument must be MPFR object.");
}
mpfr_swap(ptr_self, ptr_other);
@@ -720,21 +836,25 @@
MPFR *ptr_self, *ptr_other, *ptr_return;
VALUE val_ret;
r_mpfr_get_struct(ptr_self, self);
r_mpfr_make_struct_init(val_ret, ptr_return);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FIXNUM){
mpfr_add_si(ptr_return, ptr_self, FIX2LONG(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FLOAT){
mpfr_add_d(ptr_return, ptr_self, NUM2DBL(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_BIGNUM){
volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
r_mpfr_get_struct(ptr_other, tmp);
mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
+ }else if(rb_respond_to(other, to_fr)){
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
+ r_mpfr_get_struct(ptr_other, tmp);
+ mpfr_add(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else{
rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
}
return val_ret;
}
@@ -745,21 +865,25 @@
MPFR *ptr_self, *ptr_other, *ptr_return;
VALUE val_ret;
r_mpfr_get_struct(ptr_self, self);
r_mpfr_make_struct_init(val_ret, ptr_return);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FIXNUM){
mpfr_sub_si(ptr_return, ptr_self, FIX2LONG(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FLOAT){
mpfr_sub_d(ptr_return, ptr_self, NUM2DBL(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_BIGNUM){
volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
r_mpfr_get_struct(ptr_other, tmp);
mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
+ }else if(rb_respond_to(other, to_fr)){
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
+ r_mpfr_get_struct(ptr_other, tmp);
+ mpfr_sub(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else{
rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
}
return val_ret;
}
@@ -770,21 +894,25 @@
MPFR *ptr_self, *ptr_other, *ptr_return;
VALUE val_ret;
r_mpfr_get_struct(ptr_self, self);
r_mpfr_make_struct_init(val_ret, ptr_return);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FIXNUM){
mpfr_mul_si(ptr_return, ptr_self, FIX2LONG(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FLOAT){
mpfr_mul_d(ptr_return, ptr_self, NUM2DBL(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_BIGNUM){
volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
r_mpfr_get_struct(ptr_other, tmp);
mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
+ }else if(rb_respond_to(other, to_fr)){
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
+ r_mpfr_get_struct(ptr_other, tmp);
+ mpfr_mul(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else{
rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
}
return val_ret;
}
@@ -795,21 +923,25 @@
MPFR *ptr_self, *ptr_other, *ptr_return;
VALUE val_ret;
r_mpfr_get_struct(ptr_self, self);
r_mpfr_make_struct_init(val_ret, ptr_return);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FIXNUM){
mpfr_div_si(ptr_return, ptr_self, FIX2LONG(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_FLOAT){
mpfr_div_d(ptr_return, ptr_self, NUM2DBL(other), mpfr_get_default_rounding_mode());
}else if(TYPE(other) == T_BIGNUM){
volatile VALUE tmp = rb_funcall(__mpfr_class__, new, 1, other);
r_mpfr_get_struct(ptr_other, tmp);
mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
+ }else if(rb_respond_to(other, to_fr)){
+ volatile VALUE tmp = rb_funcall(other, to_fr, 0);
+ r_mpfr_get_struct(ptr_other, tmp);
+ mpfr_div(ptr_return, ptr_self, ptr_other, mpfr_get_default_rounding_mode());
}else{
rb_raise(rb_eArgError, "Argument must be MPFR, Fixnum, Float, or Bignum.");
}
return val_ret;
}
@@ -873,11 +1005,11 @@
VALUE val_ret;
volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
r_mpfr_get_struct(ptr_arg1, tmp_argv0);
r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
+ if(MPFR_P(argv[1])){
r_mpfr_get_struct(ptr_arg2, argv[1]);
mpfr_add(ptr_return, ptr_arg1, ptr_arg2, rnd);
}else if(TYPE(argv[1]) == T_FIXNUM){
mpfr_add_si(ptr_return, ptr_arg1, FIX2LONG(argv[1]), rnd);
}else{
@@ -897,11 +1029,11 @@
VALUE val_ret;
volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
r_mpfr_get_struct(ptr_arg1, tmp_argv0);
r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
+ if(MPFR_P(argv[1])){
r_mpfr_get_struct(ptr_arg2, argv[1]);
mpfr_sub(ptr_return, ptr_arg1, ptr_arg2, rnd);
}else if(TYPE(argv[1]) == T_FIXNUM){
mpfr_sub_si(ptr_return, ptr_arg1, FIX2LONG(argv[1]), rnd);
}else{
@@ -921,11 +1053,11 @@
VALUE val_ret;
volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
r_mpfr_get_struct(ptr_arg1, tmp_argv0);
r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
+ if(MPFR_P(argv[1])){
r_mpfr_get_struct(ptr_arg2, argv[1]);
mpfr_mul(ptr_return, ptr_arg1, ptr_arg2, rnd);
}else if(TYPE(argv[1]) == T_FIXNUM){
mpfr_mul_si(ptr_return, ptr_arg1, FIX2LONG(argv[1]), rnd);
}else{
@@ -945,11 +1077,11 @@
VALUE val_ret;
volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
r_mpfr_get_struct(ptr_arg1, tmp_argv0);
r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[1]))){
+ if(MPFR_P(argv[1])){
r_mpfr_get_struct(ptr_arg2, argv[1]);
mpfr_div(ptr_return, ptr_arg1, ptr_arg2, rnd);
}else if(TYPE(argv[1]) == T_FIXNUM){
mpfr_div_si(ptr_return, ptr_arg1, FIX2LONG(argv[1]), rnd);
}else{
@@ -1126,11 +1258,11 @@
{
MPFR *ptr_self, *ptr_other;
r_mpfr_get_struct(ptr_self, self);
int val_ret;
- if(RTEST(rb_funcall(__mpfr_class__, eqq, 1, other))){
+ if(MPFR_P(other)){
r_mpfr_get_struct(ptr_other, other);
val_ret = mpfr_cmp(ptr_self, ptr_other);
}else if(TYPE(other) == T_FIXNUM){
val_ret = mpfr_cmp_si(ptr_self, FIX2LONG(other));
}else if(TYPE(other) == T_FLOAT){
@@ -1889,11 +2021,11 @@
/* Return [sin, cos] such as mpfr_sin_cos(sin, cos, p1, rnd). */
static VALUE r_mpfr_math_sin_cos(int argc, VALUE *argv, VALUE self)
{
mp_rnd_t rnd;
mp_prec_t prec;
- r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 2, 4, argc, argv);
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 1, 3, argc, argv);
MPFR *ptr_arg1, *ptr_return1, *ptr_return2;
VALUE val_ret1, val_ret2;
volatile VALUE tmp_argv0 = r_mpfr_new_fr_obj(argv[0]);
r_mpfr_get_struct(ptr_arg1, tmp_argv0);
r_mpfr_make_struct_init2(val_ret1, ptr_return1, prec);
@@ -2547,11 +2679,11 @@
/* Calculate sum of MPFR objects. */
static VALUE r_mpfr_math_sum(int argc, VALUE *argv, VALUE self){
int num;
for (num = 0; num < argc; num += 1) {
- if(!RTEST(rb_funcall(__mpfr_class__, eqq, 1, argv[num]))){ break; }
+ if(!MPFR_P(argv[num])){ break; }
}
mp_rnd_t rnd;
mp_prec_t prec;
r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, num, num + 2, argc, argv);
@@ -2708,10 +2840,49 @@
}
}
return self;
}
+/* Conversion to MPFR. */
+
+/* Convert to MPFR. */
+static VALUE r_mpfr_float_to_fr (int argc, VALUE *argv, VALUE self)
+{
+ MPFR *ptr_return;
+ VALUE val_ret;
+ mp_rnd_t rnd;
+ mp_prec_t prec;
+ r_mpfr_get_rnd_prec_from_optional_arguments(&rnd, &prec, 0, 2, argc, argv);
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
+ mpfr_set_d(ptr_return, NUM2DBL(self), rnd);
+ return val_ret;
+}
+
+/* Convert to MPFR. */
+static VALUE r_mpfr_fixnum_to_fr (int argc, VALUE *argv, VALUE self)
+{
+ MPFR *ptr_return;
+ VALUE val_ret;
+ mp_prec_t prec;
+ prec = r_mpfr_prec_from_optional_argument(0, 1, argc, argv);
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
+ mpfr_set_si(ptr_return, NUM2INT(self), MPFR_RNDN);
+ return val_ret;
+}
+
+/* Convert to MPFR. */
+static VALUE r_mpfr_bignum_to_fr (int argc, VALUE *argv, VALUE self)
+{
+ MPFR *ptr_return;
+ VALUE val_ret;
+ mp_prec_t prec;
+ prec = r_mpfr_prec_from_optional_argument(0, 1, argc, argv);
+ r_mpfr_make_struct_init2(val_ret, ptr_return, prec);
+ r_mpfr_convert_to_str_set(ptr_return, self, MPFR_RNDN);
+ return val_ret;
+}
+
void Init_mpfr()
{
/* ------------------------------ Class MPFR Start ------------------------------ */
/*
@@ -2768,10 +2939,25 @@
== Conversion to String
MPFR#to_s makes a string corresponding to mpfr_printf("%.Re", fr).
If you want to adjust format of string, you can MPFR#to_strf.
MPFR#to_strf(format) returns a string corresponding to mpfr_printf(format, fr).
+
+ == Conversion to MPFR
+
+ ruby-mpfr defines methods 'to_fr' for Float, Fixnum, and Bignum and
+ uses these methods to convert an object of MPFR.
+ In particular, MPFR() uses method 'to_fr'.
+ The method 'to_fr' must accept two optional arguments that are rounding mode and precision
+ if you want to define a method 'to_fr' for your class.
+
+ == Conversion between MPFR and GMP (experimental)
+
+ We can use ruby-mpfr with gmp bindings of ruby (https://github.com/srawlins/gmp).
+ If we add require 'mpfr/gmp' in ruby code,
+ some conversion methods between MPFR and GMP are added.
+
*/
r_mpfr_class = rb_define_class("MPFR", rb_cNumeric);
rb_include_module(r_mpfr_class, rb_mComparable);
/* ------------------------------ Class MPFR End ------------------------------ */
@@ -2796,20 +2982,26 @@
/* Integer that is macro MPFR_EMAX_DEFAULT. */
rb_define_const(r_mpfr_class, "EMAX_DEFAULT", INT2NUM(MPFR_EMAX_DEFAULT));
/* Integer whichi is MPFR_EMIN_DEFAULT. */
rb_define_const(r_mpfr_class, "EMIN_DEFAULT", INT2NUM(MPFR_EMIN_DEFAULT));
+ id_rndn = rb_intern("RNDN");
+ id_rndz = rb_intern("RNDZ");
+ id_rndu = rb_intern("RNDU");
+ id_rndd = rb_intern("RNDD");
+ id_rnda = rb_intern("RNDA");
+
/* Integer that is macro MPFR_RNDN. */
- rb_define_const(r_mpfr_class, "RNDN", INT2NUM(MPFR_RNDN));
+ rb_define_const(r_mpfr_class, "RNDN", ID2SYM(id_rndn));
/* Integer that is macro MPFR_RNDZ. */
- rb_define_const(r_mpfr_class, "RNDZ", INT2NUM(MPFR_RNDZ));
+ rb_define_const(r_mpfr_class, "RNDZ", ID2SYM(id_rndz));
/* Integer that is macro MPFR_RNDU. */
- rb_define_const(r_mpfr_class, "RNDU", INT2NUM(MPFR_RNDU));
+ rb_define_const(r_mpfr_class, "RNDU", ID2SYM(id_rndu));
/* Integer that is macro MPFR_RNDD. */
- rb_define_const(r_mpfr_class, "RNDD", INT2NUM(MPFR_RNDD));
+ rb_define_const(r_mpfr_class, "RNDD", ID2SYM(id_rndd));
/* Integer that is macro MPFR_RNDD. */
- rb_define_const(r_mpfr_class, "RNDA", INT2NUM(MPFR_RNDA));
+ rb_define_const(r_mpfr_class, "RNDA", ID2SYM(id_rnda));
/* ------------------------------ Constants End ------------------------------ */
rb_define_singleton_method(r_mpfr_class, "get_version", r_mpfr_get_version, 0);
rb_define_singleton_method(r_mpfr_class, "get_patches", r_mpfr_get_patches, 0);
@@ -3112,15 +3304,24 @@
/* ------------------------------ MPFR::Math Miscellaneous Functions End ------------------------------ */
/* ------------------------------ Module MPFR::Math End ------------------------------ */
+ /* ------------------------------ Conversion to MPFR Start ------------------------------ */
+
+ rb_define_method(rb_cFloat, "to_fr", r_mpfr_float_to_fr, -1);
+ rb_define_method(rb_cFixnum, "to_fr", r_mpfr_fixnum_to_fr, -1);
+ rb_define_method(rb_cBignum, "to_fr", r_mpfr_bignum_to_fr, -1);
+
+ /* ------------------------------ Conversion to MPFR End ------------------------------ */
+
eqq = rb_intern("===");
to_s = rb_intern("to_s");
new = rb_intern("new");
class = rb_intern("class");
method_defined = rb_intern("method_defined?");
object_id = rb_intern("object_id");
+ to_fr = rb_intern("to_fr");
__mpfr_class__ = rb_eval_string("MPFR");
__sym_to_s__ = rb_eval_string(":to_s");
__sym_to_str__ = rb_eval_string(":to_str");