[libc-commits] [libc] [libc][math][c23] adds `nanf128` (PR #85201)
Michael Flanders via libc-commits
libc-commits at lists.llvm.org
Thu Mar 14 18:06:10 PDT 2024
https://github.com/Flandini updated https://github.com/llvm/llvm-project/pull/85201
>From 64f967943cc2abc383955aa7e1ce2831e1d56b0f Mon Sep 17 00:00:00 2001
From: Michael Flanders <mkf727 at cs.washington.edu>
Date: Thu, 14 Mar 2024 07:49:14 +0000
Subject: [PATCH 1/5] adds nanf128, change strtointeger to support types with
width more than ULL
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/spec/stdc.td | 1 +
libc/src/__support/UInt.h | 9 ++++
libc/src/__support/str_to_float.h | 26 ++++-----
libc/src/__support/str_to_integer.h | 24 +++++----
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/generic/CMakeLists.txt | 13 +++++
libc/src/math/generic/nanf128.cpp | 23 ++++++++
libc/src/math/nanf128.h | 20 +++++++
libc/test/src/math/smoke/CMakeLists.txt | 16 ++++++
libc/test/src/math/smoke/nanf128_test.cpp | 64 +++++++++++++++++++++++
13 files changed, 176 insertions(+), 24 deletions(-)
create mode 100644 libc/src/math/generic/nanf128.cpp
create mode 100644 libc/src/math/nanf128.h
create mode 100644 libc/test/src/math/smoke/nanf128_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 7d69099e3cb9db..43c9e81f17833e 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -468,6 +468,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.lrintf128
libc.src.math.lroundf128
libc.src.math.modff128
+ libc.src.math.nanf128
libc.src.math.nextafterf128
libc.src.math.rintf128
libc.src.math.roundf128
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index b1c9dd0428eea5..99ef84d3f73974 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -476,6 +476,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.lrintf128
libc.src.math.lroundf128
libc.src.math.modff128
+ libc.src.math.nanf128
libc.src.math.nextafterf128
libc.src.math.rintf128
libc.src.math.roundf128
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 4fb31c593b9dc7..a8b416aa9a0cda 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -481,6 +481,7 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.lrintf128
libc.src.math.lroundf128
libc.src.math.modff128
+ libc.src.math.nanf128
libc.src.math.nextafterf128
libc.src.math.rintf128
libc.src.math.roundf128
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index afe01b1bb68566..2bc9bc8b9b1a6f 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -559,6 +559,7 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>,
FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>,
+ GuardedFunctionSpec<"nanf128", RetValSpec<Float128Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT128">,
]
>;
diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index d92d61ed094ebe..97ecfe8606dbfb 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -993,6 +993,15 @@ struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {};
template <class T>
LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value;
+// make_unsigned and make_signed type traits
+template <size_t Bits, bool Signed, typename T>
+struct cpp::make_unsigned<BigInt<Bits, Signed, T>>
+ : cpp::type_identity<BigInt<Bits, false, T>> {};
+
+template <size_t Bits, bool Signed, typename T>
+struct cpp::make_signed<BigInt<Bits, Signed, T>>
+ : cpp::type_identity<BigInt<Bits, true, T>> {};
+
namespace cpp {
// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 073e1dc6721723..2cf2cfb027243e 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -1056,17 +1056,17 @@ hexadecimal_string_to_float(const char *__restrict src,
return output;
}
-LIBC_INLINE uint64_t
+template <class T>
+LIBC_INLINE typename fputil::FPBits<T>::StorageType
nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) {
- uint64_t nan_mantissa = 0;
+ using FPBits = typename fputil::FPBits<T>;
+ using StorageType = typename FPBits::StorageType;
+
+ StorageType nan_mantissa = 0;
if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) {
- // This is to prevent errors when StorageType is larger than 64
- // bits, since strtointeger only supports up to 64 bits. This is
- // actually more than is required by the specification, which says
- // for the input type "NAN(n-char-sequence)" that "the meaning of
- // the n-char sequence is implementation-defined."
- auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0);
+ StrToNumResult<StorageType> strtoint_result =
+ strtointeger<StorageType>(ncharseq.data(), 0);
if (!strtoint_result.has_error())
nan_mantissa = strtoint_result.value;
@@ -1172,9 +1172,8 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) {
++index;
if (src[index] == ')') {
++index;
- auto nan_mantissa_result = nan_mantissa_from_ncharseq(
+ nan_mantissa = nan_mantissa_from_ncharseq<T>(
cpp::string_view(src + (left_paren + 1), index - left_paren - 2));
- nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
} else {
index = left_paren;
}
@@ -1221,11 +1220,8 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
while (isalnum(arg[index]) || arg[index] == '_')
++index;
- if (arg[index] == '\0') {
- auto nan_mantissa_result =
- nan_mantissa_from_ncharseq(cpp::string_view(arg, index));
- nan_mantissa = static_cast<StorageType>(nan_mantissa_result);
- }
+ if (arg[index] == '\0')
+ nan_mantissa = nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index));
result = FPBits::quiet_nan(fputil::Sign::POS, nan_mantissa);
return {result.get_val(), 0, error};
diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h
index b87808993fee50..85a46065203f17 100644
--- a/libc/src/__support/str_to_integer.h
+++ b/libc/src/__support/str_to_integer.h
@@ -11,6 +11,7 @@
#include "src/__support/CPP/limits.h"
#include "src/__support/CPP/type_traits.h"
+#include "src/__support/UInt128.h"
#include "src/__support/common.h"
#include "src/__support/ctype_utils.h"
#include "src/__support/str_to_num_result.h"
@@ -75,8 +76,12 @@ template <class T>
LIBC_INLINE StrToNumResult<T>
strtointeger(const char *__restrict src, int base,
const size_t src_len = cpp::numeric_limits<size_t>::max()) {
- // TODO: Rewrite to support numbers longer than long long
- unsigned long long result = 0;
+ using ResultType = typename cpp::conditional_t<(cpp::is_same_v<T, UInt128> ||
+ cpp::is_same_v<T, Int128>),
+ UInt128, unsigned long long>;
+
+ ResultType result = 0;
+
bool is_number = false;
size_t src_cur = 0;
int error_val = 0;
@@ -101,15 +106,16 @@ strtointeger(const char *__restrict src, int base,
if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur))
src_cur = src_cur + 2;
- constexpr bool IS_UNSIGNED = (cpp::numeric_limits<T>::min() == 0);
+ constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>;
const bool is_positive = (result_sign == '+');
- unsigned long long constexpr NEGATIVE_MAX =
- !IS_UNSIGNED
- ? static_cast<unsigned long long>(cpp::numeric_limits<T>::max()) + 1
- : cpp::numeric_limits<T>::max();
- unsigned long long const abs_max =
+
+ ResultType constexpr NEGATIVE_MAX =
+ !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1
+ : cpp::numeric_limits<T>::max();
+ ResultType const abs_max =
(is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX);
- unsigned long long const abs_max_div_by_base = abs_max / base;
+ ResultType const abs_max_div_by_base = abs_max / base;
+
while (src_cur < src_len && isalnum(src[src_cur])) {
int cur_digit = b36_char_to_int(src[src_cur]);
if (cur_digit >= base)
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 750fd5f0e3a9ba..cd03065399480e 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -190,6 +190,7 @@ add_math_entrypoint_object(modff128)
add_math_entrypoint_object(nan)
add_math_entrypoint_object(nanf)
add_math_entrypoint_object(nanl)
+add_math_entrypoint_object(nanf128)
add_math_entrypoint_object(nearbyint)
add_math_entrypoint_object(nearbyintf)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 667381d615d1e0..87f53105a1b317 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1780,6 +1780,19 @@ add_entrypoint_object(
-O3
)
+add_entrypoint_object(
+ nanf128
+ SRCS
+ nanf128.cpp
+ HDRS
+ ../nanf128.h
+ DEPENDS
+ libc.src.__support.str_to_float
+ libc.src.errno.errno
+ COMPILE_OPTIONS
+ -O3
+)
+
add_entrypoint_object(
nextafter
SRCS
diff --git a/libc/src/math/generic/nanf128.cpp b/libc/src/math/generic/nanf128.cpp
new file mode 100644
index 00000000000000..f087c9f074fde8
--- /dev/null
+++ b/libc/src/math/generic/nanf128.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of nanf128 function --------------------------------===//
+//
+// 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/math/nanf128.h"
+#include "src/__support/common.h"
+#include "src/__support/str_to_float.h"
+#include "src/errno/libc_errno.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, nanf128, (const char *arg)) {
+ auto result = internal::strtonan<float128>(arg);
+ if (result.has_error())
+ libc_errno = result.error;
+ return result.value;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/nanf128.h b/libc/src/math/nanf128.h
new file mode 100644
index 00000000000000..b06d14e2f945e1
--- /dev/null
+++ b/libc/src/math/nanf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for nanf128 -----------------------*- 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_MATH_NANF128_H
+#define LLVM_LIBC_SRC_MATH_NANF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 nanf128(const char *arg);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_NANF128_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 293e65abd44f5a..80ea9d1109a0cf 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1506,6 +1506,22 @@ add_fp_unittest(
UNIT_TEST_ONLY
)
+add_fp_unittest(
+ nanf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ nanf128_test.cpp
+ DEPENDS
+ libc.include.math
+ libc.include.signal
+ libc.src.math.nanf128
+ libc.src.__support.FPUtil.fp_bits
+ # FIXME: The nan tests currently have death tests, which aren't supported for
+ # hermetic tests.
+ UNIT_TEST_ONLY
+)
+
add_fp_unittest(
nextafter_test
SUITE
diff --git a/libc/test/src/math/smoke/nanf128_test.cpp b/libc/test/src/math/smoke/nanf128_test.cpp
new file mode 100644
index 00000000000000..f90f052ec254d8
--- /dev/null
+++ b/libc/test/src/math/smoke/nanf128_test.cpp
@@ -0,0 +1,64 @@
+//===-- Unittests for nanf128 ---------------------------------------------===//
+//
+// 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/math/nanf128.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcNanf128Test : public LIBC_NAMESPACE::testing::Test {
+public:
+ using FPBits128 = LIBC_NAMESPACE::fputil::FPBits<float128>;
+ using StorageType = FPBits128::StorageType;
+
+ const UInt128 QUIET_NAN = FPBits128::quiet_nan(
+ LIBC_NAMESPACE::fputil::Sign::POS, 0).uintval();
+
+ const UInt128 ONE = UInt128(1);
+ const UInt128 ZERO = UInt128(0);
+
+ void run_test(const char *input_str, StorageType bits) {
+ float128 result = LIBC_NAMESPACE::nanf128(input_str);
+ auto actual_fp = FPBits128(result);
+ auto expected_fp = FPBits128(bits);
+ EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval());
+ };
+};
+
+TEST_F(LlvmLibcNanf128Test, NCharSeq) {
+ run_test("", QUIET_NAN);
+ run_test("1234", QUIET_NAN | 1234);
+ run_test("0x1234", QUIET_NAN | 0x1234);
+ run_test("2417851639229258349412352", QUIET_NAN | (ONE << 81));
+ run_test("0x200000000000000000000", QUIET_NAN | (ONE << 81));
+ run_test("10384593717069655257060992658440191",
+ QUIET_NAN | (~ZERO & FPBits128::SIG_MASK));
+ run_test("0x1ffffffffffffffffffffffffffff",
+ QUIET_NAN | (~ZERO & FPBits128::SIG_MASK));
+ run_test("10384593717069655257060992658440192", QUIET_NAN);
+ run_test("0x20000000000000000000000000000", QUIET_NAN);
+ run_test("1a", QUIET_NAN);
+ run_test("10000000000000000000000000000000000000000000000000", QUIET_NAN);
+}
+
+TEST_F(LlvmLibcNanf128Test, RandomString) {
+ run_test(" 1234", QUIET_NAN);
+ run_test("-1234", QUIET_NAN);
+ run_test("asd&f", QUIET_NAN);
+ run_test("123 ", QUIET_NAN);
+ run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_",
+ QUIET_NAN);
+}
+
+#ifndef LIBC_HAVE_ADDRESS_SANITIZER
+#include <signal.h>
+TEST_F(LlvmLibcNanf128Test, InvalidInput) {
+ EXPECT_DEATH([] { LIBC_NAMESPACE::nanf128(nullptr); }, WITH_SIGNAL(SIGSEGV));
+}
+#endif // LIBC_HAVE_ADDRESS_SANITIZER
>From 9545de3aa765c933d7c8607d1e04a16aa5206d45 Mon Sep 17 00:00:00 2001
From: Michael Flanders <mkf727 at cs.washington.edu>
Date: Thu, 14 Mar 2024 09:00:22 +0000
Subject: [PATCH 2/5] fix formatting in nanf128_test.cpp
---
libc/test/src/math/smoke/nanf128_test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/test/src/math/smoke/nanf128_test.cpp b/libc/test/src/math/smoke/nanf128_test.cpp
index f90f052ec254d8..1f752c75db5bc0 100644
--- a/libc/test/src/math/smoke/nanf128_test.cpp
+++ b/libc/test/src/math/smoke/nanf128_test.cpp
@@ -17,8 +17,8 @@ class LlvmLibcNanf128Test : public LIBC_NAMESPACE::testing::Test {
using FPBits128 = LIBC_NAMESPACE::fputil::FPBits<float128>;
using StorageType = FPBits128::StorageType;
- const UInt128 QUIET_NAN = FPBits128::quiet_nan(
- LIBC_NAMESPACE::fputil::Sign::POS, 0).uintval();
+ const UInt128 QUIET_NAN =
+ FPBits128::quiet_nan(LIBC_NAMESPACE::fputil::Sign::POS, 0).uintval();
const UInt128 ONE = UInt128(1);
const UInt128 ZERO = UInt128(0);
>From 19275a316997b148e7e96c61f9fd2c8956ba6c6c Mon Sep 17 00:00:00 2001
From: Michael Flanders <mkf727 at cs.washington.edu>
Date: Thu, 14 Mar 2024 15:57:14 +0000
Subject: [PATCH 3/5] adds nanf128 to status docs
---
libc/docs/math/index.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index ed54a7d091ecb1..3240a8c5d2456a 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -259,6 +259,8 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| nanl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| nanf128 | |check| | |check| | | |check| | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| nearbyint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| nearbyintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
>From 18c9bd375764e8fb7659784d6171bf0dab46268a Mon Sep 17 00:00:00 2001
From: Michael Flanders <mkf727 at cs.washington.edu>
Date: Thu, 14 Mar 2024 17:16:00 +0000
Subject: [PATCH 4/5] address review comments in nanf128_test
---
libc/test/src/math/smoke/nanf128_test.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/libc/test/src/math/smoke/nanf128_test.cpp b/libc/test/src/math/smoke/nanf128_test.cpp
index 1f752c75db5bc0..7767bf29718e31 100644
--- a/libc/test/src/math/smoke/nanf128_test.cpp
+++ b/libc/test/src/math/smoke/nanf128_test.cpp
@@ -17,11 +17,8 @@ class LlvmLibcNanf128Test : public LIBC_NAMESPACE::testing::Test {
using FPBits128 = LIBC_NAMESPACE::fputil::FPBits<float128>;
using StorageType = FPBits128::StorageType;
- const UInt128 QUIET_NAN =
- FPBits128::quiet_nan(LIBC_NAMESPACE::fputil::Sign::POS, 0).uintval();
-
+ const UInt128 QUIET_NAN = FPBits128::quiet_nan().uintval();
const UInt128 ONE = UInt128(1);
- const UInt128 ZERO = UInt128(0);
void run_test(const char *input_str, StorageType bits) {
float128 result = LIBC_NAMESPACE::nanf128(input_str);
@@ -38,9 +35,9 @@ TEST_F(LlvmLibcNanf128Test, NCharSeq) {
run_test("2417851639229258349412352", QUIET_NAN | (ONE << 81));
run_test("0x200000000000000000000", QUIET_NAN | (ONE << 81));
run_test("10384593717069655257060992658440191",
- QUIET_NAN | (~ZERO & FPBits128::SIG_MASK));
+ QUIET_NAN | FPBits128::SIG_MASK);
run_test("0x1ffffffffffffffffffffffffffff",
- QUIET_NAN | (~ZERO & FPBits128::SIG_MASK));
+ QUIET_NAN | FPBits128::SIG_MASK);
run_test("10384593717069655257060992658440192", QUIET_NAN);
run_test("0x20000000000000000000000000000", QUIET_NAN);
run_test("1a", QUIET_NAN);
>From fb1b50dfacccfad65a50f7773260cb64999e6ef4 Mon Sep 17 00:00:00 2001
From: Michael Flanders <mkf727 at cs.washington.edu>
Date: Fri, 15 Mar 2024 01:05:53 +0000
Subject: [PATCH 5/5] address remaining review comments; fix formatting
---
libc/src/__support/UInt.h | 56 +++++++++++++++++++++--
libc/src/__support/str_to_integer.h | 10 ++--
libc/test/src/math/smoke/nanf128_test.cpp | 3 +-
3 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index 97ecfe8606dbfb..7a7e946b10bac5 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -993,15 +993,65 @@ struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {};
template <class T>
LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value;
-// make_unsigned and make_signed type traits
+// extensions of type traits to include BigInt
+
+// is_integral_or_big_int
+template <typename T>
+struct is_integral_or_big_int
+ : cpp::bool_constant<(cpp::is_integral_v<T> || is_big_int_v<T>)> {};
+
+template <typename T>
+LIBC_INLINE_VAR constexpr bool is_integral_or_big_int_v =
+ is_integral_or_big_int<T>::value;
+
+// make_big_int_unsigned
+template <typename T> struct make_big_int_unsigned;
+
template <size_t Bits, bool Signed, typename T>
-struct cpp::make_unsigned<BigInt<Bits, Signed, T>>
+struct make_big_int_unsigned<BigInt<Bits, Signed, T>>
: cpp::type_identity<BigInt<Bits, false, T>> {};
+template <typename T>
+using make_big_int_unsigned_t = typename make_big_int_unsigned<T>::type;
+
+// make_big_int_signed
+template <typename T> struct make_big_int_signed;
+
template <size_t Bits, bool Signed, typename T>
-struct cpp::make_signed<BigInt<Bits, Signed, T>>
+struct make_big_int_signed<BigInt<Bits, Signed, T>>
: cpp::type_identity<BigInt<Bits, true, T>> {};
+template <typename T>
+using make_big_int_signed_t = typename make_big_int_signed<T>::type;
+
+// make_integral_or_big_int_unsigned
+template <typename T> struct make_integral_or_big_int_unsigned;
+
+template <size_t Bits, bool Signed, typename T>
+struct make_integral_or_big_int_unsigned<BigInt<Bits, Signed, T>>
+ : make_big_int_unsigned<BigInt<Bits, Signed, T>> {};
+
+template <typename T>
+struct make_integral_or_big_int_unsigned : cpp::make_unsigned<T> {};
+
+template <typename T>
+using make_integral_or_big_int_unsigned_t =
+ typename make_integral_or_big_int_unsigned<T>::type;
+
+// make_integral_or_big_int_signed
+template <typename T> struct make_integral_or_big_int_signed;
+
+template <size_t Bits, bool Signed, typename T>
+struct make_integral_or_big_int_signed<BigInt<Bits, Signed, T>>
+ : make_big_int_signed<BigInt<Bits, Signed, T>> {};
+
+template <typename T>
+struct make_integral_or_big_int_signed : cpp::make_signed<T> {};
+
+template <typename T>
+using make_integral_or_big_int_signed_t =
+ typename make_integral_or_big_int_signed<T>::type;
+
namespace cpp {
// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h
index 85a46065203f17..02c71d40a1c0ad 100644
--- a/libc/src/__support/str_to_integer.h
+++ b/libc/src/__support/str_to_integer.h
@@ -155,10 +155,12 @@ strtointeger(const char *__restrict src, int base,
return {cpp::numeric_limits<T>::min(), str_len, error_val};
}
- return {is_positive
- ? static_cast<T>(result)
- : static_cast<T>(-static_cast<cpp::make_unsigned_t<T>>(result)),
- str_len, error_val};
+ return {
+ is_positive
+ ? static_cast<T>(result)
+ : static_cast<T>(
+ -static_cast<make_integral_or_big_int_unsigned_t<T>>(result)),
+ str_len, error_val};
}
} // namespace internal
diff --git a/libc/test/src/math/smoke/nanf128_test.cpp b/libc/test/src/math/smoke/nanf128_test.cpp
index 7767bf29718e31..2a9f57de5b43bc 100644
--- a/libc/test/src/math/smoke/nanf128_test.cpp
+++ b/libc/test/src/math/smoke/nanf128_test.cpp
@@ -36,8 +36,7 @@ TEST_F(LlvmLibcNanf128Test, NCharSeq) {
run_test("0x200000000000000000000", QUIET_NAN | (ONE << 81));
run_test("10384593717069655257060992658440191",
QUIET_NAN | FPBits128::SIG_MASK);
- run_test("0x1ffffffffffffffffffffffffffff",
- QUIET_NAN | FPBits128::SIG_MASK);
+ run_test("0x1ffffffffffffffffffffffffffff", QUIET_NAN | FPBits128::SIG_MASK);
run_test("10384593717069655257060992658440192", QUIET_NAN);
run_test("0x20000000000000000000000000000", QUIET_NAN);
run_test("1a", QUIET_NAN);
More information about the libc-commits
mailing list