Skip to content

Commit 7902239

Browse files
committed
Fix div and mult sign when result overflows or underflows
1 parent 1ee52bb commit 7902239

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

ext/bigdecimal/bigdecimal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5996,11 +5996,11 @@ VpMult(Real *c, Real *a, Real *b)
59965996
/* set LHSV c info */
59975997

59985998
c->exponent = a->exponent; /* set exponent */
5999+
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
59996000
if (!AddExponent(c, b->exponent)) {
60006001
if (w) rbd_free_struct(c);
60016002
return 0;
60026003
}
6003-
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
60046004
carry = 0;
60056005
nc = ind_c = MxIndAB;
60066006
memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
@@ -6247,10 +6247,10 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
62476247
out_side:
62486248
c->Prec = word_c;
62496249
c->exponent = a->exponent;
6250+
VpSetSign(c, VpGetSign(a) * VpGetSign(b));
62506251
if (!AddExponent(c, 2)) return 0;
62516252
if (!AddExponent(c, -(b->exponent))) return 0;
62526253

6253-
VpSetSign(c, VpGetSign(a) * VpGetSign(b));
62546254
VpNmlz(c); /* normalize c */
62556255
r->Prec = word_r;
62566256
r->exponent = a->exponent;

test/bigdecimal/test_bigdecimal.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,45 @@ def test_exception_overflow
460460
end
461461
end
462462

463+
def test_mult_div_overflow_underflow_sign
464+
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
465+
BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false)
466+
467+
large_x = BigDecimal("10")
468+
100.times do
469+
x2 = large_x * large_x
470+
break if x2.infinite?
471+
large_x = x2
472+
end
473+
474+
small_x = BigDecimal("0.1")
475+
100.times do
476+
x2 = small_x * small_x
477+
break if x2.zero?
478+
small_x = x2
479+
end
480+
481+
assert_positive_infinite(large_x * large_x)
482+
assert_negative_infinite(large_x * (-large_x))
483+
assert_negative_infinite((-large_x) * large_x)
484+
assert_positive_infinite((-large_x) * (-large_x))
485+
486+
assert_positive_zero(small_x * small_x)
487+
assert_negative_zero(small_x * (-small_x))
488+
assert_negative_zero((-small_x) * small_x)
489+
assert_positive_zero((-small_x) * (-small_x))
490+
491+
assert_positive_infinite(large_x.div(small_x, 10))
492+
assert_negative_infinite(large_x.div(-small_x, 10))
493+
assert_negative_infinite((-large_x).div(small_x, 10))
494+
assert_positive_infinite((-large_x).div(-small_x, 10))
495+
496+
assert_positive_zero(small_x.div(large_x, 10))
497+
assert_negative_zero(small_x.div(-large_x, 10))
498+
assert_negative_zero((-small_x).div(large_x, 10))
499+
assert_positive_zero((-small_x).div(-large_x, 10))
500+
end
501+
463502
def test_exception_zerodivide
464503
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
465504
_test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal("0") }

0 commit comments

Comments
 (0)