Skip to content

Commit e4fa07a

Browse files
committed
[libc][math][c23] Add scalblnf16 C23 math function
1 parent faa9f52 commit e4fa07a

18 files changed

+118
-12
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
540540
libc.src.math.rintf16
541541
libc.src.math.roundf16
542542
libc.src.math.roundevenf16
543+
libc.src.math.scalblnf16
543544
libc.src.math.scalbnf16
544545
libc.src.math.truncf16
545546
libc.src.math.ufromfpf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
570570
libc.src.math.rintf16
571571
libc.src.math.roundf16
572572
libc.src.math.roundevenf16
573+
libc.src.math.scalblnf16
573574
libc.src.math.scalbnf16
574575
libc.src.math.truncf16
575576
libc.src.math.ufromfpf16

libc/docs/math/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ Basic Operations
208208
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
209209
| roundeven | |check| | |check| | |check| | |check| | |check| | 7.12.9.8 | F.10.6.8 |
210210
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
211+
| scalbln | | | | |check| | | 7.12.6.19 | F.10.3.19 |
212+
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
211213
| scalbn | |check| | |check| | |check| | |check| | |check| | 7.12.6.19 | F.10.3.19 |
212214
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
213215
| trunc | |check| | |check| | |check| | |check| | |check| | 7.12.9.9 | F.10.6.9 |

