mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Import bigdecimal-1.4.0.pre-20181204a
* https://github.com/ruby/bigdecimal/compare/v1.4.0.pre.20181130a..v1.4.0.pre.20181204a git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66183 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
242ce4b1d3
commit
8891bb3bd6
4 changed files with 143 additions and 52 deletions
|
@ -646,7 +646,7 @@ VP_EXPORT Real *
|
||||||
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
||||||
{
|
{
|
||||||
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
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;
|
RTYPEDDATA_DATA(obj) = pv;
|
||||||
pv->obj = obj;
|
pv->obj = obj;
|
||||||
RB_OBJ_FREEZE(obj);
|
RB_OBJ_FREEZE(obj);
|
||||||
|
@ -2538,28 +2538,6 @@ BigDecimal_power_op(VALUE self, VALUE exp)
|
||||||
return BigDecimal_power(1, &exp, self);
|
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:
|
/* :nodoc:
|
||||||
*
|
*
|
||||||
* private method for dup and clone the provided BigDecimal +other+
|
* private method for dup and clone the provided BigDecimal +other+
|
||||||
|
@ -2582,19 +2560,60 @@ BigDecimal_clone(VALUE self)
|
||||||
return self;
|
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 *
|
static Real *
|
||||||
BigDecimal_new(int argc, VALUE *argv)
|
BigDecimal_new(int argc, VALUE *argv)
|
||||||
{
|
{
|
||||||
size_t mf;
|
size_t mf;
|
||||||
|
VALUE opts = Qnil;
|
||||||
VALUE nFig;
|
VALUE nFig;
|
||||||
VALUE iniValue;
|
VALUE iniValue;
|
||||||
double d;
|
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;
|
mf = 0;
|
||||||
}
|
}
|
||||||
else {
|
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)) {
|
switch (TYPE(iniValue)) {
|
||||||
|
@ -2617,11 +2636,17 @@ BigDecimal_new(int argc, VALUE *argv)
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
if (mf > DBL_DIG+1) {
|
if (mf > DBL_DIG+1) {
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
rb_raise(rb_eArgError, "precision too large.");
|
rb_raise(rb_eArgError, "precision too large.");
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case T_RATIONAL:
|
case T_RATIONAL:
|
||||||
if (NIL_P(nFig)) {
|
if (NIL_P(nFig)) {
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
rb_raise(rb_eArgError,
|
rb_raise(rb_eArgError,
|
||||||
"can't omit precision for a %"PRIsVALUE".",
|
"can't omit precision for a %"PRIsVALUE".",
|
||||||
RB_OBJ_CLASSNAME(iniValue));
|
RB_OBJ_CLASSNAME(iniValue));
|
||||||
|
@ -2633,8 +2658,13 @@ BigDecimal_new(int argc, VALUE *argv)
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
StringValueCStr(iniValue);
|
||||||
return VpAlloc(mf, RSTRING_PTR(iniValue), 1);
|
return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call-seq:
|
/* call-seq:
|
||||||
|
@ -2669,14 +2699,16 @@ BigDecimal_new(int argc, VALUE *argv)
|
||||||
* value is omitted, this exception is raised.
|
* value is omitted, this exception is raised.
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
|
f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
ENTER(1);
|
ENTER(1);
|
||||||
Real *pv;
|
Real *pv;
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
|
|
||||||
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
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);
|
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
||||||
RTYPEDDATA_DATA(obj) = pv;
|
RTYPEDDATA_DATA(obj) = pv;
|
||||||
RB_OBJ_FREEZE(obj);
|
RB_OBJ_FREEZE(obj);
|
||||||
|
@ -3112,7 +3144,7 @@ rmpd_util_str_to_d(VALUE str)
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
|
|
||||||
c_str = StringValueCStr(str);
|
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);
|
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
||||||
RB_OBJ_FREEZE(obj);
|
RB_OBJ_FREEZE(obj);
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -3259,7 +3291,7 @@ Init_bigdecimal(void)
|
||||||
rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
|
rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
|
||||||
|
|
||||||
/* Global function */
|
/* Global function */
|
||||||
rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
|
rb_define_global_function("BigDecimal", f_BigDecimal, -1);
|
||||||
|
|
||||||
/* Class methods */
|
/* Class methods */
|
||||||
rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
|
rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
|
||||||
|
@ -3387,14 +3419,13 @@ Init_bigdecimal(void)
|
||||||
|
|
||||||
arg = rb_str_new2("+Infinity");
|
arg = rb_str_new2("+Infinity");
|
||||||
/* Positive infinity value. */
|
/* 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");
|
arg = rb_str_new2("NaN");
|
||||||
/* 'Not a Number' value. */
|
/* '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 */
|
/* 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, "initialize_copy", BigDecimal_initialize_copy, 1);
|
||||||
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
|
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
|
||||||
|
|
||||||
|
@ -3687,9 +3718,9 @@ VpSetRoundMode(unsigned short n)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 0.0 & 1.0 generator
|
* 0.0 & 1.0 generator
|
||||||
* These gOne_..... can be any name
|
* These gZero_..... and gOne_..... can be any name
|
||||||
* referenced from nowhere except One().
|
* referenced from nowhere except Zero() and One().
|
||||||
* gOne_..... must have global scope
|
* gZero_..... and gOne_..... must have global scope
|
||||||
* (to let the compiler know they may be changed in outside
|
* (to let the compiler know they may be changed in outside
|
||||||
* (... but not actually..)).
|
* (... but not actually..)).
|
||||||
*/
|
*/
|
||||||
|
@ -3931,8 +3962,8 @@ VpInit(BDIGIT BaseVal)
|
||||||
VpGetDoubleNegZero();
|
VpGetDoubleNegZero();
|
||||||
|
|
||||||
/* Allocates Vp constants. */
|
/* Allocates Vp constants. */
|
||||||
VpConstOne = VpAlloc(1UL, "1", 1);
|
VpConstOne = VpAlloc(1UL, "1", 1, 1);
|
||||||
VpPt5 = VpAlloc(1UL, ".5", 1);
|
VpPt5 = VpAlloc(1UL, ".5", 1, 1);
|
||||||
|
|
||||||
#ifdef BIGDECIMAL_DEBUG
|
#ifdef BIGDECIMAL_DEBUG
|
||||||
gnAlloc = 0;
|
gnAlloc = 0;
|
||||||
|
@ -4056,7 +4087,7 @@ rmpd_parse_special_string(const char *str)
|
||||||
* NULL be returned if memory allocation is failed,or any error.
|
* NULL be returned if memory allocation is failed,or any error.
|
||||||
*/
|
*/
|
||||||
VP_EXPORT Real *
|
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;
|
const char *orig_szVal = szVal;
|
||||||
size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
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, int strict_p)
|
||||||
if (!strict_p) {
|
if (!strict_p) {
|
||||||
goto return_zero;
|
goto return_zero;
|
||||||
}
|
}
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
str = rb_str_new2(orig_szVal);
|
str = rb_str_new2(orig_szVal);
|
||||||
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
|
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
|
||||||
}
|
}
|
||||||
|
@ -4832,7 +4865,7 @@ VpMult(Real *c, Real *a, Real *b)
|
||||||
|
|
||||||
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
|
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
|
||||||
w = c;
|
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;
|
MxIndC = MxIndAB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6000,8 +6033,8 @@ VpSqrt(Real *y, Real *x)
|
||||||
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
|
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
|
||||||
|
|
||||||
/* allocate temporally variables */
|
/* allocate temporally variables */
|
||||||
f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1);
|
f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
|
||||||
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1);
|
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
|
||||||
|
|
||||||
nr = 0;
|
nr = 0;
|
||||||
y_prec = y->MaxPrec;
|
y_prec = y->MaxPrec;
|
||||||
|
@ -6453,8 +6486,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
||||||
|
|
||||||
/* Allocate working variables */
|
/* Allocate working variables */
|
||||||
|
|
||||||
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1);
|
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
|
||||||
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1);
|
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
|
||||||
/* calculation start */
|
/* calculation start */
|
||||||
|
|
||||||
VpAsgn(y, x, 1);
|
VpAsgn(y, x, 1);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
bigdecimal_version = '1.4.0.pre.20181121a'
|
bigdecimal_version = '1.4.0.pre.20181204a'
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = "bigdecimal"
|
s.name = "bigdecimal"
|
||||||
|
@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
||||||
s.files = %w[
|
s.files = %w[
|
||||||
bigdecimal.gemspec
|
bigdecimal.gemspec
|
||||||
ext/bigdecimal/bigdecimal.c
|
ext/bigdecimal/bigdecimal.c
|
||||||
|
ext/bigdecimal/bigdecimal.def
|
||||||
ext/bigdecimal/bigdecimal.h
|
ext/bigdecimal/bigdecimal.h
|
||||||
ext/bigdecimal/depend
|
ext/bigdecimal/depend
|
||||||
ext/bigdecimal/extconf.rb
|
ext/bigdecimal/extconf.rb
|
||||||
|
|
|
@ -308,7 +308,7 @@ VP_EXPORT size_t VpInit(BDIGIT BaseVal);
|
||||||
VP_EXPORT void *VpMemAlloc(size_t mb);
|
VP_EXPORT void *VpMemAlloc(size_t mb);
|
||||||
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
|
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
|
||||||
VP_EXPORT void VpFree(Real *pv);
|
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 VpAsgn(Real *c, Real *a, int isw);
|
||||||
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
|
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
|
||||||
VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
|
VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
|
||||||
|
|
|
@ -151,6 +151,63 @@ class TestBigDecimal < Test::Unit::TestCase
|
||||||
$SAFE = 0
|
$SAFE = 0
|
||||||
end
|
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
|
def test_s_ver
|
||||||
assert_raise(NoMethodError, /undefined method `ver`/) { BigDecimal.ver }
|
assert_raise(NoMethodError, /undefined method `ver`/) { BigDecimal.ver }
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue