1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Import bigdecimal-1.4.0.pre-20181130a

* https://github.com/ruby/bigdecimal/compare/74d25ef..v1.4.0.pre.20181130a

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66124 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mrkn 2018-12-02 05:21:54 +00:00
parent 096d362939
commit a0e438cd3c
13 changed files with 469 additions and 287 deletions

View file

@ -135,24 +135,6 @@ rb_rational_den(VALUE rat)
*/
#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
*/
@ -664,9 +646,10 @@ VP_EXPORT Real *
VpNewRbClass(size_t mx, const char *str, VALUE klass)
{
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
Real *pv = VpAlloc(mx,str);
Real *pv = VpAlloc(mx, str, 1);
RTYPEDDATA_DATA(obj) = pv;
pv->obj = obj;
RB_OBJ_FREEZE(obj);
return pv;
}
@ -2165,15 +2148,10 @@ BigDecimal_exponent(VALUE self)
return INT2NUM(e);
}
/* Returns debugging information about the value as a string of comma-separated
* values in angle brackets with a leading #:
/* Returns a string representation of self.
*
* BigDecimal("1234.5678").inspect
* #=> "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
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);
if (VpIsNaN(x)) {
y = VpCreateRbObject(n, "0#");
y = VpCreateRbObject(n, "0");
RB_GC_GUARD(y->obj);
VpSetNaN(y);
return ToValue(y);
@ -2459,7 +2437,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
}
else {
y = VpCreateRbObject(n, "0#");
y = VpCreateRbObject(n, "0");
if (BIGDECIMAL_NEGATIVE_P(x)) {
if (is_integer(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)))) {
if (is_negative(vexp)) {
y = VpCreateRbObject(n, "0#");
y = VpCreateRbObject(n, "0");
if (is_even(vexp)) {
VpSetInf(y, VpGetSign(x));
}
@ -2510,7 +2488,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
else {
if (is_positive(vexp)) {
y = VpCreateRbObject(n, "0#");
y = VpCreateRbObject(n, "0");
if (is_even(vexp)) {
VpSetInf(y, VpGetSign(x));
}
@ -2560,52 +2538,8 @@ BigDecimal_power_op(VALUE self, VALUE exp)
return BigDecimal_power(1, &exp, self);
}
static VALUE
BigDecimal_s_allocate(VALUE klass)
{
return VpNewRbClass(0, NULL, klass)->obj;
}
static Real *BigDecimal_new(int argc, VALUE *argv);
/* call-seq:
* new(initial, digits)
*
* Create a new BigDecimal object.
*
* initial:: The initial value, as an Integer, a Float, a Rational,
* a BigDecimal, or a String.
*
* If it is a String, spaces are ignored and unrecognized characters
* terminate the value.
*
* digits:: The number of significant digits, as an Integer. If omitted or 0,
* the number of significant digits is determined from the initial
* value.
*
* The actual number of significant digits used in computation is usually
* larger than the specified number.
*
* ==== Exceptions
*
* TypeError:: If the +initial+ type is neither Integer, Float,
* Rational, nor BigDecimal, this exception is raised.
*
* TypeError:: If the +digits+ is not an Integer, this exception is raised.
*
* ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
* Float::DIG + 1, this exception is raised.
*
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
* value is omitted, this exception is raised.
*/
static VALUE
BigDecimal_s_new(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)
{
@ -2700,10 +2634,40 @@ BigDecimal_new(int argc, VALUE *argv)
break;
}
StringValueCStr(iniValue);
return VpAlloc(mf, RSTRING_PTR(iniValue));
return VpAlloc(mf, RSTRING_PTR(iniValue), 1);
}
/* See also BigDecimal.new */
/* call-seq:
* BigDecimal(initial, digits)
*
* Create a new BigDecimal object.
*
* initial:: The initial value, as an Integer, a Float, a Rational,
* a BigDecimal, or a String.
*
* If it is a String, spaces are ignored and unrecognized characters
* terminate the value.
*
* digits:: The number of significant digits, as an Integer. If omitted or 0,
* the number of significant digits is determined from the initial
* value.
*
* The actual number of significant digits used in computation is usually
* larger than the specified number.
*
* ==== Exceptions
*
* TypeError:: If the +initial+ type is neither Integer, Float,
* Rational, nor BigDecimal, this exception is raised.
*
* TypeError:: If the +digits+ is not an Integer, this exception is raised.
*
* ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
* Float::DIG + 1, this exception is raised.
*
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
* value is omitted, this exception is raised.
*/
static VALUE
BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
{
@ -2715,6 +2679,7 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(pv, BigDecimal_new(argc, argv));
if (ToValue(pv)) pv = VpCopy(NULL, pv);
RTYPEDDATA_DATA(obj) = pv;
RB_OBJ_FREEZE(obj);
return pv->obj = obj;
}
@ -3138,6 +3103,21 @@ get_vp_value:
return y;
}
VALUE
rmpd_util_str_to_d(VALUE str)
{
ENTER(1);
char const *c_str;
Real *pv;
VALUE obj;
c_str = StringValueCStr(str);
GUARD_OBJ(pv, VpAlloc(0, c_str, 0));
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
RB_OBJ_FREEZE(obj);
return obj;
}
/* Document-class: BigDecimal
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
*
@ -3277,18 +3257,17 @@ Init_bigdecimal(void)
/* Class and method registration */
rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
/* Global function */
rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
/* 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, "limit", BigDecimal_limit, -1);
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, "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_rounding_mode", BigDecimal_save_rounding_mode, 0);
@ -3745,25 +3724,19 @@ One(void)
VP_EXPORT double
VpGetDoubleNaN(void) /* Returns the value of NaN */
{
static double fNaN = 0.0;
if (fNaN == 0.0) fNaN = Zero()/Zero();
return fNaN;
return nan("");
}
VP_EXPORT double
VpGetDoublePosInf(void) /* Returns the value of +Infinity */
{
static double fInf = 0.0;
if (fInf == 0.0) fInf = One()/Zero();
return fInf;
return HUGE_VAL;
}
VP_EXPORT double
VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
{
static double fInf = 0.0;
if (fInf == 0.0) fInf = -(One()/Zero());
return fInf;
return -HUGE_VAL;
}
VP_EXPORT double
@ -3964,8 +3937,8 @@ VpInit(BDIGIT BaseVal)
VpGetDoubleNegZero();
/* Allocates Vp constants. */
VpConstOne = VpAlloc(1UL, "1");
VpPt5 = VpAlloc(1UL, ".5");
VpConstOne = VpAlloc(1UL, "1", 1);
VpPt5 = VpAlloc(1UL, ".5", 1);
#ifdef BIGDECIMAL_DEBUG
gnAlloc = 0;
@ -4029,6 +4002,52 @@ overflow:
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.
* [Input]
@ -4043,10 +4062,10 @@ overflow:
* NULL be returned if memory allocation is failed,or any error.
*/
VP_EXPORT Real *
VpAlloc(size_t mx, const char *szVal)
VpAlloc(size_t mx, const char *szVal, int strict_p)
{
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;
int sign=1;
Real *vp = NULL;
@ -4057,7 +4076,10 @@ VpAlloc(size_t mx, const char *szVal)
if (mx == 0) ++mx;
if (szVal) {
/* Skipping leading spaces */
while (ISSPACE(*szVal)) szVal++;
/* Processing the leading one `#` */
if (*szVal != '#') {
if (mf) {
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
@ -4071,6 +4093,7 @@ VpAlloc(size_t mx, const char *szVal)
}
}
else {
return_zero:
/* necessary to be able to store */
/* at least mx digits. */
/* szVal==NULL ==> allocate zero value. */
@ -4081,105 +4104,166 @@ VpAlloc(size_t mx, const char *szVal)
return vp;
}
/* Skip all '_' after digit: 2006-6-30 */
ni = 0;
/* Check on Inf & NaN */
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);
psz = RSTRING_PTR(buf);
i = 0;
ipn = 0;
while ((psz[i] = szVal[ipn]) != 0) {
if (ISSPACE(psz[i])) {
psz[i] = 0;
/* cursor: i for psz, and j for szVal */
i = j = 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;
}
if (ISDIGIT(psz[i])) ++ni;
if (psz[i] == '_') {
if (v == '_') {
if (ni > 0) {
ipn++;
continue;
v = szVal[j+1];
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;
}
++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;
++i;
++j;
}
nf = 0;
ipf = 0;
ipe = 0;
ne = 0;
/* Scanning: fractional part */
nf = 0; /* number of digits in the fractional part */
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;
exp_seen = 0;
if (v) {
/* other than digit nor \0 */
if (szVal[i] == '.') { /* xxx. */
if (v != '\0') {
/* Scanning fractional part */
if ((psz[i] = szVal[j]) == '.') {
dot_seen = 1;
++i;
++j;
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;
++i;
++j;
++nf;
}
}
ipe = 0; /* Exponent */
switch (szVal[i]) {
case '\0':
break;
case 'e': case 'E':
case 'd': case 'D':
exp_seen = 1;
++i;
ipe = i;
v = szVal[i];
if ((v == '-') || (v == '+')) ++i;
while ((v=szVal[i]) != 0) {
if (!ISDIGIT(v)) break;
/* Scanning exponential part */
if (v != '\0') {
switch ((psz[i] = szVal[j])) {
case '\0':
break;
case 'e': case 'E':
case 'd': case 'D':
exp_seen = 1;
++i;
++ne;
}
break;
default:
break;
++j;
ipe = i;
v = psz[i] = szVal[j];
if ((v == '-') || (v == '+')) {
++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)) {
VALUE str = rb_str_new2(orig_szVal);
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
VALUE str;
invalid_value:
if (!strict_p) {
goto return_zero;
}
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 */
@ -4191,7 +4275,7 @@ VpAlloc(size_t mx, const char *szVal)
/* xmalloc() alway returns(or throw interruption) */
vp->MaxPrec = mx; /* set max precision */
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);
return vp;
}
@ -4754,7 +4838,7 @@ VpMult(Real *c, Real *a, Real *b)
if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
w = c;
c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0");
c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1);
MxIndC = MxIndAB;
}
@ -5922,8 +6006,8 @@ VpSqrt(Real *y, Real *x)
if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
/* allocate temporally variables */
f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1");
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1");
f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1);
r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1);
nr = 0;
y_prec = y->MaxPrec;
@ -6375,8 +6459,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
/* Allocate working variables */
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1);
w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1);
/* calculation start */
VpAsgn(y, x, 1);

