/// magnitude in the current semantics.
bool isSmallest() const;
+ /// Returns true if this is the smallest (by magnitude) normalized finite
+ /// number in the given semantics.
+ bool isSmallestNormalized() const;
+
/// Returns true if and only if the number has the largest possible finite
/// magnitude in the current semantics.
bool isLargest() const;
bool isSignificandAllOnesExceptLSB() const;
/// Return true if the significand excluding the integral bit is all zeros.
bool isSignificandAllZeros() const;
+ bool isSignificandAllZerosExceptMSB() const;
/// @}
bool isDenormal() const;
bool isSmallest() const;
+ bool isSmallestNormalized() const;
bool isLargest() const;
bool isInteger() const;
bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); }
bool isIEEE() const { return usesLayout<IEEEFloat>(getSemantics()); }
+ bool isSmallestNormalized() const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(isSmallestNormalized());
+ }
+
APFloat &operator=(const APFloat &RHS) = default;
APFloat &operator=(APFloat &&RHS) = default;
significandMSB() == 0;
}
+bool IEEEFloat::isSmallestNormalized() const {
+ return getCategory() == fcNormal && exponent == semantics->minExponent &&
+ isSignificandAllZerosExceptMSB();
+}
+
bool IEEEFloat::isSignificandAllOnes() const {
// Test if the significand excluding the integral bit is all ones. This allows
// us to test for binade boundaries.
return true;
}
+bool IEEEFloat::isSignificandAllZerosExceptMSB() const {
+ const integerPart *Parts = significandParts();
+ const unsigned PartCount = partCountForBits(semantics->precision);
+
+ for (unsigned i = 0; i < PartCount - 1; i++) {
+ if (Parts[i])
+ return false;
+ }
+
+ const unsigned NumHighBits =
+ PartCount * integerPartWidth - semantics->precision + 1;
+ return Parts[PartCount - 1] == integerPart(1)
+ << (integerPartWidth - NumHighBits);
+}
+
bool IEEEFloat::isLargest() const {
if (semantics->nonFiniteBehavior == fltNonfiniteBehavior::NanOnly) {
// The largest number by magnitude in our format will be the floating point
return Tmp.compare(*this) == cmpEqual;
}
+bool DoubleAPFloat::isSmallestNormalized() const {
+ if (getCategory() != fcNormal)
+ return false;
+
+ DoubleAPFloat Tmp(*this);
+ Tmp.makeSmallestNormalized(this->isNegative());
+ return Tmp.compare(*this) == cmpEqual;
+}
+
bool DoubleAPFloat::isLargest() const {
if (getCategory() != fcNormal)
return false;
}
}
+TEST(APFloatTest, IsSmallestNormalized) {
+ for (unsigned I = 0; I != APFloat::S_MaxSemantics + 1; ++I) {
+ const fltSemantics &Semantics =
+ APFloat::EnumToSemantics(static_cast<APFloat::Semantics>(I));
+
+ EXPECT_FALSE(APFloat::getZero(Semantics, false).isSmallestNormalized());
+ EXPECT_FALSE(APFloat::getZero(Semantics, true).isSmallestNormalized());
+
+ EXPECT_FALSE(APFloat::getInf(Semantics, false).isSmallestNormalized());
+ EXPECT_FALSE(APFloat::getInf(Semantics, true).isSmallestNormalized());
+
+ EXPECT_FALSE(APFloat::getQNaN(Semantics).isSmallestNormalized());
+ EXPECT_FALSE(APFloat::getSNaN(Semantics).isSmallestNormalized());
+
+ EXPECT_FALSE(APFloat::getLargest(Semantics).isSmallestNormalized());
+ EXPECT_FALSE(APFloat::getLargest(Semantics, true).isSmallestNormalized());
+
+ EXPECT_FALSE(APFloat::getSmallest(Semantics).isSmallestNormalized());
+ EXPECT_FALSE(APFloat::getSmallest(Semantics, true).isSmallestNormalized());
+
+ EXPECT_FALSE(APFloat::getAllOnesValue(Semantics).isSmallestNormalized());
+
+ APFloat PosSmallestNormalized =
+ APFloat::getSmallestNormalized(Semantics, false);
+ APFloat NegSmallestNormalized =
+ APFloat::getSmallestNormalized(Semantics, true);
+ EXPECT_TRUE(PosSmallestNormalized.isSmallestNormalized());
+ EXPECT_TRUE(NegSmallestNormalized.isSmallestNormalized());
+
+ for (APFloat *Val : {&PosSmallestNormalized, &NegSmallestNormalized}) {
+ bool OldSign = Val->isNegative();
+
+ // Step down, make sure it's still not smallest normalized.
+ EXPECT_EQ(APFloat::opOK, Val->next(false));
+ EXPECT_EQ(OldSign, Val->isNegative());
+ EXPECT_FALSE(Val->isSmallestNormalized());
+ EXPECT_EQ(OldSign, Val->isNegative());
+
+ // Step back up should restore it to being smallest normalized.
+ EXPECT_EQ(APFloat::opOK, Val->next(true));
+ EXPECT_TRUE(Val->isSmallestNormalized());
+ EXPECT_EQ(OldSign, Val->isNegative());
+
+ // Step beyond should no longer smallest normalized.
+ EXPECT_EQ(APFloat::opOK, Val->next(true));
+ EXPECT_FALSE(Val->isSmallestNormalized());
+ EXPECT_EQ(OldSign, Val->isNegative());
+ }
+ }
+}
+
TEST(APFloatTest, Zero) {
EXPECT_EQ(0.0f, APFloat(0.0f).convertToFloat());
EXPECT_EQ(-0.0f, APFloat(-0.0f).convertToFloat());
EXPECT_TRUE(test.isFiniteNonZero());
EXPECT_FALSE(test.isDenormal());
EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
test = APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
expected = APFloat(APFloat::IEEEsingle(), "-0x1p-126");
EXPECT_TRUE(test.isFiniteNonZero());
EXPECT_FALSE(test.isDenormal());
EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
+
+ test = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false);
+ expected = APFloat(APFloat::IEEEdouble(), "0x1p-1022");
+ EXPECT_FALSE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
+
+ test = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true);
+ expected = APFloat(APFloat::IEEEdouble(), "-0x1p-1022");
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), false);
expected = APFloat(APFloat::IEEEquad(), "0x1p-16382");
EXPECT_TRUE(test.isFiniteNonZero());
EXPECT_FALSE(test.isDenormal());
EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), true);
expected = APFloat(APFloat::IEEEquad(), "-0x1p-16382");
EXPECT_TRUE(test.isFiniteNonZero());
EXPECT_FALSE(test.isDenormal());
EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ EXPECT_TRUE(test.isSmallestNormalized());
}
TEST(APFloatTest, getZero) {