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

ruby-changes:44967

From: mrkn <ko1@a...>
Date: Sat, 10 Dec 2016 16:49:21 +0900 (JST)
Subject: [ruby-changes:44967] mrkn:r57040 (trunk): bigdecimal: import version 1.3.0.pre

mrkn	2016-12-10 16:49:15 +0900 (Sat, 10 Dec 2016)

  New Revision: 57040

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

  Log:
    bigdecimal: import version 1.3.0.pre
    
    Import bigdecimal version 1.3.0.pre.  The full commit log of this
    changes can be found at:
    
        https://github.com/ruby/bigdecimal/compare/5c43a9e...v1.3.0.pre

  Modified files:
    trunk/ext/bigdecimal/bigdecimal.c
    trunk/ext/bigdecimal/bigdecimal.gemspec
    trunk/ext/bigdecimal/bigdecimal.h
    trunk/ext/bigdecimal/depend
    trunk/ext/bigdecimal/extconf.rb
    trunk/ext/bigdecimal/lib/bigdecimal/util.rb
    trunk/test/bigdecimal/test_bigdecimal.rb
Index: ext/bigdecimal/depend
===================================================================
--- ext/bigdecimal/depend	(revision 57039)
+++ ext/bigdecimal/depend	(revision 57040)
@@ -1,7 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/depend#L1
 # AUTOGENERATED DEPENDENCIES START
 bigdecimal.o: $(RUBY_EXTCONF_H)
 bigdecimal.o: $(arch_hdrdir)/ruby/config.h
-bigdecimal.o: $(hdrdir)/ruby/backward.h
 bigdecimal.o: $(hdrdir)/ruby/defines.h
 bigdecimal.o: $(hdrdir)/ruby/intern.h
 bigdecimal.o: $(hdrdir)/ruby/missing.h
Index: ext/bigdecimal/bigdecimal.c
===================================================================
--- ext/bigdecimal/bigdecimal.c	(revision 57039)
+++ ext/bigdecimal/bigdecimal.c	(revision 57040)
@@ -62,6 +62,7 @@ static ID id_ceil; https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L62
 static ID id_floor;
 static ID id_to_r;
 static ID id_eq;
+static ID id_half;
 
 /* MACRO's to guard objects from GC by keeping them in stack */
 #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
@@ -126,6 +127,9 @@ rb_rational_den(VALUE rat) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L127
 }
 #endif
 
+#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
+#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
+
 /*
  * ================== Ruby Interface part ==========================
  */
