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/