View file

@ -0,0 +1,3 @@
EXPORTS
rmpd_util_str_to_d
Init_bigdecimal

View file

@ -1,6 +1,6 @@
# coding: utf-8
bigdecimal_version = '1.3.4'
bigdecimal_version = '1.4.0.pre.20181121a'
Gem::Specification.new do |s|
s.name = "bigdecimal"
@ -14,13 +14,15 @@ Gem::Specification.new do |s|
s.license = "ruby"
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[
bigdecimal.gemspec
ext/bigdecimal/bigdecimal.c
ext/bigdecimal/bigdecimal.h
ext/bigdecimal/depend
ext/bigdecimal/extconf.rb
ext/bigdecimal/util/extconf.rb
ext/bigdecimal/util/util.c
lib/bigdecimal/jacobian.rb
lib/bigdecimal/ludcmp.rb
lib/bigdecimal/math.rb
@ -31,9 +33,11 @@ Gem::Specification.new do |s|
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-compiler", ">= 0.9"
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"
end

View file

@ -308,7 +308,7 @@ VP_EXPORT size_t VpInit(BDIGIT BaseVal);
VP_EXPORT void *VpMemAlloc(size_t mb);
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
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);
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 VpMult(Real *c,Real *a,Real *b);

View file

@ -1,6 +1,10 @@
# frozen_string_literal: false
require 'mkmf'
def windows_platform?
/cygwin|mingw|mswin/ === RUBY_PLATFORM
end
gemspec_name = gemspec_path = nil
unless ['', '../../'].any? {|dir|
gemspec_name = "#{dir}bigdecimal.gemspec"
@ -17,8 +21,6 @@ bigdecimal_version =
$defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"]
alias __have_macro__ have_macro
have_func("labs", "stdlib.h")
have_func("llabs", "stdlib.h")
have_func("finite", "math.h")
@ -30,6 +32,38 @@ have_func("rb_rational_den", "ruby.h")
have_func("rb_array_const_ptr", "ruby.h")
have_func("rb_sym2str", "ruby.h")
if windows_platform?
library_base_name = "ruby-bigdecimal"
case RUBY_PLATFORM
when /cygwin|mingw/
import_library_name = "libruby-bigdecimal.a"
when /mswin/
import_library_name = "bigdecimal-$(arch).lib"
end
end
checking_for(checking_message("Windows")) do
if windows_platform?
case RUBY_PLATFORM
when /cygwin|mingw/
$DLDFLAGS << " $(srcdir)/bigdecimal.def"
$DLDFLAGS << " -Wl,--out-implib=$(TARGET_SO_DIR)#{import_library_name}"
when /mswin/
$DLDFLAGS << " /DEF:$(srcdir)/bigdecimal.def"
end
$cleanfiles << import_library_name
true
else
false
end
end
create_makefile('bigdecimal') {|mf|
mf << "\nall:\n\nextconf.h: $(srcdir)/#{gemspec_name}\n"
case RUBY_PLATFORM
when /mswin/
mf << "\nall:\n\tdir $(TARGET_SO_DIR)"
else
mf << "\nall:\n\tls $(TARGET_SO_DIR)"
end
}

View file

@ -21,6 +21,9 @@
#
# fx is f.values(x).
#
require 'bigdecimal'
module Jacobian
module_function

View file

@ -5,6 +5,8 @@
# and provides BigDecimal#to_d and BigDecimal#to_digits.
#++
require 'bigdecimal'
require 'bigdecimal/util.so'
class Integer < Numeric
# call-seq:
@ -42,8 +44,8 @@ class Float < Numeric
#
# See also BigDecimal::new.
#
def to_d(precision=nil)
BigDecimal(self, precision || Float::DIG)
def to_d(precision=Float::DIG)
BigDecimal(self, precision)
end
end
@ -64,13 +66,6 @@ class String
#
# See also BigDecimal::new.
#
def to_d
begin
BigDecimal(self)
rescue ArgumentError
BigDecimal(0)
end
end
end
@ -132,3 +127,20 @@ class Rational < Numeric
BigDecimal(self, precision)
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

View file

@ -28,8 +28,8 @@ def rd_order(na)
end
na = ARGV.size
zero = BigDecimal.new("0.0")
one = BigDecimal.new("1.0")
zero = BigDecimal("0.0")
one = BigDecimal("1.0")
while (n=rd_order(na))>0
a = []
@ -37,27 +37,28 @@ while (n=rd_order(na))>0
b = []
if na <= 0
# 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 j in 0...n do
printf("A[%d,%d]? ",i,j); s = ARGF.gets
a << BigDecimal.new(s);
as << BigDecimal.new(s);
a << BigDecimal(s)
as << BigDecimal(s)
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
else
# 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
s = ARGF.gets
printf("%d) %s",i,s)
s = s.split
for j in 0...n do
a << BigDecimal.new(s[j]);
as << BigDecimal.new(s[j]);
a << BigDecimal(s[j])
as << BigDecimal(s[j])
end
b << BigDecimal.new(s[n]);
b << BigDecimal(s[n])
end
end
x = lusolve(a,b,ludecomp(a,n,zero,one),zero)

View file

@ -12,11 +12,11 @@ include Newton
class Function # :nodoc: all
def initialize()
@zero = BigDecimal.new("0.0")
@one = BigDecimal.new("1.0")
@two = BigDecimal.new("2.0")
@ten = BigDecimal.new("10.0")
@eps = BigDecimal.new("1.0e-16")
@zero = BigDecimal("0.0")
@one = BigDecimal("1.0")
@two = BigDecimal("2.0")
@ten = BigDecimal("10.0")
@eps = BigDecimal("1.0e-16")
end
def zero;@zero;end
def one ;@one ;end

View file

@ -0,0 +1,40 @@
# frozen_string_literal: false
require 'mkmf'
def windows_platform?
/cygwin|mingw|mswin/ === RUBY_PLATFORM
end
if windows_platform?
library_base_name = "ruby-bigdecimal"
case RUBY_PLATFORM
when /cygwin|mingw/
import_library_name = "libruby-bigdecimal.a"
when /mswin/
import_library_name = "bigdecimal-$(arch).lib"
end
end
checking_for(checking_message("Windows")) do
if windows_platform?
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
case RUBY_PLATFORM
when /cygwin|mingw/
$LDFLAGS << " -L#{build_dir} -L.. -L .."
$libs << " -l#{library_base_name}"
when /mswin/
$DLDFLAGS << " /libpath:#{build_dir} /libpath:.."
$libs << " #{import_library_name}"
end
true
else
false
end
end
create_makefile('bigdecimal/util')

View 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);
}

