mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 17:29:19 +00:00
Fix a bug that APFloat::fusedMultiplyAdd() mistakenly evaluate "14.5f * -14.5f + 225.0f" to 225.0f.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181715 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
151687cb8c
commit
4b6b53b0ce
@ -872,7 +872,21 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
|
||||
omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
|
||||
exponent += rhs.exponent;
|
||||
|
||||
// Assume the operands involved in the multiplication are single-precision
|
||||
// FP, and the two multiplicants are:
|
||||
// *this = a23 . a22 ... a0 * 2^e1
|
||||
// rhs = b23 . b22 ... b0 * 2^e2
|
||||
// the result of multiplication is:
|
||||
// *this = c47 c46 . c45 ... c0 * 2^(e1+e2)
|
||||
// Note that there are two significant bits at the left-hand side of the
|
||||
// radix point. Move the radix point toward left by one bit, and adjust
|
||||
// exponent accordingly.
|
||||
exponent += 1;
|
||||
|
||||
if (addend) {
|
||||
// The intermediate result of the multiplication has "2 * precision"
|
||||
// signicant bit; adjust the addend to be consistent with mul result.
|
||||
//
|
||||
Significand savedSignificand = significand;
|
||||
const fltSemantics *savedSemantics = semantics;
|
||||
fltSemantics extendedSemantics;
|
||||
@ -880,8 +894,9 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
|
||||
unsigned int extendedPrecision;
|
||||
|
||||
/* Normalize our MSB. */
|
||||
extendedPrecision = precision + precision - 1;
|
||||
extendedPrecision = 2 * precision;
|
||||
if (omsb != extendedPrecision) {
|
||||
assert(extendedPrecision > omsb);
|
||||
APInt::tcShiftLeft(fullSignificand, newPartsCount,
|
||||
extendedPrecision - omsb);
|
||||
exponent -= extendedPrecision - omsb;
|
||||
@ -912,8 +927,18 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend)
|
||||
omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1;
|
||||
}
|
||||
|
||||
exponent -= (precision - 1);
|
||||
// Convert the result having "2 * precision" significant-bits back to the one
|
||||
// having "precision" significant-bits. First, move the radix point from
|
||||
// poision "2*precision - 1" to "precision - 1". The exponent need to be
|
||||
// adjusted by "2*precision - 1" - "precision - 1" = "precision".
|
||||
exponent -= precision;
|
||||
|
||||
// In case MSB resides at the left-hand side of radix point, shift the
|
||||
// mantissa right by some amount to make sure the MSB reside right before
|
||||
// the radix point (i.e. "MSB . rest-significant-bits").
|
||||
//
|
||||
// Note that the result is not normalized when "omsb < precision". So, the
|
||||
// caller needs to call APFloat::normalize() if normalized value is expected.
|
||||
if (omsb > precision) {
|
||||
unsigned int bits, significantParts;
|
||||
lostFraction lf;
|
||||
|
@ -33,6 +33,29 @@ static std::string convertToString(double d, unsigned Prec, unsigned Pad) {
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(APFloatTest, FMA) {
|
||||
APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
|
||||
|
||||
{
|
||||
APFloat f1(14.5f);
|
||||
APFloat f2(-14.5f);
|
||||
APFloat f3(225.0f);
|
||||
f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
|
||||
EXPECT_EQ(14.75f, f1.convertToFloat());
|
||||
}
|
||||
|
||||
{
|
||||
APFloat Val2(2.0f);
|
||||
APFloat f1((float)1.17549435e-38F);
|
||||
APFloat f2((float)1.17549435e-38F);
|
||||
f1.divide(Val2, rdmd);
|
||||
f2.divide(Val2, rdmd);
|
||||
APFloat f3(12.0f);
|
||||
f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
|
||||
EXPECT_EQ(12.0f, f1.convertToFloat());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(APFloatTest, Denormal) {
|
||||
APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user