From dd0c75fdc2104a6ba38b68d4431a572504a3bbc2 Mon Sep 17 00:00:00 2001 From: Kenta Murata Date: Tue, 8 Oct 2019 09:06:28 +0900 Subject: Import changes from ruby/bigdecimal (#2531) Sync to ruby/bigdecimal@92356ba71c6bd325b0ab618c634a7aecf8cdc767 --- ext/bigdecimal/bigdecimal.c | 44 +++++++++++++--------- ext/bigdecimal/bigdecimal.def | 3 -- ext/bigdecimal/bigdecimal.gemspec | 10 +---- ext/bigdecimal/extconf.rb | 21 ++++++++--- ext/bigdecimal/lib/bigdecimal.rb | 5 --- ext/bigdecimal/lib/bigdecimal/jacobian.rb | 7 ++-- ext/bigdecimal/lib/bigdecimal/util.rb | 4 +- ext/bigdecimal/util/extconf.rb | 24 ------------ ext/bigdecimal/util/util.c | 9 ----- test/bigdecimal/test_bigdecimal.rb | 62 ++++++++++++++++++++----------- test/bigdecimal/test_bigdecimal_util.rb | 2 + 11 files changed, 93 insertions(+), 98 deletions(-) delete mode 100644 ext/bigdecimal/bigdecimal.def delete mode 100644 ext/bigdecimal/util/extconf.rb delete mode 100644 ext/bigdecimal/util/util.c diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 6d5047553b..b2354038ac 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -1756,12 +1756,15 @@ BigDecimal_fix(VALUE self) * round(n, mode) * * Round to the nearest integer (by default), returning the result as a - * BigDecimal. + * BigDecimal if n is specified, or as an Integer if it isn't. * * BigDecimal('3.14159').round #=> 3 * BigDecimal('8.7').round #=> 9 * BigDecimal('-9.9').round #=> -10 * + * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal" + * BigDecimal('3.14159').round.class.name #=> "Integer" + * * If n is specified and positive, the fractional part of the result has no * more than that many digits. * @@ -2585,7 +2588,7 @@ opts_exception_p(VALUE opts) #endif static Real * -BigDecimal_new(int argc, VALUE *argv) +VpNewVarArg(int argc, VALUE *argv) { size_t mf; VALUE opts = Qnil; @@ -2726,7 +2729,7 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self) if (argc == 1 || (argc == 2 && RB_TYPE_P(argv[1], T_HASH))) return argv[0]; } obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - pv = BigDecimal_new(argc, argv); + pv = VpNewVarArg(argc, argv); if (pv == NULL) return Qnil; SAVE(pv); if (ToValue(pv)) pv = VpCopy(NULL, pv); @@ -2735,6 +2738,20 @@ f_BigDecimal(int argc, VALUE *argv, VALUE self) return pv->obj = obj; } +static VALUE +BigDecimal_s_interpret_loosely(VALUE klass, 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(klass, &BigDecimal_data_type, pv); + RB_OBJ_FREEZE(pv->obj); + return pv->obj; +} + /* call-seq: * BigDecimal.limit(digits) * @@ -2954,6 +2971,10 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) n = prec + rmpd_double_figures(); negative = BIGDECIMAL_NEGATIVE_P(vx); if (negative) { + VALUE x_zero = INT2NUM(1); + VALUE x_copy = f_BigDecimal(1, &x_zero, klass); + x = BigDecimal_initialize_copy(x_copy, x); + vx = DATA_PTR(x); VpSetSign(vx, 1); } @@ -3155,20 +3176,6 @@ get_vp_value: 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 * BigDecimal provides arbitrary-precision floating point decimal arithmetic. * @@ -3315,6 +3322,7 @@ Init_bigdecimal(void) /* Class methods */ rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate"); rb_undef_method(CLASS_OF(rb_cBigDecimal), "new"); + rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 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, "double_fig", BigDecimal_double_fig, 0); @@ -4296,7 +4304,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc) psz[i] = '\0'; - if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) { + if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0))) { VALUE str; invalid_value: if (!strict_p) { diff --git a/ext/bigdecimal/bigdecimal.def b/ext/bigdecimal/bigdecimal.def deleted file mode 100644 index 615bf72e20..0000000000 --- a/ext/bigdecimal/bigdecimal.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS -rmpd_util_str_to_d -Init_bigdecimal diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec index c483cfb43c..53dbe91147 100644 --- a/ext/bigdecimal/bigdecimal.gemspec +++ b/ext/bigdecimal/bigdecimal.gemspec @@ -1,6 +1,6 @@ # coding: utf-8 -bigdecimal_version = '1.4.2' +bigdecimal_version = '2.0.0.dev' Gem::Specification.new do |s| s.name = "bigdecimal" @@ -14,16 +14,11 @@ Gem::Specification.new do |s| s.license = "ruby" s.require_paths = %w[lib] - s.extensions = %w[ext/bigdecimal/extconf.rb ext/bigdecimal/util/extconf.rb] + s.extensions = %w[ext/bigdecimal/extconf.rb] s.files = %w[ bigdecimal.gemspec ext/bigdecimal/bigdecimal.c - ext/bigdecimal/bigdecimal.def ext/bigdecimal/bigdecimal.h - ext/bigdecimal/depend - ext/bigdecimal/extconf.rb - ext/bigdecimal/util/extconf.rb - ext/bigdecimal/util/util.c lib/bigdecimal.rb lib/bigdecimal/jacobian.rb lib/bigdecimal/ludcmp.rb @@ -39,7 +34,6 @@ Gem::Specification.new do |s| 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", "< 5.0.0" s.add_development_dependency "pry" end diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb index 7a7af10a2d..b4098fdacf 100644 --- a/ext/bigdecimal/extconf.rb +++ b/ext/bigdecimal/extconf.rb @@ -1,6 +1,21 @@ # frozen_string_literal: false require 'mkmf' +def check_bigdecimal_version(gemspec_path) + message "checking RUBY_BIGDECIMAL_VERSION... " + + bigdecimal_version = + IO.readlines(gemspec_path) + .grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([^\']+)\'/, 1] + + version_components = bigdecimal_version.split('.') + bigdecimal_version = version_components[0, 3].join('.') + bigdecimal_version << "-#{version_components[3]}" if version_components[3] + $defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"] + + message "#{bigdecimal_version}\n" +end + gemspec_name = gemspec_path = nil unless ['', '../../'].any? {|dir| gemspec_name = "#{dir}bigdecimal.gemspec" @@ -11,11 +26,7 @@ unless ['', '../../'].any? {|dir| abort end -bigdecimal_version = - IO.readlines(gemspec_path) - .grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([\d\.]+)\'/, 1] - -$defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"] +check_bigdecimal_version(gemspec_path) have_func("labs", "stdlib.h") have_func("llabs", "stdlib.h") diff --git a/ext/bigdecimal/lib/bigdecimal.rb b/ext/bigdecimal/lib/bigdecimal.rb index 96995a32b3..8fd2587c84 100644 --- a/ext/bigdecimal/lib/bigdecimal.rb +++ b/ext/bigdecimal/lib/bigdecimal.rb @@ -1,6 +1 @@ require 'bigdecimal.so' - -def BigDecimal.new(*args, **kwargs) - warn "BigDecimal.new is deprecated; use BigDecimal() method instead.", uplevel: 1 - BigDecimal(*args, **kwargs) -end diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb index 84c50248b7..5e29304299 100644 --- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb +++ b/ext/bigdecimal/lib/bigdecimal/jacobian.rb @@ -1,5 +1,7 @@ # frozen_string_literal: false -# + +require 'bigdecimal' + # require 'bigdecimal/jacobian' # # Provides methods to compute the Jacobian matrix of a set of equations at a @@ -21,9 +23,6 @@ # # fx is f.values(x). # - -require 'bigdecimal' - module Jacobian module_function diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb index 88f490cb45..4ece8347bd 100644 --- a/ext/bigdecimal/lib/bigdecimal/util.rb +++ b/ext/bigdecimal/lib/bigdecimal/util.rb @@ -6,7 +6,6 @@ #++ require 'bigdecimal' -require 'bigdecimal/util.so' class Integer < Numeric # call-seq: @@ -66,6 +65,9 @@ class String # # See also BigDecimal::new. # + def to_d + BigDecimal.interpret_loosely(self) + end end diff --git a/ext/bigdecimal/util/extconf.rb b/ext/bigdecimal/util/extconf.rb deleted file mode 100644 index b0d56358f8..0000000000 --- a/ext/bigdecimal/util/extconf.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' - -checking_for(checking_message("Windows")) do - case RUBY_PLATFORM - when /cygwin|mingw/ - if ARGV.include?('-rdevkit') # check `rake -rdevkit compile` case - base_dir = File.expand_path('../../../..', __FILE__) - build_dir = File.join(base_dir, "tmp", RUBY_PLATFORM, "bigdecimal", RUBY_VERSION, "") - else - build_dir = "$(TARGET_SO_DIR)../" - end - $libs << " #{build_dir}bigdecimal.so" - true - when /mswin/ - $DLDFLAGS << " -libpath:.." - $libs << " bigdecimal-$(arch).lib" - true - else - false - end -end - -create_makefile('bigdecimal/util') diff --git a/ext/bigdecimal/util/util.c b/ext/bigdecimal/util/util.c deleted file mode 100644 index 8d38d87852..0000000000 --- a/ext/bigdecimal/util/util.c +++ /dev/null @@ -1,9 +0,0 @@ -#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); -} diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb index 63db005588..f6ef88e3f5 100644 --- a/test/bigdecimal/test_bigdecimal.rb +++ b/test/bigdecimal/test_bigdecimal.rb @@ -77,6 +77,14 @@ class TestBigDecimal < Test::Unit::TestCase end end + def test_BigDecimal_bug7522 + bd = BigDecimal("1.12", 1) + assert_same(bd, BigDecimal(bd)) + assert_same(bd, BigDecimal(bd, exception: false)) + assert_not_same(bd, BigDecimal(bd, 1)) + assert_not_same(bd, BigDecimal(bd, 1, exception: false)) + end + def test_BigDecimal_with_invalid_string [ '', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d', @@ -222,16 +230,30 @@ class TestBigDecimal < Test::Unit::TestCase end def test_s_new - # TODO: BigDecimal.new will be removed on 1.5 - # assert_raise_with_message(NoMethodError, /undefined method `new'/) { BigDecimal.new("1") } - verbose, $VERBOSE = $VERBOSE, nil - assert_equal(BigDecimal(1), BigDecimal.new(1)) - assert_raise(ArgumentError) { BigDecimal.new(',', exception: true) } - assert_nothing_raised { assert_equal(nil, BigDecimal.new(',', exception: false)) } - assert_raise(TypeError) { BigDecimal.new(nil, exception: true) } - assert_nothing_raised { assert_equal(nil, BigDecimal.new(nil, exception: false)) } - ensure - $VERBOSE = verbose + assert_raise_with_message(NoMethodError, /undefined method `new'/) { BigDecimal.new("1") } + end + + def test_s_interpret_loosely + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1__1_1")) + assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5")) + assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5 degrees")) + assert_equal(BigDecimal('2.5e1'), BigDecimal.interpret_loosely("2.5e1 degrees")) + assert_equal(BigDecimal('0'), BigDecimal.interpret_loosely("degrees 100.0")) + assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5")) + assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5__")) + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1_.125")) + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1._125")) + assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1__2_5")) + assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1_e10")) + assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1e_10")) + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("0.1e1__0")) + assert_equal(BigDecimal('1.2'), BigDecimal.interpret_loosely("1.2.3")) + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1.")) + assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1e")) + + assert_equal(BigDecimal('0.0'), BigDecimal.interpret_loosely("invalid")) + + assert(BigDecimal.interpret_loosely("2.5").frozen?) end def _test_mode(type) @@ -1597,6 +1619,13 @@ class TestBigDecimal < Test::Unit::TestCase end end + def test_exp_with_negative + x = BigDecimal(-1) + y = BigMath.exp(x, 20) + assert_equal(y, BigMath.exp(-1, 20)) + assert_equal(BigDecimal(-1), x) + end + def test_exp_with_negative_infinite BigDecimal.save_exception_mode do BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) @@ -1833,18 +1862,9 @@ class TestBigDecimal < Test::Unit::TestCase end end - def test_dup_subclass + def test_new_subclass c = Class.new(BigDecimal) - # TODO: BigDecimal.new will be removed on 1.5 - # assert_raise_with_message(NoMethodError, /undefined method `new'/) { c.new(1) } - verbose, $VERBOSE = $VERBOSE, nil - assert_equal(BigDecimal(1), c.new(1)) - assert_raise(ArgumentError) { c.new(',', exception: true) } - assert_nothing_raised { assert_equal(nil, c.new(',', exception: false)) } - assert_raise(TypeError) { c.new(nil, exception: true) } - assert_nothing_raised { assert_equal(nil, c.new(nil, exception: false)) } - ensure - $VERBOSE = verbose + assert_raise_with_message(NoMethodError, /undefined method `new'/) { c.new(1) } end def test_to_d diff --git a/test/bigdecimal/test_bigdecimal_util.rb b/test/bigdecimal/test_bigdecimal_util.rb index bb9ed83185..b963fcdeeb 100644 --- a/test/bigdecimal/test_bigdecimal_util.rb +++ b/test/bigdecimal/test_bigdecimal_util.rb @@ -75,6 +75,8 @@ class TestBigDecimalUtil < Test::Unit::TestCase assert_equal(BigDecimal('0.1'), "0.1e_10".to_d) assert_equal(BigDecimal('1'), "0.1e1__0".to_d) assert_equal(BigDecimal('1.2'), "1.2.3".to_d) + assert_equal(BigDecimal('1'), "1.".to_d) + assert_equal(BigDecimal('1'), "1e".to_d) assert("2.5".to_d.frozen?) end -- cgit v1.2.3