@@ -240,9 +244,8 @@ again: https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L244
 	if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
 	d = RFLOAT_VALUE(v);
 	if (!isfinite(d)) {
-	    pv = VpCreateRbObject(prec, NULL);
-	    pv->sign = isnan(d) ? VP_SIGN_NaN :
-		d > 0 ? VP_SIGN_POSITIVE_INFINITE : VP_SIGN_NEGATIVE_FINITE;
+	    pv = VpCreateRbObject(1, NULL);
+	    VpDtoV(pv, d);
 	    return pv;
 	}
 	if (d != 0.0) {
@@ -385,9 +388,9 @@ BigDecimal_hash(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L388
  * Method used to provide marshalling support.
  *
  *      inf = BigDecimal.new('Infinity')
- *        #=> #<BigDecimal:1e16fa8,'Infinity',9(9)>
+ *        #=> Infinity
  *      BigDecimal._load(inf._dump)
- *        #=> #<BigDecimal:1df8dc8,'Infinity',9(9)>
+ *        #=> Infinity
  *
  * See the Marshal module.
  */
@@ -441,6 +444,54 @@ BigDecimal_load(VALUE self, VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L444
 }
 
 static unsigned short
+check_rounding_mode_option(VALUE const opts)
+{
+    VALUE mode;
+    char const *s;
+    long l;
+
+    assert(RB_TYPE_P(opts, T_HASH));
+
+    if (NIL_P(opts))
+        goto noopt;
+
+    mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
+    if (mode == Qundef)
+        goto noopt;
+
+    if (SYMBOL_P(mode))
+        mode = rb_sym2str(mode);
+    else if (!RB_TYPE_P(mode, T_STRING)) {
+	VALUE str_mode = rb_check_string_type(mode);
+	if (NIL_P(str_mode)) goto invalid;
+	mode = str_mode;
+    }
+    s = RSTRING_PTR(mode);
+    l = RSTRING_LEN(mode);
+    switch (l) {
+      case 2:
+        if (strncasecmp(s, "up", 2) == 0)
+            return VP_ROUND_HALF_UP;
+        break;
+      case 4:
+        if (strncasecmp(s, "even", 4) == 0)
+            return VP_ROUND_HALF_EVEN;
+        else if (strncasecmp(s, "down", 4) == 0)
+            return VP_ROUND_HALF_DOWN;
+      default:
+        break;
+    }
+  invalid:
+    if (NIL_P(mode))
+	rb_raise(rb_eArgError, "invalid rounding mode: nil");
+    else
+	rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
+
+  noopt:
+    return VpGetRoundMode();
+}
+
+static unsigned short
 check_rounding_mode(VALUE const v)
 {
     unsigned short sw;
@@ -562,7 +613,7 @@ BigDecimal_mode(int argc, VALUE *argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L613
 	fo = VpSetRoundMode(sw);
 	return INT2FIX(fo);
     }
-    rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
+    rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
     return Qnil;
 }
 
@@ -682,7 +733,7 @@ static VALUE BigDecimal_split(VALUE self https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L733
 
 /* Returns the value as an Integer.
  *
- * If the BigNumber is infinity or NaN, raises FloatDomainError.
+ * If the BigDecimal is infinity or NaN, raises FloatDomainError.
  */
 static VALUE
 BigDecimal_to_i(VALUE self)
@@ -707,7 +758,7 @@ BigDecimal_to_i(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L758
 	VALUE ret;
 	ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
 
-	if (VpGetSign(p) < 0) {
+	if (BIGDECIMAL_NEGATIVE_P(p)) {
 	    numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
 	}
 	if (dpower < 0) {
@@ -762,17 +813,17 @@ BigDecimal_to_f(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L813
 
 overflow:
     VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
-    if (p->sign >= 0)
-	return rb_float_new(VpGetDoublePosInf());
-    else
+    if (BIGDECIMAL_NEGATIVE_P(p))
 	return rb_float_new(VpGetDoubleNegInf());
+    else
+	return rb_float_new(VpGetDoublePosInf());
 
 underflow:
     VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
-    if (p->sign >= 0)
-	return rb_float_new(0.0);
-    else
+    if (BIGDECIMAL_NEGATIVE_P(p))
 	return rb_float_new(-0.0);
+    else
+	return rb_float_new(0.0);
 }
 
 
@@ -1720,11 +1771,21 @@ BigDecimal_round(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1771
 	iLoc = 0;
 	break;
       case 1:
-	iLoc = NUM2INT(vLoc);
+        if (RB_TYPE_P(vLoc, T_HASH)) {
+	    sw = check_rounding_mode_option(vLoc);
+	}
+	else {
+	    iLoc = NUM2INT(vLoc);
+	}
 	break;
       case 2:
 	iLoc = NUM2INT(vLoc);
-	sw = check_rounding_mode(vRound);
+	if (RB_TYPE_P(vRound, T_HASH)) {
+	    sw = check_rounding_mode_option(vRound);
+	}
+	else {
+	    sw = check_rounding_mode(vRound);
+	}
 	break;
       default:
 	break;
@@ -2066,7 +2127,7 @@ BigDecimal_exponent(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2127
  * values in angle brackets with a leading #:
  *
  *   BigDecimal.new("1234.5678").inspect
- *     #=> "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
+ *     #=> "0.12345678e4"
  *
  * The first part is the address, the second is the value as a string, and
  * the final part ss(mm) is the current number of significant digits and the
@@ -2077,23 +2138,16 @@ BigDecimal_inspect(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2138
 {
     ENTER(5);
     Real *vp;
-    volatile VALUE obj;
+    volatile VALUE str;
     size_t nc;
-    char *psz, *tmp;
 
     GUARD_OBJ(vp, GetVpValue(self, 1));
     nc = VpNumOfChars(vp, "E");
-    nc += (nc + 9) / 10;
 
-    obj = rb_str_new(0, nc+256);
-    psz = RSTRING_PTR(obj);
-    sprintf(psz, "#<BigDecimal:%"PRIxVALUE",'", self);
-    tmp = psz + strlen(psz);
-    VpToString(vp, tmp, 10, 0);
-    tmp += strlen(tmp);
-    sprintf(tmp, "',%"PRIuSIZE"(%"PRIuSIZE")>", VpPrec(vp)*VpBaseFig(), VpMaxPrec(vp)*VpBaseFig());
-    rb_str_resize(obj, strlen(psz));
-    return obj;
+    str = rb_str_new(0, nc);
+    VpToString(vp, RSTRING_PTR(str), 0, 0);
+    rb_str_resize(str, strlen(RSTRING_PTR(str)));
+    return str;
 }
 
 static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
@@ -2303,7 +2357,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2357
 	if (is_negative(vexp)) {
 	    y = VpCreateRbObject(n, "#0");
 	    RB_GC_GUARD(y->obj);
-	    if (VpGetSign(x) < 0) {
+	    if (BIGDECIMAL_NEGATIVE_P(x)) {
 		if (is_integer(vexp)) {
 		    if (is_even(vexp)) {
 			/* (-0) ** (-even_integer)  -> Infinity */
@@ -2342,7 +2396,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2396
 
     if (VpIsInf(x)) {
 	if (is_negative(vexp)) {
-	    if (VpGetSign(x) < 0) {
+	    if (BIGDECIMAL_NEGATIVE_P(x)) {
 		if (is_integer(vexp)) {
 		    if (is_even(vexp)) {
 			/* (-Infinity) ** (-even_integer) -> +0 */
@@ -2364,7 +2418,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2418
 	}
 	else {
 	    y = VpCreateRbObject(n, "0#");
-	    if (VpGetSign(x) < 0) {
+	    if (BIGDECIMAL_NEGATIVE_P(x)) {
 		if (is_integer(vexp)) {
 		    if (is_even(vexp)) {
 			VpSetPosInf(y);
@@ -2405,7 +2459,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2459
 		}
 		return ToValue(y);
 	    }
-	    else if (VpGetSign(x) < 0 && is_even(vexp)) {
+	    else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
 		return ToValue(VpCreateRbObject(n, "-0"));
 	    }
 	    else {
@@ -2423,7 +2477,7 @@ BigDecimal_power(int argc, VALUE*argv, V https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2477
 		}
 		return ToValue(y);
 	    }
-	    else if (VpGetSign(x) < 0 && is_even(vexp)) {
+	    else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
 		return ToValue(VpCreateRbObject(n, "-0"));
 	    }
 	    else {
@@ -2545,6 +2599,7 @@ BigDecimal_new(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2599
     size_t mf;
     VALUE  nFig;
     VALUE  iniValue;
+    double d;
 
     if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
         mf = 0;
@@ -2566,6 +2621,12 @@ BigDecimal_new(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2621
 	return GetVpValue(iniValue, 1);
 
       case T_FLOAT:
+        d = RFLOAT_VALUE(iniValue);
+        if (!isfinite(d)) {
+            Real *pv = VpCreateRbObject(1, NULL);
+            VpDtoV(pv, d);
+            return pv;
+        }
 	if (mf > DBL_DIG+1) {
 	    rb_raise(rb_eArgError, "precision too large.");
 	}
@@ -2766,7 +2827,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALU https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2827
       case T_DATA:
 	if (!is_kind_of_BigDecimal(x)) break;
 	vx = DATA_PTR(x);
-	negative = VpGetSign(vx) < 0;
+	negative = BIGDECIMAL_NEGATIVE_P(vx);
 	infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
 	nan = VpIsNaN(vx);
 	break;
@@ -2819,7 +2880,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALU https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2880
     x = vx->obj;
 
     n = prec + rmpd_double_figures();
-    negative = VpGetSign(vx) < 0;
+    negative = BIGDECIMAL_NEGATIVE_P(vx);
     if (negative) {
 	VpSetSign(vx, 1);
     }
@@ -2905,7 +2966,7 @@ BigMath_s_log(VALUE klass, VALUE x, VALU https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L2966
 	  if (!is_kind_of_BigDecimal(x)) break;
 	  vx = DATA_PTR(x);
 	  zero = VpIsZero(vx);
-	  negative = VpGetSign(vx) < 0;
+	  negative = BIGDECIMAL_NEGATIVE_P(vx);
 	  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
 	  nan = VpIsNaN(vx);
 	  break;
@@ -3208,7 +3269,7 @@ Init_bigdecimal(void) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3269
     rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
 
     /*
-     * 0x01: Determines what happens when a division by zero is performed.
+     * 0x10: Determines what happens when a division by zero is performed.
      * See BigDecimal.mode.
      */
     rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
@@ -3350,6 +3411,7 @@ Init_bigdecimal(void) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3411
     id_floor = rb_intern_const("floor");
     id_to_r = rb_intern_const("to_r");
     id_eq = rb_intern_const("==");
+    id_half = rb_intern_const("half");
 }
 
 /*
@@ -3377,7 +3439,14 @@ static Real *VpPt5;        /* constant 0 https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3439
 #define MemCmp(x,y,z) memcmp(x,y,z)
 #define StrCmp(x,y)   strcmp(x,y)
 
-static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
+enum op_sw {
+    OP_SW_ADD = 1,  /* + */
+    OP_SW_SUB,      /* - */
+    OP_SW_MULT,     /* * */
+    OP_SW_DIV       /* / */
+};
+
+static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
 static int AddExponent(Real *a, SIGNED_VALUE n);
 static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
 static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
@@ -3404,7 +3473,7 @@ VpMemAlloc(size_t mb) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3473
     return p;
 }
 
-    VP_EXPORT void *
+VP_EXPORT void *
 VpMemRealloc(void *ptr, size_t mb)
 {
     void *p = xrealloc(ptr, mb);
@@ -3664,7 +3733,7 @@ VpException(unsigned short f, const char https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3733
 /* Throw exception or returns 0,when resulting c is Inf or NaN */
 /*  sw=1:+ 2:- 3:* 4:/ */
 static int
-VpIsDefOP(Real *c,Real *a,Real *b,int sw)
+VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
 {
     if (VpIsNaN(a) || VpIsNaN(b)) {
 	/* at least a or b is NaN */
@@ -3675,7 +3744,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3744
     if (VpIsInf(a)) {
 	if (VpIsInf(b)) {
 	    switch(sw) {
-	      case 1: /* + */
+	      case OP_SW_ADD: /* + */
 		if (VpGetSign(a) == VpGetSign(b)) {
 		    VpSetInf(c, VpGetSign(a));
 		    goto Inf;
@@ -3684,7 +3753,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3753
 		    VpSetNaN(c);
 		    goto NaN;
 		}
-	      case 2: /* - */
+	      case OP_SW_SUB: /* - */
 		if (VpGetSign(a) != VpGetSign(b)) {
 		    VpSetInf(c, VpGetSign(a));
 		    goto Inf;
@@ -3693,12 +3762,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3762
 		    VpSetNaN(c);
 		    goto NaN;
 		}
-		break;
-	      case 3: /* * */
+	      case OP_SW_MULT: /* * */
 		VpSetInf(c, VpGetSign(a)*VpGetSign(b));
 		goto Inf;
-		break;
-	      case 4: /* / */
+	      case OP_SW_DIV: /* / */
 		VpSetNaN(c);
 		goto NaN;
 	    }
@@ -3707,18 +3774,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3774
 	}
 	/* Inf op Finite */
 	switch(sw) {
-	  case 1: /* + */
-	  case 2: /* - */
+	  case OP_SW_ADD: /* + */
+	  case OP_SW_SUB: /* - */
 	    VpSetInf(c, VpGetSign(a));
 	    break;
-	  case 3: /* * */
+	  case OP_SW_MULT: /* * */
 	    if (VpIsZero(b)) {
 		VpSetNaN(c);
 		goto NaN;
 	    }
 	    VpSetInf(c, VpGetSign(a)*VpGetSign(b));
 	    break;
-	  case 4: /* / */
+	  case OP_SW_DIV: /* / */
 	    VpSetInf(c, VpGetSign(a)*VpGetSign(b));
 	}
 	goto Inf;
@@ -3726,20 +3793,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3793
 
     if (VpIsInf(b)) {
 	switch(sw) {
-	  case 1: /* + */
+	  case OP_SW_ADD: /* + */
 	    VpSetInf(c, VpGetSign(b));
 	    break;
-	  case 2: /* - */
+	  case OP_SW_SUB: /* - */
 	    VpSetInf(c, -VpGetSign(b));
 	    break;
-	  case 3: /* * */
+	  case OP_SW_MULT: /* * */
 	    if (VpIsZero(a)) {
 		VpSetNaN(c);
 		goto NaN;
 	    }
 	    VpSetInf(c, VpGetSign(a)*VpGetSign(b));
 	    break;
-	  case 4: /* / */
+	  case OP_SW_DIV: /* / */
 	    VpSetZero(c, VpGetSign(a)*VpGetSign(b));
 	}
 	goto Inf;
@@ -3747,7 +3814,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3814
     return 1; /* Results OK */
 
 Inf:
-    return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
+    if (VpIsPosInf(c)) {
+	return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
+    }
+    else {
+	return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
+    }
+
 NaN:
     return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
 }
@@ -3894,7 +3967,8 @@ overflow: https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3967
 VP_EXPORT Real *
 VpAlloc(size_t mx, const char *szVal)
 {
-    size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
+    const char *orig_szVal = szVal;
+    size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
     char v, *psz;
     int  sign=1;
     Real *vp = NULL;
@@ -3929,6 +4003,26 @@ VpAlloc(size_t mx, const char *szVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4003
         return vp;
     }
 
+    /* Check on Inf & NaN */
+    if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
+        vp = VpAllocReal(1);
+        vp->MaxPrec = 1;    /* set max precision */
+        VpSetPosInf(vp);
+        return vp;
+    }
+    if (StrCmp(szVal, SZ_NINF) == 0) {
+        vp = VpAllocReal(1);
+        vp->MaxPrec = 1;    /* set max precision */
+        VpSetNegInf(vp);
+        return vp;
+    }
+    if (StrCmp(szVal, SZ_NaN) == 0) {
+        vp = VpAllocReal(1);
+        vp->MaxPrec = 1;    /* set max precision */
+        VpSetNaN(vp);
+        return vp;
+    }
+
     /* Skip all '_' after digit: 2006-6-30 */
     ni = 0;
     buf = rb_str_tmp_new(strlen(szVal) + 1);
@@ -3954,26 +4048,6 @@ VpAlloc(size_t mx, const char *szVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4048
     }
     szVal = psz;
 
-    /* Check on Inf & NaN */
-    if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
-        vp = VpAllocReal(1);
-        vp->MaxPrec = 1;    /* set max precision */
-        VpSetPosInf(vp);
-        return vp;
-    }
-    if (StrCmp(szVal, SZ_NINF) == 0) {
-        vp = VpAllocReal(1);
-        vp->MaxPrec = 1;    /* set max precision */
-        VpSetNegInf(vp);
-        return vp;
-    }
-    if (StrCmp(szVal, SZ_NaN) == 0) {
-        vp = VpAllocReal(1);
-        vp->MaxPrec = 1;    /* set max precision */
-        VpSetNaN(vp);
-        return vp;
-    }
-
     /* check on number szVal[] */
     ipn = i = 0;
     if      (szVal[i] == '-') { sign=-1; ++i; }
@@ -3989,9 +4063,12 @@ VpAlloc(size_t mx, const char *szVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4063
     ipf = 0;
     ipe = 0;
     ne  = 0;
+    dot_seen = 0;
+    exp_seen = 0;
     if (v) {
         /* other than digit nor \0 */
         if (szVal[i] == '.') {    /* xxx. */
+            dot_seen = 1;
             ++i;
             ipf = i;
             while ((v = szVal[i]) != 0) {    /* get fraction part. */
@@ -4007,6 +4084,7 @@ VpAlloc(size_t mx, const char *szVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4084
                 break;
             case 'e': case 'E':
             case 'd': case 'D':
+                exp_seen = 1;
                 ++i;
                 ipe = i;
                 v = szVal[i];
@@ -4021,6 +4099,11 @@ VpAlloc(size_t mx, const char *szVal) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4099
                 break;
         }
     }
+    if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
+	VALUE str = rb_str_new2(orig_szVal);
+	rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
+    }
+
     nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1;    /* set effective allocation  */
     /* units for szVal[]  */
     if (mx == 0) mx = 1;
@@ -4107,7 +4190,7 @@ VpAddSub(Real *c, Real *a, Real *b, int https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4190
     }
 #endif /* BIGDECIMAL_DEBUG */
 
-    if (!VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2)) return 0; /* No significant digits */
+    if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
 
     /* check if a or b is zero  */
     if (VpIsZero(a)) {
@@ -4563,7 +4646,7 @@ VpMult(Real *c, Real *a, Real *b) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L4646
     }
 #endif /* BIGDECIMAL_DEBUG */
 
-    if (!VpIsDefOP(c, a, b, 3)) return 0; /* No sig (... truncated)

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

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