aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ADT/APFloatTest.cpp
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2021-05-07 02:17:42 +0700
committerSerge Pavlov <sepavloff@gmail.com>2021-05-21 11:02:51 +0700
commitc162f086ba632ffaedfe92d63bf21571bc8ae4da (patch)
tree6798043c54cf97d5db4d936c36fe7b689aaace48 /llvm/unittests/ADT/APFloatTest.cpp
parent49028858637946ce8c00f12e41138b5ed7783276 (diff)
downloadllvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.zip
llvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.tar.gz
llvm-c162f086ba632ffaedfe92d63bf21571bc8ae4da.tar.bz2
[APFloat] convertToDouble/Float can work on shorter types
Previously APFloat::convertToDouble may be called only for APFloats that were built using double semantics. Other semantics like single precision were not allowed although corresponding numbers could be converted to double without loss of precision. The similar restriction applied to APFloat::convertToFloat. With this change any APFloat that can be precisely represented by double can be handled with convertToDouble. Behavior of convertToFloat was updated similarly. It make the conversion operations more convenient and adds support for formats like half and bfloat. Differential Revision: https://reviews.llvm.org/D102671
Diffstat (limited to 'llvm/unittests/ADT/APFloatTest.cpp')
-rw-r--r--llvm/unittests/ADT/APFloatTest.cpp261
1 files changed, 259 insertions, 2 deletions
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 2088df0..1683a9d 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -1271,8 +1271,10 @@ TEST(APFloatTest, makeNaN) {
#ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG
TEST(APFloatTest, SemanticsDeath) {
- EXPECT_DEATH(APFloat(APFloat::IEEEsingle(), 0).convertToDouble(), "Float semantics are not IEEEdouble");
- EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(), "Float semantics are not IEEEsingle");
+ EXPECT_DEATH(APFloat(APFloat::IEEEquad(), 0).convertToDouble(),
+ "Float semantics is not representable by IEEEdouble");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(),
+ "Float semantics is not representable by IEEEsingle");
}
#endif
#endif
@@ -4709,4 +4711,259 @@ TEST(APFloatTest, x87Next) {
F.next(false);
EXPECT_TRUE(ilogb(F) == -1);
}
+
+TEST(APFloatTest, ToDouble) {
+ APFloat DPosZero(0.0);
+ APFloat DPosZeroToDouble(DPosZero.convertToDouble());
+ EXPECT_TRUE(DPosZeroToDouble.isPosZero());
+ APFloat DNegZero(-0.0);
+ APFloat DNegZeroToDouble(DNegZero.convertToDouble());
+ EXPECT_TRUE(DNegZeroToDouble.isNegZero());
+
+ APFloat DOne(1.0);
+ EXPECT_EQ(1.0, DOne.convertToDouble());
+ APFloat DPosLargest = APFloat::getLargest(APFloat::IEEEdouble(), false);
+ EXPECT_EQ(std::numeric_limits<double>::max(), DPosLargest.convertToDouble());
+ APFloat DNegLargest = APFloat::getLargest(APFloat::IEEEdouble(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::max(), DNegLargest.convertToDouble());
+ APFloat DPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false);
+ EXPECT_EQ(std::numeric_limits<double>::min(), DPosSmallest.convertToDouble());
+ APFloat DNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::min(),
+ DNegSmallest.convertToDouble());
+
+ APFloat DSmallestDenorm = APFloat::getSmallest(APFloat::IEEEdouble(), false);
+ EXPECT_EQ(std::numeric_limits<double>::denorm_min(),
+ DSmallestDenorm.convertToDouble());
+ APFloat DLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFFFFFFFFFp-1022");
+ EXPECT_EQ(/*0x0.FFFFFFFFFFFFFp-1022*/ 2.225073858507201e-308,
+ DLargestDenorm.convertToDouble());
+
+ APFloat DPosInf = APFloat::getInf(APFloat::IEEEdouble());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), DPosInf.convertToDouble());
+ APFloat DNegInf = APFloat::getInf(APFloat::IEEEdouble(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+ DNegInf.convertToDouble());
+ APFloat DQNaN = APFloat::getQNaN(APFloat::IEEEdouble());
+ EXPECT_TRUE(std::isnan(DQNaN.convertToDouble()));
+
+ APFloat FPosZero(0.0F);
+ APFloat FPosZeroToDouble(FPosZero.convertToDouble());
+ EXPECT_TRUE(FPosZeroToDouble.isPosZero());
+ APFloat FNegZero(-0.0F);
+ APFloat FNegZeroToDouble(FNegZero.convertToDouble());
+ EXPECT_TRUE(FNegZeroToDouble.isNegZero());
+
+ APFloat FOne(1.0F);
+ EXPECT_EQ(1.0, FOne.convertToDouble());
+ APFloat FPosLargest = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToDouble());
+ APFloat FNegLargest = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToDouble());
+ APFloat FPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToDouble());
+ APFloat FNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToDouble());
+
+ APFloat FSmallestDenorm = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
+ FSmallestDenorm.convertToDouble());
+ APFloat FLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFEp-126");
+ EXPECT_EQ(/*0x0.FFFFFEp-126*/ 1.1754942106924411e-38,
+ FLargestDenorm.convertToDouble());
+
+ APFloat FPosInf = APFloat::getInf(APFloat::IEEEsingle());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), FPosInf.convertToDouble());
+ APFloat FNegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+ FNegInf.convertToDouble());
+ APFloat FQNaN = APFloat::getQNaN(APFloat::IEEEsingle());
+ EXPECT_TRUE(std::isnan(FQNaN.convertToDouble()));
+
+ APFloat HPosZero = APFloat::getZero(APFloat::IEEEhalf());
+ APFloat HPosZeroToDouble(HPosZero.convertToDouble());
+ EXPECT_TRUE(HPosZeroToDouble.isPosZero());
+ APFloat HNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+ APFloat HNegZeroToDouble(HNegZero.convertToDouble());
+ EXPECT_TRUE(HNegZeroToDouble.isNegZero());
+
+ APFloat HOne(APFloat::IEEEhalf(), "1.0");
+ EXPECT_EQ(1.0, HOne.convertToDouble());
+ APFloat HPosLargest = APFloat::getLargest(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(65504.0, HPosLargest.convertToDouble());
+ APFloat HNegLargest = APFloat::getLargest(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(-65504.0, HNegLargest.convertToDouble());
+ APFloat HPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05, HPosSmallest.convertToDouble());
+ APFloat HNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05, HNegSmallest.convertToDouble());
+
+ APFloat HSmallestDenorm = APFloat::getSmallest(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08,
+ HSmallestDenorm.convertToDouble());
+ APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
+ EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461,
+ HLargestDenorm.convertToDouble());
+
+ APFloat HPosInf = APFloat::getInf(APFloat::IEEEhalf());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), HPosInf.convertToDouble());
+ APFloat HNegInf = APFloat::getInf(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+ HNegInf.convertToDouble());
+ APFloat HQNaN = APFloat::getQNaN(APFloat::IEEEhalf());
+ EXPECT_TRUE(std::isnan(HQNaN.convertToDouble()));
+
+ APFloat BPosZero = APFloat::getZero(APFloat::IEEEhalf());
+ APFloat BPosZeroToDouble(BPosZero.convertToDouble());
+ EXPECT_TRUE(BPosZeroToDouble.isPosZero());
+ APFloat BNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+ APFloat BNegZeroToDouble(BNegZero.convertToDouble());
+ EXPECT_TRUE(BNegZeroToDouble.isNegZero());
+
+ APFloat BOne(APFloat::BFloat(), "1.0");
+ EXPECT_EQ(1.0, BOne.convertToDouble());
+ APFloat BPosLargest = APFloat::getLargest(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38,
+ BPosLargest.convertToDouble());
+ APFloat BNegLargest = APFloat::getLargest(APFloat::BFloat(), true);
+ EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38,
+ BNegLargest.convertToDouble());
+ APFloat BPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38,
+ BPosSmallest.convertToDouble());
+ APFloat BNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::BFloat(), true);
+ EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38,
+ BNegSmallest.convertToDouble());
+
+ APFloat BSmallestDenorm = APFloat::getSmallest(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41,
+ BSmallestDenorm.convertToDouble());
+ APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
+ EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38,
+ BLargestDenorm.convertToDouble());
+
+ APFloat BPosInf = APFloat::getInf(APFloat::BFloat());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), BPosInf.convertToDouble());
+ APFloat BNegInf = APFloat::getInf(APFloat::BFloat(), true);
+ EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+ BNegInf.convertToDouble());
+ APFloat BQNaN = APFloat::getQNaN(APFloat::BFloat());
+ EXPECT_TRUE(std::isnan(BQNaN.convertToDouble()));
+}
+
+TEST(APFloatTest, ToFloat) {
+ APFloat FPosZero(0.0F);
+ APFloat FPosZeroToFloat(FPosZero.convertToFloat());
+ EXPECT_TRUE(FPosZeroToFloat.isPosZero());
+ APFloat FNegZero(-0.0F);
+ APFloat FNegZeroToFloat(FNegZero.convertToFloat());
+ EXPECT_TRUE(FNegZeroToFloat.isNegZero());
+
+ APFloat FOne(1.0F);
+ EXPECT_EQ(1.0F, FOne.convertToFloat());
+ APFloat FPosLargest = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToFloat());
+ APFloat FNegLargest = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToFloat());
+ APFloat FPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToFloat());
+ APFloat FNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToFloat());
+
+ APFloat FSmallestDenorm = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
+ FSmallestDenorm.convertToFloat());
+ APFloat FLargestDenorm(APFloat::IEEEsingle(), "0x1.FFFFFEp-126");
+ EXPECT_EQ(/*0x1.FFFFFEp-126*/ 2.3509885615147286e-38F,
+ FLargestDenorm.convertToFloat());
+
+ APFloat FPosInf = APFloat::getInf(APFloat::IEEEsingle());
+ EXPECT_EQ(std::numeric_limits<float>::infinity(), FPosInf.convertToFloat());
+ APFloat FNegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::infinity(), FNegInf.convertToFloat());
+ APFloat FQNaN = APFloat::getQNaN(APFloat::IEEEsingle());
+ EXPECT_TRUE(std::isnan(FQNaN.convertToFloat()));
+
+ APFloat HPosZero = APFloat::getZero(APFloat::IEEEhalf());
+ APFloat HPosZeroToFloat(HPosZero.convertToFloat());
+ EXPECT_TRUE(HPosZeroToFloat.isPosZero());
+ APFloat HNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+ APFloat HNegZeroToFloat(HNegZero.convertToFloat());
+ EXPECT_TRUE(HNegZeroToFloat.isNegZero());
+
+ APFloat HOne(APFloat::IEEEhalf(), "1.0");
+ EXPECT_EQ(1.0F, HOne.convertToFloat());
+ APFloat HPosLargest = APFloat::getLargest(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(/*0x1.FFCp15*/ 65504.0F, HPosLargest.convertToFloat());
+ APFloat HNegLargest = APFloat::getLargest(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(/*-0x1.FFCp15*/ -65504.0F, HNegLargest.convertToFloat());
+ APFloat HPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05F, HPosSmallest.convertToFloat());
+ APFloat HNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05F, HNegSmallest.convertToFloat());
+
+ APFloat HSmallestDenorm = APFloat::getSmallest(APFloat::IEEEhalf(), false);
+ EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08F,
+ HSmallestDenorm.convertToFloat());
+ APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
+ EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461F,
+ HLargestDenorm.convertToFloat());
+
+ APFloat HPosInf = APFloat::getInf(APFloat::IEEEhalf());
+ EXPECT_EQ(std::numeric_limits<float>::infinity(), HPosInf.convertToFloat());
+ APFloat HNegInf = APFloat::getInf(APFloat::IEEEhalf(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::infinity(), HNegInf.convertToFloat());
+ APFloat HQNaN = APFloat::getQNaN(APFloat::IEEEhalf());
+ EXPECT_TRUE(std::isnan(HQNaN.convertToFloat()));
+
+ APFloat BPosZero = APFloat::getZero(APFloat::BFloat());
+ APFloat BPosZeroToDouble(BPosZero.convertToFloat());
+ EXPECT_TRUE(BPosZeroToDouble.isPosZero());
+ APFloat BNegZero = APFloat::getZero(APFloat::BFloat(), true);
+ APFloat BNegZeroToDouble(BNegZero.convertToFloat());
+ EXPECT_TRUE(BNegZeroToDouble.isNegZero());
+
+ APFloat BOne(APFloat::BFloat(), "1.0");
+ EXPECT_EQ(1.0F, BOne.convertToFloat());
+ APFloat BPosLargest = APFloat::getLargest(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38F,
+ BPosLargest.convertToFloat());
+ APFloat BNegLargest = APFloat::getLargest(APFloat::BFloat(), true);
+ EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38F,
+ BNegLargest.convertToFloat());
+ APFloat BPosSmallest =
+ APFloat::getSmallestNormalized(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38F,
+ BPosSmallest.convertToFloat());
+ APFloat BNegSmallest =
+ APFloat::getSmallestNormalized(APFloat::BFloat(), true);
+ EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38F,
+ BNegSmallest.convertToFloat());
+
+ APFloat BSmallestDenorm = APFloat::getSmallest(APFloat::BFloat(), false);
+ EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41F,
+ BSmallestDenorm.convertToFloat());
+ APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
+ EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38F,
+ BLargestDenorm.convertToFloat());
+
+ APFloat BPosInf = APFloat::getInf(APFloat::BFloat());
+ EXPECT_EQ(std::numeric_limits<float>::infinity(), BPosInf.convertToFloat());
+ APFloat BNegInf = APFloat::getInf(APFloat::BFloat(), true);
+ EXPECT_EQ(-std::numeric_limits<float>::infinity(), BNegInf.convertToFloat());
+ APFloat BQNaN = APFloat::getQNaN(APFloat::BFloat());
+ EXPECT_TRUE(std::isnan(BQNaN.convertToFloat()));
+}
}