1
0
Fork 0
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:
mrkn 2011-05-31 14:43:39 +00:00
parent b54141bb1b
commit 100931ac2c
3 changed files with 94 additions and 41 deletions

View file

@ -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> Tue May 31 22:44:00 2011 Kenta Murata <mrkn@mrkn.jp>
* ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation a * ext/bigdecimal/bigdecimal.c (BigDecimal_new): support instantiation a

View file

@ -131,11 +131,13 @@ ToValue(Real *p)
return p->obj; return p->obj;
} }
static Real * static VALUE BigDecimal_div2(int, VALUE*, VALUE);
GetVpValue(VALUE v, int must)
static Real*
GetVpValueWithPrec(VALUE v, long prec, int must)
{ {
Real *pv; Real *pv;
VALUE bg; VALUE num, bg, args[2];
char szD[128]; char szD[128];
VALUE orig = Qundef; VALUE orig = Qundef;
int util_loaded = 0; int util_loaded = 0;
@ -143,54 +145,71 @@ GetVpValue(VALUE v, int must)
again: again:
switch(TYPE(v)) switch(TYPE(v))
{ {
case T_RATIONAL: case T_RATIONAL:
if(orig == Qundef ? (orig = v, 1) : orig != v) { if (prec < 0) goto unable_to_coerce_without_prec;
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_DATA: if (orig == Qundef ? (orig = v, 1) : orig != v) {
if(rb_typeddata_is_kind_of(v, &BigDecimal_data_type)) { num = RRATIONAL(v)->num;
pv = DATA_PTR(v); pv = GetVpValueWithPrec(num, -1, must);
return pv; if (pv == NULL) goto SomeOneMayDoIt;
} else {
goto SomeOneMayDoIt; args[0] = RRATIONAL(v)->den;
} args[1] = LONG2NUM(prec);
break; v = BigDecimal_div2(2, args, ToValue(pv));
case T_FIXNUM: goto again;
sprintf(szD, "%ld", FIX2LONG(v)); }
return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
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 #ifdef ENABLE_NUMERIC_STRING
case T_STRING: case T_STRING:
SafeStringValue(v); SafeStringValue(v);
return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1, return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
RSTRING_PTR(v)); RSTRING_PTR(v));
#endif /* ENABLE_NUMERIC_STRING */ #endif /* ENABLE_NUMERIC_STRING */
case T_BIGNUM: case T_BIGNUM:
bg = rb_big2str(v, 10); bg = rb_big2str(v, 10);
return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1, return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
RSTRING_PTR(bg)); RSTRING_PTR(bg));
default: default:
goto SomeOneMayDoIt; goto SomeOneMayDoIt;
} }
SomeOneMayDoIt: SomeOneMayDoIt:
if(must) { if (must) {
rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal", rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
rb_special_const_p(v)? rb_special_const_p(v) ? RSTRING_PTR(rb_inspect(v)) : rb_obj_classname(v));
RSTRING_PTR(rb_inspect(v)):
rb_obj_classname(v)
);
} }
return NULL; /* NULL means to coerce */ 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: /* call-seq:
@ -1775,6 +1794,12 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
case T_BIGNUM: case T_BIGNUM:
return ToValue(GetVpValue(iniValue, 1)); 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: case T_STRING:
/* fall through */ /* fall through */
default: default:

View file

@ -36,6 +36,12 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100)) assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100))
end 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 def test_new
assert_equal(1, BigDecimal.new("1")) assert_equal(1, BigDecimal.new("1"))
assert_equal(1, BigDecimal.new("1", 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)) assert_equal(BigDecimal((-2**100).to_s), BigDecimal.new(-2**100))
end 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) def _test_mode(type)
BigDecimal.mode(type, true) BigDecimal.mode(type, true)
assert_raise(FloatDomainError) { yield } assert_raise(FloatDomainError) { yield }