aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ADT/APFloatTest.cpp
diff options
context:
space:
mode:
authorEhud Katz <ehudkatz@gmail.com>2020-01-21 20:17:42 +0200
committerEhud Katz <ehudkatz@gmail.com>2020-01-21 20:22:27 +0200
commit68122b5826b56f547e8fbae7cf4d455afeda8400 (patch)
treed9b666b4086ffe7063125a2b30ac63e0667b31f5 /llvm/unittests/ADT/APFloatTest.cpp
parent6b2f820221c78c05527d6edb756b4f1f44665968 (diff)
downloadllvm-68122b5826b56f547e8fbae7cf4d455afeda8400.zip
llvm-68122b5826b56f547e8fbae7cf4d455afeda8400.tar.gz
llvm-68122b5826b56f547e8fbae7cf4d455afeda8400.tar.bz2
[APFloat] Extend conversion from special strings
Add support for converting Signaling NaN, and a NaN Payload from string. The NaNs (the string "nan" or "NaN") may be prefixed with 's' or 'S' for defining a Signaling NaN. A payload for a NaN can be specified as a suffix. It may be a octal/decimal/hexadecimal number in parentheses or without. Differential Revision: https://reviews.llvm.org/D69773
Diffstat (limited to 'llvm/unittests/ADT/APFloatTest.cpp')
-rw-r--r--llvm/unittests/ADT/APFloatTest.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 65b831c..fa12b5f 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -919,6 +919,120 @@ TEST(APFloatTest, fromDecimalString) {
EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828"));
}
+TEST(APFloatTest, fromStringSpecials) {
+ const fltSemantics &Sem = APFloat::IEEEdouble();
+ const unsigned Precision = 53;
+ const unsigned PayloadBits = Precision - 2;
+ uint64_t PayloadMask = (uint64_t(1) << PayloadBits) - uint64_t(1);
+
+ uint64_t NaNPayloads[] = {
+ 0,
+ 1,
+ 123,
+ 0xDEADBEEF,
+ uint64_t(-2),
+ uint64_t(1) << PayloadBits, // overflow bit
+ uint64_t(1) << (PayloadBits - 1), // signaling bit
+ uint64_t(1) << (PayloadBits - 2) // highest possible bit
+ };
+
+ // Convert payload integer to decimal string representation.
+ std::string NaNPayloadDecStrings[array_lengthof(NaNPayloads)];
+ for (size_t I = 0; I < array_lengthof(NaNPayloads); ++I)
+ NaNPayloadDecStrings[I] = utostr(NaNPayloads[I]);
+
+ // Convert payload integer to hexadecimal string representation.
+ std::string NaNPayloadHexStrings[array_lengthof(NaNPayloads)];
+ for (size_t I = 0; I < array_lengthof(NaNPayloads); ++I)
+ NaNPayloadHexStrings[I] = "0x" + utohexstr(NaNPayloads[I]);
+
+ // Fix payloads to expected result.
+ for (uint64_t &Payload : NaNPayloads)
+ Payload &= PayloadMask;
+
+ // Signaling NaN must have a non-zero payload. In case a zero payload is
+ // requested, a default arbitrary payload is set instead. Save this payload
+ // for testing.
+ const uint64_t SNaNDefaultPayload =
+ APFloat::getSNaN(Sem).bitcastToAPInt().getZExtValue() & PayloadMask;
+
+ // Negative sign prefix (or none - for positive).
+ const char Signs[] = {0, '-'};
+
+ // "Signaling" prefix (or none - for "Quiet").
+ const char NaNTypes[] = {0, 's', 'S'};
+
+ const StringRef NaNStrings[] = {"nan", "NaN"};
+ for (StringRef NaNStr : NaNStrings)
+ for (char TypeChar : NaNTypes) {
+ bool Signaling = (TypeChar == 's' || TypeChar == 'S');
+
+ for (size_t J = 0; J < array_lengthof(NaNPayloads); ++J) {
+ uint64_t Payload = (Signaling && !NaNPayloads[J]) ? SNaNDefaultPayload
+ : NaNPayloads[J];
+ std::string &PayloadDec = NaNPayloadDecStrings[J];
+ std::string &PayloadHex = NaNPayloadHexStrings[J];
+
+ for (char SignChar : Signs) {
+ bool Negative = (SignChar == '-');
+
+ std::string TestStrings[5];
+ size_t NumTestStrings = 0;
+
+ std::string Prefix;
+ if (SignChar)
+ Prefix += SignChar;
+ if (TypeChar)
+ Prefix += TypeChar;
+ Prefix += NaNStr;
+
+ // Test without any paylod.
+ if (!Payload)
+ TestStrings[NumTestStrings++] = Prefix;
+
+ // Test with the payload as a suffix.
+ TestStrings[NumTestStrings++] = Prefix + PayloadDec;
+ TestStrings[NumTestStrings++] = Prefix + PayloadHex;
+
+ // Test with the payload inside parentheses.
+ TestStrings[NumTestStrings++] = Prefix + '(' + PayloadDec + ')';
+ TestStrings[NumTestStrings++] = Prefix + '(' + PayloadHex + ')';
+
+ for (size_t K = 0; K < NumTestStrings; ++K) {
+ StringRef TestStr = TestStrings[K];
+
+ APFloat F(Sem);
+ bool HasError = !F.convertFromString(
+ TestStr, llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_FALSE(HasError);
+ EXPECT_TRUE(F.isNaN());
+ EXPECT_EQ(Signaling, F.isSignaling());
+ EXPECT_EQ(Negative, F.isNegative());
+ uint64_t PayloadResult =
+ F.bitcastToAPInt().getZExtValue() & PayloadMask;
+ EXPECT_EQ(Payload, PayloadResult);
+ }
+ }
+ }
+ }
+
+ const StringRef InfStrings[] = {"inf", "INFINITY", "+Inf",
+ "-inf", "-INFINITY", "-Inf"};
+ for (StringRef InfStr : InfStrings) {
+ bool Negative = InfStr.front() == '-';
+
+ StringRef TestStr;
+ APFloat F(Sem);
+ bool HasError =
+ !F.convertFromString(InfStr, llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_FALSE(HasError);
+ EXPECT_TRUE(F.isInfinity());
+ EXPECT_EQ(Negative, F.isNegative());
+ uint64_t PayloadResult = F.bitcastToAPInt().getZExtValue() & PayloadMask;
+ EXPECT_EQ(0, PayloadResult);
+ }
+}
+
TEST(APFloatTest, fromToStringSpecials) {
auto expects = [] (const char *first, const char *second) {
std::string roundtrip = convertToString(convertToDoubleFromString(second), 0, 3);