diff options
author | Ehud Katz <ehudkatz@gmail.com> | 2020-01-21 20:17:42 +0200 |
---|---|---|
committer | Ehud Katz <ehudkatz@gmail.com> | 2020-01-21 20:22:27 +0200 |
commit | 68122b5826b56f547e8fbae7cf4d455afeda8400 (patch) | |
tree | d9b666b4086ffe7063125a2b30ac63e0667b31f5 /llvm/lib/Support/APFloat.cpp | |
parent | 6b2f820221c78c05527d6edb756b4f1f44665968 (diff) | |
download | llvm-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/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 050c37b..37392e9 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -2621,24 +2621,70 @@ IEEEFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) { } bool IEEEFloat::convertFromStringSpecials(StringRef str) { + const size_t MIN_NAME_SIZE = 3; + + if (str.size() < MIN_NAME_SIZE) + return false; + if (str.equals("inf") || str.equals("INFINITY") || str.equals("+Inf")) { makeInf(false); return true; } - if (str.equals("-inf") || str.equals("-INFINITY") || str.equals("-Inf")) { - makeInf(true); - return true; + bool IsNegative = str.front() == '-'; + if (IsNegative) { + str = str.drop_front(); + if (str.size() < MIN_NAME_SIZE) + return false; + + if (str.equals("inf") || str.equals("INFINITY") || str.equals("Inf")) { + makeInf(true); + return true; + } } - if (str.equals("nan") || str.equals("NaN")) { - makeNaN(false, false); - return true; + // If we have a 's' (or 'S') prefix, then this is a Signaling NaN. + bool IsSignaling = str.front() == 's' || str.front() == 'S'; + if (IsSignaling) { + str = str.drop_front(); + if (str.size() < MIN_NAME_SIZE) + return false; } - if (str.equals("-nan") || str.equals("-NaN")) { - makeNaN(false, true); - return true; + if (str.startswith("nan") || str.startswith("NaN")) { + str = str.drop_front(3); + + // A NaN without payload. + if (str.empty()) { + makeNaN(IsSignaling, IsNegative); + return true; + } + + // Allow the payload to be inside parentheses. + if (str.front() == '(') { + // Parentheses should be balanced (and not empty). + if (str.size() <= 2 || str.back() != ')') + return false; + + str = str.slice(1, str.size() - 1); + } + + // Determine the payload number's radix. + unsigned Radix = 10; + if (str[0] == '0') { + if (str.size() > 1 && tolower(str[1]) == 'x') { + str = str.drop_front(2); + Radix = 16; + } else + Radix = 8; + } + + // Parse the payload and make the NaN. + APInt Payload; + if (!str.getAsInteger(Radix, Payload)) { + makeNaN(IsSignaling, IsNegative, &Payload); + return true; + } } return false; |