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

ruby-changes:53963

From: mrkn <ko1@a...>
Date: Tue, 4 Dec 2018 13:22:13 +0900 (JST)
Subject: [ruby-changes:53963] mrkn:r66183 (trunk): Import bigdecimal-1.4.0.pre-20181204a

mrkn	2018-12-04 13:22:09 +0900 (Tue, 04 Dec 2018)

  New Revision: 66183

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66183

  Log:
    Import bigdecimal-1.4.0.pre-20181204a
    
    * https://github.com/ruby/bigdecimal/compare/v1.4.0.pre.20181130a..v1.4.0.pre.20181204a

  Modified files:
    trunk/ext/bigdecimal/bigdecimal.c
    trunk/ext/bigdecimal/bigdecimal.gemspec
    trunk/ext/bigdecimal/bigdecimal.h
    trunk/test/bigdecimal/test_bigdecimal.rb
Index: test/bigdecimal/test_bigdecimal.rb
===================================================================
--- test/bigdecimal/test_bigdecimal.rb	(revision 66182)
+++ test/bigdecimal/test_bigdecimal.rb	(revision 66183)
@@ -151,6 +151,63 @@ class TestBigDecimal < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/bigdecimal/test_bigdecimal.rb#L151
     $SAFE = 0
   end
 
+  def test_BigDecimal_with_exception_keyword
+    assert_raise(ArgumentError) {
+      BigDecimal('.', exception: true)
+    }
+    assert_nothing_raised(ArgumentError) {
+      assert_equal(nil, BigDecimal(".", exception: false))
+    }
+    assert_raise(ArgumentError) {
+      BigDecimal("1", -1, exception: true)
+    }
+    assert_nothing_raised(ArgumentError) {
+      assert_equal(nil, BigDecimal("1", -1, exception: false))
+    }
+    assert_raise(ArgumentError) {
+      BigDecimal(42.quo(7), exception: true)
+    }
+    assert_nothing_raised(ArgumentError) {
+      assert_equal(nil, BigDecimal(42.quo(7), exception: false))
+    }
+    assert_raise(ArgumentError) {
+      BigDecimal(4.2, exception: true)
+    }
+    assert_nothing_raised(ArgumentError) {
+      assert_equal(nil, BigDecimal(4.2, exception: false))
+    }
+    # TODO: support conversion from complex
+    # assert_raise(RangeError) {
+    #   BigDecimal(1i, exception: true)
+    # }
+    # assert_nothing_raised(RangeError) {
+    #   assert_equal(nil, BigDecimal(1i, exception: false))
+    # }
+    assert_raise(TypeError) {
+      BigDecimal(nil, exception: true)
+    }
+    assert_nothing_raised(TypeError) {
+      assert_equal(nil, BigDecimal(nil, exception: false))
+    }
+    assert_nothing_raised(TypeError) {
+      assert_equal(nil, BigDecimal(:test, exception: false))
+    }
+    assert_nothing_raised(TypeError) {
+      assert_equal(nil, BigDecimal(Object.new, exception: false))
+    }
+    # TODO: support to_d
+    # assert_nothing_raised(TypeError) {
+    #   o = Object.new
+    #   def o.to_d; 3.14; end
+    #   assert_equal(3.14, BigDecimal(o, exception: false))
+    # }
+    # assert_nothing_raised(RuntimeError) {
+    #   o = Object.new
+    #   def o.to_d; raise; end
+    #   assert_equal(nil, BigDecimal(o, exception: false))
+    # }
+  end
+
   def test_s_ver
     assert_raise(NoMethodError, /undefined method `ver`/) { BigDecimal.ver }
   end
