diff --git a/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java b/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java index 4ed1840aa58..d4a28469171 100644 --- a/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java +++ b/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java @@ -110,7 +110,7 @@ public class RubyBigDecimal extends RubyNumeric { @JRubyConstant public final static int EXCEPTION_ALL = 255; - private static final ByteList VERSION = ByteList.create("1.3.4"); + private static final ByteList VERSION = ByteList.create("3.1.4"); // (MRI-like) internals @@ -1027,7 +1027,8 @@ public IRubyObject remainder19(ThreadContext context, IRubyObject arg) { private IRubyObject remainderInternal(ThreadContext context, RubyBigDecimal val, IRubyObject arg) { if (isInfinity() || isNaN()) return getNaN(context.runtime); if (val == null) return callCoerced(context, sites(context).remainder, arg, true); - if (val.isInfinity() || val.isNaN() || val.isZero()) return getNaN(context.runtime); + if (val.isInfinity()) return this; + if (val.isNaN() || val.isZero()) return getNaN(context.runtime); // Java and MRI definitions of remainder are the same. return new RubyBigDecimal(context.runtime, value.remainder(val.value)).setResult(); @@ -2113,7 +2114,12 @@ private static RoundingMode javaRoundingModeFromRubyRoundingMode(ThreadContext c if (opts != context.nil) { arg = ArgsUtil.extractKeywordArg(context, (RubyHash) opts, "half"); if (arg == null || arg == context.nil) return getRoundingMode(context.runtime); - String roundingMode = arg.asJavaString(); + String roundingMode; + if (arg instanceof RubySymbol) { + roundingMode = arg.asJavaString(); + } else { + roundingMode = arg.toString(); + } switch (roundingMode) { case "up": return RoundingMode.HALF_UP; @@ -2122,7 +2128,7 @@ private static RoundingMode javaRoundingModeFromRubyRoundingMode(ThreadContext c case "even" : return RoundingMode.HALF_EVEN; default : - throw context.runtime.newArgumentError("invalid rounding mode: " + roundingMode); + throw context.runtime.newArgumentError("invalid rounding mode (" + roundingMode + ")"); } } if (arg instanceof RubySymbol) { @@ -2148,7 +2154,7 @@ private static RoundingMode javaRoundingModeFromRubyRoundingMode(ThreadContext c case "floor" : return RoundingMode.FLOOR; default : - throw context.runtime.newArgumentError("invalid rounding mode: " + roundingMode); + throw context.runtime.newArgumentError("invalid rounding mode (" + roundingMode + ")"); } } else { int ordinal = num2int(arg); diff --git a/spec/tags/ruby/library/bigdecimal/BigDecimal_tags.txt b/spec/tags/ruby/library/bigdecimal/BigDecimal_tags.txt index 1e25d8ef340..968d1c4de51 100644 --- a/spec/tags/ruby/library/bigdecimal/BigDecimal_tags.txt +++ b/spec/tags/ruby/library/bigdecimal/BigDecimal_tags.txt @@ -3,5 +3,4 @@ fails:Kernel#BigDecimal when interacting with Rational has the expected maximum fails:Kernel#BigDecimal when interacting with Rational BigDecimal precision is the number of digits rounded up to a multiple of nine fails:Kernel#BigDecimal when interacting with Rational BigDecimal maximum precision is nine more than precision except for abnormals fails:Kernel#BigDecimal when interacting with Rational BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect -fails:Kernel#BigDecimal when interacting with Rational produces the expected result fails:Kernel#BigDecimal with exception: false returns nil for invalid strings diff --git a/spec/tags/ruby/library/bigdecimal/round_tags.txt b/spec/tags/ruby/library/bigdecimal/round_tags.txt deleted file mode 100644 index b1b94811730..00000000000 --- a/spec/tags/ruby/library/bigdecimal/round_tags.txt +++ /dev/null @@ -1 +0,0 @@ -fails:BigDecimal#round raise for a non-existent round mode diff --git a/test/mri/bigdecimal/test_bigdecimal.rb b/test/mri/bigdecimal/test_bigdecimal.rb index 825d7ec93f8..2fc22d224f6 100644 --- a/test/mri/bigdecimal/test_bigdecimal.rb +++ b/test/mri/bigdecimal/test_bigdecimal.rb @@ -294,7 +294,11 @@ def test_s_ver end def test_s_allocate - assert_raise_with_message(TypeError, /allocator undefined for BigDecimal/) { BigDecimal.allocate } + if RUBY_ENGINE == "truffleruby" + assert_raise_with_message(NoMethodError, /undefined.+allocate.+for BigDecimal/) { BigDecimal.allocate } + else + assert_raise_with_message(TypeError, /allocator undefined for BigDecimal/) { BigDecimal.allocate } + end end def test_s_new @@ -973,7 +977,14 @@ def test_div assert_raise_with_message(FloatDomainError, "Computation results in '-Infinity'") { BigDecimal("-1") / 0 } end - def test_dev_precision + def test_div_gh220 + x = BigDecimal("1.0") + y = BigDecimal("3672577333.6608990499165058135986328125") + c = BigDecimal("0.272288343892592687909520102748926752911779209181321744700032723729015151607289998e-9") + assert_equal(c, x / y, "[GH-220]") + end + + def test_div_precision bug13754 = '[ruby-core:82107] [Bug #13754]' a = BigDecimal('101') b = BigDecimal('0.9163472602589686') @@ -1363,8 +1374,18 @@ def test_round_half_nil end def test_round_half_invalid_option - assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('12.5').round(half: :invalid) } - assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('2.15').round(1, half: :invalid) } + assert_raise_with_message(ArgumentError, "invalid rounding mode (upp)") do + BigDecimal('12.5').round(half: :upp) + end + assert_raise_with_message(ArgumentError, "invalid rounding mode (evenn)") do + BigDecimal('2.15').round(1, half: :evenn) + end + assert_raise_with_message(ArgumentError, "invalid rounding mode (downn)") do + BigDecimal('2.15').round(1, half: :downn) + end + assert_raise_with_message(ArgumentError, "invalid rounding mode (42)") do + BigDecimal('2.15').round(1, half: 42) + end end def test_truncate @@ -2239,6 +2260,17 @@ def test_llong_min_gh_200 assert_equal(BigDecimal(minus_ullong_max.to_s), BigDecimal(minus_ullong_max), "[GH-200]") end + def test_reminder_infinity_gh_187 + # https://github.com/ruby/bigdecimal/issues/187 + BigDecimal.save_exception_mode do + BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) + BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) + bd = BigDecimal("4.2") + assert_equal(bd.remainder(BigDecimal("+Infinity")), bd) + assert_equal(bd.remainder(BigDecimal("-Infinity")), bd) + end + end + def assert_no_memory_leak(code, *rest, **opt) code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}" super(["-rbigdecimal"], diff --git a/test/mri/excludes/TestBigDecimal.rb b/test/mri/excludes/TestBigDecimal.rb index 640d56f7782..c414705a126 100644 --- a/test/mri/excludes/TestBigDecimal.rb +++ b/test/mri/excludes/TestBigDecimal.rb @@ -6,3 +6,4 @@ exclude :test_thread_local_mode, "needs investigation" exclude :"test_new_subclass", "work in progress" exclude :"test_s_new", "work in progress" +exclude :test_div_gh220, "needs investigation"