Skip to content

Commit 30d7f8d

Browse files
committed
Fix divmod and modulo by infinity to match Float#divmod and Float#modulo
1 parent 07696bc commit 30d7f8d

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

ext/bigdecimal/bigdecimal.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,17 +1733,25 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, NULLABLE_BDVALUE *div, NULLABLE_BDVALUE
17331733
*mod = (NULLABLE_BDVALUE) { nan, DATA_PTR(nan) };
17341734
goto Done;
17351735
}
1736-
if (VpIsInf(b.real)) {
1737-
VALUE zero = BigDecimal_positive_zero();
1738-
*div = (NULLABLE_BDVALUE) { zero, DATA_PTR(zero) };
1739-
*mod = bdvalue_nullable(a);
1740-
goto Done;
1741-
}
17421736
if (VpIsZero(a.real)) {
17431737
VALUE zero = BigDecimal_positive_zero();
17441738
*div = *mod = (NULLABLE_BDVALUE) { zero, DATA_PTR(zero) };
17451739
goto Done;
17461740
}
1741+
if (VpIsInf(b.real)) {
1742+
if (!truncate && VpGetSign(a.real) * VpGetSign(b.real) < 0) {
1743+
BDVALUE minus_one = NewZeroWrap(1, BASE_FIG);
1744+
VpSetOne(minus_one.real);
1745+
VpSetSign(minus_one.real, -1);
1746+
*div = bdvalue_nullable(minus_one);
1747+
*mod = bdvalue_nullable(b);
1748+
} else {
1749+
VALUE zero = BigDecimal_positive_zero();
1750+
*div = (NULLABLE_BDVALUE) { zero, DATA_PTR(zero) };
1751+
*mod = bdvalue_nullable(a);
1752+
}
1753+
goto Done;
1754+
}
17471755

17481756
a_exponent = VpExponent10(a.real);
17491757
b_exponent = VpExponent10(b.real);

test/bigdecimal/test_bigdecimal.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,14 +2697,22 @@ def test_llong_min_gh_200
26972697
assert_equal(BigDecimal(minus_ullong_max.to_s), BigDecimal(minus_ullong_max), "[GH-200]")
26982698
end
26992699

2700-
def test_reminder_infinity_gh_187
2701-
# https://github.com/ruby/bigdecimal/issues/187
2700+
def test_divmod_modulo_remainder_infinity
27022701
BigDecimal.save_exception_mode do
27032702
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
27042703
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
2705-
bd = BigDecimal("4.2")
2706-
assert_equal(bd.remainder(BigDecimal("+Infinity")), bd)
2707-
assert_equal(bd.remainder(BigDecimal("-Infinity")), bd)
2704+
pinf = BigDecimal("+Infinity")
2705+
minf = BigDecimal("-Infinity")
2706+
assert_nan(pinf.modulo(pinf))
2707+
assert_nan(pinf.remainder(pinf))
2708+
[BigDecimal("-4.2"), BigDecimal(0), BigDecimal("4.2")].each do |x|
2709+
assert_equal(x.to_f.divmod(pinf.to_f), x.divmod(pinf))
2710+
assert_equal(x.to_f.divmod(minf.to_f), x.divmod(minf))
2711+
assert_equal(x.to_f.modulo(pinf.to_f), x.modulo(pinf))
2712+
assert_equal(x.to_f.modulo(minf.to_f), x.modulo(minf))
2713+
assert_equal(x.to_f.remainder(pinf.to_f), x.remainder(pinf))
2714+
assert_equal(x.to_f.remainder(minf.to_f), x.remainder(minf))
2715+
end
27082716
end
27092717
end
27102718

0 commit comments

Comments
 (0)