Index: ext/bigdecimal/bigdecimal.c
===================================================================
--- ext/bigdecimal/bigdecimal.c	(revision 66182)
+++ ext/bigdecimal/bigdecimal.c	(revision 66183)
@@ -646,7 +646,7 @@ VP_EXPORT Real * https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L646
 VpNewRbClass(size_t mx, const char *str, VALUE klass)
 {
     VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
-    Real *pv = VpAlloc(mx, str, 1);
+    Real *pv = VpAlloc(mx, str, 1, 1);
     RTYPEDDATA_DATA(obj) = pv;
     pv->obj = obj;
     RB_OBJ_FREEZE(obj);
@@ -2313,7 +2313,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2313
     n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
 
     if (VpIsNaN(x)) {
-        y = VpCreateRbObject(n, "0");
+	y = VpCreateRbObject(n, "0");
 	RB_GC_GUARD(y->obj);
 	VpSetNaN(y);
 	return ToValue(y);
@@ -2437,7 +2437,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2437
 	    }
 	}
 	else {
-            y = VpCreateRbObject(n, "0");
+	    y = VpCreateRbObject(n, "0");
 	    if (BIGDECIMAL_NEGATIVE_P(x)) {
 		if (is_integer(vexp)) {
 		    if (is_even(vexp)) {
@@ -2470,7 +2470,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2470
 	}
 	else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
 	    if (is_negative(vexp)) {
-                y = VpCreateRbObject(n, "0");
+		y = VpCreateRbObject(n, "0");
 		if (is_even(vexp)) {
 		    VpSetInf(y, VpGetSign(x));
 		}
@@ -2488,7 +2488,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2488
 	}
 	else {
 	    if (is_positive(vexp)) {
-                y = VpCreateRbObject(n, "0");
+		y = VpCreateRbObject(n, "0");
 		if (is_even(vexp)) {
 		    VpSetInf(y, VpGetSign(x));
 		}
@@ -2538,28 +2538,6 @@ BigDecimal_power_op(VALUE self, VALUE ex https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2538
     return BigDecimal_power(1, &exp, self);
 }
 
-static Real *BigDecimal_new(int argc, VALUE *argv);
-
-static VALUE
-BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
-{
-    ENTER(1);
-    Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
-    Real *x;
-
-    GUARD_OBJ(x, BigDecimal_new(argc, argv));
-    if (ToValue(x)) {
-	pv = VpCopy(pv, x);
-    }
-    else {
-	VpFree(pv);
-	pv = x;
-    }
-    DATA_PTR(self) = pv;
-    pv->obj = self;
-    return self;
-}
-
 /* :nodoc:
  *
  * private method for dup and clone the provided BigDecimal +other+
@@ -2582,19 +2560,60 @@ BigDecimal_clone(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2560
   return self;
 }
 
+static int
+opts_exception_p(VALUE opts)
+{
+    static ID kwds[1];
+    VALUE exception;
+    if (!kwds[0]) {
+        kwds[0] = rb_intern_const("exception");
+    }
+    rb_get_kwargs(opts, kwds, 0, 1, &exception);
+    return exception != Qfalse;
+}
+
 static Real *
 BigDecimal_new(int argc, VALUE *argv)
 {
     size_t mf;
+    VALUE  opts = Qnil;
     VALUE  nFig;
     VALUE  iniValue;
     double d;
+    int    exc;
 
-    if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
+    argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
+    exc = opts_exception_p(opts);
+
+    if (argc == 1) {
         mf = 0;
     }
     else {
-        mf = GetPrecisionInt(nFig);
+        /* expand GetPrecisionInt for exception suppression */
+        ssize_t n = NUM2INT(nFig);
+        if (n < 0) {
+            if (!exc) {
+                return NULL;
+            }
+            rb_raise(rb_eArgError, "negative precision");
+        }
+        mf = (size_t)n;
+    }
+
+    if (SPECIAL_CONST_P(iniValue)) {
+        switch (iniValue) {
+          case Qnil:
+            if (!exc) return NULL;
+            rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
+          case Qtrue:
+            if (!exc) return NULL;
+            rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
+          case Qfalse:
+            if (!exc) return NULL;
+            rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
+          default:
+            break;
+        }
     }
 
     switch (TYPE(iniValue)) {
@@ -2617,11 +2636,17 @@ BigDecimal_new(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2636
             return pv;
         }
 	if (mf > DBL_DIG+1) {
+            if (!exc) {
+                return NULL;
+            }
 	    rb_raise(rb_eArgError, "precision too large.");
 	}
 	/* fall through */
       case T_RATIONAL:
 	if (NIL_P(nFig)) {
+            if (!exc) {
+                return NULL;
+            }
 	    rb_raise(rb_eArgError,
 		     "can't omit precision for a %"PRIsVALUE".",
 		     RB_OBJ_CLASSNAME(iniValue));
@@ -2633,8 +2658,13 @@ BigDecimal_new(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2658
       default:
 	break;
     }
+    /* TODO: support to_d */
+    if (!exc) {
+        iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
+        if (NIL_P(iniValue)) return NULL;
+    }
     StringValueCStr(iniValue);
-    return VpAlloc(mf, RSTRING_PTR(iniValue), 1);
+    return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
 }
 
 /* call-seq:
@@ -2669,14 +2699,16 @@ BigDecimal_new(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2699
  *                 value is omitted, this exception is raised.
  */
 static VALUE
-BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
+f_BigDecimal(int argc, VALUE *argv, VALUE self)
 {
     ENTER(1);
     Real *pv;
     VALUE obj;
 
     obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
-    GUARD_OBJ(pv, BigDecimal_new(argc, argv));
+    pv = BigDecimal_new(argc, argv);
+    if (pv == NULL) return Qnil;
+    SAVE(pv);
     if (ToValue(pv)) pv = VpCopy(NULL, pv);
     RTYPEDDATA_DATA(obj) = pv;
     RB_OBJ_FREEZE(obj);
@@ -3112,7 +3144,7 @@ rmpd_util_str_to_d(VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3144
   VALUE obj;
 
   c_str = StringValueCStr(str);
-  GUARD_OBJ(pv, VpAlloc(0, c_str, 0));
+  GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
   obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
   RB_OBJ_FREEZE(obj);
   return obj;
@@ -3259,7 +3291,7 @@ Init_bigdecimal(void) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3291
     rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
 
     /* Global function */
-    rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
+    rb_define_global_function("BigDecimal", f_BigDecimal, -1);
 
     /* Class methods */
     rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
@@ -3387,14 +3419,13 @@ Init_bigdecimal(void) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3419
 
     arg = rb_str_new2("+Infinity");
     /* Positive infinity value. */
-    rb_define_const(rb_cBigDecimal, "INFINITY", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
+    rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal));
     arg = rb_str_new2("NaN");
     /* 'Not a Number' value. */
-    rb_define_const(rb_cBigDecimal, "NAN", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
+    rb_define_const(rb_cBigDecimal, "NAN", f_BigDecimal(1, &arg, rb_cBigDecimal));
 
 
     /* instance methods */
-    rb_define_method(rb_cBigDecimal, "initialize", BigDecimal_initialize, -1);
     rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
     rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
 
@@ -3687,13 +3718,13 @@ VpSetRoundMode(unsigned short n) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3718
 
 /*
  *  0.0 & 1.0 generator
- *    These gOne_..... can be any name
- *    referenced from nowhere except One().
- *    gOne_..... must have global scope
+ *    These gZero_..... and gOne_..... can be any name
+ *    referenced from nowhere except Zero() and One().
+ *    gZero_..... and gOne_..... must have global scope
  *    (to let the compiler know they may be changed in outside
  *    (... but not actually..)).
  */
-volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
+volatile const double gOne_ABCED9B4_CE73__00400511F31D  = 1.0;
 
 static double
 One(void)
@@ -3931,8 +3962,8 @@ VpInit(BDIGIT BaseVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3962
     VpGetDoubleNegZero();
 
     /* Allocates Vp constants. */
-    VpConstOne = VpAlloc(1UL, "1", 1);
-    VpPt5 = VpAlloc(1UL, ".5", 1);
+    VpConstOne = VpAlloc(1UL, "1", 1, 1);
+    VpPt5 = VpAlloc(1UL, ".5", 1, 1);
 
 #ifdef BIGDECIMAL_DEBUG
     gnAlloc = 0;
@@ -4056,7 +4087,7 @@ rmpd_parse_special_string(const char *st https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4087
  *   NULL be returned if memory allocation is failed,or any error.
  */
 VP_EXPORT Real *
-VpAlloc(size_t mx, const char *szVal, int strict_p)
+VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
 {
     const char *orig_szVal = szVal;
     size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
@@ -4255,7 +4286,9 @@ VpAlloc(size_t mx, const char *szVal, in https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4286
         if (!strict_p) {
             goto return_zero;
         }
-
+        if (!exc) {
+            return NULL;
+        }
         str = rb_str_new2(orig_szVal);
         rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
     }
@@ -4832,7 +4865,7 @@ VpMult(Real *c, Real *a, Real *b) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4865
 
     if (MxIndC < MxIndAB) {    /* The Max. prec. of c < Prec(a)+Prec(b) */
 	w = c;
-        c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1);
+	c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
 	MxIndC = MxIndAB;
     }
 
@@ -6000,8 +6033,8 @@ VpSqrt(Real *y, Real *x) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L6033
     if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
 
     /* allocate temporally variables  */
-    f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1);
-    r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1);
+    f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
+    r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
 
     nr = 0;
     y_prec = y->MaxPrec;
@@ -6453,8 +6486,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L6486
 
     /* Allocate working variables  */
 
-    w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1);
-    w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1);
+    w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
+    w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
     /* calculation start */
 
     VpAsgn(y, x, 1);
Index: ext/bigdecimal/bigdecimal.gemspec
===================================================================
--- ext/bigdecimal/bigdecimal.gemspec	(revision 66182)
+++ ext/bigdecimal/bigdecimal.gemspec	(revision 66183)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.gemspec#L1
 # coding: utf-8
 
-bigdecimal_version = '1.4.0.pre.20181121a'
+bigdecimal_version = '1.4.0.pre.20181204a'
 
 Gem::Specification.new do |s|
   s.name          = "bigdecimal"
@@ -18,6 +18,7 @@ Gem::Specification.new do |s| https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.gemspec#L18
   s.files         = %w[
     bigdecimal.gemspec
     ext/bigdecimal/bigdecimal.c
+    ext/bigdecimal/bigdecimal.def
     ext/bigdecimal/bigdecimal.h
     ext/bigdecimal/depend
     ext/bigdecimal/extconf.rb
Index: ext/bigdecimal/bigdecimal.h
===================================================================
--- ext/bigdecimal/bigdecimal.h	(revision 66182)
+++ ext/bigdecimal/bigdecimal.h	(revision 66183)
@@ -308,7 +308,7 @@ VP_EXPORT size_t VpInit(BDIGIT BaseVal); https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.h#L308
 VP_EXPORT void *VpMemAlloc(size_t mb);
 VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
 VP_EXPORT void VpFree(Real *pv);
-VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p);
+VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
 VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
 VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
 VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);

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

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