[libc-commits] [libc] [libc][math][c23] Add {ldexp, scalbn, scalbln}f16 C23 math functions (PR #94797)
via libc-commits
libc-commits at lists.llvm.org
Fri Jun 7 13:04:31 PDT 2024
https://github.com/overmighty created https://github.com/llvm/llvm-project/pull/94797
Part of #93566.
>From 845a74cab68495cd66d1dfa2d5e5e8bf5b527ea6 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Fri, 7 Jun 2024 15:27:58 +0200
Subject: [PATCH 1/3] [libc][math][c23] Add ldexpf16 C23 math function
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/docs/math/index.rst | 2 +-
libc/spec/stdc.td | 1 +
.../__support/FPUtil/ManipulationFunctions.h | 2 +-
libc/src/__support/FPUtil/dyadic_float.h | 5 +++++
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/generic/CMakeLists.txt | 13 ++++++++++++
libc/src/math/generic/ldexpf16.cpp | 19 ++++++++++++++++++
libc/src/math/ldexpf16.h | 20 +++++++++++++++++++
libc/test/src/math/smoke/CMakeLists.txt | 15 ++++++++++++++
libc/test/src/math/smoke/LdExpTest.h | 16 +++++++--------
libc/test/src/math/smoke/ldexpf16_test.cpp | 13 ++++++++++++
13 files changed, 99 insertions(+), 10 deletions(-)
create mode 100644 libc/src/math/generic/ldexpf16.cpp
create mode 100644 libc/src/math/ldexpf16.h
create mode 100644 libc/test/src/math/smoke/ldexpf16_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 33ecff813a1fb..b5d8e894398ce 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -517,6 +517,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.fminimum_numf16
libc.src.math.fromfpf16
libc.src.math.fromfpxf16
+ libc.src.math.ldexpf16
libc.src.math.llrintf16
libc.src.math.llroundf16
libc.src.math.lrintf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e3ca544ae0185..e8fd94ed00a87 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -549,6 +549,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.fminimum_numf16
libc.src.math.fromfpf16
libc.src.math.fromfpxf16
+ libc.src.math.ldexpf16
libc.src.math.llrintf16
libc.src.math.llroundf16
libc.src.math.lrintf16
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index b9507f0887cd7..f99e9d5ebabad 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -170,7 +170,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| ilogb | |check| | |check| | |check| | | |check| | 7.12.6.8 | F.10.3.8 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| ldexp | |check| | |check| | |check| | | |check| | 7.12.6.9 | F.10.3.9 |
+| ldexp | |check| | |check| | |check| | |check| | |check| | 7.12.6.9 | F.10.3.9 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| llogb | |check| | |check| | |check| | | |check| | 7.12.6.10 | F.10.3.10 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 9a436c8ae38d2..d81bfd0442b08 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -525,6 +525,7 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"ldexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
FunctionSpec<"ldexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
FunctionSpec<"ldexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+ GuardedFunctionSpec<"ldexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"ldexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"log10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index a289c2ef70467..11ea6e3738d28 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -185,7 +185,7 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
}
// For all other values, NormalFloat to T conversion handles it the right way.
- DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());
+ DyadicFloat<cpp::max(FPBits<T>::STORAGE_LEN, 32)> normal(bits.get_val());
normal.exponent += exp;
return static_cast<T>(normal);
}
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 12a69228d36c7..f1791f9da56ad 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -14,6 +14,7 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/big_int.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/types.h" // float16
#include <stddef.h>
@@ -183,6 +184,10 @@ template <size_t Bits> struct DyadicFloat {
return r;
}
+ LIBC_INLINE explicit constexpr operator float16() const {
+ return static_cast<float16>(static_cast<float>(*this));
+ }
+
LIBC_INLINE explicit constexpr operator MantissaType() const {
if (mantissa.is_zero())
return 0;
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 7a349ddc53724..7e40a5f387d31 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -218,6 +218,7 @@ add_math_entrypoint_object(llogbf128)
add_math_entrypoint_object(ldexp)
add_math_entrypoint_object(ldexpf)
add_math_entrypoint_object(ldexpl)
+add_math_entrypoint_object(ldexpf16)
add_math_entrypoint_object(ldexpf128)
add_math_entrypoint_object(log10)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index b1d786fc6b29f..230fd95baaefb 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1448,6 +1448,19 @@ add_entrypoint_object(
libc.src.__support.FPUtil.manipulation_functions
)
+add_entrypoint_object(
+ ldexpf16
+ SRCS
+ ldexpf16.cpp
+ HDRS
+ ../ldexpf16.h
+ COMPILE_OPTIONS
+ -O0 -ggdb3
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.manipulation_functions
+)
+
add_entrypoint_object(
ldexpf128
SRCS
diff --git a/libc/src/math/generic/ldexpf16.cpp b/libc/src/math/generic/ldexpf16.cpp
new file mode 100644
index 0000000000000..ed15c4572edf5
--- /dev/null
+++ b/libc/src/math/generic/ldexpf16.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ldexpf16 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/ldexpf16.h"
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float16, ldexpf16, (float16 x, int exp)) {
+ return fputil::ldexp(x, exp);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/ldexpf16.h b/libc/src/math/ldexpf16.h
new file mode 100644
index 0000000000000..7303610b18dff
--- /dev/null
+++ b/libc/src/math/ldexpf16.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ldexpf16 ----------------------*- 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_LDEXPF16_H
+#define LLVM_LIBC_SRC_MATH_LDEXPF16_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float16 ldexpf16(float16 x, int exp);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_LDEXPF16_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 110fa1de97d6d..7329a87dd9ee6 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1508,6 +1508,21 @@ add_fp_unittest(
libc.src.__support.FPUtil.normal_float
)
+add_fp_unittest(
+ ldexpf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ldexpf16_test.cpp
+ HDRS
+ LdExpTest.h
+ DEPENDS
+ libc.src.math.ldexpf16
+ libc.src.__support.CPP.limits
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.normal_float
+)
+
add_fp_unittest(
ldexpf128_test
SUITE
diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h
index 713d305c47494..19c02d2dc7d0f 100644
--- a/libc/test/src/math/smoke/LdExpTest.h
+++ b/libc/test/src/math/smoke/LdExpTest.h
@@ -31,7 +31,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
const T nan = FPBits::quiet_nan().get_val();
// A normalized mantissa to be used with tests.
- static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x1234;
+ static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x123;
public:
typedef T (*LdExpFunc)(T, int);
@@ -60,7 +60,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
void testOverflow(LdExpFunc func) {
NormalFloat x(Sign::POS, FPBits::MAX_BIASED_EXPONENT - 10,
- NormalFloat::ONE + 0xF00BA);
+ NormalFloat::ONE + 0xF00);
for (int32_t exp = 10; exp < 100; ++exp) {
ASSERT_FP_EQ(inf, func(T(x), exp));
ASSERT_FP_EQ(neg_inf, func(-T(x), exp));
@@ -95,10 +95,10 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
void testNormalOperation(LdExpFunc func) {
T val_array[] = {// Normal numbers
- NormalFloat(Sign::POS, 100, MANTISSA),
- NormalFloat(Sign::POS, -100, MANTISSA),
- NormalFloat(Sign::NEG, 100, MANTISSA),
- NormalFloat(Sign::NEG, -100, MANTISSA),
+ NormalFloat(Sign::POS, 10, MANTISSA),
+ NormalFloat(Sign::POS, -10, MANTISSA),
+ NormalFloat(Sign::NEG, 10, MANTISSA),
+ NormalFloat(Sign::NEG, -10, MANTISSA),
// Subnormal numbers
NormalFloat(Sign::POS, -FPBits::EXP_BIAS, MANTISSA),
NormalFloat(Sign::NEG, -FPBits::EXP_BIAS, MANTISSA)};
@@ -114,8 +114,8 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
NormalFloat two_to_exp = NormalFloat(static_cast<T>(1.L));
two_to_exp = two_to_exp.mul2(exp);
- ASSERT_FP_EQ(func(x, exp), x * two_to_exp);
- ASSERT_FP_EQ(func(x, -exp), x / two_to_exp);
+ ASSERT_FP_EQ(func(x, exp), x * static_cast<T>(two_to_exp));
+ ASSERT_FP_EQ(func(x, -exp), x / static_cast<T>(two_to_exp));
}
}
diff --git a/libc/test/src/math/smoke/ldexpf16_test.cpp b/libc/test/src/math/smoke/ldexpf16_test.cpp
new file mode 100644
index 0000000000000..ecf8f76a3aac8
--- /dev/null
+++ b/libc/test/src/math/smoke/ldexpf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ldexpf16 --------------------------------------------===//
+//
+// 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 "LdExpTest.h"
+
+#include "src/math/ldexpf16.h"
+
+LIST_LDEXP_TESTS(float16, LIBC_NAMESPACE::ldexpf16);
>From f772f7ed5ae966098348fe869d42a1ff2c82adfa Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Fri, 7 Jun 2024 21:21:34 +0200
Subject: [PATCH 2/3] [libc][math][c23] Add scalbnf16 C23 math function
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/docs/math/index.rst | 2 +-
libc/spec/stdc.td | 1 +
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/generic/CMakeLists.txt | 14 ++++++++++++
libc/src/math/generic/scalbnf16.cpp | 25 +++++++++++++++++++++
libc/src/math/scalbnf16.h | 20 +++++++++++++++++
libc/test/src/math/smoke/CMakeLists.txt | 13 +++++++++++
libc/test/src/math/smoke/scalbnf16_test.cpp | 13 +++++++++++
10 files changed, 90 insertions(+), 1 deletion(-)
create mode 100644 libc/src/math/generic/scalbnf16.cpp
create mode 100644 libc/src/math/scalbnf16.h
create mode 100644 libc/test/src/math/smoke/scalbnf16_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b5d8e894398ce..fca339726802e 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -533,6 +533,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.scalbnf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e8fd94ed00a87..4c0472661de63 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -562,6 +562,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.scalbnf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index f99e9d5ebabad..4ec3cab3593c7 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -208,7 +208,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| roundeven | |check| | |check| | |check| | |check| | |check| | 7.12.9.8 | F.10.6.8 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| scalbn | |check| | |check| | |check| | | |check| | 7.12.6.19 | F.10.3.19 |
+| scalbn | |check| | |check| | |check| | |check| | |check| | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| trunc | |check| | |check| | |check| | |check| | |check| | 7.12.9.9 | F.10.6.9 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index d81bfd0442b08..011e7876fd52e 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -686,6 +686,7 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
+ GuardedFunctionSpec<"scalbnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"scalbnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 7e40a5f387d31..48ca0a350024d 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -333,6 +333,7 @@ add_math_entrypoint_object(roundevenf128)
add_math_entrypoint_object(scalbn)
add_math_entrypoint_object(scalbnf)
add_math_entrypoint_object(scalbnl)
+add_math_entrypoint_object(scalbnf16)
add_math_entrypoint_object(scalbnf128)
add_math_entrypoint_object(sincos)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 230fd95baaefb..d567a7f2abee2 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3407,6 +3407,20 @@ add_entrypoint_object(
-O3
)
+add_entrypoint_object(
+ scalbnf16
+ SRCS
+ scalbnf16.cpp
+ HDRS
+ ../scalbnf16.h
+ DEPENDS
+ libc.hdr.float_macros
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.manipulation_functions
+ COMPILE_OPTIONS
+ -O3
+)
+
add_entrypoint_object(
scalbnf128
SRCS
diff --git a/libc/src/math/generic/scalbnf16.cpp b/libc/src/math/generic/scalbnf16.cpp
new file mode 100644
index 0000000000000..a42fdfffd569f
--- /dev/null
+++ b/libc/src/math/generic/scalbnf16.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of scalbnf16 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/scalbnf16.h"
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+
+#include "hdr/float_macros.h"
+
+#if FLT_RADIX != 2
+#error "FLT_RADIX != 2 is not supported."
+#endif
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float16, scalbnf16, (float16 x, int n)) {
+ return fputil::ldexp(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/scalbnf16.h b/libc/src/math/scalbnf16.h
new file mode 100644
index 0000000000000..95e4862f38070
--- /dev/null
+++ b/libc/src/math/scalbnf16.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for scalbnf16 ---------------------*- 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_SCALBNF16_H
+#define LLVM_LIBC_SRC_MATH_SCALBNF16_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float16 scalbnf16(float16 x, int n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_SCALBNF16_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 7329a87dd9ee6..368a9be2c1169 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3345,6 +3345,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ scalbnf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ scalbnf16_test.cpp
+ HDRS
+ ScalbnTest.h
+ DEPENDS
+ libc.src.math.scalbnf16
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
scalbnf128_test
SUITE
diff --git a/libc/test/src/math/smoke/scalbnf16_test.cpp b/libc/test/src/math/smoke/scalbnf16_test.cpp
new file mode 100644
index 0000000000000..407cad5e7fabd
--- /dev/null
+++ b/libc/test/src/math/smoke/scalbnf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for scalbnf16 -------------------------------------------===//
+//
+// 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 "ScalbnTest.h"
+
+#include "src/math/scalbnf16.h"
+
+LIST_SCALBN_TESTS(float16, LIBC_NAMESPACE::scalbnf16)
>From ba03740b837e04578245bf7255238f054bc18429 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Fri, 7 Jun 2024 21:51:02 +0200
Subject: [PATCH 3/3] [libc][math][c23] Add scalblnf16 C23 math function
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/docs/math/index.rst | 2 ++
libc/spec/stdc.td | 2 ++
.../__support/FPUtil/ManipulationFunctions.h | 6 +++--
libc/src/math/CMakeLists.txt | 2 ++
libc/src/math/generic/CMakeLists.txt | 14 +++++++++++
libc/src/math/generic/scalblnf16.cpp | 25 +++++++++++++++++++
libc/src/math/scalblnf16.h | 20 +++++++++++++++
libc/test/src/math/smoke/CMakeLists.txt | 13 ++++++++++
libc/test/src/math/smoke/LdExpTest.h | 17 ++++++++++---
libc/test/src/math/smoke/ScalbnTest.h | 4 +--
libc/test/src/math/smoke/scalblnf16_test.cpp | 13 ++++++++++
libc/test/src/math/smoke/scalbn_test.cpp | 2 +-
libc/test/src/math/smoke/scalbnf128_test.cpp | 2 +-
libc/test/src/math/smoke/scalbnf16_test.cpp | 2 +-
libc/test/src/math/smoke/scalbnf_test.cpp | 2 +-
libc/test/src/math/smoke/scalbnl_test.cpp | 2 +-
18 files changed, 118 insertions(+), 12 deletions(-)
create mode 100644 libc/src/math/generic/scalblnf16.cpp
create mode 100644 libc/src/math/scalblnf16.h
create mode 100644 libc/test/src/math/smoke/scalblnf16_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index fca339726802e..f73b5c2f355d3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -533,6 +533,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.scalblnf16
libc.src.math.scalbnf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 4c0472661de63..2fd89386c084d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -562,6 +562,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
+ libc.src.math.scalblnf16
libc.src.math.scalbnf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index 4ec3cab3593c7..fbcec72b0a1c7 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -208,6 +208,8 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| roundeven | |check| | |check| | |check| | |check| | |check| | 7.12.9.8 | F.10.6.8 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
+| scalbln | | | | |check| | | 7.12.6.19 | F.10.3.19 |
++------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| scalbn | |check| | |check| | |check| | |check| | |check| | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| trunc | |check| | |check| | |check| | |check| | |check| | 7.12.9.9 | F.10.6.9 |
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 011e7876fd52e..ed3461bfeab53 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -683,6 +683,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
+ GuardedFunctionSpec<"scalblnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT16">,
+
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index 11ea6e3738d28..a9c64122d9311 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -143,7 +143,7 @@ LIBC_INLINE constexpr T logb(T x) {
}
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE constexpr T ldexp(T x, int exp) {
+LIBC_INLINE constexpr T ldexp(T x, long exp) {
FPBits<T> bits(x);
if (LIBC_UNLIKELY((exp == 0) || bits.is_zero() || bits.is_inf_or_nan()))
return x;
@@ -186,7 +186,9 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
// For all other values, NormalFloat to T conversion handles it the right way.
DyadicFloat<cpp::max(FPBits<T>::STORAGE_LEN, 32)> normal(bits.get_val());
- normal.exponent += exp;
+ // Make sure that exp fits into an int when not taking the fast paths above.
+ static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
+ normal.exponent += static_cast<int>(exp);
return static_cast<T>(normal);
}
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 48ca0a350024d..f7d3998fe318c 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -330,6 +330,8 @@ add_math_entrypoint_object(roundevenl)
add_math_entrypoint_object(roundevenf16)
add_math_entrypoint_object(roundevenf128)
+add_math_entrypoint_object(scalblnf16)
+
add_math_entrypoint_object(scalbn)
add_math_entrypoint_object(scalbnf)
add_math_entrypoint_object(scalbnl)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index d567a7f2abee2..406afa6fa251a 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3368,6 +3368,20 @@ add_entrypoint_object(
libc.src.__support.macros.optimization
)
+add_entrypoint_object(
+ scalblnf16
+ SRCS
+ scalblnf16.cpp
+ HDRS
+ ../scalblnf16.h
+ DEPENDS
+ libc.hdr.float_macros
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.manipulation_functions
+ COMPILE_OPTIONS
+ -O3
+)
+
add_entrypoint_object(
scalbn
SRCS
diff --git a/libc/src/math/generic/scalblnf16.cpp b/libc/src/math/generic/scalblnf16.cpp
new file mode 100644
index 0000000000000..844a071d754a6
--- /dev/null
+++ b/libc/src/math/generic/scalblnf16.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of scalblnf16 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/scalblnf16.h"
+#include "src/__support/FPUtil/ManipulationFunctions.h"
+#include "src/__support/common.h"
+
+#include "hdr/float_macros.h"
+
+#if FLT_RADIX != 2
+#error "FLT_RADIX != 2 is not supported."
+#endif
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float16, scalblnf16, (float16 x, long n)) {
+ return fputil::ldexp(x, n);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/scalblnf16.h b/libc/src/math/scalblnf16.h
new file mode 100644
index 0000000000000..be93fab1bf68a
--- /dev/null
+++ b/libc/src/math/scalblnf16.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for scalblnf16 --------------------*- 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_SCALBLNF16_H
+#define LLVM_LIBC_SRC_MATH_SCALBLNF16_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float16 scalblnf16(float16 x, long n);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_SCALBLNF16_H
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 368a9be2c1169..a302e9d89511d 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3306,6 +3306,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)
+add_fp_unittest(
+ scalblnf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ scalblnf16_test.cpp
+ HDRS
+ ScalbnTest.h
+ DEPENDS
+ libc.src.math.scalblnf16
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
scalbn_test
SUITE
diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h
index 19c02d2dc7d0f..231535a9a505e 100644
--- a/libc/test/src/math/smoke/LdExpTest.h
+++ b/libc/test/src/math/smoke/LdExpTest.h
@@ -18,7 +18,7 @@
#include <stdint.h>
-template <typename T>
+template <typename T, typename U = int>
class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
using NormalFloat = LIBC_NAMESPACE::fputil::NormalFloat<T>;
@@ -34,10 +34,10 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x123;
public:
- typedef T (*LdExpFunc)(T, int);
+ typedef T (*LdExpFunc)(T, U);
void testSpecialNumbers(LdExpFunc func) {
- int exp_array[5] = {-INT_MAX - 1, -10, 0, 10, INT_MAX};
+ int exp_array[5] = {INT_MIN, -10, 0, 10, INT_MAX};
for (int exp : exp_array) {
ASSERT_FP_EQ(zero, func(zero, exp));
ASSERT_FP_EQ(neg_zero, func(neg_zero, exp));
@@ -45,6 +45,17 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
ASSERT_FP_EQ(neg_inf, func(neg_inf, exp));
ASSERT_FP_EQ(nan, func(nan, exp));
}
+
+ if constexpr (sizeof(U) < sizeof(long) || sizeof(long) == sizeof(int))
+ return;
+ long long_exp_array[4] = {LONG_MIN, INT_MIN - 1L, INT_MAX + 1L, LONG_MAX};
+ for (long exp : long_exp_array) {
+ ASSERT_FP_EQ(zero, func(zero, exp));
+ ASSERT_FP_EQ(neg_zero, func(neg_zero, exp));
+ ASSERT_FP_EQ(inf, func(inf, exp));
+ ASSERT_FP_EQ(neg_inf, func(neg_inf, exp));
+ ASSERT_FP_EQ(nan, func(nan, exp));
+ }
}
void testPowersOfTwo(LdExpFunc func) {
diff --git a/libc/test/src/math/smoke/ScalbnTest.h b/libc/test/src/math/smoke/ScalbnTest.h
index e1d035c4ea3aa..67ea30f9f0df6 100644
--- a/libc/test/src/math/smoke/ScalbnTest.h
+++ b/libc/test/src/math/smoke/ScalbnTest.h
@@ -12,8 +12,8 @@
#include "LdExpTest.h"
#include "test/UnitTest/Test.h"
-#define LIST_SCALBN_TESTS(T, func) \
- using LlvmLibcScalbnTest = LdExpTestTemplate<T>; \
+#define LIST_SCALBN_TESTS(T, U, func) \
+ using LlvmLibcScalbnTest = LdExpTestTemplate<T, U>; \
TEST_F(LlvmLibcScalbnTest, SpecialNumbers) { testSpecialNumbers(&func); } \
TEST_F(LlvmLibcScalbnTest, PowersOfTwo) { testPowersOfTwo(&func); } \
TEST_F(LlvmLibcScalbnTest, OverFlow) { testOverflow(&func); } \
diff --git a/libc/test/src/math/smoke/scalblnf16_test.cpp b/libc/test/src/math/smoke/scalblnf16_test.cpp
new file mode 100644
index 0000000000000..a678254292901
--- /dev/null
+++ b/libc/test/src/math/smoke/scalblnf16_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for scalblnf16 ------------------------------------------===//
+//
+// 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 "ScalbnTest.h"
+
+#include "src/math/scalblnf16.h"
+
+LIST_SCALBN_TESTS(float16, long, LIBC_NAMESPACE::scalblnf16)
diff --git a/libc/test/src/math/smoke/scalbn_test.cpp b/libc/test/src/math/smoke/scalbn_test.cpp
index 413a2395ca3c5..86ad71b01c2bb 100644
--- a/libc/test/src/math/smoke/scalbn_test.cpp
+++ b/libc/test/src/math/smoke/scalbn_test.cpp
@@ -10,4 +10,4 @@
#include "src/math/scalbn.h"
-LIST_SCALBN_TESTS(double, LIBC_NAMESPACE::scalbn)
+LIST_SCALBN_TESTS(double, int, LIBC_NAMESPACE::scalbn)
diff --git a/libc/test/src/math/smoke/scalbnf128_test.cpp b/libc/test/src/math/smoke/scalbnf128_test.cpp
index dc259de211489..b42902a76a228 100644
--- a/libc/test/src/math/smoke/scalbnf128_test.cpp
+++ b/libc/test/src/math/smoke/scalbnf128_test.cpp
@@ -10,4 +10,4 @@
#include "src/math/scalbnf128.h"
-LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128)
+LIST_SCALBN_TESTS(float128, int, LIBC_NAMESPACE::scalbnf128)
diff --git a/libc/test/src/math/smoke/scalbnf16_test.cpp b/libc/test/src/math/smoke/scalbnf16_test.cpp
index 407cad5e7fabd..9cee0d04780e5 100644
--- a/libc/test/src/math/smoke/scalbnf16_test.cpp
+++ b/libc/test/src/math/smoke/scalbnf16_test.cpp
@@ -10,4 +10,4 @@
#include "src/math/scalbnf16.h"
-LIST_SCALBN_TESTS(float16, LIBC_NAMESPACE::scalbnf16)
+LIST_SCALBN_TESTS(float16, int, LIBC_NAMESPACE::scalbnf16)
diff --git a/libc/test/src/math/smoke/scalbnf_test.cpp b/libc/test/src/math/smoke/scalbnf_test.cpp
index e97781c2b2354..b25db4e8175e9 100644
--- a/libc/test/src/math/smoke/scalbnf_test.cpp
+++ b/libc/test/src/math/smoke/scalbnf_test.cpp
@@ -10,4 +10,4 @@
#include "src/math/scalbnf.h"
-LIST_SCALBN_TESTS(float, LIBC_NAMESPACE::scalbnf)
+LIST_SCALBN_TESTS(float, int, LIBC_NAMESPACE::scalbnf)
diff --git a/libc/test/src/math/smoke/scalbnl_test.cpp b/libc/test/src/math/smoke/scalbnl_test.cpp
index b0e0053790902..838b0650c5ad9 100644
--- a/libc/test/src/math/smoke/scalbnl_test.cpp
+++ b/libc/test/src/math/smoke/scalbnl_test.cpp
@@ -10,4 +10,4 @@
#include "src/math/scalbnl.h"
-LIST_SCALBN_TESTS(long double, LIBC_NAMESPACE::scalbnl)
+LIST_SCALBN_TESTS(long double, int, LIBC_NAMESPACE::scalbnl)
More information about the libc-commits
mailing list