@@ -1607,7 +1607,8 @@ IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode,
1607
1607
/* Before rounding normalize the exponent of fcNormal numbers. */
1608
1608
omsb = significandMSB () + 1 ;
1609
1609
1610
- if (omsb) {
1610
+ // Only skip this `if` if the value is exactly zero.
1611
+ if (omsb || lost_fraction != lfExactlyZero) {
1611
1612
/* OMSB is numbered from 1. We want to place it in the integer
1612
1613
bit numbered PRECISION if possible, with a compensating change in
1613
1614
the exponent. */
@@ -1782,7 +1783,7 @@ IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs,
1782
1783
/* Add or subtract two normal numbers. */
1783
1784
lostFraction IEEEFloat::addOrSubtractSignificand (const IEEEFloat &rhs,
1784
1785
bool subtract) {
1785
- integerPart carry;
1786
+ integerPart carry = 0 ;
1786
1787
lostFraction lost_fraction;
1787
1788
int bits;
1788
1789
@@ -1796,35 +1797,55 @@ lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
1796
1797
/* Subtraction is more subtle than one might naively expect. */
1797
1798
if (subtract) {
1798
1799
IEEEFloat temp_rhs (rhs);
1800
+ bool lost_fraction_is_from_rhs = false ;
1799
1801
1800
1802
if (bits == 0 )
1801
1803
lost_fraction = lfExactlyZero;
1802
1804
else if (bits > 0 ) {
1803
1805
lost_fraction = temp_rhs.shiftSignificandRight (bits - 1 );
1806
+ lost_fraction_is_from_rhs = true ;
1804
1807
shiftSignificandLeft (1 );
1805
1808
} else {
1806
1809
lost_fraction = shiftSignificandRight (-bits - 1 );
1807
1810
temp_rhs.shiftSignificandLeft (1 );
1808
1811
}
1809
1812
1810
1813
// 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);
1814
1827
copySignificand (temp_rhs);
1815
1828
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
+ }
1819
1847
}
1820
1848
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
-
1828
1849
/* The code above is intended to ensure that no borrow is
1829
1850
necessary. */
1830
1851
assert (!carry);
0 commit comments