View file

@ -44,49 +44,71 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_not_equal
assert_not_equal BigDecimal("1"), BigDecimal.allocate
assert_not_equal BigDecimal("1"), BigDecimal("2")
end
def test_global_new
def test_BigDecimal
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_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r"))
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.mode(BigDecimal::EXCEPTION_OVERFLOW, 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_negative_infinite(BigDecimal("-Infinity"))
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"))
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',
'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|
assert_raise_with_message(ArgumentError, %Q[invalid value for BigDecimal(): "#{invalid_string}"]) do
BigDecimal(invalid_string)
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
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((2**100).to_s), BigDecimal(2**100))
assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100))
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_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { BigDecimal(42.quo(7)) }
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_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
def test_global_new_with_big_decimal
def test_BigDecimal_with_big_decimal
assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
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
def test_global_new_with_tainted_string
def test_BigDecimal_with_tainted_string
Thread.new {
$SAFE = 1
BigDecimal('1'.taint)
@ -130,75 +152,15 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_s_ver
assert_warning(/BigDecimal\.ver is deprecated; use BigDecimal::VERSION instead/) do
BigDecimal.ver
end
assert_raise(NoMethodError, /undefined method `ver`/) { BigDecimal.ver }
end
def test_s_allocate
assert_raise(NoMethodError, /undefined method `allocate`/) { BigDecimal.allocate }
end
def test_s_new
assert_warning(/BigDecimal.new is deprecated/) do
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
assert_raise(NoMethodError, /undefined method `new`/) { BigDecimal.new("1") }
end
def _test_mode(type)
@ -1778,6 +1740,12 @@ class TestBigDecimal < Test::Unit::TestCase
EOS
end
def test_frozen_p
x = BigDecimal(1)
assert(x.frozen?)
assert((x + x).frozen?)
end
def test_clone
assert_warning(/^$/) do
x = BigDecimal(0)
@ -1795,14 +1763,8 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_dup_subclass
assert_warning(/BigDecimal\.new is deprecated/) do
c = Class.new(BigDecimal)
x = c.new(1)
y = x.dup
assert_same(x, y)
assert_equal(1, y)
assert_kind_of(c, y)
end
c = Class.new(BigDecimal)
assert_raise(NoMethodError, /undefined method `new`/) { c.new(1) }
end
def test_to_d
@ -1834,7 +1796,7 @@ class TestBigDecimal < Test::Unit::TestCase
assert_no_memory_leak("BigDecimal()")
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(b)")
end

View file

@ -12,6 +12,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
def test_Integer_to_d
assert_equal(BigDecimal(1), 1.to_d)
assert_equal(BigDecimal(2<<100), (2<<100).to_d)
assert(1.to_d.frozen?)
end
def test_Float_to_d_without_precision
@ -22,6 +24,11 @@ class TestBigDecimalUtil < Test::Unit::TestCase
bug9214 = '[ruby-core:58858]'
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
def test_Float_to_d_with_precision
@ -32,6 +39,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
bug9214 = '[ruby-core:58858]'
assert_equal((-0.0).to_d(digits).sign, -1, bug9214)
assert(1.1.to_d(digits).frozen?)
end
def test_Rational_to_d
@ -39,6 +48,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase
delta = 1.0/10**(digits)
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(355.quo(113).to_d(digits).frozen?)
end
def test_Rational_to_d_with_zero_precision
@ -50,11 +61,30 @@ class TestBigDecimalUtil < Test::Unit::TestCase
end
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
def test_invalid_String_to_d
assert_equal("invalid".to_d, BigDecimal('0.0'))
end
def test_Nil_to_d
assert_equal(nil.to_d, BigDecimal('0.0'))
assert(nil.to_d)
end
end