From b5efd214297a50664cf3373362db29432c883ebd Mon Sep 17 00:00:00 2001 From: OverMighty Date: Fri, 21 Jun 2024 15:01:47 +0200 Subject: [libc][math][c23] Add {ldexp,scalbn,scalbln}f16 C23 math functions (#94797) Part of #93566. --- libc/config/linux/aarch64/entrypoints.txt | 3 ++ libc/config/linux/x86_64/entrypoints.txt | 3 ++ libc/docs/math/index.rst | 6 ++-- libc/spec/stdc.td | 4 +++ libc/src/__support/FPUtil/CMakeLists.txt | 2 +- libc/src/__support/FPUtil/ManipulationFunctions.h | 10 ++++-- libc/src/__support/FPUtil/dyadic_float.h | 24 ++++++++----- libc/src/__support/big_int.h | 3 +- libc/src/math/CMakeLists.txt | 4 +++ libc/src/math/generic/CMakeLists.txt | 41 +++++++++++++++++++++++ libc/src/math/generic/ldexpf16.cpp | 19 +++++++++++ libc/src/math/generic/scalblnf16.cpp | 25 ++++++++++++++ libc/src/math/generic/scalbnf16.cpp | 25 ++++++++++++++ libc/src/math/ldexpf16.h | 20 +++++++++++ libc/src/math/scalblnf16.h | 20 +++++++++++ libc/src/math/scalbnf16.h | 20 +++++++++++ libc/test/src/math/smoke/CMakeLists.txt | 41 +++++++++++++++++++++++ libc/test/src/math/smoke/LdExpTest.h | 33 ++++++++++++------ libc/test/src/math/smoke/ScalbnTest.h | 4 +-- libc/test/src/math/smoke/ldexpf16_test.cpp | 13 +++++++ libc/test/src/math/smoke/scalblnf16_test.cpp | 13 +++++++ libc/test/src/math/smoke/scalbn_test.cpp | 2 +- libc/test/src/math/smoke/scalbnf128_test.cpp | 2 +- libc/test/src/math/smoke/scalbnf16_test.cpp | 13 +++++++ libc/test/src/math/smoke/scalbnf_test.cpp | 2 +- libc/test/src/math/smoke/scalbnl_test.cpp | 2 +- 26 files changed, 322 insertions(+), 32 deletions(-) create mode 100644 libc/src/math/generic/ldexpf16.cpp create mode 100644 libc/src/math/generic/scalblnf16.cpp create mode 100644 libc/src/math/generic/scalbnf16.cpp create mode 100644 libc/src/math/ldexpf16.h create mode 100644 libc/src/math/scalblnf16.h create mode 100644 libc/src/math/scalbnf16.h create mode 100644 libc/test/src/math/smoke/ldexpf16_test.cpp create mode 100644 libc/test/src/math/smoke/scalblnf16_test.cpp create mode 100644 libc/test/src/math/smoke/scalbnf16_test.cpp (limited to 'libc') diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index aa223a6..63238ec 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -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 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index ab7f572..ac170bf 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -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 diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index c9b1238..d6e642c 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -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 | +------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index f0b36f82..73d00c3 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -533,6 +533,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"ldexp", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"ldexpf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"ldexpl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"ldexpf16", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, GuardedFunctionSpec<"ldexpf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"log10", RetValSpec, [ArgSpec]>, @@ -695,9 +696,12 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"asinhf", RetValSpec, [ArgSpec]>, FunctionSpec<"atanhf", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"scalblnf16", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, + FunctionSpec<"scalbn", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"scalbnf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"scalbnl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"scalbnf16", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, GuardedFunctionSpec<"scalbnf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"nanf", RetValSpec, [ArgSpec]>, diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index 01ca425..4ede742 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -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 ) diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h index a289c2e..97c4312 100644 --- a/libc/src/__support/FPUtil/ManipulationFunctions.h +++ b/libc/src/__support/FPUtil/ManipulationFunctions.h @@ -142,8 +142,10 @@ LIBC_INLINE constexpr T logb(T x) { return static_cast(normal.get_unbiased_exponent()); } -template , int> = 0> -LIBC_INLINE constexpr T ldexp(T x, int exp) { +template +LIBC_INLINE constexpr cpp::enable_if_t< + cpp::is_floating_point_v && cpp::is_integral_v, T> +ldexp(T x, U exp) { FPBits 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::MAX_BIASED_EXPONENT + FPBits::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::STORAGE_LEN> normal(bits.get_val()); - normal.exponent += exp; + normal.exponent += static_cast(exp); return static_cast(normal); } diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index 12a6922..63cb983 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -126,7 +126,7 @@ template struct DyadicFloat { shift >= MantissaType::BITS ? MantissaType(0) : mantissa >> shift; T d_hi = FPBits::create_value( - sign, exp_hi, + sign, static_cast(exp_hi), (static_cast(m_hi) & FPBits::SIG_MASK) | IMPLICIT_MASK) .get_val(); @@ -143,25 +143,32 @@ template 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::create_value(sign, FPBits::EXP_BIAS + scale_up_exponent, + FPBits::create_value(sign, + static_cast( + FPBits::EXP_BIAS + scale_up_exponent), IMPLICIT_MASK) .get_val(); T scale_down_factor = - FPBits::create_value(sign, FPBits::EXP_BIAS - scale_up_exponent, + FPBits::create_value(sign, + static_cast( + FPBits::EXP_BIAS - scale_up_exponent), IMPLICIT_MASK) .get_val(); - d_lo = FPBits::create_value(sign, exp_lo + scale_up_exponent, - IMPLICIT_MASK) + d_lo = FPBits::create_value( + sign, static_cast(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::create_value(sign, exp_lo, IMPLICIT_MASK).get_val(); + d_lo = FPBits::create_value(sign, static_cast(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 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::SIG_LEN); + output_bits_t clear_exp = static_cast( + output_bits_t(exp_hi) << FPBits::SIG_LEN); output_bits_t r_bits = FPBits(r).uintval() - clear_exp; if (!(r_bits & FPBits::EXP_MASK)) { // Output is denormal after rounding, clear the implicit bit for 80-bit diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h index c30c3ec..5ce9541 100644 --- a/libc/src/__support/big_int.h +++ b/libc/src/__support/big_int.h @@ -302,7 +302,8 @@ LIBC_INLINE constexpr cpp::array shift(cpp::array array, dst = static_cast((part1 << bit_offset) | (part2 >> (WORD_BITS - bit_offset))); else - dst = (part1 >> bit_offset) | (part2 << (WORD_BITS - bit_offset)); + dst = static_cast((part1 >> bit_offset) | + (part2 << (WORD_BITS - bit_offset))); } return out; } diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 92e0cd2..a921939 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -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) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index f509b97..a0114aa 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1488,6 +1488,19 @@ add_entrypoint_object( ) 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 ldexpf128.cpp @@ -3502,6 +3515,20 @@ add_entrypoint_object( ) 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 scalbn.cpp @@ -3541,6 +3568,20 @@ add_entrypoint_object( ) 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 scalbnf128.cpp diff --git a/libc/src/math/generic/ldexpf16.cpp b/libc/src/math/generic/ldexpf16.cpp new file mode 100644 index 0000000..ed15c45 --- /dev/null +++ b/libc/src/math/generic/ldexpf16.cpp @@ -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 diff --git a/libc/src/math/generic/scalblnf16.cpp b/libc/src/math/generic/scalblnf16.cpp new file mode 100644 index 0000000..844a071 --- /dev/null +++ b/libc/src/math/generic/scalblnf16.cpp @@ -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 diff --git a/libc/src/math/generic/scalbnf16.cpp b/libc/src/math/generic/scalbnf16.cpp new file mode 100644 index 0000000..a42fdff --- /dev/null +++ b/libc/src/math/generic/scalbnf16.cpp @@ -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 diff --git a/libc/src/math/ldexpf16.h b/libc/src/math/ldexpf16.h new file mode 100644 index 0000000..7303610 --- /dev/null +++ b/libc/src/math/ldexpf16.h @@ -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 diff --git a/libc/src/math/scalblnf16.h b/libc/src/math/scalblnf16.h new file mode 100644 index 0000000..be93fab --- /dev/null +++ b/libc/src/math/scalblnf16.h @@ -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 diff --git a/libc/src/math/scalbnf16.h b/libc/src/math/scalbnf16.h new file mode 100644 index 0000000..95e4862 --- /dev/null +++ b/libc/src/math/scalbnf16.h @@ -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 diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index bd8de18..8cae52f 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1551,6 +1551,21 @@ add_fp_unittest( ) 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 libc-math-smoke-tests @@ -3456,6 +3471,19 @@ add_fp_unittest( ) 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 libc-math-smoke-tests @@ -3495,6 +3523,19 @@ add_fp_unittest( ) 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 libc-math-smoke-tests diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h index 713d305..7739bd7 100644 --- a/libc/test/src/math/smoke/LdExpTest.h +++ b/libc/test/src/math/smoke/LdExpTest.h @@ -18,7 +18,7 @@ #include -template +template class LdExpTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { using FPBits = LIBC_NAMESPACE::fputil::FPBits; using NormalFloat = LIBC_NAMESPACE::fputil::NormalFloat; @@ -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(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(two_to_exp)); + ASSERT_FP_EQ(func(x, -exp), x / static_cast(two_to_exp)); } } diff --git a/libc/test/src/math/smoke/ScalbnTest.h b/libc/test/src/math/smoke/ScalbnTest.h index e1d035c..67ea30f 100644 --- a/libc/test/src/math/smoke/ScalbnTest.h +++ b/libc/test/src/math/smoke/ScalbnTest.h @@ -12,8 +12,8 @@ #include "LdExpTest.h" #include "test/UnitTest/Test.h" -#define LIST_SCALBN_TESTS(T, func) \ - using LlvmLibcScalbnTest = LdExpTestTemplate; \ +#define LIST_SCALBN_TESTS(T, U, func) \ + using LlvmLibcScalbnTest = LdExpTestTemplate; \ TEST_F(LlvmLibcScalbnTest, SpecialNumbers) { testSpecialNumbers(&func); } \ TEST_F(LlvmLibcScalbnTest, PowersOfTwo) { testPowersOfTwo(&func); } \ TEST_F(LlvmLibcScalbnTest, OverFlow) { testOverflow(&func); } \ diff --git a/libc/test/src/math/smoke/ldexpf16_test.cpp b/libc/test/src/math/smoke/ldexpf16_test.cpp new file mode 100644 index 0000000..ecf8f76 --- /dev/null +++ b/libc/test/src/math/smoke/ldexpf16_test.cpp @@ -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); diff --git a/libc/test/src/math/smoke/scalblnf16_test.cpp b/libc/test/src/math/smoke/scalblnf16_test.cpp new file mode 100644 index 0000000..a678254 --- /dev/null +++ b/libc/test/src/math/smoke/scalblnf16_test.cpp @@ -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) diff --git a/libc/test/src/math/smoke/scalbn_test.cpp b/libc/test/src/math/smoke/scalbn_test.cpp index 413a239..86ad71b 100644 --- a/libc/test/src/math/smoke/scalbn_test.cpp +++ b/libc/test/src/math/smoke/scalbn_test.cpp @@ -10,4 +10,4 @@ #include "src/math/scalbn.h" -LIST_SCALBN_TESTS(double, LIBC_NAMESPACE::scalbn) +LIST_SCALBN_TESTS(double, int, LIBC_NAMESPACE::scalbn) diff --git a/libc/test/src/math/smoke/scalbnf128_test.cpp b/libc/test/src/math/smoke/scalbnf128_test.cpp index dc259de..b42902a 100644 --- a/libc/test/src/math/smoke/scalbnf128_test.cpp +++ b/libc/test/src/math/smoke/scalbnf128_test.cpp @@ -10,4 +10,4 @@ #include "src/math/scalbnf128.h" -LIST_SCALBN_TESTS(float128, LIBC_NAMESPACE::scalbnf128) +LIST_SCALBN_TESTS(float128, int, LIBC_NAMESPACE::scalbnf128) diff --git a/libc/test/src/math/smoke/scalbnf16_test.cpp b/libc/test/src/math/smoke/scalbnf16_test.cpp new file mode 100644 index 0000000..9cee0d0 --- /dev/null +++ b/libc/test/src/math/smoke/scalbnf16_test.cpp @@ -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) diff --git a/libc/test/src/math/smoke/scalbnf_test.cpp b/libc/test/src/math/smoke/scalbnf_test.cpp index e97781c..b25db4e 100644 --- a/libc/test/src/math/smoke/scalbnf_test.cpp +++ b/libc/test/src/math/smoke/scalbnf_test.cpp @@ -10,4 +10,4 @@ #include "src/math/scalbnf.h" -LIST_SCALBN_TESTS(float, LIBC_NAMESPACE::scalbnf) +LIST_SCALBN_TESTS(float, int, LIBC_NAMESPACE::scalbnf) diff --git a/libc/test/src/math/smoke/scalbnl_test.cpp b/libc/test/src/math/smoke/scalbnl_test.cpp index b0e0053..838b065 100644 --- a/libc/test/src/math/smoke/scalbnl_test.cpp +++ b/libc/test/src/math/smoke/scalbnl_test.cpp @@ -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) -- cgit v1.1