APFloat: x - NaN needs to flip the signbit of NaN when x is a number.

Because we don't have a separate negate( ) function, 0 - NaN does double-duty as the IEEE-754 negate( ) operation, which (unlike most FP ops) *does* attach semantic meaning to the signbit of NaN.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210428 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Stephen Canon 2014-06-08 16:53:31 +00:00
parent c50f986b4d
commit bef256f49b
2 changed files with 27 additions and 25 deletions

View File

@ -1372,7 +1372,9 @@ APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract)
case PackCategoriesIntoKey(fcZero, fcNaN): case PackCategoriesIntoKey(fcZero, fcNaN):
case PackCategoriesIntoKey(fcNormal, fcNaN): case PackCategoriesIntoKey(fcNormal, fcNaN):
case PackCategoriesIntoKey(fcInfinity, fcNaN): case PackCategoriesIntoKey(fcInfinity, fcNaN):
sign = false; // We need to be sure to flip the sign here for subtraction because we
// don't have a separate negate operation so -NaN becomes 0 - NaN here.
sign = rhs.sign ^ subtract;
category = fcNaN; category = fcNaN;
copySignificand(rhs); copySignificand(rhs);
return opOK; return opOK;

View File

@ -1844,10 +1844,10 @@ TEST(APFloatTest, subtract) {
{ PInf, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity }, { PInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
@ -1861,10 +1861,10 @@ TEST(APFloatTest, subtract) {
{ MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
{ MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
{ MInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
{ MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
{ MInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity }, { MInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
@ -1878,10 +1878,10 @@ TEST(APFloatTest, subtract) {
{ PZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
{ PZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { PZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
{ PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ PZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
@ -1895,10 +1895,10 @@ TEST(APFloatTest, subtract) {
{ MZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ MZero, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero }, { MZero, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
{ MZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { MZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
{ MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ MZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
@ -1946,10 +1946,10 @@ TEST(APFloatTest, subtract) {
{ PNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PNormalValue, PZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PNormalValue, PZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ PNormalValue, MZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal }, { PNormalValue, MZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { PNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
{ PNormalValue, MNormalValue, "0x1p+1", APFloat::opOK, APFloat::fcNormal }, { PNormalValue, MNormalValue, "0x1p+1", APFloat::opOK, APFloat::fcNormal },
@ -1963,10 +1963,10 @@ TEST(APFloatTest, subtract) {
{ MNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ MNormalValue, PZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MNormalValue, PZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ MNormalValue, MZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal }, { MNormalValue, MZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
{ MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MNormalValue, PNormalValue, "-0x1p+1", APFloat::opOK, APFloat::fcNormal }, { MNormalValue, PNormalValue, "-0x1p+1", APFloat::opOK, APFloat::fcNormal },
{ MNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero }, { MNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
@ -1980,10 +1980,10 @@ TEST(APFloatTest, subtract) {
{ PLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PLargestValue, PZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { PLargestValue, PZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
{ PLargestValue, MZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { PLargestValue, MZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
{ PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
{ PLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { PLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
@ -1997,10 +1997,10 @@ TEST(APFloatTest, subtract) {
{ MLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ MLargestValue, PZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { MLargestValue, PZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
{ MLargestValue, MZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal }, { MLargestValue, MZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
{ MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
{ MLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal }, { MLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
@ -2014,10 +2014,10 @@ TEST(APFloatTest, subtract) {
{ PSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PSmallestValue, PZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal }, { PSmallestValue, PZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
{ PSmallestValue, MZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal }, { PSmallestValue, MZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
{ PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
{ PSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
@ -2031,10 +2031,10 @@ TEST(APFloatTest, subtract) {
{ MSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ MSmallestValue, PZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal }, { MSmallestValue, PZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
{ MSmallestValue, MZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal }, { MSmallestValue, MZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
{ MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
{ MSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
@ -2048,10 +2048,10 @@ TEST(APFloatTest, subtract) {
{ PSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { PSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ PSmallestNormalized, PZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal }, { PSmallestNormalized, PZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
{ PSmallestNormalized, MZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal }, { PSmallestNormalized, MZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
{ PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { PSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ PSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { PSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ PSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
{ PSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { PSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
@ -2065,10 +2065,10 @@ TEST(APFloatTest, subtract) {
{ MSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity }, { MSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
{ MSmallestNormalized, PZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal }, { MSmallestNormalized, PZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
{ MSmallestNormalized, MZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal }, { MSmallestNormalized, MZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
{ MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN }, { MSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
#if 0 #if 0
// See Note 1. // See Note 1.
{ MSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN }, { MSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
#endif #endif
{ MSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
{ MSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal }, { MSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },