diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index 5f72793beecb4..c4ec03fc146e8 100644 --- a/libc/config/baremetal/aarch64/entrypoints.txt +++ b/libc/config/baremetal/aarch64/entrypoints.txt @@ -788,6 +788,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 244dd2e87b1fd..d9e173a71e47a 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -791,6 +791,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 32980c4a1d222..9b0cf14037fae 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -791,6 +791,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt index 3684713474cbc..2a634852a2ed0 100644 --- a/libc/config/darwin/aarch64/entrypoints.txt +++ b/libc/config/darwin/aarch64/entrypoints.txt @@ -621,6 +621,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt index 7482a80c37d33..6a18d557f86fb 100644 --- a/libc/config/darwin/x86_64/entrypoints.txt +++ b/libc/config/darwin/x86_64/entrypoints.txt @@ -264,6 +264,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt index a88c74be2997a..008f7c7bd642c 100644 --- a/libc/config/gpu/amdgpu/entrypoints.txt +++ b/libc/config/gpu/amdgpu/entrypoints.txt @@ -647,6 +647,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt index d10b820caeeac..7d36aa4eb40f9 100644 --- a/libc/config/gpu/nvptx/entrypoints.txt +++ b/libc/config/gpu/nvptx/entrypoints.txt @@ -649,6 +649,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index b1fdee76af934..d04a382de494d 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -876,6 +876,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 8f21976e9e88e..865392a918624 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -491,6 +491,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 69d7519118198..207608c431a9b 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -894,6 +894,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 786c16dac5b06..2ba2b6874e2e5 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -927,6 +927,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 541d9fee1adf5..32a6a578aae13 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -337,6 +337,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS libc.src.math.fromfpbf16 libc.src.math.fromfpxbf16 libc.src.math.getpayloadbf16 + libc.src.math.nanbf16 libc.src.math.nextafterbf16 libc.src.math.nextdownbf16 libc.src.math.nexttowardbf16 diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst index 4d6e0cc4c88f1..1481992815857 100644 --- a/libc/docs/headers/math/index.rst +++ b/libc/docs/headers/math/index.rst @@ -211,7 +211,7 @@ Basic Operations +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ | modf | |check| | |check| | |check| | |check| | |check| | | 7.12.6.18 | F.10.3.18 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ -| nan | |check| | |check| | |check| | |check| | |check| | | 7.12.11.2 | F.10.8.2 | +| nan | |check| | |check| | |check| | |check| | |check| | |check| | 7.12.11.2 | F.10.8.2 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ | nearbyint | |check| | |check| | |check| | |check| | |check| | | 7.12.9.3 | F.10.6.3 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index 2357b053b60b8..994237ba8492e 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -354,7 +354,10 @@ LIBC_INLINE cpp::enable_if_t, T> getpayload(T x) { return static_cast(payload_dfloat); } else { - return static_cast(payload); + if constexpr (cpp::is_same_v) + return T(static_cast(payload)); + else + return static_cast(payload); } } diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index d3afce514a000..a90c5ebcee244 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -422,6 +422,7 @@ add_math_entrypoint_object(nanf) add_math_entrypoint_object(nanl) add_math_entrypoint_object(nanf16) add_math_entrypoint_object(nanf128) +add_math_entrypoint_object(nanbf16) 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 fd3442f912172..3f13066c19d3a 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -3432,6 +3432,22 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + nanbf16 + SRCS + nanbf16.cpp + HDRS + ../nanbf16.h + DEPENDS + libc.src.errno.errno + libc.src.__support.common + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.libc_errno + libc.src.__support.macros.config + libc.src.__support.macros.properties.types + libc.src.__support.str_to_float +) + add_entrypoint_object( nextafter SRCS diff --git a/libc/src/math/generic/nanbf16.cpp b/libc/src/math/generic/nanbf16.cpp new file mode 100644 index 0000000000000..678dd6aed9ee3 --- /dev/null +++ b/libc/src/math/generic/nanbf16.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of nanbf16 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/nanbf16.h" +#include "src/__support/FPUtil/bfloat16.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(bfloat16, nanbf16, (const char *arg)) { + auto result = internal::strtonan(arg); + if (result.has_error()) + libc_errno = result.error; + return result.value; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/nanbf16.h b/libc/src/math/nanbf16.h new file mode 100644 index 0000000000000..1551044677768 --- /dev/null +++ b/libc/src/math/nanbf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for nanbf16 -----------------------*- 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_NANBF16_H +#define LLVM_LIBC_SRC_MATH_NANBF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +bfloat16 nanbf16(const char *arg); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_NANBF16_H diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index a44f237cf0aad..65da1198a4044 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -3515,6 +3515,22 @@ add_fp_unittest( UNIT_TEST_ONLY ) +add_fp_unittest( + nanbf16_test + SUITE + libc-math-smoke-tests + SRCS + nanbf16_test.cpp + DEPENDS + libc.hdr.signal_macros + libc.src.math.nanbf16 + libc.src.__support.FPUtil.bfloat16 + 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( nearbyint_test SUITE diff --git a/libc/test/src/math/smoke/nanbf16_test.cpp b/libc/test/src/math/smoke/nanbf16_test.cpp new file mode 100644 index 0000000000000..4154f6ed637c8 --- /dev/null +++ b/libc/test/src/math/smoke/nanbf16_test.cpp @@ -0,0 +1,55 @@ +//===-- Unittests for nanbf16 ---------------------------------------------===// +// +// 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 "hdr/signal_macros.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/bfloat16.h" +#include "src/math/nanbf16.h" +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +class LlvmLibcNanf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest { +public: + using StorageType = LIBC_NAMESPACE::fputil::FPBits::StorageType; + + void run_test(const char *input_str, StorageType bits) { + bfloat16 result = LIBC_NAMESPACE::nanbf16(input_str); + auto actual_fp = LIBC_NAMESPACE::fputil::FPBits(result); + auto expected_fp = LIBC_NAMESPACE::fputil::FPBits(bits); + EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval()); + } +}; + +TEST_F(LlvmLibcNanf16Test, NCharSeq) { + run_test("", 0x7fc0); + + // 0x7fc0 + 0x1f (31) = 0x7cdf + run_test("31", 0x7fdf); + + // 0x7fc0 + 0x15 = 0x7fd5 + run_test("0x15", 0x7fd5); + + run_test("1a", 0x7fc0); + run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_", + 0x7fc0); + run_test("10000000000000000000000000000", 0x7fc0); +} + +TEST_F(LlvmLibcNanf16Test, RandomString) { + run_test(" 1234", 0x7fc0); + run_test("-1234", 0x7fc0); + run_test("asd&f", 0x7fc0); + run_test("123 ", 0x7fc0); +} + +#if defined(LIBC_ADD_NULL_CHECKS) +TEST_F(LlvmLibcNanf16Test, InvalidInput) { + EXPECT_DEATH([] { LIBC_NAMESPACE::nanbf16(nullptr); }, WITH_SIGNAL(-1)); +} +#endif // LIBC_ADD_NULL_CHECKS