[前][次][番号順一覧][スレッド一覧]

ruby-changes:19818

From: mrkn <ko1@a...>
Date: Tue, 31 May 2011 23:44:23 +0900 (JST)
Subject: [ruby-changes:19818] mrkn:r31864 (trunk): * ext/bigdecimal/bigdecimal.c (GetVpValueWithPrec): replace the algorithm for

mrkn	2011-05-31 23:43:39 +0900 (Tue, 31 May 2011)

  New Revision: 31864

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31864

  Log:
    * ext/bigdecimal/bigdecimal.c (GetVpValueWithPrec): replace the algorithm for
      coercing from a Rational to stop requiring "bigecimal/util.rb".
      [ruby-core:34318]
    * ext/bigdecimal/bigdecimal.c (GetVpValue): refactoring.
    * ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation from a
      Rational.
    * test/bigdecimal/test_bigdecimal.rb (test_global_new_with_rationao): add a
      test for the above change.
    * test/bigdecimal/test_bigdecimal.rb (test_new_with_rationao): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/bigdecimal/bigdecimal.c
    trunk/test/bigdecimal/test_bigdecimal.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31863)
+++ ChangeLog	(revision 31864)
@@ -1,3 +1,19 @@
+Tue May 31 23:43:00 2011  Kenta Murata  <mrkn@m...>
+
+	* ext/bigdecimal/bigdecimal.c (GetVpValueWithPrec): replace the algorithm for
+	  coercing from a Rational to stop requiring "bigecimal/util.rb".
+	  [ruby-core:34318]
+
+	* ext/bigdecimal/bigdecimal.c (GetVpValue): refactoring.
+
+	* ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation from a
+	  Rational.
+
+	* test/bigdecimal/test_bigdecimal.rb (test_global_new_with_rationao): add a
+	  test for the above change.
+
+	* test/bigdecimal/test_bigdecimal.rb (test_new_with_rationao): ditto.
+
 Tue May 31 22:44:00 2011  Kenta Murata  <mrkn@m...>
 
 	* ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation a
Index: ext/bigdecimal/bigdecimal.c
===================================================================
--- ext/bigdecimal/bigdecimal.c	(revision 31863)
+++ ext/bigdecimal/bigdecimal.c	(revision 31864)
@@ -131,11 +131,13 @@
     return p->obj;
 }
 
-static Real *
-GetVpValue(VALUE v, int must)
+static VALUE BigDecimal_div2(int, VALUE*, VALUE);
+
+static Real*
+GetVpValueWithPrec(VALUE v, long prec, int must)
 {
     Real *pv;
-    VALUE bg;
+    VALUE num, bg, args[2];
     char szD[128];
     VALUE orig = Qundef;
     int util_loaded = 0;
@@ -143,56 +145,73 @@
 again:
     switch(TYPE(v))
     {
-    case T_RATIONAL:
-        if(orig == Qundef ? (orig = v, 1) : orig != v) {
-            if(!util_loaded) {
-                rb_require("bigdecimal/util");
-                util_loaded = 1;
-            }
-            v = rb_funcall2(v, rb_intern("to_d"), 0, 0);
-            goto again;
-        }
-        v = orig;
-        goto SomeOneMayDoIt;
+      case T_RATIONAL:
+	if (prec < 0) goto unable_to_coerce_without_prec;
 
-    case T_DATA:
-        if(rb_typeddata_is_kind_of(v, &BigDecimal_data_type)) {
-            pv = DATA_PTR(v);
-            return pv;
-        } else {
-            goto SomeOneMayDoIt;
-        }
-        break;
-    case T_FIXNUM:
-        sprintf(szD, "%ld", FIX2LONG(v));
-        return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
+	if (orig == Qundef ? (orig = v, 1) : orig != v) {
+	    num = RRATIONAL(v)->num;
+	    pv = GetVpValueWithPrec(num, -1, must);
+	    if (pv == NULL) goto SomeOneMayDoIt;
 
+	    args[0] = RRATIONAL(v)->den;
+	    args[1] = LONG2NUM(prec);
+	    v = BigDecimal_div2(2, args, ToValue(pv));
+	    goto again;
+	}
+
+	v = orig;
+	goto SomeOneMayDoIt;
+
+      case T_DATA:
+	if (rb_typeddata_is_kind_of(v, &BigDecimal_data_type)) {
+	    pv = DATA_PTR(v);
+	    return pv;
+	}
+	else {
+	    goto SomeOneMayDoIt;
+	}
+	break;
+      case T_FIXNUM:
+	sprintf(szD, "%ld", FIX2LONG(v));
+	return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
+
 #ifdef ENABLE_NUMERIC_STRING
-    case T_STRING:
-        SafeStringValue(v);
-        return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
-                                RSTRING_PTR(v));
+      case T_STRING:
+	SafeStringValue(v);
+	return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
+				RSTRING_PTR(v));
 #endif /* ENABLE_NUMERIC_STRING */
 
