mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31864 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b54141bb1b
commit
100931ac2c
3 changed files with 94 additions and 41 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
Tue May 31 23:43:00 2011 Kenta Murata <mrkn@mrkn.jp>
|
||||
|
||||
* 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@mrkn.jp>
|
||||
|
||||
* ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation a
|
||||
|
|
|
@ -131,11 +131,13 @@ ToValue(Real *p)
|
|||
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,54 +145,71 @@ GetVpValue(VALUE v, int must)
|
|||
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:
|
||||
|
@ -1775,6 +1794,12 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
|
|||
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:
|
||||
|
|
|
@ -36,6 +36,12 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||
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 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||
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 }
|
||||
|
|
Loading…
Reference in a new issue