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

Import changes from ruby/bigdecimal (#2531)

Sync to ruby/bigdecimal@92356ba71c
This commit is contained in:
Kenta Murata 2019-10-08 09:06:28 +09:00 committed by GitHub
parent 59c3b1c9c8
commit dd0c75fdc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2019-10-08 09:06:54 +09:00
Merged-By: mrkn <mrkn@ruby-lang.org>
11 changed files with 93 additions and 98 deletions

View file

@ -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) {

View file

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

View file

@ -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

View file

@ -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")

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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')

View file

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

View file

@ -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

View file

@ -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