mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 04:16:07 +00:00
[libc][math][c23] Add {ldexp,scalbn,scalbln}f16 C23 math functions (#94797)
Part of #93566.
This commit is contained in:
parent
c399aeacf6
commit
b5efd21429
@ -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
|
||||
@ -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
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -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 |
|
||||
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
|
||||
@ -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 |
|
||||
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
|
||||
|
@ -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>]>,
|
||||
@ -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>]>,
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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;
|
||||
@ -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();
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
@ -143,25 +143,32 @@ 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);
|
||||
@ -169,7 +176,8 @@ template <size_t Bits> struct DyadicFloat {
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
@ -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)
|
||||
|
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
19
libc/src/math/generic/ldexpf16.cpp
Normal file
19
libc/src/math/generic/ldexpf16.cpp
Normal file
@ -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
libc/src/math/generic/scalblnf16.cpp
Normal file
25
libc/src/math/generic/scalblnf16.cpp
Normal file
@ -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
libc/src/math/generic/scalbnf16.cpp
Normal file
25
libc/src/math/generic/scalbnf16.cpp
Normal file
@ -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
libc/src/math/ldexpf16.h
Normal file
20
libc/src/math/ldexpf16.h
Normal file
@ -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
libc/src/math/scalblnf16.h
Normal file
20
libc/src/math/scalblnf16.h
Normal file
@ -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
|
20
libc/src/math/scalbnf16.h
Normal file
20
libc/src/math/scalbnf16.h
Normal file
@ -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
|
@ -1550,6 +1550,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
|
||||
@ -3455,6 +3470,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
|
||||
@ -3494,6 +3522,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
|
||||
|
@ -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>;
|
||||
@ -31,13 +31,13 @@ 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);
|
||||
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 @@ public:
|
||||
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) {
|
||||
@ -60,7 +71,7 @@ public:
|
||||
|
||||
void testOverflow(LdExpFunc func) {
|
||||
NormalFloat x(Sign::POS, FPBits::MAX_BIASED_EXPONENT - 10,
|
||||
NormalFloat::ONE + 0xF00BA);
|
||||
NormalFloat::ONE + 0xFB);
|
||||
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 +106,10 @@ public:
|
||||
|
||||
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 +125,8 @@ public:
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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); } \
|
||||
|
13
libc/test/src/math/smoke/ldexpf16_test.cpp
Normal file
13
libc/test/src/math/smoke/ldexpf16_test.cpp
Normal file
@ -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);
|
13
libc/test/src/math/smoke/scalblnf16_test.cpp
Normal file
13
libc/test/src/math/smoke/scalblnf16_test.cpp
Normal file
@ -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)
|
@ -10,4 +10,4 @@
|
||||
|
||||
#include "src/math/scalbn.h"
|
||||
|
||||
LIST_SCALBN_TESTS(double, LIBC_NAMESPACE::scalbn)
|
||||
LIST_SCALBN_TESTS(double, int, LIBC_NAMESPACE::scalbn)
|
||||
|
@ -10,4 +10,4 @@
|
||||
|
||||
#include "src/math/scalbnf128.h"
|
||||
|
||||
LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128)
|
||||
LIST_SCALBN_TESTS(float128, int, LIBC_NAMESPACE::scalbnf128)
|
||||
|
13
libc/test/src/math/smoke/scalbnf16_test.cpp
Normal file
13
libc/test/src/math/smoke/scalbnf16_test.cpp
Normal file
@ -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, int, LIBC_NAMESPACE::scalbnf16)
|
@ -10,4 +10,4 @@
|
||||
|
||||
#include "src/math/scalbnf.h"
|
||||
|
||||
LIST_SCALBN_TESTS(float, LIBC_NAMESPACE::scalbnf)
|
||||
LIST_SCALBN_TESTS(float, int, LIBC_NAMESPACE::scalbnf)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user