@@ -1607,7 +1607,8 @@ IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode,
16071607 /* Before rounding normalize the exponent of fcNormal numbers. */
16081608 omsb = significandMSB () + 1 ;
16091609
1610- if (omsb) {
1610+ // Only skip this `if` if the value is exactly zero.
1611+ if (omsb || lost_fraction != lfExactlyZero) {
16111612 /* OMSB is numbered from 1. We want to place it in the integer
16121613 bit numbered PRECISION if possible, with a compensating change in
16131614 the exponent. */
@@ -1782,7 +1783,7 @@ IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs,
17821783/* Add or subtract two normal numbers. */
17831784lostFraction IEEEFloat::addOrSubtractSignificand (const IEEEFloat &rhs,
17841785 bool subtract) {
1785- integerPart carry;
1786+ integerPart carry = 0 ;
17861787 lostFraction lost_fraction;
17871788 int bits;
17881789
@@ -1796,35 +1797,55 @@ lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
17961797 /* Subtraction is more subtle than one might naively expect. */
17971798 if (subtract) {
17981799 IEEEFloat temp_rhs (rhs);
1800+ bool lost_fraction_is_from_rhs = false ;
17991801
18001802 if (bits == 0 )
18011803 lost_fraction = lfExactlyZero;
18021804 else if (bits > 0 ) {
18031805 lost_fraction = temp_rhs.shiftSignificandRight (bits - 1 );
1806+ lost_fraction_is_from_rhs = true ;
18041807 shiftSignificandLeft (1 );
18051808 } else {
18061809 lost_fraction = shiftSignificandRight (-bits - 1 );
18071810 temp_rhs.shiftSignificandLeft (1 );
18081811 }
18091812
18101813 // Should we reverse the subtraction.
1811- if (compareAbsoluteValue (temp_rhs) == cmpLessThan) {
1812- carry = temp_rhs.subtractSignificand
1813- (*this , lost_fraction != lfExactlyZero);
1814+ cmpResult cmp_result = compareAbsoluteValue (temp_rhs);
1815+ if (cmp_result == cmpLessThan) {
1816+ bool borrow = false ;
1817+ if (lost_fraction != lfExactlyZero && !lost_fraction_is_from_rhs) {
1818+ // The lost fraction is being subtracted, borrow from the significand
1819+ // and invert `lost_fraction`.
1820+ borrow = true ;
1821+ if (lost_fraction == lfLessThanHalf)
1822+ lost_fraction = lfMoreThanHalf;
1823+ else if (lost_fraction == lfMoreThanHalf)
1824+ lost_fraction = lfLessThanHalf;
1825+ }
1826+ carry = temp_rhs.subtractSignificand (*this , borrow);
18141827 copySignificand (temp_rhs);
18151828 sign = !sign;
1816- } else {
1817- carry = subtractSignificand
1818- (temp_rhs, lost_fraction != lfExactlyZero);
1829+ } else if (cmp_result == cmpGreaterThan) {
1830+ bool borrow = false ;
1831+ if (lost_fraction != lfExactlyZero && lost_fraction_is_from_rhs) {
1832+ // The lost fraction is being subtracted, borrow from the significand
1833+ // and invert `lost_fraction`.
1834+ borrow = true ;
1835+ if (lost_fraction == lfLessThanHalf)
1836+ lost_fraction = lfMoreThanHalf;
1837+ else if (lost_fraction == lfMoreThanHalf)
1838+ lost_fraction = lfLessThanHalf;
1839+ }
1840+ carry = subtractSignificand (temp_rhs, borrow);
1841+ } else { // cmpEqual
1842+ zeroSignificand ();
1843+ if (lost_fraction != lfExactlyZero && lost_fraction_is_from_rhs) {
1844+ // rhs is slightly larger due to the lost fraction, flip the sign.
1845+ sign = !sign;
1846+ }
18191847 }
18201848
1821- /* Invert the lost fraction - it was on the RHS and
1822- subtracted. */
1823- if (lost_fraction == lfLessThanHalf)
1824- lost_fraction = lfMoreThanHalf;
1825- else if (lost_fraction == lfMoreThanHalf)
1826- lost_fraction = lfLessThanHalf;
1827-
18281849 /* The code above is intended to ensure that no borrow is
18291850 necessary. */
18301851 assert (!carry);
0 commit comments