Skip to content

Commit 4e4a9e1

Browse files
committed
fixup! [libc][math][c23] Add ldexpf16 C23 math function
1 parent 4541c4c commit 4e4a9e1

File tree

5 files changed

+27
-21
lines changed

5 files changed

+27
-21
lines changed

libc/src/__support/FPUtil/ManipulationFunctions.h

Lines changed: 7 additions & 5 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, long 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, long 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();
@@ -185,9 +189,7 @@ LIBC_INLINE constexpr T ldexp(T x, long exp) {
185189
}
186190

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

libc/src/__support/FPUtil/dyadic_float.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "src/__support/CPP/type_traits.h"
1515
#include "src/__support/big_int.h"
1616
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
17-
#include "src/__support/macros/properties/types.h" // float16
1817

1918
#include <stddef.h>
2019

@@ -127,7 +126,7 @@ template <size_t Bits> struct DyadicFloat {
127126
shift >= MantissaType::BITS ? MantissaType(0) : mantissa >> shift;
128127

129128
T d_hi = FPBits<T>::create_value(
130-
sign, exp_hi,
129+
sign, static_cast<output_bits_t>(exp_hi),
131130
(static_cast<output_bits_t>(m_hi) & FPBits<T>::SIG_MASK) |
132131
IMPLICIT_MASK)
133132
.get_val();
@@ -144,33 +143,41 @@ template <size_t Bits> struct DyadicFloat {
144143

145144
if (LIBC_UNLIKELY(exp_lo <= 0)) {
146145
// d_lo is denormal, but the output is normal.
147-
int scale_up_exponent = 2 * PRECISION;
146+
int scale_up_exponent = 1 - exp_lo;
148147
T scale_up_factor =
149-
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),
150151
IMPLICIT_MASK)
151152
.get_val();
152153
T scale_down_factor =
153-
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),
154157
IMPLICIT_MASK)
155158
.get_val();
156159

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

161165
return multiply_add(d_lo, T(round_and_sticky), d_hi * scale_up_factor) *
162166
scale_down_factor;
163167
}
164168

165-
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();
166172

167173
// Still correct without FMA instructions if `d_lo` is not underflow.
168174
T r = multiply_add(d_lo, T(round_and_sticky), d_hi);
169175

170176
if (LIBC_UNLIKELY(denorm)) {
171177
// Exponent before rounding is in denormal range, simply clear the
172178
// exponent field.
173-
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);
174181
output_bits_t r_bits = FPBits<T>(r).uintval() - clear_exp;
175182
if (!(r_bits & FPBits<T>::EXP_MASK)) {
176183
// Output is denormal after rounding, clear the implicit bit for 80-bit
@@ -184,10 +191,6 @@ template <size_t Bits> struct DyadicFloat {
184191
return r;
185192
}
186193

187-
LIBC_INLINE explicit constexpr operator float16() const {
188-
return static_cast<float16>(static_cast<float>(*this));
189-
}
190-
191194
LIBC_INLINE explicit constexpr operator MantissaType() const {
192195
if (mantissa.is_zero())
193196
return 0;

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/generic/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,7 @@ add_entrypoint_object(
14941494
HDRS
14951495
../ldexpf16.h
14961496
COMPILE_OPTIONS
1497-
-O0 -ggdb3
1497+
-O3
14981498
DEPENDS
14991499
libc.src.__support.macros.properties.types
15001500
libc.src.__support.FPUtil.manipulation_functions

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
7171

7272
void testOverflow(LdExpFunc func) {
7373
NormalFloat x(Sign::POS, FPBits::MAX_BIASED_EXPONENT - 10,
74-
NormalFloat::ONE + 0xF00);
74+
NormalFloat::ONE + 0xFB);
7575
for (int32_t exp = 10; exp < 100; ++exp) {
7676
ASSERT_FP_EQ(inf, func(T(x), exp));
7777
ASSERT_FP_EQ(neg_inf, func(-T(x), exp));

0 commit comments

Comments
 (0)