1aa1902f9SMichael Jones //===-- Unittests for strtold ---------------------------------------------===// 2aa1902f9SMichael Jones // 3aa1902f9SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4aa1902f9SMichael Jones // See https://llvm.org/LICENSE.txt for license information. 5aa1902f9SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6aa1902f9SMichael Jones // 7aa1902f9SMichael Jones //===----------------------------------------------------------------------===// 8aa1902f9SMichael Jones 9aa1902f9SMichael Jones #include "src/__support/FPUtil/FPBits.h" 1009efe848SGuillaume Chatelet #include "src/__support/uint128.h" 1104a9c625SMichael Jones #include "src/errno/libc_errno.h" 12aa1902f9SMichael Jones #include "src/stdlib/strtold.h" 13aa1902f9SMichael Jones 14af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 15aa1902f9SMichael Jones 16aa1902f9SMichael Jones #include <stddef.h> 17aa1902f9SMichael Jones 18f7d4236aSGuillaume Chatelet #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) 195d1dbe11SMichael Jones #define SELECT_CONST(val, _, __) val 20f7d4236aSGuillaume Chatelet #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) 215d1dbe11SMichael Jones #define SELECT_CONST(_, val, __) val 22f7d4236aSGuillaume Chatelet #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) 235d1dbe11SMichael Jones #define SELECT_CONST(_, __, val) val 24f7d4236aSGuillaume Chatelet #else 25f7d4236aSGuillaume Chatelet #error "Unknown long double type" 265d1dbe11SMichael Jones #endif 275d1dbe11SMichael Jones 28b6bc9d72SGuillaume Chatelet class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test { 29aa1902f9SMichael Jones public: 30f7d4236aSGuillaume Chatelet #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) 3125226f3eSMichael Jones void run_test(const char *inputString, const ptrdiff_t expectedStrLen, 325d1dbe11SMichael Jones const uint64_t expectedRawData, const int expectedErrno = 0) 335d1dbe11SMichael Jones #else 345d1dbe11SMichael Jones void run_test(const char *inputString, const ptrdiff_t expectedStrLen, 35300f8da8SSiva Chandra Reddy const UInt128 expectedRawData, const int expectedErrno = 0) 365d1dbe11SMichael Jones #endif 375d1dbe11SMichael Jones { 38aa1902f9SMichael Jones // expectedRawData64 is the expected long double result as a uint64_t, 39aa1902f9SMichael Jones // organized according to the IEEE754 double precision format: 40aa1902f9SMichael Jones // 41aa1902f9SMichael Jones // +-- 1 Sign Bit +-- 52 Mantissa bits 42aa1902f9SMichael Jones // | | 43aa1902f9SMichael Jones // | +-------------------------+------------------------+ 44aa1902f9SMichael Jones // | | | 45aa1902f9SMichael Jones // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 46aa1902f9SMichael Jones // | | 47aa1902f9SMichael Jones // +----+----+ 48aa1902f9SMichael Jones // | 49aa1902f9SMichael Jones // +-- 11 Exponent Bits 50aa1902f9SMichael Jones 51300f8da8SSiva Chandra Reddy // expectedRawData80 is the expected long double result as a UInt128, 52aa1902f9SMichael Jones // organized according to the x86 extended precision format: 53aa1902f9SMichael Jones // 54aa1902f9SMichael Jones // +-- 1 Sign Bit 55aa1902f9SMichael Jones // | 56aa1902f9SMichael Jones // | +-- 1 Integer part bit (1 unless this is a subnormal) 57aa1902f9SMichael Jones // | | 58aa1902f9SMichael Jones // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M 59aa1902f9SMichael Jones // | | | | 60aa1902f9SMichael Jones // +------+------+ +---------------------------+--------------------------+ 61aa1902f9SMichael Jones // | | 62aa1902f9SMichael Jones // +-- 15 Exponent Bits +-- 63 Mantissa bits 63aa1902f9SMichael Jones 64300f8da8SSiva Chandra Reddy // expectedRawData128 is the expected long double result as a UInt128, 65aa1902f9SMichael Jones // organized according to IEEE754 quadruple precision format: 66aa1902f9SMichael Jones // 67aa1902f9SMichael Jones // +-- 1 Sign Bit +-- 112 Mantissa bits 68aa1902f9SMichael Jones // | | 69aa1902f9SMichael Jones // | +----------------------------+--------------------------+ 70aa1902f9SMichael Jones // | | | 71aa1902f9SMichael Jones // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M 72aa1902f9SMichael Jones // | | 73aa1902f9SMichael Jones // +------+------+ 74aa1902f9SMichael Jones // | 75aa1902f9SMichael Jones // +-- 15 Exponent Bits 7625226f3eSMichael Jones char *str_end = nullptr; 77aa1902f9SMichael Jones 78*7302c8dbSNick Desaulniers using FPBits = LIBC_NAMESPACE::fputil::FPBits<long double>; 79*7302c8dbSNick Desaulniers FPBits expected_fp = 80*7302c8dbSNick Desaulniers FPBits(static_cast<FPBits::StorageType>(expectedRawData)); 815d1dbe11SMichael Jones const int expected_errno = expectedErrno; 82aa1902f9SMichael Jones 833eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 84b6bc9d72SGuillaume Chatelet long double result = LIBC_NAMESPACE::strtold(inputString, &str_end); 85aa1902f9SMichael Jones 86b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::FPBits<long double> actual_fp = 87b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fputil::FPBits<long double>(); 88b6bc9d72SGuillaume Chatelet actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result); 89aa1902f9SMichael Jones 9025226f3eSMichael Jones EXPECT_EQ(str_end - inputString, expectedStrLen); 91aa1902f9SMichael Jones 92d02471edSGuillaume Chatelet EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval()); 9311ec512fSGuillaume Chatelet EXPECT_EQ(actual_fp.is_neg(), expected_fp.is_neg()); 9425226f3eSMichael Jones EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent()); 9525226f3eSMichael Jones EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa()); 9673874f7aSGuillaume Chatelet ASSERT_ERRNO_EQ(expected_errno); 97aa1902f9SMichael Jones } 98aa1902f9SMichael Jones }; 99aa1902f9SMichael Jones 100aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SimpleTest) { 1015d1dbe11SMichael Jones run_test("123", 3, 1025d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x405ec00000000000), 103300f8da8SSiva Chandra Reddy UInt128(0x4005f60000) << 40, 104300f8da8SSiva Chandra Reddy UInt128(0x4005ec0000000000) << 64)); 105aa1902f9SMichael Jones 106aa1902f9SMichael Jones // This should fail on Eisel-Lemire, forcing a fallback to simple decimal 107aa1902f9SMichael Jones // conversion. 1085d1dbe11SMichael Jones run_test("12345678901234549760", 20, 1095d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x43e56a95319d63d8), 110300f8da8SSiva Chandra Reddy (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400), 111300f8da8SSiva Chandra Reddy (UInt128(0x403e56a95319d63d) << 64) + 112300f8da8SSiva Chandra Reddy UInt128(0x8800000000000000))); 113aa1902f9SMichael Jones 114aa1902f9SMichael Jones // Found while looking for difficult test cases here: 115aa1902f9SMichael Jones // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt 1165d1dbe11SMichael Jones run_test("1090544144181609348835077142190", 31, 1175d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x462b8779f2474dfb), 118300f8da8SSiva Chandra Reddy (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402), 119300f8da8SSiva Chandra Reddy (UInt128(0x4062b8779f2474df) << 64) + 120300f8da8SSiva Chandra Reddy UInt128(0xa804bfd8c6d5c000))); 121aa1902f9SMichael Jones 1225d1dbe11SMichael Jones run_test("0x123", 5, 1235d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x4072300000000000), 124300f8da8SSiva Chandra Reddy (UInt128(0x4007918000) << 40), 125300f8da8SSiva Chandra Reddy (UInt128(0x4007230000000000) << 64))); 126aa1902f9SMichael Jones } 127aa1902f9SMichael Jones 128aa1902f9SMichael Jones // These are tests that have caused problems for doubles in the past. 129aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) { 1305d1dbe11SMichael Jones run_test("3E70000000000000", 16, 1315d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x7FF0000000000000), 132300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000) << 40), 133300f8da8SSiva Chandra Reddy (UInt128(0x7fff000000000000) << 64)), 1345d1dbe11SMichael Jones ERANGE); 1355d1dbe11SMichael Jones run_test("358416272e-33", 13, 1365d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9), 137300f8da8SSiva Chandra Reddy (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400), 138300f8da8SSiva Chandra Reddy (UInt128(0x3fadbbb2a68c9d0b) << 64) + 139300f8da8SSiva Chandra Reddy UInt128(0x8800e7969e1c5fc8))); 1405d1dbe11SMichael Jones run_test("2.16656806400000023841857910156251e9", 36, 1415d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x41e0246690000001), 142300f8da8SSiva Chandra Reddy (UInt128(0x401e812334) << 40) + UInt128(0x8000000400), 143300f8da8SSiva Chandra Reddy (UInt128(0x401e024669000000) << 64) + 144300f8da8SSiva Chandra Reddy UInt128(0x800000000000018))); 1455d1dbe11SMichael Jones run_test("27949676547093071875", 20, 1465d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x43f83e132bc608c9), 147300f8da8SSiva Chandra Reddy (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402), 148300f8da8SSiva Chandra Reddy (UInt128(0x403f83e132bc608c) << 64) + 149300f8da8SSiva Chandra Reddy UInt128(0x8803000000000000))); 150aa1902f9SMichael Jones } 151aa1902f9SMichael Jones 152ae3b59e6SMichael Jones TEST_F(LlvmLibcStrToLDTest, Float80SpecificFailures) { 153ae3b59e6SMichael Jones run_test("7777777777777777777777777777777777777777777777777777777777777777777" 154ae3b59e6SMichael Jones "777777777777777777777777777777777", 155ae3b59e6SMichael Jones 100, 156ae3b59e6SMichael Jones SELECT_CONST(uint64_t(0x54ac729b8fcaf734), 157ae3b59e6SMichael Jones (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2), 158ae3b59e6SMichael Jones (UInt128(0x414ac729b8fcaf73) << 64) + 159ae3b59e6SMichael Jones UInt128(0x4184a3d793224129))); 160ae3b59e6SMichael Jones } 161ae3b59e6SMichael Jones 162aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) { 1635d1dbe11SMichael Jones run_test("1.1897314953572317650e4932", 26, 1645d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x7FF0000000000000), 165300f8da8SSiva Chandra Reddy (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff), 166300f8da8SSiva Chandra Reddy (UInt128(0x7ffeffffffffffff) << 64) + 167300f8da8SSiva Chandra Reddy UInt128(0xfffd57322e3f8675)), 1685d1dbe11SMichael Jones SELECT_CONST(ERANGE, 0, 0)); 1695d1dbe11SMichael Jones run_test("1.18973149535723176508e4932", 27, 1705d1dbe11SMichael Jones SELECT_CONST(uint64_t(0x7FF0000000000000), 171300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000) << 40), 172300f8da8SSiva Chandra Reddy (UInt128(0x7ffeffffffffffff) << 64) + 173300f8da8SSiva Chandra Reddy UInt128(0xffffd2478338036c)), 1745d1dbe11SMichael Jones SELECT_CONST(ERANGE, ERANGE, 0)); 175aa1902f9SMichael Jones } 176aa1902f9SMichael Jones 177aa1902f9SMichael Jones // These tests check subnormal behavior for 80 bit and 128 bit floats. They will 178aa1902f9SMichael Jones // be too small for 64 bit floats. 179aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SubnormalTests) { 1805d1dbe11SMichael Jones run_test("1e-4950", 7, 181300f8da8SSiva Chandra Reddy SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)), 182300f8da8SSiva Chandra Reddy (UInt128(0x000000000000000000057c9647e1a018))), 183aa1902f9SMichael Jones ERANGE); 1845d1dbe11SMichael Jones run_test("1.89e-4951", 10, 185300f8da8SSiva Chandra Reddy SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)), 186300f8da8SSiva Chandra Reddy (UInt128(0x0000000000000000000109778a006738))), 187aa1902f9SMichael Jones ERANGE); 1885d1dbe11SMichael Jones run_test("4e-4966", 7, 189300f8da8SSiva Chandra Reddy SELECT_CONST(uint64_t(0), (UInt128(0)), 190300f8da8SSiva Chandra Reddy (UInt128(0x00000000000000000000000000000001))), 191aa1902f9SMichael Jones ERANGE); 192aa1902f9SMichael Jones } 193aa1902f9SMichael Jones 194aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) { 195300f8da8SSiva Chandra Reddy run_test("3.37e-4932", 10, 196300f8da8SSiva Chandra Reddy SELECT_CONST( 197300f8da8SSiva Chandra Reddy uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712), 198300f8da8SSiva Chandra Reddy (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)), 1995d1dbe11SMichael Jones SELECT_CONST(ERANGE, 0, 0)); 200aa1902f9SMichael Jones } 201aa1902f9SMichael Jones 202aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) { 2035d1dbe11SMichael Jones run_test("0x1p16383", 9, 204300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40), 205300f8da8SSiva Chandra Reddy (UInt128(0x7ffe000000000000) << 64)), 2065d1dbe11SMichael Jones SELECT_CONST(ERANGE, 0, 0)); 2075d1dbe11SMichael Jones run_test("0x123456789abcdef", 17, 2085d1dbe11SMichael Jones SELECT_CONST(0x43723456789abcdf, 209300f8da8SSiva Chandra Reddy (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780), 210300f8da8SSiva Chandra Reddy (UInt128(0x403723456789abcd) << 64) + 211300f8da8SSiva Chandra Reddy UInt128(0xef00000000000000))); 2125d1dbe11SMichael Jones run_test("0x123456789abcdef0123456789ABCDEF", 33, 2135d1dbe11SMichael Jones SELECT_CONST(0x47723456789abcdf, 214300f8da8SSiva Chandra Reddy (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781), 215300f8da8SSiva Chandra Reddy (UInt128(0x407723456789abcd) << 64) + 216300f8da8SSiva Chandra Reddy UInt128(0xef0123456789abce))); 217aa1902f9SMichael Jones } 218aa1902f9SMichael Jones 219aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, InfTests) { 2205d1dbe11SMichael Jones run_test("INF", 3, 221300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), 222300f8da8SSiva Chandra Reddy (UInt128(0x7fff000000000000) << 64))); 2235d1dbe11SMichael Jones run_test("INFinity", 8, 224300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), 225300f8da8SSiva Chandra Reddy (UInt128(0x7fff000000000000) << 64))); 2265d1dbe11SMichael Jones run_test("-inf", 4, 227300f8da8SSiva Chandra Reddy SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40), 228300f8da8SSiva Chandra Reddy (UInt128(0xffff000000000000) << 64))); 229aa1902f9SMichael Jones } 230aa1902f9SMichael Jones 231aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, NaNTests) { 2325d1dbe11SMichael Jones run_test("NaN", 3, 233300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 234300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64))); 2355d1dbe11SMichael Jones run_test("-nAn", 4, 236300f8da8SSiva Chandra Reddy SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40), 237300f8da8SSiva Chandra Reddy (UInt128(0xffff800000000000) << 64))); 2385d1dbe11SMichael Jones run_test("NaN()", 5, 239300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 240300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64))); 2415d1dbe11SMichael Jones run_test("NaN(1234)", 9, 2425d1dbe11SMichael Jones SELECT_CONST(0x7ff80000000004d2, 243300f8da8SSiva Chandra Reddy (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2), 244300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2))); 2455d1dbe11SMichael Jones run_test("NaN(0xffffffffffff)", 19, 2465d1dbe11SMichael Jones SELECT_CONST(0x7ff8ffffffffffff, 247300f8da8SSiva Chandra Reddy (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff), 248300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64) + 249300f8da8SSiva Chandra Reddy UInt128(0xffffffffffff))); 2505d1dbe11SMichael Jones run_test("NaN(0xfffffffffffff)", 20, 2515d1dbe11SMichael Jones SELECT_CONST(0x7fffffffffffffff, 252300f8da8SSiva Chandra Reddy (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff), 253300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64) + 254300f8da8SSiva Chandra Reddy UInt128(0xfffffffffffff))); 2555d1dbe11SMichael Jones run_test("NaN(0xffffffffffffffff)", 23, 2565d1dbe11SMichael Jones SELECT_CONST(0x7fffffffffffffff, 257300f8da8SSiva Chandra Reddy (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff), 258300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64) + 259300f8da8SSiva Chandra Reddy UInt128(0xffffffffffffffff))); 2605d1dbe11SMichael Jones run_test("NaN( 1234)", 3, 261300f8da8SSiva Chandra Reddy SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), 262300f8da8SSiva Chandra Reddy (UInt128(0x7fff800000000000) << 64))); 263aa1902f9SMichael Jones } 264