Skip to content

Commit 9747ab5

Browse files
overmightyAlexisPerry
authored andcommitted
[libc][math][c23] Add {ldexp,scalbn,scalbln}f16 C23 math functions (llvm#94797)
Part of llvm#93566.
1 parent 02ed4f5 commit 9747ab5

26 files changed

+322
-32
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
524524
libc.src.math.fromfpxf16
525525
libc.src.math.getpayloadf16
526526
libc.src.math.ilogbf16
527+
libc.src.math.ldexpf16
527528
libc.src.math.llogbf16
528529
libc.src.math.llrintf16
529530
libc.src.math.llroundf16
@@ -545,6 +546,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
545546
libc.src.math.rintf16
546547
libc.src.math.roundf16
547548
libc.src.math.roundevenf16
549+
libc.src.math.scalblnf16
550+
libc.src.math.scalbnf16
548551
libc.src.math.setpayloadf16
549552
libc.src.math.setpayloadsigf16
550553
libc.src.math.totalorderf16

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
557557
libc.src.math.fromfpxf16
558558
libc.src.math.getpayloadf16
559559
libc.src.math.ilogbf16
560+
libc.src.math.ldexpf16
560561
libc.src.math.llogbf16
561562
libc.src.math.llrintf16
562563
libc.src.math.llroundf16
@@ -575,6 +576,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
575576
libc.src.math.rintf16
576577
libc.src.math.roundf16
577578
libc.src.math.roundevenf16
579+
libc.src.math.scalblnf16
580+
libc.src.math.scalbnf16
578581
libc.src.math.setpayloadf16
579582
libc.src.math.setpayloadsigf16
580583
libc.src.math.totalorderf16

libc/docs/math/index.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Basic Operations
174174
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
175175
| ilogb | |check| | |check| | |check| | |check| | |check| | 7.12.6.8 | F.10.3.8 |
176176
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
177-
| ldexp | |check| | |check| | |check| | | |check| | 7.12.6.9 | F.10.3.9 |
177+
| ldexp | |check| | |check| | |check| | |check| | |check| | 7.12.6.9 | F.10.3.9 |
178178
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
179179
| llogb | |check| | |check| | |check| | |check| | |check| | 7.12.6.10 | F.10.3.10 |
180180
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
@@ -212,7 +212,9 @@ Basic Operations
212212
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
213213
| roundeven | |check| | |check| | |check| | |check| | |check| | 7.12.9.8 | F.10.6.8 |
214214
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
215-
| scalbn | |check| | |check| | |check| | | |check| | 7.12.6.19 | F.10.3.19 |
215+
| scalbln | | | | |check| | | 7.12.6.19 | F.10.3.19 |
216+
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
217+
| scalbn | |check| | |check| | |check| | |check| | |check| | 7.12.6.19 | F.10.3.19 |
216218
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
217219
| setpayload | | | | |check| | | F.10.13.2 | N/A |
218220
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

libc/spec/stdc.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ def StdC : StandardSpec<"stdc"> {
533533
FunctionSpec<"ldexp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
534534
FunctionSpec<"ldexpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
535535
FunctionSpec<"ldexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
536+
GuardedFunctionSpec<"ldexpf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
536537
GuardedFunctionSpec<"ldexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
537538

538539
FunctionSpec<"log10", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>,
@@ -695,9 +696,12 @@ def StdC : StandardSpec<"stdc"> {
695696
FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
696697
FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
697698

699+
GuardedFunctionSpec<"scalblnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<LongType>], "LIBC_TYPES_HAS_FLOAT16">,
700+
698701
FunctionSpec<"scalbn", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>]>,
699702
FunctionSpec<"scalbnf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>]>,
700703
FunctionSpec<"scalbnl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>]>,
704+
GuardedFunctionSpec<"scalbnf16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT16">,
701705
GuardedFunctionSpec<"scalbnf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntType>], "LIBC_TYPES_HAS_FLOAT128">,
702706

703707
FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>,

libc/src/__support/FPUtil/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ add_header_library(
201201
DEPENDS
202202
.fp_bits
203203
.multiply_add
204+
libc.src.__support.CPP.type_traits
204205
libc.src.__support.big_int
205-
libc.src.__support.common
206206
libc.src.__support.macros.optimization
207207
)
208208

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,10 @@ LIBC_INLINE constexpr T logb(T x) {
142142
return static_cast<T>(normal.get_unbiased_exponent());
143143
}
144144

145-
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
146-
LIBC_INLINE constexpr T ldexp(T x, int exp) {
145+
template <typename T, typename U>
146+
LIBC_INLINE constexpr cpp::enable_if_t<
147+
cpp::is_floating_point_v<T> && cpp::is_integral_v<U>, T>
148+
ldexp(T x, U exp) {
147149
FPBits<T> bits(x);
148150
if (LIBC_UNLIKELY((exp == 0) || bits.is_zero() || bits.is_inf_or_nan()))
149151
return x;
@@ -156,6 +158,8 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
156158
// calculating the limit.
157159
constexpr int EXP_LIMIT =
158160
FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
161+
// Make sure that we can safely cast exp to int when not returning early.
162+
static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
159163
if (LIBC_UNLIKELY(exp > EXP_LIMIT)) {
160164
int rounding_mode = quick_get_round();
161165
Sign sign = bits.sign();
@@ -186,7 +190,7 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
186190

187191
// For all other values, NormalFloat to T conversion handles it the right way.
188192
DyadicFloat<FPBits<T>::STORAGE_LEN> normal(bits.get_val());
189-
normal.exponent += exp;
193+
normal.exponent += static_cast<int>(exp);
190194
return static_cast<T>(normal);
191195
}
192196

libc/src/__support/FPUtil/dyadic_float.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ template <size_t Bits> struct DyadicFloat {
126126
shift >= MantissaType::BITS ? MantissaType(0) : mantissa >> shift;
127127

128128
T d_hi = FPBits<T>::create_value(
129-
sign, exp_hi,
129+
sign, static_cast<output_bits_t>(exp_hi),
130130
(static_cast<output_bits_t>(m_hi) & FPBits<T>::SIG_MASK) |
131131
IMPLICIT_MASK)
132132
.get_val();
@@ -143,33 +143,41 @@ template <size_t Bits> struct DyadicFloat {
143143

144144
if (LIBC_UNLIKELY(exp_lo <= 0)) {
145145
// d_lo is denormal, but the output is normal.
146-
int scale_up_exponent = 2 * PRECISION;
146+
int scale_up_exponent = 1 - exp_lo;
147147
T scale_up_factor =
148-
FPBits<T>::create_value(sign, FPBits<T>::EXP_BIAS + scale_up_exponent,
148+
FPBits<T>::create_value(sign,
149+
static_cast<output_bits_t>(
150+
FPBits<T>::EXP_BIAS + scale_up_exponent),
149151
IMPLICIT_MASK)
150152
.get_val();
151153
T scale_down_factor =
152-
FPBits<T>::create_value(sign, FPBits<T>::EXP_BIAS - scale_up_exponent,
154+
FPBits<T>::create_value(sign,
155+
static_cast<output_bits_t>(
156+
FPBits<T>::EXP_BIAS - scale_up_exponent),
153157
IMPLICIT_MASK)
154158
.get_val();
155159

156-
d_lo = FPBits<T>::create_value(sign, exp_lo + scale_up_exponent,
157-
IMPLICIT_MASK)
160+
d_lo = FPBits<T>::create_value(
161+
sign, static_cast<output_bits_t>(exp_lo + scale_up_exponent),
162+
IMPLICIT_MASK)
158163
.get_val();
159164

160165
return multiply_add(d_lo, T(round_and_sticky), d_hi * scale_up_factor) *
161166
scale_down_factor;
162167
}
163168

164-
d_lo = FPBits<T>::create_value(sign, exp_lo, IMPLICIT_MASK).get_val();
169+
d_lo = FPBits<T>::create_value(sign, static_cast<output_bits_t>(exp_lo),
170+
IMPLICIT_MASK)
171+
.get_val();
165172

166173
// Still correct without FMA instructions if `d_lo` is not underflow.
167174
T r = multiply_add(d_lo, T(round_and_sticky), d_hi);
168175

169176
if (LIBC_UNLIKELY(denorm)) {
170177
// Exponent before rounding is in denormal range, simply clear the
171178
// exponent field.
172-
output_bits_t clear_exp = (output_bits_t(exp_hi) << FPBits<T>::SIG_LEN);
179+
output_bits_t clear_exp = static_cast<output_bits_t>(
180+
output_bits_t(exp_hi) << FPBits<T>::SIG_LEN);
173181
output_bits_t r_bits = FPBits<T>(r).uintval() - clear_exp;
174182
if (!(r_bits & FPBits<T>::EXP_MASK)) {
175183
// Output is denormal after rounding, clear the implicit bit for 80-bit

libc/src/__support/big_int.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
302302
dst = static_cast<word>((part1 << bit_offset) |
303303
(part2 >> (WORD_BITS - bit_offset)));
304304
else
305-
dst = (part1 >> bit_offset) | (part2 << (WORD_BITS - bit_offset));
305+
dst = static_cast<word>((part1 >> bit_offset) |
306+
(part2 << (WORD_BITS - bit_offset)));
306307
}
307308
return out;
308309
}

libc/src/math/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ add_math_entrypoint_object(llogbf128)
230230
add_math_entrypoint_object(ldexp)
231231
add_math_entrypoint_object(ldexpf)
232232
add_math_entrypoint_object(ldexpl)
233+
add_math_entrypoint_object(ldexpf16)
233234
add_math_entrypoint_object(ldexpf128)
234235

235236
add_math_entrypoint_object(log10)
@@ -347,9 +348,12 @@ add_math_entrypoint_object(roundevenl)
347348
add_math_entrypoint_object(roundevenf16)
348349
add_math_entrypoint_object(roundevenf128)
349350

351+
add_math_entrypoint_object(scalblnf16)
352+
350353
add_math_entrypoint_object(scalbn)
351354
add_math_entrypoint_object(scalbnf)
352355
add_math_entrypoint_object(scalbnl)
356+
add_math_entrypoint_object(scalbnf16)
353357
add_math_entrypoint_object(scalbnf128)
354358

355359
add_math_entrypoint_object(setpayloadf16)

libc/src/math/generic/CMakeLists.txt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,19 @@ add_entrypoint_object(
14871487
libc.src.__support.FPUtil.manipulation_functions
14881488
)
14891489

1490+
add_entrypoint_object(
1491+
ldexpf16
1492+
SRCS
1493+
ldexpf16.cpp
1494+
HDRS
1495+
../ldexpf16.h
1496+
COMPILE_OPTIONS
1497+
-O3
1498+
DEPENDS
1499+
libc.src.__support.macros.properties.types
1500+
libc.src.__support.FPUtil.manipulation_functions
1501+
)
1502+
14901503
add_entrypoint_object(
14911504
ldexpf128
14921505
SRCS
@@ -3501,6 +3514,20 @@ add_entrypoint_object(
35013514
libc.src.__support.macros.optimization
35023515
)
35033516

3517+
add_entrypoint_object(
3518+
scalblnf16
3519+
SRCS
3520+
scalblnf16.cpp
3521+
HDRS
3522+
../scalblnf16.h
3523+
DEPENDS
3524+
libc.hdr.float_macros
3525+
libc.src.__support.macros.properties.types
3526+
libc.src.__support.FPUtil.manipulation_functions
3527+
COMPILE_OPTIONS
3528+
-O3
3529+
)
3530+
35043531
add_entrypoint_object(
35053532
scalbn
35063533
SRCS
@@ -3540,6 +3567,20 @@ add_entrypoint_object(
35403567
-O3
35413568
)
35423569

3570+
add_entrypoint_object(
3571+
scalbnf16
3572+
SRCS
3573+
scalbnf16.cpp
3574+
HDRS
3575+
../scalbnf16.h
3576+
DEPENDS
3577+
libc.hdr.float_macros
3578+
libc.src.__support.macros.properties.types
3579+
libc.src.__support.FPUtil.manipulation_functions
3580+
COMPILE_OPTIONS
3581+
-O3
3582+
)
3583+
35433584
add_entrypoint_object(
35443585
scalbnf128
35453586
SRCS

libc/src/math/generic/ldexpf16.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of ldexpf16 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/ldexpf16.h"
10+
#include "src/__support/FPUtil/ManipulationFunctions.h"
11+
#include "src/__support/common.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(float16, ldexpf16, (float16 x, int exp)) {
16+
return fputil::ldexp(x, exp);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

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/generic/scalbnf16.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===-- Implementation of scalbnf16 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/scalbnf16.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, scalbnf16, (float16 x, int n)) {
22+
return fputil::ldexp(x, n);
23+
}
24+
25+
} // namespace LIBC_NAMESPACE

libc/src/math/ldexpf16.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for ldexpf16 ----------------------*- 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_LDEXPF16_H
10+
#define LLVM_LIBC_SRC_MATH_LDEXPF16_H
11+
12+
#include "src/__support/macros/properties/types.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
float16 ldexpf16(float16 x, int exp);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_MATH_LDEXPF16_H

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

0 commit comments

Comments
 (0)