Skip to content

Commit

Permalink
[libc][math][c23] Add {ldexp,scalbn,scalbln}f16 C23 math functions (l…
Browse files Browse the repository at this point in the history
  • Loading branch information
overmighty authored and AlexisPerry committed Jun 27, 2024
1 parent 02ed4f5 commit 9747ab5
Show file tree
Hide file tree
Showing 26 changed files with 322 additions and 32 deletions.
3 changes: 3 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.fromfpxf16
libc.src.math.getpayloadf16
libc.src.math.ilogbf16
libc.src.math.ldexpf16
libc.src.math.llogbf16
libc.src.math.llrintf16
libc.src.math.llroundf16
Expand All @@ -545,6 +546,8 @@ 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.setpayloadf16
libc.src.math.setpayloadsigf16
libc.src.math.totalorderf16
Expand Down
3 changes: 3 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.fromfpxf16
libc.src.math.getpayloadf16
libc.src.math.ilogbf16
libc.src.math.ldexpf16
libc.src.math.llogbf16
libc.src.math.llrintf16
libc.src.math.llroundf16
Expand All @@ -575,6 +576,8 @@ 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.setpayloadf16
libc.src.math.setpayloadsigf16
libc.src.math.totalorderf16
Expand Down
6 changes: 4 additions & 2 deletions libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| ilogb | |check| | |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| | |check| | 7.12.6.10 | F.10.3.10 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down Expand Up @@ -212,7 +212,9 @@ 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 |
| scalbln | | | | |check| | | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| scalbn | |check| | |check| | |check| | |check| | |check| | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| setpayload | | | | |check| | | F.10.13.2 | N/A |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down
4 changes: 4 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,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>]>,
Expand Down Expand Up @@ -695,9 +696,12 @@ 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>]>,
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>]>,
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ add_header_library(
DEPENDS
.fp_bits
.multiply_add
libc.src.__support.CPP.type_traits
libc.src.__support.big_int
libc.src.__support.common
libc.src.__support.macros.optimization
)

Expand Down
10 changes: 7 additions & 3 deletions libc/src/__support/FPUtil/ManipulationFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ LIBC_INLINE constexpr T logb(T x) {
return static_cast<T>(normal.get_unbiased_exponent());
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE constexpr T ldexp(T x, int exp) {
template <typename T, typename U>
LIBC_INLINE constexpr cpp::enable_if_t<
cpp::is_floating_point_v<T> && cpp::is_integral_v<U>, T>
ldexp(T x, U exp) {
FPBits<T> bits(x);
if (LIBC_UNLIKELY((exp == 0) || bits.is_zero() || bits.is_inf_or_nan()))
return x;
Expand All @@ -156,6 +158,8 @@ LIBC_INLINE constexpr T ldexp(T x, int exp) {
// calculating the limit.
constexpr int EXP_LIMIT =
FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
// Make sure that we can safely cast exp to int when not returning early.
static_assert(EXP_LIMIT <= INT_MAX && -EXP_LIMIT >= INT_MIN);
if (LIBC_UNLIKELY(exp > EXP_LIMIT)) {
int rounding_mode = quick_get_round();
Sign sign = bits.sign();
Expand Down Expand Up @@ -186,7 +190,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());
normal.exponent += exp;
normal.exponent += static_cast<int>(exp);
return static_cast<T>(normal);
}

Expand Down
24 changes: 16 additions & 8 deletions libc/src/__support/FPUtil/dyadic_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ template <size_t Bits> struct DyadicFloat {
shift >= MantissaType::BITS ? MantissaType(0) : mantissa >> shift;

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

if (LIBC_UNLIKELY(exp_lo <= 0)) {
// d_lo is denormal, but the output is normal.
int scale_up_exponent = 2 * PRECISION;
int scale_up_exponent = 1 - exp_lo;
T scale_up_factor =
FPBits<T>::create_value(sign, FPBits<T>::EXP_BIAS + scale_up_exponent,
FPBits<T>::create_value(sign,
static_cast<output_bits_t>(
FPBits<T>::EXP_BIAS + scale_up_exponent),
IMPLICIT_MASK)
.get_val();
T scale_down_factor =
FPBits<T>::create_value(sign, FPBits<T>::EXP_BIAS - scale_up_exponent,
FPBits<T>::create_value(sign,
static_cast<output_bits_t>(
FPBits<T>::EXP_BIAS - scale_up_exponent),
IMPLICIT_MASK)
.get_val();

d_lo = FPBits<T>::create_value(sign, exp_lo + scale_up_exponent,
IMPLICIT_MASK)
d_lo = FPBits<T>::create_value(
sign, static_cast<output_bits_t>(exp_lo + scale_up_exponent),
IMPLICIT_MASK)
.get_val();

return multiply_add(d_lo, T(round_and_sticky), d_hi * scale_up_factor) *
scale_down_factor;
}

d_lo = FPBits<T>::create_value(sign, exp_lo, IMPLICIT_MASK).get_val();
d_lo = FPBits<T>::create_value(sign, static_cast<output_bits_t>(exp_lo),
IMPLICIT_MASK)
.get_val();

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

if (LIBC_UNLIKELY(denorm)) {
// Exponent before rounding is in denormal range, simply clear the
// exponent field.
output_bits_t clear_exp = (output_bits_t(exp_hi) << FPBits<T>::SIG_LEN);
output_bits_t clear_exp = static_cast<output_bits_t>(
output_bits_t(exp_hi) << FPBits<T>::SIG_LEN);
output_bits_t r_bits = FPBits<T>(r).uintval() - clear_exp;
if (!(r_bits & FPBits<T>::EXP_MASK)) {
// Output is denormal after rounding, clear the implicit bit for 80-bit
Expand Down
3 changes: 2 additions & 1 deletion libc/src/__support/big_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
dst = static_cast<word>((part1 << bit_offset) |
(part2 >> (WORD_BITS - bit_offset)));
else
dst = (part1 >> bit_offset) | (part2 << (WORD_BITS - bit_offset));
dst = static_cast<word>((part1 >> bit_offset) |
(part2 << (WORD_BITS - bit_offset)));
}
return out;
}
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,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)
Expand Down Expand Up @@ -347,9 +348,12 @@ 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)
add_math_entrypoint_object(scalbnf16)
add_math_entrypoint_object(scalbnf128)

add_math_entrypoint_object(setpayloadf16)
Expand Down
41 changes: 41 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,19 @@ add_entrypoint_object(
libc.src.__support.FPUtil.manipulation_functions
)

add_entrypoint_object(
ldexpf16
SRCS
ldexpf16.cpp
HDRS
../ldexpf16.h
COMPILE_OPTIONS
-O3
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.manipulation_functions
)

add_entrypoint_object(
ldexpf128
SRCS
Expand Down Expand Up @@ -3501,6 +3514,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
Expand Down Expand Up @@ -3540,6 +3567,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
Expand Down
19 changes: 19 additions & 0 deletions libc/src/math/generic/ldexpf16.cpp
Original file line number Diff line number Diff line change
@@ -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
25 changes: 25 additions & 0 deletions libc/src/math/generic/scalblnf16.cpp
Original file line number Diff line number Diff line change
@@ -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
25 changes: 25 additions & 0 deletions libc/src/math/generic/scalbnf16.cpp
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions libc/src/math/ldexpf16.h
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions libc/src/math/scalblnf16.h
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 9747ab5

Please sign in to comment.