From 30069b451b9f3c87e7a3019de9f11c59855a8a0b Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Fri, 14 Nov 2025 06:32:12 +0000 Subject: [PATCH 1/2] [libc] Implement wcstod and wcstold. These are simply implemented as specializations of strtofloatingpoint for double / long double and for wchar_t. The unit tests are copied from the strtod / strtold ones. --- libc/config/linux/x86_64/entrypoints.txt | 2 + libc/include/wchar.yaml | 14 + libc/src/wchar/CMakeLists.txt | 22 + libc/src/wchar/wcstod.cpp | 30 ++ libc/src/wchar/wcstod.h | 20 + libc/src/wchar/wcstold.cpp | 30 ++ libc/src/wchar/wcstold.h | 21 + libc/test/src/wchar/CMakeLists.txt | 29 +- libc/test/src/wchar/wcstod_test.cpp | 585 +++++++++++++++++++++++ libc/test/src/wchar/wcstold_test.cpp | 262 ++++++++++ 10 files changed, 1014 insertions(+), 1 deletion(-) create mode 100644 libc/src/wchar/wcstod.cpp create mode 100644 libc/src/wchar/wcstod.h create mode 100644 libc/src/wchar/wcstold.cpp create mode 100644 libc/src/wchar/wcstold.h create mode 100644 libc/test/src/wchar/wcstod_test.cpp create mode 100644 libc/test/src/wchar/wcstold_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index d3bcad470b3e1..5036c9438a503 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -398,9 +398,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.wchar.wmemchr libc.src.wchar.wcpcpy libc.src.wchar.wcpncpy + libc.src.wchar.wcstod libc.src.wchar.wcstof libc.src.wchar.wcstok libc.src.wchar.wcstol + libc.src.wchar.wcstold libc.src.wchar.wcstoll libc.src.wchar.wcstoul libc.src.wchar.wcstoull diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml index faceb9bb4e12d..a524c7f56bed0 100644 --- a/libc/include/wchar.yaml +++ b/libc/include/wchar.yaml @@ -367,3 +367,17 @@ functions: arguments: - type: const wchar_t *__restrict - type: wchar_t **__restrict + - name: wcstod + standards: + - stdc + return_type: double + arguments: + - type: const wchar_t *__restrict + - type: wchar_t **__restrict + - name: wcstold + standards: + - stdc + return_type: long double + arguments: + - type: const wchar_t *__restrict + - type: wchar_t **__restrict diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt index e3fac9fb80529..e6d9af9eacf73 100644 --- a/libc/src/wchar/CMakeLists.txt +++ b/libc/src/wchar/CMakeLists.txt @@ -110,6 +110,28 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + wcstod + SRCS + wcstod.cpp + HDRS + wcstod.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno +) + +add_entrypoint_object( + wcstold + SRCS + wcstold.cpp + HDRS + wcstold.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno +) + add_entrypoint_object( wcstok SRCS diff --git a/libc/src/wchar/wcstod.cpp b/libc/src/wchar/wcstod.cpp new file mode 100644 index 0000000000000..95351c304c0ff --- /dev/null +++ b/libc/src/wchar/wcstod.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of wcstod ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/wchar/wcstod.h" +#include "src/__support/common.h" +#include "src/__support/libc_errno.h" +#include "src/__support/macros/config.h" +#include "src/__support/str_to_float.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(double, wcstod, + (const wchar_t *__restrict str, + wchar_t **__restrict str_end)) { + auto result = internal::strtofloatingpoint(str); + if (result.has_error()) + libc_errno = result.error; + + if (str_end != nullptr) + *str_end = const_cast(str + result.parsed_len); + + return result.value; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcstod.h b/libc/src/wchar/wcstod.h new file mode 100644 index 0000000000000..ff397b93d405d --- /dev/null +++ b/libc/src/wchar/wcstod.h @@ -0,0 +1,20 @@ +//===-- Implementation header for wcstod ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOD_H +#define LLVM_LIBC_SRC_WCHAR_WCSTOD_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +double wcstod(const wchar_t *__restrict str, wchar_t **__restrict str_end); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCSTOD_H diff --git a/libc/src/wchar/wcstold.cpp b/libc/src/wchar/wcstold.cpp new file mode 100644 index 0000000000000..ffbc3f248b883 --- /dev/null +++ b/libc/src/wchar/wcstold.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of wcstold -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/wchar/wcstold.h" +#include "src/__support/common.h" +#include "src/__support/libc_errno.h" +#include "src/__support/macros/config.h" +#include "src/__support/str_to_float.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(long double, wcstold, + (const wchar_t *__restrict str, + wchar_t **__restrict str_end)) { + auto result = internal::strtofloatingpoint(str); + if (result.has_error()) + libc_errno = result.error; + + if (str_end != nullptr) + *str_end = const_cast(str + result.parsed_len); + + return result.value; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/wchar/wcstold.h b/libc/src/wchar/wcstold.h new file mode 100644 index 0000000000000..1525362b33571 --- /dev/null +++ b/libc/src/wchar/wcstold.h @@ -0,0 +1,21 @@ +//===-- Implementation header for wcstold -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOLD_H +#define LLVM_LIBC_SRC_WCHAR_WCSTOLD_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +long double wcstold(const wchar_t *__restrict str, + wchar_t **__restrict str_end); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_WCHAR_WCSTOLD_H diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt index 122cad2575327..a62a30fe00124 100644 --- a/libc/test/src/wchar/CMakeLists.txt +++ b/libc/test/src/wchar/CMakeLists.txt @@ -538,5 +538,32 @@ add_libc_test( DEPENDS libc.src.wchar.wcstof libc.test.UnitTest.ErrnoCheckingTest - libc.test.UnitTest.LibcFPTestHelpers + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + wcstod_test + SUITE + libc_wchar_unittests + SRCS + wcstod_test.cpp + DEPENDS + libc.src.wchar.wcstod + libc.test.UnitTest.ErrnoCheckingTest + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + wcstold_test + SUITE + libc_wchar_unittests + SRCS + wcstold_test.cpp + DEPENDS + libc.src.__support.FPUtil.fp_bits + libc.src.__support.uint128 + libc.src.wchar.wcstold + libc.test.UnitTest.ErrnoCheckingTest ) diff --git a/libc/test/src/wchar/wcstod_test.cpp b/libc/test/src/wchar/wcstod_test.cpp new file mode 100644 index 0000000000000..ac6c48d39d287 --- /dev/null +++ b/libc/test/src/wchar/wcstod_test.cpp @@ -0,0 +1,585 @@ +//===-- Unittests for wcstod ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/wchar/wcstod.h" + +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/ErrnoCheckingTest.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/RoundingModeUtils.h" +#include "test/UnitTest/Test.h" + +#include + +using LIBC_NAMESPACE::fputil::testing::ForceRoundingModeTest; +using LIBC_NAMESPACE::fputil::testing::RoundingMode; + +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + +class LlvmLibcWcstodTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest, + ForceRoundingModeTest { +public: + void run_test(const wchar_t *inputString, const ptrdiff_t expectedStrLen, + const uint64_t expectedRawData, const int expectedErrno = 0) { + // expectedRawData is the expected double result as a uint64_t, organized + // according to IEEE754: + // + // +-- 1 Sign Bit +-- 52 Mantissa bits + // | | + // | +-------------------------+------------------------+ + // | | | + // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + // | | + // +----+----+ + // | + // +-- 11 Exponent Bits + // + // This is so that the result can be compared in parts. + wchar_t *str_end = nullptr; + + LIBC_NAMESPACE::fputil::FPBits expected_fp = + LIBC_NAMESPACE::fputil::FPBits(expectedRawData); + + double result = LIBC_NAMESPACE::wcstod(inputString, &str_end); + if (expectedErrno == 0) + EXPECT_THAT(result, Succeeds(expected_fp.get_val())); + else + EXPECT_THAT(result, Fails(expectedErrno, expected_fp.get_val())); + EXPECT_EQ(str_end - inputString, expectedStrLen); + } +}; + +TEST_F(LlvmLibcWcstodTest, SimpleTest) { + run_test(L"123", 3, uint64_t(0x405ec00000000000)); + + // This should fail on Eisel-Lemire, forcing a fallback to simple decimal + // conversion. + run_test(L"12345678901234549760", 20, uint64_t(0x43e56a95319d63d8)); + + // Found while looking for difficult test cases here: + // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt + run_test(L"1090544144181609348835077142190", 31, uint64_t(0x462b8779f2474dfb)); + + run_test(L"0x123", 5, uint64_t(0x4072300000000000)); +} + +// These are tests that have caused problems in the past. +TEST_F(LlvmLibcWcstodTest, SpecificFailures) { + run_test(L"3E70000000000000", 16, uint64_t(0x7FF0000000000000), ERANGE); + run_test(L"358416272e-33", 13, uint64_t(0x3adbbb2a68c9d0b9)); + run_test(L"2.16656806400000023841857910156251e9", 36, + uint64_t(0x41e0246690000001)); + run_test(L"27949676547093071875", 20, uint64_t(0x43f83e132bc608c9)); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000e-800", + 806, 0x3ff0000000000000); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000e-799", + 806, 0x4024000000000000); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000e-800", + 807, 0x4024000000000000); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000e-64", + 69, 0x3ff0000000000000); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000e-128", + 134, 0x3ff0000000000000); + run_test(L"100000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000e-256", + 262, 0x3ff0000000000000); + run_test(L"100000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000e-512", + 518, 0x3ff0000000000000); + run_test( + L"10000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000e-1024", + 1031, 0x3ff0000000000000); + run_test( + L"0" + "100000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000e-1024", + 1032, 0x3ff0000000000000); +} + +TEST_F(LlvmLibcWcstodTest, FuzzFailures) { + run_test(L"-\xff\xff\xff\xff\xff\xff\xff\x01", 0, uint64_t(0)); + run_test(L"-.????", 0, uint64_t(0)); + run_test( + L"44444444444444444444444444444444444444444444444444A44444444444444444" + "44444444444*\x99\xff\xff\xff\xff", + 50, uint64_t(0x4a3e68fdd0e0b2d8)); + run_test(L"-NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKNNNNNNNNNNNNNNNNNN?" + "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN?", + 0, uint64_t(0)); + run_test(L"0x.666E40", 9, uint64_t(0x3fd99b9000000000)); + + // glibc version 2.36 and higher (not tested with lower versions) disagrees + // with this result, but ours is correct for the nearest rounding mode. See + // this bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30220 + run_test(L"0x30000002222225p-1077", 22, uint64_t(0x0006000000444445), ERANGE); + + // This value triggered a bug by having an exponent exactly equal to the + // maximum. The overflow checks would accept a value less than the max value + // as valid and greater than the max value as invalid (and set it to the max), + // but an exponent of exactly max value hit the else condition which is + // intended for underflow and set the exponent to the min exponent. + run_test( + L"18477446000000000000000000000000000005230000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000935166201543003765631683711878842" + "388777446000000000000430037600000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000005238581124701719460000000" + "000000000017194600000000000000000070046000000000000000000000000100000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000002000000000000000" + "000000000000056316837118788423887774460000000000000000000000000000052385" + "811247017194600000000000000000171946000000000000000000700460000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000002000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000523858112470171946000000" + "000000000001719460000000000000000007004600000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "0200000000000000000E608", + 1462, uint64_t(0x7ff0000000000000), ERANGE); + + // Same as above but for hex. + run_test(L"0x0164810157p2047", 17, uint64_t(0x7ff0000000000000), ERANGE); + + // This test ensures that only the correct number of characters is accepted. + // An exponent symbol followed by a sign isn't a valid exponent. + run_test(L"2e+", 1, uint64_t(0x4000000000000000)); + run_test(L"0x2p+", 3, uint64_t(0x4000000000000000)); + + // This bug was in the handling of very large exponents in the exponent + // marker. Previously anything greater than 10,000 would be set to 10,000. + // This caused incorrect behavior if there were more than 10,000 '0's in the + // input number, and then a correspondingly large exponent. This test case has + // 24,744 zeroes. + run_test( + L"0x." + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000fp551615", + 24755, uint64_t(0x7ff0000000000000), ERANGE); +} diff --git a/libc/test/src/wchar/wcstold_test.cpp b/libc/test/src/wchar/wcstold_test.cpp new file mode 100644 index 0000000000000..3a7fdfce3e732 --- /dev/null +++ b/libc/test/src/wchar/wcstold_test.cpp @@ -0,0 +1,262 @@ +//===-- Unittests for wcstold ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/uint128.h" +#include "src/wchar/wcstold.h" + +#include "test/UnitTest/ErrnoCheckingTest.h" +#include "test/UnitTest/Test.h" + +#include + +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) +#define SELECT_CONST(val, _, __) val +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) +#define SELECT_CONST(_, val, __) val +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) +#define SELECT_CONST(_, __, val) val +#else +#error "Unknown long double type" +#endif + +class LlvmLibcWcstoldTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest { +public: +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + void run_test(const wchar_t *inputString, const ptrdiff_t expectedStrLen, + const uint64_t expectedRawData, const int expectedErrno = 0) +#else + void run_test(const wchar_t *inputString, const ptrdiff_t expectedStrLen, + const UInt128 expectedRawData, const int expectedErrno = 0) +#endif + { + // expectedRawData64 is the expected long double result as a uint64_t, + // organized according to the IEEE754 double precision format: + // + // +-- 1 Sign Bit +-- 52 Mantissa bits + // | | + // | +-------------------------+------------------------+ + // | | | + // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + // | | + // +----+----+ + // | + // +-- 11 Exponent Bits + + // expectedRawData80 is the expected long double result as a UInt128, + // organized according to the x86 extended precision format: + // + // +-- 1 Sign Bit + // | + // | +-- 1 Integer part bit (1 unless this is a subnormal) + // | | + // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M + // | | | | + // +------+------+ +---------------------------+--------------------------+ + // | | + // +-- 15 Exponent Bits +-- 63 Mantissa bits + + // expectedRawData128 is the expected long double result as a UInt128, + // organized according to IEEE754 quadruple precision format: + // + // +-- 1 Sign Bit +-- 112 Mantissa bits + // | | + // | +----------------------------+--------------------------+ + // | | | + // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M + // | | + // +------+------+ + // | + // +-- 15 Exponent Bits + wchar_t *str_end = nullptr; + + using FPBits = LIBC_NAMESPACE::fputil::FPBits; + FPBits expected_fp = + FPBits(static_cast(expectedRawData)); + const int expected_errno = expectedErrno; + + long double result = LIBC_NAMESPACE::wcstold(inputString, &str_end); + + LIBC_NAMESPACE::fputil::FPBits actual_fp = + LIBC_NAMESPACE::fputil::FPBits(); + actual_fp = LIBC_NAMESPACE::fputil::FPBits(result); + + EXPECT_EQ(str_end - inputString, expectedStrLen); + + EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval()); + EXPECT_EQ(actual_fp.is_neg(), expected_fp.is_neg()); + EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent()); + EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa()); + ASSERT_ERRNO_EQ(expected_errno); + } +}; + +TEST_F(LlvmLibcWcstoldTest, SimpleTest) { + run_test(L"123", 3, + SELECT_CONST(uint64_t(0x405ec00000000000), + UInt128(0x4005f60000) << 40, + UInt128(0x4005ec0000000000) << 64)); + + // This should fail on Eisel-Lemire, forcing a fallback to simple decimal + // conversion. + run_test(L"12345678901234549760", 20, + SELECT_CONST(uint64_t(0x43e56a95319d63d8), + (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400), + (UInt128(0x403e56a95319d63d) << 64) + + UInt128(0x8800000000000000))); + + // Found while looking for difficult test cases here: + // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt + run_test(L"1090544144181609348835077142190", 31, + SELECT_CONST(uint64_t(0x462b8779f2474dfb), + (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402), + (UInt128(0x4062b8779f2474df) << 64) + + UInt128(0xa804bfd8c6d5c000))); + + run_test(L"0x123", 5, + SELECT_CONST(uint64_t(0x4072300000000000), + (UInt128(0x4007918000) << 40), + (UInt128(0x4007230000000000) << 64))); +} + +// These are tests that have caused problems for doubles in the past. +TEST_F(LlvmLibcWcstoldTest, Float64SpecificFailures) { + run_test(L"3E70000000000000", 16, + SELECT_CONST(uint64_t(0x7FF0000000000000), + (UInt128(0x7fff800000) << 40), + (UInt128(0x7fff000000000000) << 64)), + ERANGE); + run_test(L"358416272e-33", 13, + SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9), + (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400), + (UInt128(0x3fadbbb2a68c9d0b) << 64) + + UInt128(0x8800e7969e1c5fc8))); + run_test(L"2.16656806400000023841857910156251e9", 36, + SELECT_CONST(uint64_t(0x41e0246690000001), + (UInt128(0x401e812334) << 40) + UInt128(0x8000000400), + (UInt128(0x401e024669000000) << 64) + + UInt128(0x800000000000018))); + run_test(L"27949676547093071875", 20, + SELECT_CONST(uint64_t(0x43f83e132bc608c9), + (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402), + (UInt128(0x403f83e132bc608c) << 64) + + UInt128(0x8803000000000000))); +} + +TEST_F(LlvmLibcWcstoldTest, Float80SpecificFailures) { + run_test(L"777777777777777777777777777777777777777777777777777777777777777777" + "7777777777777777777777777777777777", + 100, + SELECT_CONST(uint64_t(0x54ac729b8fcaf734), + (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2), + (UInt128(0x414ac729b8fcaf73) << 64) + + UInt128(0x4184a3d793224129))); +} + +TEST_F(LlvmLibcWcstoldTest, MaxSizeNumbers) { + run_test(L"1.1897314953572317650e4932", 26, + SELECT_CONST(uint64_t(0x7FF0000000000000), + (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff), + (UInt128(0x7ffeffffffffffff) << 64) + + UInt128(0xfffd57322e3f8675)), + SELECT_CONST(ERANGE, 0, 0)); + run_test(L"1.18973149535723176508e4932", 27, + SELECT_CONST(uint64_t(0x7FF0000000000000), + (UInt128(0x7fff800000) << 40), + (UInt128(0x7ffeffffffffffff) << 64) + + UInt128(0xffffd2478338036c)), + SELECT_CONST(ERANGE, ERANGE, 0)); +} + +// These tests check subnormal behavior for 80 bit and 128 bit floats. They will +// be too small for 64 bit floats. +TEST_F(LlvmLibcWcstoldTest, SubnormalTests) { + run_test(L"1e-4950", 7, + SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)), + (UInt128(0x000000000000000000057c9647e1a018))), + ERANGE); + run_test(L"1.89e-4951", 10, + SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)), + (UInt128(0x0000000000000000000109778a006738))), + ERANGE); + run_test(L"4e-4966", 7, + SELECT_CONST(uint64_t(0), (UInt128(0)), + (UInt128(0x00000000000000000000000000000001))), + ERANGE); +} + +TEST_F(LlvmLibcWcstoldTest, SmallNormalTests) { + run_test(L"3.37e-4932", 10, + SELECT_CONST( + uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712), + (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)), + SELECT_CONST(ERANGE, 0, 0)); +} + +TEST_F(LlvmLibcWcstoldTest, ComplexHexadecimalTests) { + run_test(L"0x1p16383", 9, + SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40), + (UInt128(0x7ffe000000000000) << 64)), + SELECT_CONST(ERANGE, 0, 0)); + run_test(L"0x123456789abcdef", 17, + SELECT_CONST(0x43723456789abcdf, + (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780), + (UInt128(0x403723456789abcd) << 64) + + UInt128(0xef00000000000000))); + run_test(L"0x123456789abcdef0123456789ABCDEF", 33, + SELECT_CONST(0x47723456789abcdf, + (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781), + (UInt128(0x407723456789abcd) << 64) + + UInt128(0xef0123456789abce))); +} + +TEST_F(LlvmLibcWcstoldTest, InfTests) { + run_test(L"INF", 3, + SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), + (UInt128(0x7fff000000000000) << 64))); + run_test(L"INFinity", 8, + SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40), + (UInt128(0x7fff000000000000) << 64))); + run_test(L"-inf", 4, + SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40), + (UInt128(0xffff000000000000) << 64))); +} + +TEST_F(LlvmLibcWcstoldTest, NaNTests) { + run_test(L"NaN", 3, + SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), + (UInt128(0x7fff800000000000) << 64))); + run_test(L"-nAn", 4, + SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40), + (UInt128(0xffff800000000000) << 64))); + run_test(L"NaN()", 5, + SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), + (UInt128(0x7fff800000000000) << 64))); + run_test(L"NaN(1234)", 9, + SELECT_CONST(0x7ff80000000004d2, + (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2), + (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2))); + run_test(L"NaN(0xffffffffffff)", 19, + SELECT_CONST(0x7ff8ffffffffffff, + (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff), + (UInt128(0x7fff800000000000) << 64) + + UInt128(0xffffffffffff))); + run_test(L"NaN(0xfffffffffffff)", 20, + SELECT_CONST(0x7fffffffffffffff, + (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff), + (UInt128(0x7fff800000000000) << 64) + + UInt128(0xfffffffffffff))); + run_test(L"NaN(0xffffffffffffffff)", 23, + SELECT_CONST(0x7fffffffffffffff, + (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff), + (UInt128(0x7fff800000000000) << 64) + + UInt128(0xffffffffffffffff))); + run_test(L"NaN( 1234)", 3, + SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40), + (UInt128(0x7fff800000000000) << 64))); +} From 83a005f59d218e8c9adcd4de580a2a5e328f6205 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Fri, 14 Nov 2025 07:10:25 +0000 Subject: [PATCH 2/2] clang-format --- libc/test/src/wchar/wcstod_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libc/test/src/wchar/wcstod_test.cpp b/libc/test/src/wchar/wcstod_test.cpp index ac6c48d39d287..0c2b82cfba898 100644 --- a/libc/test/src/wchar/wcstod_test.cpp +++ b/libc/test/src/wchar/wcstod_test.cpp @@ -64,7 +64,8 @@ TEST_F(LlvmLibcWcstodTest, SimpleTest) { // Found while looking for difficult test cases here: // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt - run_test(L"1090544144181609348835077142190", 31, uint64_t(0x462b8779f2474dfb)); + run_test(L"1090544144181609348835077142190", 31, + uint64_t(0x462b8779f2474dfb)); run_test(L"0x123", 5, uint64_t(0x4072300000000000)); }