Import bigdecimal 1.4.0.pre.20181205a
* https://github.com/ruby/bigdecimal/compare/74d25ef..v1.4.0.pre.20181205a git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66222 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ae88d2fc93
commit
2810c12a99
19
NEWS
19
NEWS
@ -331,6 +331,11 @@ sufficient information, see the ChangeLog file or Redmine
|
|||||||
|
|
||||||
* Use 1.17.1. It's latest stable version.
|
* Use 1.17.1. It's latest stable version.
|
||||||
|
|
||||||
|
[BigDecimal]
|
||||||
|
|
||||||
|
Update to the version 1.4.0. This version includes several compatibility
|
||||||
|
issues, see Compatibility issues section below for the detail.
|
||||||
|
|
||||||
[Coverage]
|
[Coverage]
|
||||||
|
|
||||||
A oneshot_lines mode is added. [Feature #15022]
|
A oneshot_lines mode is added. [Feature #15022]
|
||||||
@ -489,6 +494,20 @@ sufficient information, see the ChangeLog file or Redmine
|
|||||||
* thwait
|
* thwait
|
||||||
* tracer
|
* tracer
|
||||||
|
|
||||||
|
[BigDecimal]
|
||||||
|
|
||||||
|
* The following methods are removed.
|
||||||
|
|
||||||
|
* BigDecimal.allocate
|
||||||
|
* BigDecimal.new
|
||||||
|
* BigDecimal.ver
|
||||||
|
|
||||||
|
* Every BigDecimal object is frozen. [Feature #13984]
|
||||||
|
|
||||||
|
* BigDecimal() parses the given string like Float().
|
||||||
|
|
||||||
|
* String#to_d parses the receiver string like String#to_f.
|
||||||
|
|
||||||
=== C API updates
|
=== C API updates
|
||||||
|
|
||||||
=== Supported platform changes
|
=== Supported platform changes
|
||||||
|
@ -135,24 +135,6 @@ rb_rational_den(VALUE rat)
|
|||||||
*/
|
*/
|
||||||
#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
|
#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the BigDecimal version number.
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
BigDecimal_version(VALUE self)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 1.0.0: Ruby 1.8.0
|
|
||||||
* 1.0.1: Ruby 1.8.1
|
|
||||||
* 1.1.0: Ruby 1.9.3
|
|
||||||
*/
|
|
||||||
#ifndef RUBY_BIGDECIMAL_VERSION
|
|
||||||
# error RUBY_BIGDECIMAL_VERSION is not defined
|
|
||||||
#endif
|
|
||||||
rb_warning("BigDecimal.ver is deprecated; use BigDecimal::VERSION instead.");
|
|
||||||
return rb_str_new2(RUBY_BIGDECIMAL_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VP routines used in BigDecimal part
|
* VP routines used in BigDecimal part
|
||||||
*/
|
*/
|
||||||
@ -664,9 +646,10 @@ 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);
|
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);
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2165,15 +2148,10 @@ BigDecimal_exponent(VALUE self)
|
|||||||
return INT2NUM(e);
|
return INT2NUM(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns debugging information about the value as a string of comma-separated
|
/* Returns a string representation of self.
|
||||||
* values in angle brackets with a leading #:
|
|
||||||
*
|
*
|
||||||
* BigDecimal("1234.5678").inspect
|
* BigDecimal("1234.5678").inspect
|
||||||
* #=> "0.12345678e4"
|
* #=> "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
|
|
||||||
* maximum number of significant digits, respectively.
|
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
BigDecimal_inspect(VALUE self)
|
BigDecimal_inspect(VALUE self)
|
||||||
@ -2335,7 +2313,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|||||||
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
||||||
|
|
||||||
if (VpIsNaN(x)) {
|
if (VpIsNaN(x)) {
|
||||||
y = VpCreateRbObject(n, "0#");
|
y = VpCreateRbObject(n, "0");
|
||||||
RB_GC_GUARD(y->obj);
|
RB_GC_GUARD(y->obj);
|
||||||
VpSetNaN(y);
|
VpSetNaN(y);
|
||||||
return ToValue(y);
|
return ToValue(y);
|
||||||
@ -2459,7 +2437,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
y = VpCreateRbObject(n, "0#");
|
y = VpCreateRbObject(n, "0");
|
||||||
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
||||||
if (is_integer(vexp)) {
|
if (is_integer(vexp)) {
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
@ -2492,7 +2470,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|||||||
}
|
}
|
||||||
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
||||||
if (is_negative(vexp)) {
|
if (is_negative(vexp)) {
|
||||||
y = VpCreateRbObject(n, "0#");
|
y = VpCreateRbObject(n, "0");
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
VpSetInf(y, VpGetSign(x));
|
VpSetInf(y, VpGetSign(x));
|
||||||
}
|
}
|
||||||
@ -2510,7 +2488,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (is_positive(vexp)) {
|
if (is_positive(vexp)) {
|
||||||
y = VpCreateRbObject(n, "0#");
|
y = VpCreateRbObject(n, "0");
|
||||||
if (is_even(vexp)) {
|
if (is_even(vexp)) {
|
||||||
VpSetInf(y, VpGetSign(x));
|
VpSetInf(y, VpGetSign(x));
|
||||||
}
|
}
|
||||||
@ -2560,16 +2538,137 @@ BigDecimal_power_op(VALUE self, VALUE exp)
|
|||||||
return BigDecimal_power(1, &exp, self);
|
return BigDecimal_power(1, &exp, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* :nodoc:
|
||||||
|
*
|
||||||
|
* private method for dup and clone the provided BigDecimal +other+
|
||||||
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
BigDecimal_s_allocate(VALUE klass)
|
BigDecimal_initialize_copy(VALUE self, VALUE other)
|
||||||
{
|
{
|
||||||
return VpNewRbClass(0, NULL, klass)->obj;
|
Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
|
||||||
|
Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
|
||||||
|
|
||||||
|
if (self != other) {
|
||||||
|
DATA_PTR(self) = VpCopy(pv, x);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Real *BigDecimal_new(int argc, VALUE *argv);
|
static VALUE
|
||||||
|
BigDecimal_clone(VALUE 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 *
|
||||||
|
BigDecimal_new(int argc, VALUE *argv)
|
||||||
|
{
|
||||||
|
size_t mf;
|
||||||
|
VALUE opts = Qnil;
|
||||||
|
VALUE nFig;
|
||||||
|
VALUE iniValue;
|
||||||
|
double d;
|
||||||
|
int exc;
|
||||||
|
|
||||||
|
argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
|
||||||
|
exc = opts_exception_p(opts);
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
mf = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* 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)) {
|
||||||
|
case T_DATA:
|
||||||
|
if (is_kind_of_BigDecimal(iniValue)) {
|
||||||
|
return DATA_PTR(iniValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_FIXNUM:
|
||||||
|
/* fall through */
|
||||||
|
case T_BIGNUM:
|
||||||
|
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) {
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rb_raise(rb_eArgError, "precision too large.");
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
case T_RATIONAL:
|
||||||
|
if (NIL_P(nFig)) {
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rb_raise(rb_eArgError,
|
||||||
|
"can't omit precision for a %"PRIsVALUE".",
|
||||||
|
RB_OBJ_CLASSNAME(iniValue));
|
||||||
|
}
|
||||||
|
return GetVpValueWithPrec(iniValue, mf, 1);
|
||||||
|
|
||||||
|
case T_STRING:
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
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);
|
||||||
|
return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
|
||||||
|
}
|
||||||
|
|
||||||
/* call-seq:
|
/* call-seq:
|
||||||
* new(initial, digits)
|
* BigDecimal(initial, digits)
|
||||||
*
|
*
|
||||||
* Create a new BigDecimal object.
|
* Create a new BigDecimal object.
|
||||||
*
|
*
|
||||||
@ -2600,121 +2699,19 @@ static Real *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_s_new(int argc, VALUE *argv, VALUE self)
|
f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
|
||||||
rb_warning("BigDecimal.new is deprecated; use Kernel.BigDecimal method instead.");
|
|
||||||
return rb_call_super(argc, 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:
|
|
||||||
*
|
|
||||||
* private method for dup and clone the provided BigDecimal +other+
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
BigDecimal_initialize_copy(VALUE self, VALUE other)
|
|
||||||
{
|
|
||||||
Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
|
|
||||||
Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
|
|
||||||
|
|
||||||
if (self != other) {
|
|
||||||
DATA_PTR(self) = VpCopy(pv, x);
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
BigDecimal_clone(VALUE self)
|
|
||||||
{
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Real *
|
|
||||||
BigDecimal_new(int argc, VALUE *argv)
|
|
||||||
{
|
|
||||||
size_t mf;
|
|
||||||
VALUE nFig;
|
|
||||||
VALUE iniValue;
|
|
||||||
double d;
|
|
||||||
|
|
||||||
if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
|
|
||||||
mf = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mf = GetPrecisionInt(nFig);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (TYPE(iniValue)) {
|
|
||||||
case T_DATA:
|
|
||||||
if (is_kind_of_BigDecimal(iniValue)) {
|
|
||||||
return DATA_PTR(iniValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_FIXNUM:
|
|
||||||
/* fall through */
|
|
||||||
case T_BIGNUM:
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
/* fall through */
|
|
||||||
case T_RATIONAL:
|
|
||||||
if (NIL_P(nFig)) {
|
|
||||||
rb_raise(rb_eArgError,
|
|
||||||
"can't omit precision for a %"PRIsVALUE".",
|
|
||||||
RB_OBJ_CLASSNAME(iniValue));
|
|
||||||
}
|
|
||||||
return GetVpValueWithPrec(iniValue, mf, 1);
|
|
||||||
|
|
||||||
case T_STRING:
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
StringValueCStr(iniValue);
|
|
||||||
return VpAlloc(mf, RSTRING_PTR(iniValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See also BigDecimal.new */
|
|
||||||
static VALUE
|
|
||||||
BigDecimal_global_new(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);
|
||||||
return pv->obj = obj;
|
return pv->obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3138,6 +3135,20 @@ get_vp_value:
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rmpd_util_str_to_d(VALUE str)
|
||||||
|
{
|
||||||
|
ENTER(1);
|
||||||
|
char const *c_str;
|
||||||
|
Real *pv;
|
||||||
|
|
||||||
|
c_str = StringValueCStr(str);
|
||||||
|
GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
|
||||||
|
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
||||||
|
RB_OBJ_FREEZE(pv->obj);
|
||||||
|
return pv->obj;
|
||||||
|
}
|
||||||
|
|
||||||
/* Document-class: BigDecimal
|
/* Document-class: BigDecimal
|
||||||
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
|
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
|
||||||
*
|
*
|
||||||
@ -3277,18 +3288,17 @@ Init_bigdecimal(void)
|
|||||||
|
|
||||||
/* Class and method registration */
|
/* Class and method registration */
|
||||||
rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
|
rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
|
||||||
rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
|
|
||||||
|
|
||||||
/* 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_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_s_new, -1);
|
rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
|
||||||
|
rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
|
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
|
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
|
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
|
rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
|
|
||||||
|
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
|
rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
|
||||||
rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
|
rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
|
||||||
@ -3408,14 +3418,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);
|
||||||
|
|
||||||
@ -3714,13 +3723,7 @@ VpSetRoundMode(unsigned short n)
|
|||||||
* (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..)).
|
||||||
*/
|
*/
|
||||||
volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
|
|
||||||
volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
|
volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
|
||||||
static double
|
|
||||||
Zero(void)
|
|
||||||
{
|
|
||||||
return gZero_ABCED9B1_CE73__00400511F31D;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double
|
static double
|
||||||
One(void)
|
One(void)
|
||||||
@ -3745,25 +3748,19 @@ One(void)
|
|||||||
VP_EXPORT double
|
VP_EXPORT double
|
||||||
VpGetDoubleNaN(void) /* Returns the value of NaN */
|
VpGetDoubleNaN(void) /* Returns the value of NaN */
|
||||||
{
|
{
|
||||||
static double fNaN = 0.0;
|
return nan("");
|
||||||
if (fNaN == 0.0) fNaN = Zero()/Zero();
|
|
||||||
return fNaN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VP_EXPORT double
|
VP_EXPORT double
|
||||||
VpGetDoublePosInf(void) /* Returns the value of +Infinity */
|
VpGetDoublePosInf(void) /* Returns the value of +Infinity */
|
||||||
{
|
{
|
||||||
static double fInf = 0.0;
|
return HUGE_VAL;
|
||||||
if (fInf == 0.0) fInf = One()/Zero();
|
|
||||||
return fInf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VP_EXPORT double
|
VP_EXPORT double
|
||||||
VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
|
VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
|
||||||
{
|
{
|
||||||
static double fInf = 0.0;
|
return -HUGE_VAL;
|
||||||
if (fInf == 0.0) fInf = -(One()/Zero());
|
|
||||||
return fInf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VP_EXPORT double
|
VP_EXPORT double
|
||||||
@ -3964,8 +3961,8 @@ VpInit(BDIGIT BaseVal)
|
|||||||
VpGetDoubleNegZero();
|
VpGetDoubleNegZero();
|
||||||
|
|
||||||
/* Allocates Vp constants. */
|
/* Allocates Vp constants. */
|
||||||
VpConstOne = VpAlloc(1UL, "1");
|
VpConstOne = VpAlloc(1UL, "1", 1, 1);
|
||||||
VpPt5 = VpAlloc(1UL, ".5");
|
VpPt5 = VpAlloc(1UL, ".5", 1, 1);
|
||||||
|
|
||||||
#ifdef BIGDECIMAL_DEBUG
|
#ifdef BIGDECIMAL_DEBUG
|
||||||
gnAlloc = 0;
|
gnAlloc = 0;
|
||||||
@ -4029,6 +4026,52 @@ overflow:
|
|||||||
return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
|
return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Real *
|
||||||
|
rmpd_parse_special_string(const char *str)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
int sign;
|
||||||
|
} table[] = {
|
||||||
|
{ SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE },
|
||||||
|
{ SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE },
|
||||||
|
{ SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE },
|
||||||
|
{ SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN }
|
||||||
|
};
|
||||||
|
static const size_t table_length = sizeof(table) / sizeof(table[0]);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < table_length; ++i) {
|
||||||
|
const char *p;
|
||||||
|
if (strncmp(str, table[i].str, table[i].len) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = str + table[i].len;
|
||||||
|
while (*p && ISSPACE(*p)) ++p;
|
||||||
|
if (*p == '\0') {
|
||||||
|
Real *vp = VpAllocReal(1);
|
||||||
|
vp->MaxPrec = 1;
|
||||||
|
switch (table[i].sign) {
|
||||||
|
default:
|
||||||
|
UNREACHABLE; break;
|
||||||
|
case VP_SIGN_POSITIVE_INFINITE:
|
||||||
|
VpSetPosInf(vp);
|
||||||
|
return vp;
|
||||||
|
case VP_SIGN_NEGATIVE_INFINITE:
|
||||||
|
VpSetNegInf(vp);
|
||||||
|
return vp;
|
||||||
|
case VP_SIGN_NaN:
|
||||||
|
VpSetNaN(vp);
|
||||||
|
return vp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates variable.
|
* Allocates variable.
|
||||||
* [Input]
|
* [Input]
|
||||||
@ -4043,10 +4086,10 @@ overflow:
|
|||||||
* 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)
|
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, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
||||||
char v, *psz;
|
char v, *psz;
|
||||||
int sign=1;
|
int sign=1;
|
||||||
Real *vp = NULL;
|
Real *vp = NULL;
|
||||||
@ -4057,7 +4100,10 @@ VpAlloc(size_t mx, const char *szVal)
|
|||||||
if (mx == 0) ++mx;
|
if (mx == 0) ++mx;
|
||||||
|
|
||||||
if (szVal) {
|
if (szVal) {
|
||||||
|
/* Skipping leading spaces */
|
||||||
while (ISSPACE(*szVal)) szVal++;
|
while (ISSPACE(*szVal)) szVal++;
|
||||||
|
|
||||||
|
/* Processing the leading one `#` */
|
||||||
if (*szVal != '#') {
|
if (*szVal != '#') {
|
||||||
if (mf) {
|
if (mf) {
|
||||||
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
|
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
|
||||||
@ -4071,6 +4117,7 @@ VpAlloc(size_t mx, const char *szVal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
return_zero:
|
||||||
/* necessary to be able to store */
|
/* necessary to be able to store */
|
||||||
/* at least mx digits. */
|
/* at least mx digits. */
|
||||||
/* szVal==NULL ==> allocate zero value. */
|
/* szVal==NULL ==> allocate zero value. */
|
||||||
@ -4081,105 +4128,168 @@ VpAlloc(size_t mx, const char *szVal)
|
|||||||
return vp;
|
return vp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip all '_' after digit: 2006-6-30 */
|
/* Check on Inf & NaN */
|
||||||
ni = 0;
|
if ((vp = rmpd_parse_special_string(szVal)) != NULL) {
|
||||||
|
return vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scanning digits */
|
||||||
|
|
||||||
|
/* A buffer for keeping scanned digits */
|
||||||
buf = rb_str_tmp_new(strlen(szVal) + 1);
|
buf = rb_str_tmp_new(strlen(szVal) + 1);
|
||||||
psz = RSTRING_PTR(buf);
|
psz = RSTRING_PTR(buf);
|
||||||
i = 0;
|
|
||||||
ipn = 0;
|
/* cursor: i for psz, and j for szVal */
|
||||||
while ((psz[i] = szVal[ipn]) != 0) {
|
i = j = 0;
|
||||||
if (ISSPACE(psz[i])) {
|
|
||||||
psz[i] = 0;
|
/* Scanning: sign part */
|
||||||
|
v = psz[i] = szVal[j];
|
||||||
|
if ((v == '-') || (v == '+')) {
|
||||||
|
sign = -(v == '-');
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scanning: integer part */
|
||||||
|
ni = 0; /* number of digits in the integer part */
|
||||||
|
while ((v = psz[i] = szVal[j]) != '\0') {
|
||||||
|
if (!strict_p && ISSPACE(v)) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ISDIGIT(psz[i])) ++ni;
|
if (v == '_') {
|
||||||
if (psz[i] == '_') {
|
|
||||||
if (ni > 0) {
|
if (ni > 0) {
|
||||||
ipn++;
|
v = szVal[j+1];
|
||||||
continue;
|
if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) {
|
||||||
|
++j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strict_p) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
psz[i] = 0;
|
goto invalid_value;
|
||||||
|
}
|
||||||
|
if (!ISDIGIT(v)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++i;
|
|
||||||
++ipn;
|
|
||||||
}
|
|
||||||
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; }
|
|
||||||
else if (szVal[i] == '+') ++i;
|
|
||||||
/* Skip digits */
|
|
||||||
ni = 0; /* digits in mantissa */
|
|
||||||
while ((v = szVal[i]) != 0) {
|
|
||||||
if (!ISDIGIT(v)) break;
|
|
||||||
++i;
|
|
||||||
++ni;
|
++ni;
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
}
|
}
|
||||||
nf = 0;
|
|
||||||
ipf = 0;
|
/* Scanning: fractional part */
|
||||||
ipe = 0;
|
nf = 0; /* number of digits in the fractional part */
|
||||||
ne = 0;
|
ne = 0; /* number of digits in the exponential part */
|
||||||
|
ipf = 0; /* index of the beginning of the fractional part */
|
||||||
|
ipe = 0; /* index of the beginning of the exponential part */
|
||||||
dot_seen = 0;
|
dot_seen = 0;
|
||||||
exp_seen = 0;
|
exp_seen = 0;
|
||||||
if (v) {
|
|
||||||
/* other than digit nor \0 */
|
if (v != '\0') {
|
||||||
if (szVal[i] == '.') { /* xxx. */
|
/* Scanning fractional part */
|
||||||
|
if ((psz[i] = szVal[j]) == '.') {
|
||||||
dot_seen = 1;
|
dot_seen = 1;
|
||||||
++i;
|
++i;
|
||||||
|
++j;
|
||||||
ipf = i;
|
ipf = i;
|
||||||
while ((v = szVal[i]) != 0) { /* get fraction part. */
|
while ((v = psz[i] = szVal[j]) != '\0') {
|
||||||
|
if (!strict_p && ISSPACE(v)) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (v == '_') {
|
||||||
|
if (nf > 0 && ISDIGIT(szVal[j+1])) {
|
||||||
|
++j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strict_p) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
|
if (nf == 0) {
|
||||||
|
dot_seen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto invalid_value;
|
||||||
|
}
|
||||||
if (!ISDIGIT(v)) break;
|
if (!ISDIGIT(v)) break;
|
||||||
++i;
|
++i;
|
||||||
|
++j;
|
||||||
++nf;
|
++nf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipe = 0; /* Exponent */
|
|
||||||
|
|
||||||
switch (szVal[i]) {
|
/* Scanning exponential part */
|
||||||
case '\0':
|
if (v != '\0') {
|
||||||
break;
|
switch ((psz[i] = szVal[j])) {
|
||||||
case 'e': case 'E':
|
case '\0':
|
||||||
case 'd': case 'D':
|
break;
|
||||||
exp_seen = 1;
|
case 'e': case 'E':
|
||||||
++i;
|
case 'd': case 'D':
|
||||||
ipe = i;
|
exp_seen = 1;
|
||||||
v = szVal[i];
|
|
||||||
if ((v == '-') || (v == '+')) ++i;
|
|
||||||
while ((v=szVal[i]) != 0) {
|
|
||||||
if (!ISDIGIT(v)) break;
|
|
||||||
++i;
|
++i;
|
||||||
++ne;
|
++j;
|
||||||
}
|
ipe = i;
|
||||||
break;
|
v = psz[i] = szVal[j];
|
||||||
default:
|
if ((v == '-') || (v == '+')) {
|
||||||
break;
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
while ((v = psz[i] = szVal[j]) != '\0') {
|
||||||
|
if (!strict_p && ISSPACE(v)) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (v == '_') {
|
||||||
|
if (ne > 0 && ISDIGIT(szVal[j+1])) {
|
||||||
|
++j;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strict_p) {
|
||||||
|
v = psz[i] = '\0';
|
||||||
|
if (ne == 0) {
|
||||||
|
exp_seen = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto invalid_value;
|
||||||
|
}
|
||||||
|
if (!ISDIGIT(v)) break;
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
++ne;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v != '\0') {
|
||||||
|
/* Scanning trailing spaces */
|
||||||
|
while (ISSPACE(szVal[j])) ++j;
|
||||||
|
|
||||||
|
/* Invalid character */
|
||||||
|
if (szVal[j]) {
|
||||||
|
goto invalid_value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
psz[i] = '\0';
|
||||||
|
|
||||||
if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
|
if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
|
||||||
VALUE str = rb_str_new2(orig_szVal);
|
VALUE str;
|
||||||
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
|
invalid_value:
|
||||||
|
if (!strict_p) {
|
||||||
|
goto return_zero;
|
||||||
|
}
|
||||||
|
if (!exc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
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 */
|
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
|
||||||
@ -4191,7 +4301,7 @@ VpAlloc(size_t mx, const char *szVal)
|
|||||||
/* xmalloc() alway returns(or throw interruption) */
|
/* xmalloc() alway returns(or throw interruption) */
|
||||||
vp->MaxPrec = mx; /* set max precision */
|
vp->MaxPrec = mx; /* set max precision */
|
||||||
VpSetZero(vp, sign);
|
VpSetZero(vp, sign);
|
||||||
VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
||||||
rb_str_resize(buf, 0);
|
rb_str_resize(buf, 0);
|
||||||
return vp;
|
return vp;
|
||||||
}
|
}
|
||||||
@ -4754,7 +4864,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");
|
c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
|
||||||
MxIndC = MxIndAB;
|
MxIndC = MxIndAB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5922,8 +6032,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");
|
f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
|
||||||
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1");
|
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
|
||||||
|
|
||||||
nr = 0;
|
nr = 0;
|
||||||
y_prec = y->MaxPrec;
|
y_prec = y->MaxPrec;
|
||||||
@ -6375,8 +6485,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|||||||
|
|
||||||
/* Allocate working variables */
|
/* Allocate working variables */
|
||||||
|
|
||||||
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
|
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
|
||||||
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
|
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
|
||||||
/* calculation start */
|
/* calculation start */
|
||||||
|
|
||||||
VpAsgn(y, x, 1);
|
VpAsgn(y, x, 1);
|
||||||
|
3
ext/bigdecimal/bigdecimal.def
Normal file
3
ext/bigdecimal/bigdecimal.def
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
EXPORTS
|
||||||
|
rmpd_util_str_to_d
|
||||||
|
Init_bigdecimal
|
@ -1,6 +1,6 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
bigdecimal_version = '1.3.4'
|
bigdecimal_version = '1.4.0.pre.20181204a'
|
||||||
|
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = "bigdecimal"
|
s.name = "bigdecimal"
|
||||||
@ -14,13 +14,16 @@ Gem::Specification.new do |s|
|
|||||||
s.license = "ruby"
|
s.license = "ruby"
|
||||||
|
|
||||||
s.require_paths = %w[lib]
|
s.require_paths = %w[lib]
|
||||||
s.extensions = %w[ext/bigdecimal/extconf.rb]
|
s.extensions = %w[ext/bigdecimal/extconf.rb ext/bigdecimal/util/extconf.rb]
|
||||||
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
|
||||||
|
ext/bigdecimal/util/extconf.rb
|
||||||
|
ext/bigdecimal/util/util.c
|
||||||
lib/bigdecimal/jacobian.rb
|
lib/bigdecimal/jacobian.rb
|
||||||
lib/bigdecimal/ludcmp.rb
|
lib/bigdecimal/ludcmp.rb
|
||||||
lib/bigdecimal/math.rb
|
lib/bigdecimal/math.rb
|
||||||
@ -31,9 +34,11 @@ Gem::Specification.new do |s|
|
|||||||
sample/pi.rb
|
sample/pi.rb
|
||||||
]
|
]
|
||||||
|
|
||||||
|
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
|
||||||
|
|
||||||
s.add_development_dependency "rake", "~> 10.0"
|
s.add_development_dependency "rake", "~> 10.0"
|
||||||
s.add_development_dependency "rake-compiler", ">= 0.9"
|
s.add_development_dependency "rake-compiler", ">= 0.9"
|
||||||
s.add_development_dependency "rake-compiler-dock", ">= 0.6.1"
|
s.add_development_dependency "rake-compiler-dock", ">= 0.6.1"
|
||||||
s.add_development_dependency "minitest", "~> 4.7.5"
|
s.add_development_dependency "minitest", "< 5.0.0"
|
||||||
s.add_development_dependency "pry"
|
s.add_development_dependency "pry"
|
||||||
end
|
end
|
||||||
|
@ -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);
|
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);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
extconf.h: $(srcdir)/$(GEMSPEC)
|
||||||
|
|
||||||
# AUTOGENERATED DEPENDENCIES START
|
# AUTOGENERATED DEPENDENCIES START
|
||||||
bigdecimal.o: $(RUBY_EXTCONF_H)
|
bigdecimal.o: $(RUBY_EXTCONF_H)
|
||||||
bigdecimal.o: $(arch_hdrdir)/ruby/config.h
|
bigdecimal.o: $(arch_hdrdir)/ruby/config.h
|
||||||
|
@ -17,8 +17,6 @@ bigdecimal_version =
|
|||||||
|
|
||||||
$defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"]
|
$defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"]
|
||||||
|
|
||||||
alias __have_macro__ have_macro
|
|
||||||
|
|
||||||
have_func("labs", "stdlib.h")
|
have_func("labs", "stdlib.h")
|
||||||
have_func("llabs", "stdlib.h")
|
have_func("llabs", "stdlib.h")
|
||||||
have_func("finite", "math.h")
|
have_func("finite", "math.h")
|
||||||
@ -31,5 +29,5 @@ have_func("rb_array_const_ptr", "ruby.h")
|
|||||||
have_func("rb_sym2str", "ruby.h")
|
have_func("rb_sym2str", "ruby.h")
|
||||||
|
|
||||||
create_makefile('bigdecimal') {|mf|
|
create_makefile('bigdecimal') {|mf|
|
||||||
mf << "\nall:\n\nextconf.h: $(srcdir)/#{gemspec_name}\n"
|
mf << "GEMSPEC = #{gemspec_name}\n"
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
#
|
#
|
||||||
# fx is f.values(x).
|
# fx is f.values(x).
|
||||||
#
|
#
|
||||||
|
|
||||||
|
require 'bigdecimal'
|
||||||
|
|
||||||
module Jacobian
|
module Jacobian
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
# and provides BigDecimal#to_d and BigDecimal#to_digits.
|
# and provides BigDecimal#to_d and BigDecimal#to_digits.
|
||||||
#++
|
#++
|
||||||
|
|
||||||
|
require 'bigdecimal'
|
||||||
|
require 'bigdecimal/util.so'
|
||||||
|
|
||||||
class Integer < Numeric
|
class Integer < Numeric
|
||||||
# call-seq:
|
# call-seq:
|
||||||
@ -42,8 +44,8 @@ class Float < Numeric
|
|||||||
#
|
#
|
||||||
# See also BigDecimal::new.
|
# See also BigDecimal::new.
|
||||||
#
|
#
|
||||||
def to_d(precision=nil)
|
def to_d(precision=Float::DIG)
|
||||||
BigDecimal(self, precision || Float::DIG)
|
BigDecimal(self, precision)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,13 +66,6 @@ class String
|
|||||||
#
|
#
|
||||||
# See also BigDecimal::new.
|
# See also BigDecimal::new.
|
||||||
#
|
#
|
||||||
def to_d
|
|
||||||
begin
|
|
||||||
BigDecimal(self)
|
|
||||||
rescue ArgumentError
|
|
||||||
BigDecimal(0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -132,3 +127,20 @@ class Rational < Numeric
|
|||||||
BigDecimal(self, precision)
|
BigDecimal(self, precision)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class NilClass
|
||||||
|
# call-seq:
|
||||||
|
# nil.to_d -> bigdecimal
|
||||||
|
#
|
||||||
|
# Returns nil represented as a BigDecimal.
|
||||||
|
#
|
||||||
|
# require 'bigdecimal'
|
||||||
|
# require 'bigdecimal/util'
|
||||||
|
#
|
||||||
|
# nil.to_d # => 0.0
|
||||||
|
#
|
||||||
|
def to_d
|
||||||
|
BigDecimal(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -28,8 +28,8 @@ def rd_order(na)
|
|||||||
end
|
end
|
||||||
|
|
||||||
na = ARGV.size
|
na = ARGV.size
|
||||||
zero = BigDecimal.new("0.0")
|
zero = BigDecimal("0.0")
|
||||||
one = BigDecimal.new("1.0")
|
one = BigDecimal("1.0")
|
||||||
|
|
||||||
while (n=rd_order(na))>0
|
while (n=rd_order(na))>0
|
||||||
a = []
|
a = []
|
||||||
@ -37,27 +37,28 @@ while (n=rd_order(na))>0
|
|||||||
b = []
|
b = []
|
||||||
if na <= 0
|
if na <= 0
|
||||||
# Read data from console.
|
# Read data from console.
|
||||||
printf("\nEnter coefficient matrix element A[i,j]\n");
|
printf("\nEnter coefficient matrix element A[i,j]\n")
|
||||||
for i in 0...n do
|
for i in 0...n do
|
||||||
for j in 0...n do
|
for j in 0...n do
|
||||||
printf("A[%d,%d]? ",i,j); s = ARGF.gets
|
printf("A[%d,%d]? ",i,j); s = ARGF.gets
|
||||||
a << BigDecimal.new(s);
|
a << BigDecimal(s)
|
||||||
as << BigDecimal.new(s);
|
as << BigDecimal(s)
|
||||||
end
|
end
|
||||||
printf("Contatant vector element b[%d] ? ",i); b << BigDecimal.new(ARGF.gets);
|
printf("Contatant vector element b[%d] ? ",i)
|
||||||
|
b << BigDecimal(ARGF.gets)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Read data from specified file.
|
# Read data from specified file.
|
||||||
printf("Coefficient matrix and constant vector.\n");
|
printf("Coefficient matrix and constant vector.\n")
|
||||||
for i in 0...n do
|
for i in 0...n do
|
||||||
s = ARGF.gets
|
s = ARGF.gets
|
||||||
printf("%d) %s",i,s)
|
printf("%d) %s",i,s)
|
||||||
s = s.split
|
s = s.split
|
||||||
for j in 0...n do
|
for j in 0...n do
|
||||||
a << BigDecimal.new(s[j]);
|
a << BigDecimal(s[j])
|
||||||
as << BigDecimal.new(s[j]);
|
as << BigDecimal(s[j])
|
||||||
end
|
end
|
||||||
b << BigDecimal.new(s[n]);
|
b << BigDecimal(s[n])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
x = lusolve(a,b,ludecomp(a,n,zero,one),zero)
|
x = lusolve(a,b,ludecomp(a,n,zero,one),zero)
|
||||||
|
@ -12,11 +12,11 @@ include Newton
|
|||||||
|
|
||||||
class Function # :nodoc: all
|
class Function # :nodoc: all
|
||||||
def initialize()
|
def initialize()
|
||||||
@zero = BigDecimal.new("0.0")
|
@zero = BigDecimal("0.0")
|
||||||
@one = BigDecimal.new("1.0")
|
@one = BigDecimal("1.0")
|
||||||
@two = BigDecimal.new("2.0")
|
@two = BigDecimal("2.0")
|
||||||
@ten = BigDecimal.new("10.0")
|
@ten = BigDecimal("10.0")
|
||||||
@eps = BigDecimal.new("1.0e-16")
|
@eps = BigDecimal("1.0e-16")
|
||||||
end
|
end
|
||||||
def zero;@zero;end
|
def zero;@zero;end
|
||||||
def one ;@one ;end
|
def one ;@one ;end
|
||||||
|
24
ext/bigdecimal/util/extconf.rb
Normal file
24
ext/bigdecimal/util/extconf.rb
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
require 'mkmf'
|
||||||
|
|
||||||
|
checking_for(checking_message("Windows")) do
|
||||||
|
case RUBY_PLATFORM
|
||||||
|
when /cygwin|mingw/
|
||||||
|
if defined?($extlist)
|
||||||
|
build_dir = "$(TARGET_SO_DIR)../"
|
||||||
|
else
|
||||||
|
base_dir = File.expand_path('../../../..', __FILE__)
|
||||||
|
build_dir = File.join(base_dir, "tmp", RUBY_PLATFORM, "bigdecimal", RUBY_VERSION, "")
|
||||||
|
end
|
||||||
|
$libs << " #{build_dir}bigdecimal.so"
|
||||||
|
true
|
||||||
|
when /mswin/
|
||||||
|
$DLDFLAGS << " -libpath:.."
|
||||||
|
$libs << " bigdecimal-$(arch).lib"
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
create_makefile('bigdecimal/util')
|
9
ext/bigdecimal/util/util.c
Normal file
9
ext/bigdecimal/util/util.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "ruby.h"
|
||||||
|
|
||||||
|
RUBY_EXTERN VALUE rmpd_util_str_to_d(VALUE str);
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_util(void)
|
||||||
|
{
|
||||||
|
rb_define_method(rb_cString, "to_d", rmpd_util_str_to_d, 0);
|
||||||
|
}
|
@ -34,11 +34,22 @@ describe "Kernel#BigDecimal" do
|
|||||||
BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1
|
BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1
|
||||||
end
|
end
|
||||||
|
|
||||||
it "ignores trailing garbage" do
|
ruby_version_is ""..."2.6" do
|
||||||
BigDecimal("123E45ruby").should == BigDecimal("123E45")
|
it "ignores trailing garbage" do
|
||||||
BigDecimal("123x45").should == BigDecimal("123")
|
BigDecimal("123E45ruby").should == BigDecimal("123E45")
|
||||||
BigDecimal("123.4%E5").should == BigDecimal("123.4")
|
BigDecimal("123x45").should == BigDecimal("123")
|
||||||
BigDecimal("1E2E3E4E5E").should == BigDecimal("100")
|
BigDecimal("123.4%E5").should == BigDecimal("123.4")
|
||||||
|
BigDecimal("1E2E3E4E5E").should == BigDecimal("100")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.6" do
|
||||||
|
it "does not ignores trailing garbage" do
|
||||||
|
lambda { BigDecimal("123E45ruby") }.should raise_error(ArgumentError)
|
||||||
|
lambda { BigDecimal("123x45") }.should raise_error(ArgumentError)
|
||||||
|
lambda { BigDecimal("123.4%E5") }.should raise_error(ArgumentError)
|
||||||
|
lambda { BigDecimal("1E2E3E4E5E") }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ruby_version_is ""..."2.4" do
|
ruby_version_is ""..."2.4" do
|
||||||
@ -59,12 +70,24 @@ describe "Kernel#BigDecimal" do
|
|||||||
BigDecimal(".123").should == BigDecimal("0.123")
|
BigDecimal(".123").should == BigDecimal("0.123")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "allows for underscores in all parts" do
|
ruby_version_is ""..."2.6" do
|
||||||
reference = BigDecimal("12345.67E89")
|
it "allows for underscores in all parts" do
|
||||||
|
reference = BigDecimal("12345.67E89")
|
||||||
|
|
||||||
BigDecimal("12_345.67E89").should == reference
|
BigDecimal("12_345.67E89").should == reference
|
||||||
BigDecimal("1_2_3_4_5_._6____7_E89").should == reference
|
BigDecimal("1_2_3_4_5_._6____7_E89").should == reference
|
||||||
BigDecimal("12345_.67E_8__9_").should == reference
|
BigDecimal("12345_.67E_8__9_").should == reference
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ruby_version_is "2.6" do
|
||||||
|
it "process underscores as Float()" do
|
||||||
|
reference = BigDecimal("12345.67E89")
|
||||||
|
|
||||||
|
BigDecimal("12_345.67E89").should == reference
|
||||||
|
lambda { BigDecimal("1_2_3_4_5_._6____7_E89") }.should raise_error(ArgumentError)
|
||||||
|
lambda { BigDecimal("12345_.67E_8__9_") }.should raise_error(ArgumentError)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "accepts NaN and [+-]Infinity" do
|
it "accepts NaN and [+-]Infinity" do
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
require_relative '../../spec_helper'
|
|
||||||
require 'bigdecimal'
|
|
||||||
|
|
||||||
describe "BigDecimal.ver" do
|
|
||||||
|
|
||||||
it "returns the Version number" do
|
|
||||||
lambda {BigDecimal.ver }.should_not raise_error()
|
|
||||||
BigDecimal.ver.should_not == nil
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
@ -44,49 +44,71 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_not_equal
|
def test_not_equal
|
||||||
assert_not_equal BigDecimal("1"), BigDecimal.allocate
|
assert_not_equal BigDecimal("1"), BigDecimal("2")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new
|
def test_BigDecimal
|
||||||
assert_equal(1, BigDecimal("1"))
|
assert_equal(1, BigDecimal("1"))
|
||||||
assert_equal(1, BigDecimal("1", 1))
|
assert_equal(1, BigDecimal("1", 1))
|
||||||
|
assert_equal(1, BigDecimal(" 1 "))
|
||||||
|
assert_equal(111, BigDecimal("1_1_1_"))
|
||||||
|
assert_equal(10**(-1), BigDecimal("1E-1"), '#4825')
|
||||||
|
assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r"))
|
||||||
|
|
||||||
assert_raise(ArgumentError) { BigDecimal("1", -1) }
|
assert_raise(ArgumentError) { BigDecimal("1", -1) }
|
||||||
|
assert_raise(ArgumentError, /"1__1_1"/) { BigDecimal("1__1_1") }
|
||||||
|
assert_raise(ArgumentError, /"_1_1_1"/) { BigDecimal("_1_1_1") }
|
||||||
|
|
||||||
BigDecimal.save_exception_mode do
|
BigDecimal.save_exception_mode do
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
||||||
assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r"))
|
assert_positive_infinite(BigDecimal("Infinity"))
|
||||||
|
assert_positive_infinite(BigDecimal("1E1111111111111111111"))
|
||||||
assert_positive_infinite(BigDecimal(" \t\n\r \rInfinity \t\n\r \r"))
|
assert_positive_infinite(BigDecimal(" \t\n\r \rInfinity \t\n\r \r"))
|
||||||
|
assert_negative_infinite(BigDecimal("-Infinity"))
|
||||||
assert_negative_infinite(BigDecimal(" \t\n\r \r-Infinity \t\n\r \r"))
|
assert_negative_infinite(BigDecimal(" \t\n\r \r-Infinity \t\n\r \r"))
|
||||||
|
assert_nan(BigDecimal("NaN"))
|
||||||
assert_nan(BigDecimal(" \t\n\r \rNaN \t\n\r \r"))
|
assert_nan(BigDecimal(" \t\n\r \rNaN \t\n\r \r"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new_with_invalid_string
|
def test_BigDecimal_with_invalid_string
|
||||||
[
|
[
|
||||||
'', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d',
|
'', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d',
|
||||||
'invlaid value'
|
'2,30', '19,000.0', '-2,30', '-19,000.0', '+2,30', '+19,000.0',
|
||||||
|
'2.3,0', '19.000,0', '-2.3,0', '-19.000,0', '+2.3,0', '+19.000,0',
|
||||||
|
'2.3.0', '19.000.0', '-2.3.0', '-19.000.0', '+2.3.0', '+19.000.0',
|
||||||
|
'invlaid value', '123 xyz'
|
||||||
].each do |invalid_string|
|
].each do |invalid_string|
|
||||||
assert_raise_with_message(ArgumentError, %Q[invalid value for BigDecimal(): "#{invalid_string}"]) do
|
assert_raise_with_message(ArgumentError, %Q[invalid value for BigDecimal(): "#{invalid_string}"]) do
|
||||||
BigDecimal(invalid_string)
|
BigDecimal(invalid_string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
BigDecimal.save_exception_mode do
|
||||||
|
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
||||||
|
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
||||||
|
assert_raise(ArgumentError, /"Infinity_"/) { BigDecimal("Infinity_") }
|
||||||
|
assert_raise(ArgumentError, /"+Infinity_"/) { BigDecimal("+Infinity_") }
|
||||||
|
assert_raise(ArgumentError, /"-Infinity_"/) { BigDecimal("-Infinity_") }
|
||||||
|
assert_raise(ArgumentError, /"NaN_"/) { BigDecimal("NaN_") }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new_with_integer
|
def test_BigDecimal_with_integer
|
||||||
assert_equal(BigDecimal("1"), BigDecimal(1))
|
assert_equal(BigDecimal("1"), BigDecimal(1))
|
||||||
assert_equal(BigDecimal("-1"), BigDecimal(-1))
|
assert_equal(BigDecimal("-1"), BigDecimal(-1))
|
||||||
assert_equal(BigDecimal((2**100).to_s), BigDecimal(2**100))
|
assert_equal(BigDecimal((2**100).to_s), BigDecimal(2**100))
|
||||||
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
|
def test_BigDecimal_with_rational
|
||||||
assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(1.quo(3), 21))
|
assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(1.quo(3), 21))
|
||||||
assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal(-1.quo(3), 21))
|
assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal(-1.quo(3), 21))
|
||||||
assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { BigDecimal(42.quo(7)) }
|
assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { BigDecimal(42.quo(7)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new_with_float
|
def test_BigDecimal_with_float
|
||||||
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
|
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
|
||||||
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
|
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
|
||||||
assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) }
|
assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) }
|
||||||
@ -107,7 +129,7 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new_with_big_decimal
|
def test_BigDecimal_with_big_decimal
|
||||||
assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
|
assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
|
||||||
assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
|
assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
|
||||||
assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0')))
|
assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0')))
|
||||||
@ -120,7 +142,7 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_global_new_with_tainted_string
|
def test_BigDecimal_with_tainted_string
|
||||||
Thread.new {
|
Thread.new {
|
||||||
$SAFE = 1
|
$SAFE = 1
|
||||||
BigDecimal('1'.taint)
|
BigDecimal('1'.taint)
|
||||||
@ -129,76 +151,73 @@ 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_warning(/BigDecimal\.ver is deprecated; use BigDecimal::VERSION instead/) do
|
assert_raise(NoMethodError, /undefined method `ver`/) { BigDecimal.ver }
|
||||||
BigDecimal.ver
|
end
|
||||||
end
|
|
||||||
|
def test_s_allocate
|
||||||
|
assert_raise(NoMethodError, /undefined method `allocate`/) { BigDecimal.allocate }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_s_new
|
def test_s_new
|
||||||
assert_warning(/BigDecimal.new is deprecated/) do
|
assert_raise(NoMethodError, /undefined method `new`/) { BigDecimal.new("1") }
|
||||||
BigDecimal.new("1")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new
|
|
||||||
assert_equal(1, BigDecimal("1"))
|
|
||||||
assert_equal(1, BigDecimal("1", 1))
|
|
||||||
assert_equal(1, BigDecimal(" 1 "))
|
|
||||||
assert_equal(111, BigDecimal("1_1_1_"))
|
|
||||||
assert_equal(10**(-1), BigDecimal("1E-1"), '#4825')
|
|
||||||
|
|
||||||
assert_raise(ArgumentError, /"_1_1_1"/) { BigDecimal("_1_1_1") }
|
|
||||||
|
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
|
||||||
assert_positive_infinite(BigDecimal("Infinity"))
|
|
||||||
assert_negative_infinite(BigDecimal("-Infinity"))
|
|
||||||
assert_nan(BigDecimal("NaN"))
|
|
||||||
assert_positive_infinite(BigDecimal("1E1111111111111111111"))
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new_with_integer
|
|
||||||
assert_equal(BigDecimal("1"), BigDecimal(1))
|
|
||||||
assert_equal(BigDecimal("-1"), BigDecimal(-1))
|
|
||||||
assert_equal(BigDecimal((2**100).to_s), BigDecimal(2**100))
|
|
||||||
assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100))
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_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_with_float
|
|
||||||
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
|
|
||||||
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
|
|
||||||
assert_raise(ArgumentError) { BigDecimal(0.1) }
|
|
||||||
assert_raise(ArgumentError) { BigDecimal(0.1, Float::DIG + 2) }
|
|
||||||
assert_nothing_raised { BigDecimal(0.1, Float::DIG + 1) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new_with_big_decimal
|
|
||||||
assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
|
|
||||||
assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
|
|
||||||
assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0')))
|
|
||||||
BigDecimal.save_exception_mode do
|
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
|
||||||
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
|
||||||
assert_positive_infinite(BigDecimal(BigDecimal('Infinity')))
|
|
||||||
assert_negative_infinite(BigDecimal(BigDecimal('-Infinity')))
|
|
||||||
assert_nan(BigDecimal(BigDecimal('NaN')))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_new_with_tainted_string
|
|
||||||
Thread.new {
|
|
||||||
$SAFE = 1
|
|
||||||
BigDecimal('1'.taint)
|
|
||||||
}.join
|
|
||||||
ensure
|
|
||||||
$SAFE = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def _test_mode(type)
|
def _test_mode(type)
|
||||||
@ -1778,6 +1797,12 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_frozen_p
|
||||||
|
x = BigDecimal(1)
|
||||||
|
assert(x.frozen?)
|
||||||
|
assert((x + x).frozen?)
|
||||||
|
end
|
||||||
|
|
||||||
def test_clone
|
def test_clone
|
||||||
assert_warning(/^$/) do
|
assert_warning(/^$/) do
|
||||||
x = BigDecimal(0)
|
x = BigDecimal(0)
|
||||||
@ -1795,14 +1820,8 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_dup_subclass
|
def test_dup_subclass
|
||||||
assert_warning(/BigDecimal\.new is deprecated/) do
|
c = Class.new(BigDecimal)
|
||||||
c = Class.new(BigDecimal)
|
assert_raise(NoMethodError, /undefined method `new`/) { c.new(1) }
|
||||||
x = c.new(1)
|
|
||||||
y = x.dup
|
|
||||||
assert_same(x, y)
|
|
||||||
assert_equal(1, y)
|
|
||||||
assert_kind_of(c, y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_to_d
|
def test_to_d
|
||||||
@ -1834,7 +1853,7 @@ class TestBigDecimal < Test::Unit::TestCase
|
|||||||
assert_no_memory_leak("BigDecimal()")
|
assert_no_memory_leak("BigDecimal()")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_no_memory_leak_global_new
|
def test_no_memory_leak_BigDecimal
|
||||||
assert_no_memory_leak("BigDecimal('10')")
|
assert_no_memory_leak("BigDecimal('10')")
|
||||||
assert_no_memory_leak("BigDecimal(b)")
|
assert_no_memory_leak("BigDecimal(b)")
|
||||||
end
|
end
|
||||||
|
@ -12,6 +12,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
|
|||||||
def test_Integer_to_d
|
def test_Integer_to_d
|
||||||
assert_equal(BigDecimal(1), 1.to_d)
|
assert_equal(BigDecimal(1), 1.to_d)
|
||||||
assert_equal(BigDecimal(2<<100), (2<<100).to_d)
|
assert_equal(BigDecimal(2<<100), (2<<100).to_d)
|
||||||
|
|
||||||
|
assert(1.to_d.frozen?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_Float_to_d_without_precision
|
def test_Float_to_d_without_precision
|
||||||
@ -22,6 +24,11 @@ class TestBigDecimalUtil < Test::Unit::TestCase
|
|||||||
|
|
||||||
bug9214 = '[ruby-core:58858]'
|
bug9214 = '[ruby-core:58858]'
|
||||||
assert_equal((-0.0).to_d.sign, -1, bug9214)
|
assert_equal((-0.0).to_d.sign, -1, bug9214)
|
||||||
|
|
||||||
|
assert_raise(TypeError) { 0.3.to_d(nil) }
|
||||||
|
assert_raise(TypeError) { 0.3.to_d(false) }
|
||||||
|
|
||||||
|
assert(1.1.to_d.frozen?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_Float_to_d_with_precision
|
def test_Float_to_d_with_precision
|
||||||
@ -32,6 +39,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
|
|||||||
|
|
||||||
bug9214 = '[ruby-core:58858]'
|
bug9214 = '[ruby-core:58858]'
|
||||||
assert_equal((-0.0).to_d(digits).sign, -1, bug9214)
|
assert_equal((-0.0).to_d(digits).sign, -1, bug9214)
|
||||||
|
|
||||||
|
assert(1.1.to_d(digits).frozen?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_Rational_to_d
|
def test_Rational_to_d
|
||||||
@ -39,6 +48,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
|
|||||||
delta = 1.0/10**(digits)
|
delta = 1.0/10**(digits)
|
||||||
assert_in_delta(BigDecimal(1.quo(2), digits), 1.quo(2).to_d(digits), delta)
|
assert_in_delta(BigDecimal(1.quo(2), digits), 1.quo(2).to_d(digits), delta)
|
||||||
assert_in_delta(BigDecimal(355.quo(113), digits), 355.quo(113).to_d(digits), delta)
|
assert_in_delta(BigDecimal(355.quo(113), digits), 355.quo(113).to_d(digits), delta)
|
||||||
|
|
||||||
|
assert(355.quo(113).to_d(digits).frozen?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_Rational_to_d_with_zero_precision
|
def test_Rational_to_d_with_zero_precision
|
||||||
@ -50,11 +61,30 @@ class TestBigDecimalUtil < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_String_to_d
|
def test_String_to_d
|
||||||
assert_equal("2.5".to_d, BigDecimal('2.5'))
|
assert_equal(BigDecimal('1'), "1__1_1".to_d)
|
||||||
|
assert_equal(BigDecimal('2.5'), "2.5".to_d)
|
||||||
|
assert_equal(BigDecimal('2.5'), "2.5 degrees".to_d)
|
||||||
|
assert_equal(BigDecimal('2.5e1'), "2.5e1 degrees".to_d)
|
||||||
|
assert_equal(BigDecimal('0'), "degrees 100.0".to_d)
|
||||||
|
assert_equal(BigDecimal('0.125'), "0.1_2_5".to_d)
|
||||||
|
assert_equal(BigDecimal('0.125'), "0.1_2_5__".to_d)
|
||||||
|
assert_equal(BigDecimal('1'), "1_.125".to_d)
|
||||||
|
assert_equal(BigDecimal('1'), "1._125".to_d)
|
||||||
|
assert_equal(BigDecimal('0.1'), "0.1__2_5".to_d)
|
||||||
|
assert_equal(BigDecimal('0.1'), "0.1_e10".to_d)
|
||||||
|
assert_equal(BigDecimal('0.1'), "0.1e_10".to_d)
|
||||||
|
assert_equal(BigDecimal('1'), "0.1e1__0".to_d)
|
||||||
|
|
||||||
|
assert("2.5".to_d.frozen?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_invalid_String_to_d
|
def test_invalid_String_to_d
|
||||||
assert_equal("invalid".to_d, BigDecimal('0.0'))
|
assert_equal("invalid".to_d, BigDecimal('0.0'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_Nil_to_d
|
||||||
|
assert_equal(nil.to_d, BigDecimal('0.0'))
|
||||||
|
|
||||||
|
assert(nil.to_d)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user