libc/spec/stdc.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ def StdC : StandardSpec<"stdc"> {
693693
FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
694694
FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
695695

696+
GuardedFunctionSpec<"scalblnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT16">,
697+
696698
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
697699
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
698700
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ LIBC_INLINE constexpr T logb(T x) {
144144
}
145145

146146
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
147-
LIBC_INLINE constexpr T ldexp(T x, int exp) {
147+
LIBC_INLINE constexpr T ldexp(T x, long exp) {
148148
FPBits<T> bits(x);
149149
if (LIBC_UNLIKELY((exp == 0) || bits.is_zero() || bits.is_inf_or_nan()))
150150
return x;
@@ -187,7 +187,9 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
187187

188188
// For all other values, NormalFloat to T conversion handles it the right way.
189189
DyadicFloat<cpp::max(FPBits<T>::STORAGE_LEN, 32)> normal(bits.get_val());
190-
normal.exponent += exp;
190+
// Make sure that exp fits into an int when not taking the fast paths above.
191+
static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
192+
normal.exponent += static_cast<int>(exp);
191193
return static_cast<T>(normal);
192194
}
193195

libc/src/math/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ add_math_entrypoint_object(roundevenl)
340340
add_math_entrypoint_object(roundevenf16)
341341
add_math_entrypoint_object(roundevenf128)
342342

343+
add_math_entrypoint_object(scalblnf16)
344+
343345
add_math_entrypoint_object(scalbn)
344346
add_math_entrypoint_object(scalbnf)
345347
add_math_entrypoint_object(scalbnl)

libc/src/math/generic/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3488,6 +3488,20 @@ add_entrypoint_object(
34883488
libc.src.__support.macros.optimization
34893489
)
34903490

3491+
add_entrypoint_object(
3492+
scalblnf16
3493+
SRCS
3494+
scalblnf16.cpp
3495+
HDRS
3496+
../scalblnf16.h
3497+
DEPENDS
3498+
libc.hdr.float_macros
3499+
libc.src.__support.macros.properties.types
3500+
libc.src.__support.FPUtil.manipulation_functions
3501+
COMPILE_OPTIONS
3502+
-O3
3503+
)
3504+
34913505
add_entrypoint_object(
34923506
scalbn
34933507
SRCS

libc/src/math/generic/scalblnf16.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===-- Implementation of scalblnf16 function -----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/math/scalblnf16.h"
10+
#include "src/__support/FPUtil/ManipulationFunctions.h"
11+
#include "src/__support/common.h"
12+
13+
#include "hdr/float_macros.h"
14+
15+
#if FLT_RADIX != 2
16+
#error "FLT_RADIX != 2 is not supported."
17+
#endif
18+
19+
namespace LIBC_NAMESPACE {
20+
21+
LLVM_LIBC_FUNCTION(float16, scalblnf16, (float16 x, long n)) {
22+
return fputil::ldexp(x, n);
23+
}
24+
25+
} // namespace LIBC_NAMESPACE

libc/src/math/scalblnf16.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for scalblnf16 --------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_MATH_SCALBLNF16_H
10+
#define LLVM_LIBC_SRC_MATH_SCALBLNF16_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 scalblnf16(float16 x, long n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_SCALBLNF16_H

libc/test/src/math/smoke/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,19 @@ add_fp_unittest(
34513451
libc.src.__support.FPUtil.fp_bits
34523452
)
34533453

3454+
add_fp_unittest(
3455+
scalblnf16_test
3456+
SUITE
3457+
libc-math-smoke-tests
3458+
SRCS
3459+
scalblnf16_test.cpp
3460+
HDRS
3461+
ScalbnTest.h
3462+
DEPENDS
3463+
libc.src.math.scalblnf16
3464+
libc.src.__support.FPUtil.fp_bits
3465+
)
3466+
34543467
add_fp_unittest(
34553468
scalbn_test
34563469
SUITE

libc/test/src/math/smoke/LdExpTest.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#include <stdint.h>
2020

21-
template <typename T>
21+
template <typename T, typename U = int>
2222
class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
2323
using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>;
2424
using NormalFloat = LIBC_NAMESPACE::fputil::NormalFloat<T>;
@@ -34,17 +34,28 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
3434
static constexpr StorageType MANTISSA = NormalFloat::ONE + 0x123;
3535

3636
public:
37-
typedef T (*LdExpFunc)(T, int);
37+
typedef T (*LdExpFunc)(T, U);
3838

3939
void testSpecialNumbers(LdExpFunc func) {
40-
int exp_array[5] = {-INT_MAX - 1, -10, 0, 10, INT_MAX};
40+
int exp_array[5] = {INT_MIN, -10, 0, 10, INT_MAX};
4141
for (int exp : exp_array) {
4242
ASSERT_FP_EQ(zero, func(zero, exp));
4343
ASSERT_FP_EQ(neg_zero, func(neg_zero, exp));
4444
ASSERT_FP_EQ(inf, func(inf, exp));
4545
ASSERT_FP_EQ(neg_inf, func(neg_inf, exp));
4646
ASSERT_FP_EQ(nan, func(nan, exp));
4747
}
48+
49+
if constexpr (sizeof(U) < sizeof(long) || sizeof(long) == sizeof(int))
50+
return;
51+
long long_exp_array[4] = {LONG_MIN, INT_MIN - 1L, INT_MAX + 1L, LONG_MAX};
52+
for (long exp : long_exp_array) {
53+
ASSERT_FP_EQ(zero, func(zero, exp));
54+
ASSERT_FP_EQ(neg_zero, func(neg_zero, exp));
55+
ASSERT_FP_EQ(inf, func(inf, exp));
56+
ASSERT_FP_EQ(neg_inf, func(neg_inf, exp));
57+
ASSERT_FP_EQ(nan, func(nan, exp));
58+
}
4859
}
4960

5061
void testPowersOfTwo(LdExpFunc func) {

libc/test/src/math/smoke/ScalbnTest.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
#include "LdExpTest.h"
1313
#include "test/UnitTest/Test.h"
1414

15-
#define LIST_SCALBN_TESTS(T, func) \
16-
using LlvmLibcScalbnTest = LdExpTestTemplate<T>; \
15+
#define LIST_SCALBN_TESTS(T, U, func) \
16+
using LlvmLibcScalbnTest = LdExpTestTemplate<T, U>; \
1717
TEST_F(LlvmLibcScalbnTest, SpecialNumbers) { testSpecialNumbers(&func); } \
1818
TEST_F(LlvmLibcScalbnTest, PowersOfTwo) { testPowersOfTwo(&func); } \
1919
TEST_F(LlvmLibcScalbnTest, OverFlow) { testOverflow(&func); } \
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//===-- Unittests for scalblnf16 ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "ScalbnTest.h"
10+
11+
#include "src/math/scalblnf16.h"
12+
13+
LIST_SCALBN_TESTS(float16, long, LIBC_NAMESPACE::scalblnf16)

libc/test/src/math/smoke/scalbn_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
#include "src/math/scalbn.h"
1212

13-
LIST_SCALBN_TESTS(double, LIBC_NAMESPACE::scalbn)
13+
LIST_SCALBN_TESTS(double, int, LIBC_NAMESPACE::scalbn)

libc/test/src/math/smoke/scalbnf128_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
#include "src/math/scalbnf128.h"
1212

13-
LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128)
13+
LIST_SCALBN_TESTS(float128, int, LIBC_NAMESPACE::scalbnf128)

libc/test/src/math/smoke/scalbnf16_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
#include "src/math/scalbnf16.h"
1212

13-
LIST_SCALBN_TESTS(float16, LIBC_NAMESPACE::scalbnf16)
13+
LIST_SCALBN_TESTS(float16, int, LIBC_NAMESPACE::scalbnf16)

libc/test/src/math/smoke/scalbnf_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
#include "src/math/scalbnf.h"
1212

13-
LIST_SCALBN_TESTS(float, LIBC_NAMESPACE::scalbnf)
13+
LIST_SCALBN_TESTS(float, int, LIBC_NAMESPACE::scalbnf)

libc/test/src/math/smoke/scalbnl_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010

1111
#include "src/math/scalbnl.h"
1212

13-
LIST_SCALBN_TESTS(long double, LIBC_NAMESPACE::scalbnl)
13+
LIST_SCALBN_TESTS(long double, int, LIBC_NAMESPACE::scalbnl)

0 commit comments

Comments
 (0)