[llvm] 9d0956e - [APFloat] Fix FP remainder operation
Ehud Katz via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 12 00:44:54 PST 2020
Author: Ehud Katz
Date: 2020-02-12T10:42:55+02:00
New Revision: 9d0956ebd47144a8e8ada237aeb4d2e5118422b6
URL: https://github.com/llvm/llvm-project/commit/9d0956ebd47144a8e8ada237aeb4d2e5118422b6
DIFF: https://github.com/llvm/llvm-project/commit/9d0956ebd47144a8e8ada237aeb4d2e5118422b6.diff
LOG: [APFloat] Fix FP remainder operation
Reimplement IEEEFloat::remainder() function.
Fix PR3359.
Differential Revision: https://reviews.llvm.org/D69776
Added:
Modified:
llvm/include/llvm/ADT/APFloat.h
llvm/lib/Support/APFloat.cpp
llvm/unittests/ADT/APFloatTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 0b744267a9ad..ce8fd6536b4b 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -511,6 +511,7 @@ class IEEEFloat final : public APFloatBase {
opStatus divideSpecials(const IEEEFloat &);
opStatus multiplySpecials(const IEEEFloat &);
opStatus modSpecials(const IEEEFloat &);
+ opStatus remainderSpecials(const IEEEFloat&);
/// @}
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 03f0bb1f705e..54f8f8e4bfdb 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -1686,6 +1686,44 @@ IEEEFloat::opStatus IEEEFloat::modSpecials(const IEEEFloat &rhs) {
}
}
+IEEEFloat::opStatus IEEEFloat::remainderSpecials(const IEEEFloat &rhs) {
+ switch (PackCategoriesIntoKey(category, rhs.category)) {
+ default:
+ llvm_unreachable(nullptr);
+
+ case PackCategoriesIntoKey(fcZero, fcNaN):
+ case PackCategoriesIntoKey(fcNormal, fcNaN):
+ case PackCategoriesIntoKey(fcInfinity, fcNaN):
+ assign(rhs);
+ LLVM_FALLTHROUGH;
+ case PackCategoriesIntoKey(fcNaN, fcZero):
+ case PackCategoriesIntoKey(fcNaN, fcNormal):
+ case PackCategoriesIntoKey(fcNaN, fcInfinity):
+ case PackCategoriesIntoKey(fcNaN, fcNaN):
+ if (isSignaling()) {
+ makeQuiet();
+ return opInvalidOp;
+ }
+ return rhs.isSignaling() ? opInvalidOp : opOK;
+
+ case PackCategoriesIntoKey(fcZero, fcInfinity):
+ case PackCategoriesIntoKey(fcZero, fcNormal):
+ case PackCategoriesIntoKey(fcNormal, fcInfinity):
+ return opOK;
+
+ case PackCategoriesIntoKey(fcNormal, fcZero):
+ case PackCategoriesIntoKey(fcInfinity, fcZero):
+ case PackCategoriesIntoKey(fcInfinity, fcNormal):
+ case PackCategoriesIntoKey(fcInfinity, fcInfinity):
+ case PackCategoriesIntoKey(fcZero, fcZero):
+ makeNaN();
+ return opInvalidOp;
+
+ case PackCategoriesIntoKey(fcNormal, fcNormal):
+ return opDivByZero; // fake status, indicating this is not a special case
+ }
+}
+
/* Change sign. */
void IEEEFloat::changeSign() {
/* Look mummy, this one's easy. */
@@ -1770,40 +1808,108 @@ IEEEFloat::opStatus IEEEFloat::divide(const IEEEFloat &rhs,
return fs;
}
-/* Normalized remainder. This is not currently correct in all cases. */
+/* Normalized remainder. */
IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) {
opStatus fs;
- IEEEFloat V = *this;
unsigned int origSign = sign;
- fs = V.divide(rhs, rmNearestTiesToEven);
- if (fs == opDivByZero)
+ // First handle the special cases.
+ fs = remainderSpecials(rhs);
+ if (fs != opDivByZero)
return fs;
- int parts = partCount();
- integerPart *x = new integerPart[parts];
- bool ignored;
- fs = V.convertToInteger(makeMutableArrayRef(x, parts),
- parts * integerPartWidth, true, rmNearestTiesToEven,
- &ignored);
- if (fs == opInvalidOp) {
- delete[] x;
- return fs;
+ fs = opOK;
+
+ // Make sure the current value is less than twice the denom. If the addition
+ // did not succeed (an overflow has happened), which means that the finite
+ // value we currently posses must be less than twice the denom (as we are
+ // using the same semantics).
+ IEEEFloat P2 = rhs;
+ if (P2.add(rhs, rmNearestTiesToEven) == opOK) {
+ fs = mod(P2);
+ assert(fs == opOK);
}
- fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
- rmNearestTiesToEven);
- assert(fs==opOK); // should always work
+ // Lets work with absolute numbers.
+ IEEEFloat P = rhs;
+ P.sign = false;
+ sign = false;
- fs = V.multiply(rhs, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // should not overflow or underflow
+ //
+ // To calculate the remainder we use the following scheme.
+ //
+ // The remainder is defained as follows:
+ //
+ // remainder = numer - rquot * denom = x - r * p
+ //
+ // Where r is the result of: x/p, rounded toward the nearest integral value
+ // (with halfway cases rounded toward the even number).
+ //
+ // Currently, (after x mod 2p):
+ // r is the number of 2p's present inside x, which is inherently, an even
+ // number of p's.
+ //
+ // We may split the remaining calculation into 4 options:
+ // - if x < 0.5p then we round to the nearest number with is 0, and are done.
+ // - if x == 0.5p then we round to the nearest even number which is 0, and we
+ // are done as well.
+ // - if 0.5p < x < p then we round to nearest number which is 1, and we have
+ // to subtract 1p at least once.
+ // - if x >= p then we must subtract p at least once, as x must be a
+ // remainder.
+ //
+ // By now, we were done, or we added 1 to r, which in turn, now an odd number.
+ //
+ // We can now split the remaining calculation to the following 3 options:
+ // - if x < 0.5p then we round to the nearest number with is 0, and are done.
+ // - if x == 0.5p then we round to the nearest even number. As r is odd, we
+ // must round up to the next even number. so we must subtract p once more.
+ // - if x > 0.5p (and inherently x < p) then we must round r up to the next
+ // integral, and subtract p once more.
+ //
+
+ // Extend the semantics to prevent an overflow/underflow or inexact result.
+ bool losesInfo;
+ fltSemantics extendedSemantics = *semantics;
+ extendedSemantics.maxExponent++;
+ extendedSemantics.minExponent--;
+ extendedSemantics.precision += 2;
- fs = subtract(V, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // likewise
+ IEEEFloat VEx = *this;
+ fs = VEx.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
+ assert(fs == opOK && !losesInfo);
+ IEEEFloat PEx = P;
+ fs = PEx.convert(extendedSemantics, rmNearestTiesToEven, &losesInfo);
+ assert(fs == opOK && !losesInfo);
+
+ // It is simpler to work with 2x instead of 0.5p, and we do not need to lose
+ // any fraction.
+ fs = VEx.add(VEx, rmNearestTiesToEven);
+ assert(fs == opOK);
+
+ if (VEx.compare(PEx) == cmpGreaterThan) {
+ fs = subtract(P, rmNearestTiesToEven);
+ assert(fs == opOK);
+
+ // Make VEx = this.add(this), but because we have
diff erent semantics, we do
+ // not want to `convert` again, so we just subtract PEx twice (which equals
+ // to the desired value).
+ fs = VEx.subtract(PEx, rmNearestTiesToEven);
+ assert(fs == opOK);
+ fs = VEx.subtract(PEx, rmNearestTiesToEven);
+ assert(fs == opOK);
+
+ cmpResult result = VEx.compare(PEx);
+ if (result == cmpGreaterThan || result == cmpEqual) {
+ fs = subtract(P, rmNearestTiesToEven);
+ assert(fs == opOK);
+ }
+ }
if (isZero())
sign = origSign; // IEEE754 requires this
- delete[] x;
+ else
+ sign ^= origSign;
return fs;
}
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index e571e04614ae..6822161729b2 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -3410,6 +3410,444 @@ TEST(APFloatTest, mod) {
}
}
+TEST(APFloatTest, remainder) {
+ // Test Special Cases against each other and normal values.
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat SNaN = APFloat(APFloat::IEEEsingle(), "snan123");
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ APFloat PVal1(APFloat::IEEEsingle(), "0x1.fffffep+126");
+ APFloat MVal1(APFloat::IEEEsingle(), "-0x1.fffffep+126");
+ APFloat PVal2(APFloat::IEEEsingle(), "0x1.fffffep-126");
+ APFloat MVal2(APFloat::IEEEsingle(), "-0x1.fffffep-126");
+ APFloat PVal3(APFloat::IEEEsingle(), "0x1p-125");
+ APFloat MVal3(APFloat::IEEEsingle(), "-0x1p-125");
+ APFloat PVal4(APFloat::IEEEsingle(), "0x1p+127");
+ APFloat MVal4(APFloat::IEEEsingle(), "-0x1p+127");
+ APFloat PVal5(APFloat::IEEEsingle(), "1.5");
+ APFloat MVal5(APFloat::IEEEsingle(), "-1.5");
+ APFloat PVal6(APFloat::IEEEsingle(), "1");
+ APFloat MVal6(APFloat::IEEEsingle(), "-1");
+
+ struct {
+ APFloat x;
+ APFloat y;
+ const char *result;
+ int status;
+ int category;
+ } SpecialCaseTests[] = {
+ { PInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PInf, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MInf, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PZero, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MZero, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, PNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { QNaN, PInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { QNaN, PNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { SNaN, PInf, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MInf, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PZero, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MZero, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, QNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PNormalValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MNormalValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PLargestValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MLargestValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestValue, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestNormalized, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestNormalized, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PNormalValue, PInf, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MInf, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PNormalValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PNormalValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, PLargestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MLargestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, PInf, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MInf, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MNormalValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MNormalValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MNormalValue, PNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, PLargestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MLargestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PInf, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MInf, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PLargestValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PLargestValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PLargestValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PInf, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MInf, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MLargestValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MLargestValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MLargestValue, PNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, PInf, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MInf, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PSmallestValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestValue, PNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PLargestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MLargestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, PSmallestNormalized, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestNormalized, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PInf, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MInf, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestValue, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MSmallestValue, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestValue, PNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PLargestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MLargestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, PSmallestNormalized, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestNormalized, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PInf, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MInf, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestNormalized, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { PSmallestNormalized, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PSmallestNormalized, PNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PLargestValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MLargestValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, PInf, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MInf, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestNormalized, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+ { MSmallestNormalized, SNaN, "nan123", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MSmallestNormalized, PNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PLargestValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MLargestValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+
+ { PVal1, PVal1, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, MVal1, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, PVal2, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, MVal2, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, PVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, MVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, PVal4, "-0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { PVal1, MVal4, "-0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { PVal1, PVal5, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, MVal5, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, PVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal1, MVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, PVal1, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, MVal1, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, PVal2, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, MVal2, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, PVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, MVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, PVal4, "0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { MVal1, MVal4, "0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { MVal1, PVal5, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, MVal5, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, PVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal1, MVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal2, PVal1, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, MVal1, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, PVal2, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal2, MVal2, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal2, PVal3, "-0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, MVal3, "-0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, PVal4, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, MVal4, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, PVal5, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, MVal5, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, PVal6, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal2, MVal6, "0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, PVal1, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, MVal1, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, PVal2, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal2, MVal2, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal2, PVal3, "0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, MVal3, "0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, PVal4, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, MVal4, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, PVal5, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, MVal5, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, PVal6, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal2, MVal6, "-0x1.fffffep-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, PVal1, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, MVal1, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, PVal2, "0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, MVal2, "0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, PVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal3, MVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal3, PVal4, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, MVal4, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, PVal5, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, MVal5, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, PVal6, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal3, MVal6, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, PVal1, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, MVal1, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, PVal2, "-0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, MVal2, "-0x0.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, PVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal3, MVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal3, PVal4, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, MVal4, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, PVal5, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, MVal5, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, PVal6, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MVal3, MVal6, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, PVal1, "0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, MVal1, "0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, PVal2, "0x0.002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, MVal2, "0x0.002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, PVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal4, MVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal4, PVal4, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal4, MVal4, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal4, PVal5, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, MVal5, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal4, PVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal4, MVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, PVal1, "-0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, MVal1, "-0x1p+103", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, PVal2, "-0x0.002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, MVal2, "-0x0.002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, PVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, MVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, PVal4, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, MVal4, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, PVal5, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, MVal5, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal4, PVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal4, MVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal5, PVal1, "1.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, MVal1, "1.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, PVal2, "0x0.00006p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, MVal2, "0x0.00006p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, PVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal5, MVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal5, PVal4, "1.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, MVal4, "1.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, PVal5, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal5, MVal5, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal5, PVal6, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal5, MVal6, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, PVal1, "-1.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, MVal1, "-1.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, PVal2, "-0x0.00006p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, MVal2, "-0x0.00006p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, PVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal5, MVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal5, PVal4, "-1.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, MVal4, "-1.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, PVal5, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal5, MVal5, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal5, PVal6, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal5, MVal6, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, PVal1, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, MVal1, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, PVal2, "0x0.00004p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, MVal2, "0x0.00004p-126", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, PVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal6, MVal3, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal6, PVal4, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, MVal4, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, PVal5, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, MVal5, "-0.5", APFloat::opOK, APFloat::fcNormal },
+ { PVal6, PVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PVal6, MVal6, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal6, PVal1, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, MVal1, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, PVal2, "-0x0.00004p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, MVal2, "-0x0.00004p-126", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, PVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal6, MVal3, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal6, PVal4, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, MVal4, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, PVal5, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, MVal5, "0.5", APFloat::opOK, APFloat::fcNormal },
+ { MVal6, PVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MVal6, MVal6, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ };
+
+ for (size_t i = 0; i < array_lengthof(SpecialCaseTests); ++i) {
+ APFloat x(SpecialCaseTests[i].x);
+ APFloat y(SpecialCaseTests[i].y);
+ APFloat::opStatus status = x.remainder(y);
+
+ APFloat result(x.getSemantics(), SpecialCaseTests[i].result);
+
+ EXPECT_TRUE(result.bitwiseIsEqual(x));
+ EXPECT_EQ(SpecialCaseTests[i].status, (int)status);
+ EXPECT_EQ(SpecialCaseTests[i].category, (int)x.getCategory());
+ }
+
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1.3333333333333p-2"); // 0.3
+ APFloat f2(APFloat::IEEEdouble(), "0x1.47ae147ae147bp-7"); // 0.01
+ APFloat expected(APFloat::IEEEdouble(), "-0x1.4p-56");
+ EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1p64"); // 1.8446744073709552e19
+ APFloat f2(APFloat::IEEEdouble(), "1.5");
+ APFloat expected(APFloat::IEEEdouble(), "-0.5");
+ EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1p1000");
+ APFloat f2(APFloat::IEEEdouble(), "0x1p-1000");
+ APFloat expected(APFloat::IEEEdouble(), "0.0");
+ EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1 = APFloat::getInf(APFloat::IEEEdouble(), false);
+ APFloat f2(APFloat::IEEEdouble(), "1.0");
+ EXPECT_EQ(f1.remainder(f2), APFloat::opInvalidOp);
+ EXPECT_TRUE(f1.isNaN());
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "-4.0");
+ APFloat f2(APFloat::IEEEdouble(), "-2.0");
+ APFloat expected(APFloat::IEEEdouble(), "-0.0");
+ EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "-4.0");
+ APFloat f2(APFloat::IEEEdouble(), "2.0");
+ APFloat expected(APFloat::IEEEdouble(), "-0.0");
+ EXPECT_EQ(APFloat::opOK, f1.remainder(f2));
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+}
+
TEST(APFloatTest, PPCDoubleDoubleAddSpecial) {
using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
APFloat::fltCategory, APFloat::roundingMode>;
More information about the llvm-commits
mailing list