diff --git a/ChangeLog b/ChangeLog index fdcb6760dd..405d1e774c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,11 @@ Tue Nov 11 14:25:25 2008 Martin Duerst * test/ruby/test_transcode.rb: added tests for the above (from Yoshihiro Kambayashi) +Tue Nov 11 13:20:23 2008 Yukihiro Matsumoto + + * ext/bigdecimal/bigdecimal.c (BigDecimal_to_r): moved from + bigdecimal/util, converted into C. [ruby-dev:36805] + Tue Nov 11 07:55:57 2008 Tadayoshi Funaba * lib/date.rb (inspect): changed the format. diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index fbc2474edf..96bd88160c 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -606,6 +606,41 @@ BigDecimal_to_f(VALUE self) return rb_float_new(d); } + +static VALUE BigDecimal_split(VALUE self); + +/* Converts a BigDecimal to a Rational. + */ +static VALUE +BigDecimal_to_r(VALUE self) +{ + Real *p; + S_LONG sign, power, denomi_power; + VALUE a, digits, numerator; + + p = GetVpValue(self,1); + sign = VpGetSign(p); + power = VpExponent10(p); + a = BigDecimal_split(self); + digits = RARRAY_PTR(a)[1]; + denomi_power = power - RSTRING_LEN(digits); + numerator = rb_funcall(digits, rb_intern("to_i"), 0); + + if (sign < 0) { + numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1)); + } + if (denomi_power < 0) { + return rb_Rational(numerator, + rb_funcall(INT2FIX(10), rb_intern("**"), 1, + INT2FIX(-denomi_power))); + } + else { + return rb_Rational1(rb_funcall(numerator, '*', 1, + rb_funcall(INT2FIX(10), rb_intern("**"), 1, + INT2FIX(denomi_power)))); + } +} + /* The coerce method provides support for Ruby type coercion. It is not * enabled by default. * @@ -1918,6 +1953,7 @@ Init_bigdecimal(void) rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1); rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0); rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0); + rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0); rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0); rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1); rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1); diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb index 09e926acd5..257781f035 100644 --- a/ext/bigdecimal/lib/bigdecimal/util.rb +++ b/ext/bigdecimal/lib/bigdecimal/util.rb @@ -39,18 +39,6 @@ class BigDecimal < Numeric i + "." + ("0"*(-z)) + f end end - - # Converts a BigDecimal to a Rational. - def to_r - sign,digits,base,power = self.split - numerator = sign*digits.to_i - denomi_power = power - digits.size # base is always 10 - if denomi_power < 0 - Rational(numerator,base ** (-denomi_power)) - else - Rational(numerator * (base ** denomi_power),1) - end - end end class Rational < Numeric