-    case T_BIGNUM:
-        bg = rb_big2str(v, 10);
-        return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
-                                RSTRING_PTR(bg));
-    default:
-        goto SomeOneMayDoIt;
+      case T_BIGNUM:
+	bg = rb_big2str(v, 10);
+	return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
+				RSTRING_PTR(bg));
+      default:
+	goto SomeOneMayDoIt;
     }
 
 SomeOneMayDoIt:
-    if(must) {
-        rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
-                    rb_special_const_p(v)?
-                    RSTRING_PTR(rb_inspect(v)):
-                    rb_obj_classname(v)
-                );
+    if (must) {
+	rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
+		 rb_special_const_p(v) ? RSTRING_PTR(rb_inspect(v)) : rb_obj_classname(v));
     }
     return NULL; /* NULL means to coerce */
+
+unable_to_coerce_without_prec:
+    if (must) {
+	rb_raise(rb_eArgError,
+		 "%s can't be coerced into BigDecimal without a precision",
+		 rb_obj_classname(v));
+    }
+    return NULL;
 }
 
+static Real*
+GetVpValue(VALUE v, int must)
+{
+    return GetVpValueWithPrec(v, -1, must);
+}
+
 /* call-seq:
  * BigDecimal.double_fig
  *
@@ -1775,6 +1794,12 @@
       case T_BIGNUM:
 	return ToValue(GetVpValue(iniValue, 1));
 
+      case T_RATIONAL:
+	if (NIL_P(nFig)) {
+	    rb_raise(rb_eArgError, "can't omit precision for a Rational.");
+	}
+	return ToValue(GetVpValueWithPrec(iniValue, mf, 1));
+
       case T_STRING:
 	/* fall through */
       default:
Index: test/bigdecimal/test_bigdecimal.rb
===================================================================
--- test/bigdecimal/test_bigdecimal.rb	(revision 31863)
+++ test/bigdecimal/test_bigdecimal.rb	(revision 31864)
@@ -36,6 +36,12 @@
     assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100))
   end
 
+  def test_global_new_with_rational
+    assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(1.quo(3), 21))
+    assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal(-1.quo(3), 21))
+    assert_raise(ArgumentError) { BigDecimal(1.quo(3)) }
+  end
+
   def test_new
     assert_equal(1, BigDecimal.new("1"))
     assert_equal(1, BigDecimal.new("1", 1))
@@ -58,6 +64,12 @@
     assert_equal(BigDecimal((-2**100).to_s), BigDecimal.new(-2**100))
   end
 
+  def test_new_with_rational
+    assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal.new(1.quo(3), 21))
+    assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal.new(-1.quo(3), 21))
+    assert_raise(ArgumentError) { BigDecimal.new(1.quo(3)) }
+  end
+
   def _test_mode(type)
     BigDecimal.mode(type, true)
     assert_raise(FloatDomainError) { yield }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]