1 //===-- Unittests for strtold ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/__support/FPUtil/FPBits.h" 10 #include "src/__support/uint128.h" 11 #include "src/errno/libc_errno.h" 12 #include "src/stdlib/strtold.h" 13 14 #include "test/UnitTest/Test.h" 15 16 #include <stddef.h> 17 18 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) 19 #define SELECT_CONST(val, _, __) val 20 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) 21 #define SELECT_CONST(_, val, __) val 22 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) 23 #define SELECT_CONST(_, __, val) val 24 #else 25 #error "Unknown long double type" 26 #endif 27 28 class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test { 29 public: 30 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) 31 void run_test(const char *inputString, const ptrdiff_t expectedStrLen, 32 const uint64_t expectedRawData, const int expectedErrno = 0) 33 #else 34 void run_test(const char *inputString, const ptrdiff_t expectedStrLen, 35 const UInt128 expectedRawData, const int expectedErrno = 0) 36 #endif 37 { 38 // expectedRawData64 is the expected long double result as a uint64_t, 39 // organized according to the IEEE754 double precision format: 40 // 41 // +-- 1 Sign Bit +-- 52 Mantissa bits 42 // | | 43 // | +-------------------------+------------------------+ 44 // | | | 45 // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 46 // | | 47 // +----+----+ 48 // | 49 // +-- 11 Exponent Bits 50 51 // expectedRawData80 is the expected long double result as a UInt128, 52 // organized according to the x86 extended precision format: 53 // 54 // +-- 1 Sign Bit 55 // | 56 // | +-- 1 Integer part bit (1 unless this is a subnormal) 57 // | | 58 // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M 59 // | | | | 60 // +------+------+ +---------------------------+--------------------------+ 61 // | | 62 // +-- 15 Exponent Bits +-- 63 Mantissa bits 63 64 // expectedRawData128 is the expected long double result as a UInt128, 65 // organized according to IEEE754 quadruple precision format: 66 // 67 // +-- 1 Sign Bit +-- 112 Mantissa bits 68 // | | 69 // | +----------------------------+--------------------------+ 70 // | | | 71 // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M 72 // | | 73 // +------+------+ 74 // | 75 // +-- 15 Exponent Bits 76 char *str_end = nullptr; 77 78 using FPBits = LIBC_NAMESPACE::fputil::FPBits<long double>; 79 FPBits expected_fp = 80 FPBits(static_cast<FPBits::StorageType>(expectedRawData)); 81 const int expected_errno = expectedErrno; 82 83 LIBC_NAMESPACE::libc_errno = 0; 84 long double result = LIBC_NAMESPACE::strtold(inputString, &str_end); 85 86 LIBC_NAMESPACE::fputil::FPBits<long double> actual_fp = 87 LIBC_NAMESPACE::fputil::FPBits<long double>(); 88 actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result); 89 90 EXPECT_EQ(str_end - inputString, expectedStrLen); 91 92 EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval()); 93 EXPECT_EQ(actual_fp.is_neg(), expected_fp.is_neg()); 94 EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent()); 95 EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa()); 96 ASSERT_ERRNO_EQ(expected_errno); 97 } 98 }; 99 100 TEST_F(LlvmLibcStrToLDTest, SimpleTest) { 101 run_test("123", 3, 102 SELECT_CONST(uint64_t(0x405ec00000000000), 103 UInt128(0x4005f60000) << 40, 104 UInt128(0x4005ec0000000000) << 64)); 105 106 // This should fail on Eisel-Lemire, forcing a fallback to simple decimal 107 // conversion. 108 run_test("12345678901234549760", 20, 109 SELECT_CONST(uint64_t(0x43e56a95319d63d8), 110 (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400), 111 (UInt128(0x403e56a95319d63d) << 64) + 112 UInt128(0x8800000000000000))); 113 114 // Found while looking for difficult test cases here: 115 // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt 116 run_test("1090544144181609348835077142190", 31, 117 SELECT_CONST(uint64_t(0x462b8779f2474dfb), 118 (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402), 119 (UInt128(0x4062b8779f2474df) << 64) + 120 UInt128(0xa804bfd8c6d5c000))); 121 122 run_test("0x123", 5, 123 SELECT_CONST(uint64_t(0x4072300000000000), 124 (UInt128(0x4007918000) << 40), 125 (UInt128(0x4007230000000000) << 64))); 126 } 127 128 // These are tests that have caused problems for doubles in the past. 129 TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) { 130 run_test("3E70000000000000", 16, 131 SELECT_CONST(uint64_t(0x7FF0000000000000), 132 (UInt128(0x7fff800000) << 40), 133 (UInt128(0x7fff000000000000) << 64)), 134 ERANGE); 135 run_test("358416272e-33", 13, 136 SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9), 137 (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400), 138 (UInt128(0x3fadbbb2a68c9d0b) << 64) + 139 UInt128(0x8800e7969e1c5fc8))); 140 run_test("2.16656806400000023841857910156251e9", 36, 141 SELECT_CONST(uint64_t(0x41e0246690000001), 142 (UInt128(0x401e812334) << 40) + UInt128(0x8000000400), 143 (UInt128(0x401e024669000000) << 64) + 144 UInt128(0x800000000000018))); 145 run_test("27949676547093071875", 20, 146 SELECT_CONST(uint64_t(0x43f83e132bc608c9), 147 (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402), 148 (UInt128(0x403f83e132bc608c) << 64) + 149 UInt128(0x8803000000000000))); 150 } 151 152 TEST_F(LlvmLibcStrToLDTest, Float80SpecificFailures) { 153 run_test("7777777777777777777777777777777777777777777777777777777777777777777" 154 "777777777777777777777777777777777", 155 100, 156 SELECT_CONST(uint64_t(0x54ac729b8fcaf734), 157 (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2), 158 (UInt128(0x414ac729b8fcaf73) << 64) + 159 UInt128(0x4184a3d793224129))); 160 } 161 162 TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) { 163 run_test("1.1897314953572317650e4932", 26, 164 SELECT_CONST(uint64_t(0x7FF0000000000000), 165 (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff), 166 (UInt128(0x7ffeffffffffffff) << 64) + 167 UInt128(0xfffd57322e3f8675)), 168 SELECT_CONST(ERANGE, 0, 0)); 169 run_test("1.18973149535723176508e4932", 27, 170 SELECT_CONST(uint64_t(0x7FF0000000000000), 171 (UInt128(0x7fff800000) << 40), 172 (UInt128(0x7ffeffffffffffff) << 64) + 173 UInt128(0xffffd2478338036c)), 174 SELECT_CONST(ERANGE, ERANGE, 0)); 175 } 176 177 // These tests check subnormal behavior for 80 bit and 128 bit floats. They will 178 // be too small for 64 bit floats. 179 TEST_F(LlvmLibcStrToLDTest, SubnormalTests) { 180 run_test("1e-4950", 7, 181 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)), 182 (UInt128(0x000000000000000000057c9647e1a018))), 183 ERANGE); 184 run_test("1.89e-4951", 10, 185 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)), 186 (UInt128(0x0000000000000000000109778a006738))), 187 ERANGE); 188 run_test("4e-4966", 7, 189 SELECT_CONST(uint64_t(0), (UInt128(0)), 190 (UInt128(0x00000000000000000000000000000001))), 191 ERANGE); 192 } 193 194 TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) { 195 run_test("3.37e-4932", 10, 196 SELECT_CONST( 197 uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712), 198 (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)), 199 SELECT_CONST(ERANGE, 0, 0)); 200 } 201 202 TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) { 203 run_test("0x1p16383", 9, 204 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40), 205 (UInt128(0x7ffe000000000000) << 64)), 206 SELECT_CONST(ERANGE, 0, 0)); 207 run_test("0x123456789abcdef", 17, 208 SELECT_CONST(0x43723456789abcdf, 209 (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780), 210 (UInt128(0x403723456789abcd) << 64) + 211 UInt128(0xef00000000000000))); 212 run_test("0x123456789abcdef0123456789ABCDEF", 33, 213 SELECT_CONST(0x47723456789abcdf, 214 (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781), 215 (UInt128(0x407723456789abcd) << 64) + 216 UInt128(0xef0123456789abce))); 217 } 218 219 TEST_F(LlvmLibcStrToLDTest, InfTests) { 220 run_test("INF", 3, 221 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), 222 (UInt128(0x7fff000000000000) << 64))); 223 run_test("INFinity", 8, 224 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), 225 (UInt128(0x7fff000000000000) << 64))); 226 run_test("-inf", 4, 227 SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40), 228 (UInt128(0xffff000000000000) << 64))); 229 } 230 231 TEST_F(LlvmLibcStrToLDTest, NaNTests) { 232 run_test("NaN", 3, 233 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 234 (UInt128(0x7fff800000000000) << 64))); 235 run_test("-nAn", 4, 236 SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40), 237 (UInt128(0xffff800000000000) << 64))); 238 run_test("NaN()", 5, 239 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 240 (UInt128(0x7fff800000000000) << 64))); 241 run_test("NaN(1234)", 9, 242 SELECT_CONST(0x7ff80000000004d2, 243 (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2), 244 (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2))); 245 run_test("NaN(0xffffffffffff)", 19, 246 SELECT_CONST(0x7ff8ffffffffffff, 247 (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff), 248 (UInt128(0x7fff800000000000) << 64) + 249 UInt128(0xffffffffffff))); 250 run_test("NaN(0xfffffffffffff)", 20, 251 SELECT_CONST(0x7fffffffffffffff, 252 (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff), 253 (UInt128(0x7fff800000000000) << 64) + 254 UInt128(0xfffffffffffff))); 255 run_test("NaN(0xffffffffffffffff)", 23, 256 SELECT_CONST(0x7fffffffffffffff, 257 (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff), 258 (UInt128(0x7fff800000000000) << 64) + 259 UInt128(0xffffffffffffffff))); 260 run_test("NaN( 1234)", 3, 261 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 262 (UInt128(0x7fff800000000000) << 64))); 263 } 264