[libc-commits] [libc] [libc][math] Add floating-point cast independent of compiler runtime (PR #105152)
via libc-commits
libc-commits at lists.llvm.org
Tue Aug 20 10:41:24 PDT 2024
https://github.com/overmighty updated https://github.com/llvm/llvm-project/pull/105152
>From 1dc49a275b06bc0378f06e1b2645a5f185f1ac71 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Thu, 4 Jul 2024 13:22:16 +0200
Subject: [PATCH 1/2] [libc][math] Add floating-point cast independent of
compiler runtime
---
.../cmake/modules/CheckCompilerFeatures.cmake | 19 ++-
.../check_float16_conversion.cpp | 30 +++++
libc/src/__support/FPUtil/CMakeLists.txt | 25 +++-
.../__support/FPUtil/ManipulationFunctions.h | 12 +-
libc/src/__support/FPUtil/cast.h | 65 ++++++++++
libc/src/__support/FPUtil/dyadic_float.h | 120 +++++++++++++++++-
.../src/__support/FPUtil/except_value_utils.h | 18 +++
.../__support/FPUtil/generic/CMakeLists.txt | 8 +-
libc/src/__support/FPUtil/generic/FMA.h | 5 +-
libc/src/__support/FPUtil/generic/add_sub.h | 5 +-
libc/src/__support/FPUtil/generic/sqrt.h | 3 +-
libc/src/math/generic/CMakeLists.txt | 24 +++-
libc/src/math/generic/ceilf16.cpp | 3 +-
libc/src/math/generic/exp10f16.cpp | 11 +-
libc/src/math/generic/exp2f16.cpp | 3 +-
libc/src/math/generic/expf16.cpp | 5 +-
libc/src/math/generic/expm1f16.cpp | 7 +-
libc/src/math/generic/floorf16.cpp | 3 +-
libc/src/math/generic/rintf16.cpp | 3 +-
libc/src/math/generic/roundevenf16.cpp | 3 +-
libc/src/math/generic/roundf16.cpp | 3 +-
libc/src/math/generic/truncf16.cpp | 3 +-
libc/test/src/math/smoke/AddTest.h | 42 +++---
libc/test/src/math/smoke/CMakeLists.txt | 15 +++
libc/test/src/math/smoke/DivTest.h | 82 ++++++------
libc/test/src/math/smoke/FModTest.h | 64 +++++-----
libc/test/src/math/smoke/FmaTest.h | 28 +++-
libc/test/src/math/smoke/ModfTest.h | 2 +-
libc/test/src/math/smoke/MulTest.h | 52 ++++----
libc/test/src/math/smoke/NextTowardTest.h | 14 +-
libc/test/src/math/smoke/SqrtTest.h | 16 ++-
libc/test/src/math/smoke/SubTest.h | 40 +++---
libc/test/src/math/smoke/exp10f16_test.cpp | 14 +-
libc/test/src/math/smoke/exp2f16_test.cpp | 14 +-
libc/test/src/math/smoke/expf16_test.cpp | 14 +-
libc/test/src/math/smoke/expm1f16_test.cpp | 44 ++++---
libc/utils/MPFRWrapper/CMakeLists.txt | 1 +
libc/utils/MPFRWrapper/MPFRUtils.cpp | 3 +-
38 files changed, 594 insertions(+), 229 deletions(-)
create mode 100644 libc/cmake/modules/compiler_features/check_float16_conversion.cpp
create mode 100644 libc/src/__support/FPUtil/cast.h
diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index 63145fe709dda0..862c7ecbd7fdf4 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -10,6 +10,7 @@ set(
"builtin_round"
"builtin_roundeven"
"float16"
+ "float16_conversion"
"float128"
"fixed_point"
)
@@ -61,15 +62,21 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
set(link_options "")
if(${feature} STREQUAL "fixed_point")
list(APPEND compile_options "-ffixed-point")
- elseif(${feature} MATCHES "^builtin_")
+ elseif(${feature} MATCHES "^builtin_" OR
+ ${feature} STREQUAL "float16_conversion")
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
set(link_options -nostdlib)
- # The compiler might handle calls to rounding builtins by generating calls
- # to the respective libc math functions, in which case we cannot use these
+ # The compiler might handle calls to math builtins by generating calls to
+ # the respective libc math functions, in which case we cannot use these
# builtins in our implementations of these functions. We check that this is
# not the case by trying to link an executable, since linking would fail due
# to unresolved references with -nostdlib if calls to libc functions were
# generated.
+ #
+ # We also had issues with soft-float float16 conversion functions using both
+ # compiler-rt and libgcc, so we also check whether we can convert from and
+ # to float16 without calls to compiler runtime functions by trying to link
+ # an executable with -nostdlib.
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
endif()
@@ -97,6 +104,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
if(${feature} STREQUAL "float16")
set(LIBC_TYPES_HAS_FLOAT16 TRUE)
+ elseif(${feature} STREQUAL "float16_conversion")
+ add_compile_definitions(__LIBC_USE_FLOAT16_CONVERSION)
elseif(${feature} STREQUAL "float128")
set(LIBC_TYPES_HAS_FLOAT128 TRUE)
elseif(${feature} STREQUAL "fixed_point")
@@ -115,6 +124,10 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
endif()
endforeach()
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
+set(link_options "")
+
message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
### Compiler Feature Detection ###
diff --git a/libc/cmake/modules/compiler_features/check_float16_conversion.cpp b/libc/cmake/modules/compiler_features/check_float16_conversion.cpp
new file mode 100644
index 00000000000000..09ac8e9c8bc9d6
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_float16_conversion.cpp
@@ -0,0 +1,30 @@
+#include "include/llvm-libc-macros/float16-macros.h"
+#include "include/llvm-libc-types/float128.h"
+
+#ifndef LIBC_TYPES_HAS_FLOAT16
+#error unsupported
+#endif
+
+_Float16 cvt_from_float(float x) { return static_cast<_Float16>(x); }
+
+_Float16 cvt_from_double(double x) { return static_cast<_Float16>(x); }
+
+_Float16 cvt_from_long_double(long double x) {
+ return static_cast<_Float16>(x);
+}
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+_Float16 cvt_from_float128(float128 x) { return static_cast<_Float16>(x); }
+#endif
+
+float cvt_to_float(_Float16 x) { return x; }
+
+double cvt_to_double(_Float16 x) { return x; }
+
+long double cvt_to_long_double(_Float16 x) { return x; }
+
+#ifdef LIBC_TYPES_HAS_FLOAT128
+float128 cvt_to_float128(_Float16 x) { return x; }
+#endif
+
+extern "C" void _start() {}
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index ea1e0e8b39d101..90901549946f42 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -97,6 +97,7 @@ add_header_library(
.rounding_mode
libc.src.__support.CPP.optional
libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.types
)
@@ -175,9 +176,13 @@ add_header_library(
.fenv_impl
.fp_bits
.multiply_add
+ .rounding_mode
+ libc.hdr.errno_macros
+ libc.hdr.fenv_macros
libc.src.__support.CPP.type_traits
libc.src.__support.big_int
libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.types
)
add_header_library(
@@ -217,18 +222,32 @@ add_header_library(
HDRS
ManipulationFunctions.h
DEPENDS
+ .cast
+ .dyadic_float
.fenv_impl
.fp_bits
- .dyadic_float
.nearest_integer_operations
.normal_float
libc.hdr.math_macros
+ libc.src.errno.errno
+ libc.src.__support.common
libc.src.__support.CPP.bit
libc.src.__support.CPP.limits
libc.src.__support.CPP.type_traits
- libc.src.__support.common
libc.src.__support.macros.optimization
- libc.src.errno.errno
+)
+
+add_header_library(
+ cast
+ HDRS
+ cast.h
+ DEPENDS
+ .dyadic_float
+ .fp_bits
+ libc.hdr.fenv_macros
+ libc.src.__support.CPP.algorithm
+ libc.src.__support.CPP.type_traits
+ libc.src.__support.macros.properties.types
)
add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index a14f355789999a..66bfe2aa377f99 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -12,6 +12,7 @@
#include "FPBits.h"
#include "NearestIntegerOperations.h"
#include "NormalFloat.h"
+#include "cast.h"
#include "dyadic_float.h"
#include "rounding_mode.h"
@@ -192,7 +193,8 @@ ldexp(T x, U 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 += static_cast<int>(exp);
- return static_cast<T>(normal);
+ // TODO: Add tests for exceptions.
+ return normal.template as<T, /*ShouldRaiseExceptions=*/true>();
}
template <typename T, typename U,
@@ -207,17 +209,17 @@ LIBC_INLINE T nextafter(T from, U to) {
FPBits<U> to_bits(to);
if (to_bits.is_nan())
- return static_cast<T>(to);
+ return cast<T>(to);
// NOTE: This would work only if `U` has a greater or equal precision than
// `T`. Otherwise `from` could loose its precision and the following statement
// could incorrectly evaluate to `true`.
- if (static_cast<U>(from) == to)
- return static_cast<T>(to);
+ if (cast<U>(from) == to)
+ return cast<T>(to);
using StorageType = typename FPBits<T>::StorageType;
if (from != T(0)) {
- if ((static_cast<U>(from) < to) == (from > T(0))) {
+ if ((cast<U>(from) < to) == (from > T(0))) {
from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
} else {
from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
new file mode 100644
index 00000000000000..126f3852137b77
--- /dev/null
+++ b/libc/src/__support/FPUtil/cast.h
@@ -0,0 +1,65 @@
+//===-- Conversion between floating-point types -----------------*- 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___SUPPORT_FPUTIL_CAST_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
+
+#include "FPBits.h"
+#include "dyadic_float.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/algorithm.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE::fputil {
+
+template <typename OutType, typename InType>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
+ cpp::is_floating_point_v<InType>,
+ OutType>
+cast(InType x) {
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+ if constexpr (cpp::is_same_v<OutType, float16> ||
+ cpp::is_same_v<InType, float16>) {
+ using InFPBits = FPBits<InType>;
+ using InStorageType = typename InFPBits::StorageType;
+ using OutFPBits = FPBits<OutType>;
+ using OutStorageType = typename OutFPBits::StorageType;
+
+ InFPBits x_bits(x);
+
+ if (x_bits.is_nan()) {
+ if (x_bits.is_signaling_nan()) {
+ raise_except_if_required(FE_INVALID);
+ return OutFPBits::quiet_nan().get_val();
+ }
+
+ InStorageType x_mant = x_bits.get_mantissa();
+ if (InFPBits::FRACTION_LEN > OutFPBits::FRACTION_LEN)
+ x_mant >>= InFPBits::FRACTION_LEN - OutFPBits::FRACTION_LEN;
+ return OutFPBits::quiet_nan(x_bits.sign(),
+ static_cast<OutStorageType>(x_mant))
+ .get_val();
+ }
+
+ if (x_bits.is_inf())
+ return OutFPBits::inf(x_bits.sign()).get_val();
+
+ constexpr size_t MAX_FRACTION_LEN =
+ cpp::max(OutFPBits::FRACTION_LEN, InFPBits::FRACTION_LEN);
+ DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
+ return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
+ }
+#endif
+
+ return static_cast<OutType>(x);
+}
+
+} // namespace LIBC_NAMESPACE::fputil
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_CAST_H
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 86346a47b35a34..814d9423a27f87 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -11,11 +11,15 @@
#include "FEnvImpl.h"
#include "FPBits.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
#include "multiply_add.h"
+#include "rounding_mode.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/big_int.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/types.h"
#include <stddef.h>
@@ -33,7 +37,8 @@ namespace fputil {
// The outputs of the constructors and most functions will be normalized.
// To simplify and improve the efficiency, many functions will assume that the
// inputs are normal.
-template <size_t Bits> struct DyadicFloat {
+template <size_t Bits> class DyadicFloat {
+public:
using MantissaType = LIBC_NAMESPACE::UInt<Bits>;
Sign sign = Sign::POS;
@@ -104,6 +109,11 @@ template <size_t Bits> struct DyadicFloat {
(FPBits<T>::FRACTION_LEN < Bits),
void>>
LIBC_INLINE constexpr T as() const {
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+ if constexpr (cpp::is_same_v<T, float16>)
+ return generic_as<T>();
+#endif
+
if (LIBC_UNLIKELY(mantissa.is_zero()))
return FPBits<T>::zero(sign).get_val();
@@ -249,6 +259,114 @@ template <size_t Bits> struct DyadicFloat {
return new_mant;
}
+
+private:
+ template <typename OutType>
+ LIBC_INLINE constexpr cpp::enable_if_t<
+ cpp::is_floating_point_v<OutType> &&
+ sizeof(typename FPBits<OutType>::StorageType) <= sizeof(MantissaType),
+ OutType>
+ generic_as() const {
+ using FPBits = FPBits<float16>;
+ using StorageType = typename FPBits::StorageType;
+
+ constexpr int EXTRA_FRACTION_LEN = Bits - 1 - FPBits::FRACTION_LEN;
+
+ if (mantissa == 0)
+ return FPBits::zero(sign).get_val();
+
+ int unbiased_exp = get_unbiased_exponent();
+
+ if (unbiased_exp + FPBits::EXP_BIAS >= FPBits::MAX_BIASED_EXPONENT) {
+ set_errno_if_required(ERANGE);
+ raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
+
+ switch (quick_get_round()) {
+ case FE_TONEAREST:
+ return FPBits::inf(sign).get_val();
+ case FE_TOWARDZERO:
+ return FPBits::max_normal(sign).get_val();
+ case FE_DOWNWARD:
+ if (sign.is_pos())
+ return FPBits::max_normal(Sign::POS).get_val();
+ return FPBits::inf(Sign::NEG).get_val();
+ case FE_UPWARD:
+ if (sign.is_neg())
+ return FPBits::max_normal(Sign::NEG).get_val();
+ return FPBits::inf(Sign::POS).get_val();
+ default:
+ __builtin_unreachable();
+ }
+ }
+
+ StorageType out_biased_exp = 0;
+ StorageType out_mantissa = 0;
+ bool round = false;
+ bool sticky = false;
+ bool underflow = false;
+
+ if (unbiased_exp < -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) {
+ sticky = true;
+ underflow = true;
+ } else if (unbiased_exp == -FPBits::EXP_BIAS - FPBits::FRACTION_LEN) {
+ round = true;
+ MantissaType sticky_mask = (MantissaType(1) << (Bits - 1)) - 1;
+ sticky = (mantissa & sticky_mask) != 0;
+ } else {
+ int extra_fraction_len = EXTRA_FRACTION_LEN;
+
+ if (unbiased_exp < 1 - FPBits::EXP_BIAS) {
+ underflow = true;
+ extra_fraction_len += 1 - FPBits::EXP_BIAS - unbiased_exp;
+ } else {
+ out_biased_exp =
+ static_cast<StorageType>(unbiased_exp + FPBits::EXP_BIAS);
+ }
+
+ MantissaType round_mask = MantissaType(1) << (extra_fraction_len - 1);
+ round = (mantissa & round_mask) != 0;
+ MantissaType sticky_mask = round_mask - 1;
+ sticky = (mantissa & sticky_mask) != 0;
+
+ out_mantissa = static_cast<StorageType>(mantissa >> extra_fraction_len);
+ }
+
+ bool lsb = (out_mantissa & 1) != 0;
+
+ StorageType result =
+ FPBits::create_value(sign, out_biased_exp, out_mantissa).uintval();
+
+ switch (quick_get_round()) {
+ case FE_TONEAREST:
+ if (round && (lsb || sticky))
+ ++result;
+ break;
+ case FE_DOWNWARD:
+ if (sign.is_neg() && (round || sticky))
+ ++result;
+ break;
+ case FE_UPWARD:
+ if (sign.is_pos() && (round || sticky))
+ ++result;
+ break;
+ default:
+ break;
+ }
+
+ if (round || sticky) {
+ int excepts = FE_INEXACT;
+ if (FPBits(result).is_inf()) {
+ set_errno_if_required(ERANGE);
+ excepts |= FE_OVERFLOW;
+ } else if (underflow) {
+ set_errno_if_required(ERANGE);
+ excepts |= FE_UNDERFLOW;
+ }
+ raise_except_if_required(excepts);
+ }
+
+ return FPBits(result).get_val();
+ }
};
// Quick add - Add 2 dyadic floats with rounding toward 0 and then normalize the
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index b9f54aa24e3a22..3b453fecdec76e 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -13,8 +13,11 @@
#include "FPBits.h"
#include "rounding_mode.h"
#include "src/__support/CPP/optional.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/macros/properties/types.h"
namespace LIBC_NAMESPACE_DECL {
@@ -113,6 +116,21 @@ template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
return tmp;
}
+#if defined(LIBC_TYPES_HAS_FLOAT16) && \
+ !defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
+template <> LIBC_INLINE float16 round_result_slightly_down(float16 value_rn) {
+ volatile float tmp = value_rn;
+ tmp -= FPBits<float16>::min_normal().get_val();
+ return cast<float16>(tmp);
+}
+
+template <> LIBC_INLINE float16 round_result_slightly_up(float16 value_rn) {
+ volatile float tmp = value_rn;
+ tmp += FPBits<float16>::min_normal().get_val();
+ return cast<float16>(tmp);
+}
+#endif
+
} // namespace fputil
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index 43096aa529fc37..b6f58f3fab571a 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -8,6 +8,7 @@ add_header_library(
libc.src.__support.common
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.dyadic_float
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
@@ -21,16 +22,17 @@ add_header_library(
FMA.h
DEPENDS
libc.hdr.fenv_macros
+ libc.src.__support.big_int
libc.src.__support.common
libc.src.__support.CPP.bit
libc.src.__support.CPP.limits
libc.src.__support.CPP.type_traits
libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.dyadic_float
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.big_int
libc.src.__support.macros.optimization
libc.src.__support.uint128
)
@@ -60,12 +62,12 @@ add_header_library(
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
libc.src.__support.FPUtil.basic_operations
+ libc.src.__support.FPUtil.cast
+ libc.src.__support.FPUtil.dyadic_float
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.dyadic_float
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.attributes
- libc.src.__support.macros.optimization
)
add_header_library(
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index e5683c8ff61ea0..bec312e44b1b10 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -14,6 +14,7 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/big_int.h"
@@ -157,7 +158,7 @@ fma(InType x, InType y, InType z) {
}
if (LIBC_UNLIKELY(x == 0 || y == 0 || z == 0))
- return static_cast<OutType>(x * y + z);
+ return cast<OutType>(x * y + z);
int x_exp = 0;
int y_exp = 0;
@@ -198,7 +199,7 @@ fma(InType x, InType y, InType z) {
if (LIBC_UNLIKELY(x_exp == InFPBits::MAX_BIASED_EXPONENT ||
y_exp == InFPBits::MAX_BIASED_EXPONENT ||
z_exp == InFPBits::MAX_BIASED_EXPONENT))
- return static_cast<OutType>(x * y + z);
+ return cast<OutType>(x * y + z);
// Extract mantissa and append hidden leading bits.
InStorageType x_mant = x_bits.get_explicit_mantissa();
diff --git a/libc/src/__support/FPUtil/generic/add_sub.h b/libc/src/__support/FPUtil/generic/add_sub.h
index 850db3f83209e6..6bc9dcd23bafad 100644
--- a/libc/src/__support/FPUtil/generic/add_sub.h
+++ b/libc/src/__support/FPUtil/generic/add_sub.h
@@ -17,6 +17,7 @@
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/macros/attributes.h"
@@ -106,14 +107,14 @@ add_or_sub(InType x, InType y) {
volatile InType tmp = y;
if constexpr (IsSub)
tmp = -tmp;
- return static_cast<OutType>(tmp);
+ return cast<OutType>(tmp);
}
if (y_bits.is_zero()) {
volatile InType tmp = y;
if constexpr (IsSub)
tmp = -tmp;
- return static_cast<OutType>(tmp);
+ return cast<OutType>(tmp);
}
}
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 4502cc07d32b31..01af4bb7c90092 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -14,6 +14,7 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/dyadic_float.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
@@ -96,7 +97,7 @@ sqrt(InType x) {
// sqrt(-0) = -0
// sqrt(NaN) = NaN
// sqrt(-NaN) = -NaN
- return static_cast<OutType>(x);
+ return cast<OutType>(x);
} else if (bits.is_neg()) {
// sqrt(-Inf) = NaN
// sqrt(-x) = NaN
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 350072f4b9649d..01ca65fda9fa18 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -109,9 +109,10 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.nearest_integer_operations
libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.macros.properties.types
FLAGS
ROUND_OPT
)
@@ -672,9 +673,10 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.nearest_integer_operations
libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.macros.properties.types
FLAGS
ROUND_OPT
)
@@ -741,9 +743,10 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.nearest_integer_operations
libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.macros.properties.types
FLAGS
ROUND_OPT
)
@@ -810,9 +813,10 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.nearest_integer_operations
libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.macros.properties.types
FLAGS
ROUND_OPT
)
@@ -881,6 +885,7 @@ add_entrypoint_object(
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.nearest_integer_operations
+ libc.src.__support.FPUtil.cast
libc.src.__support.macros.properties.cpu_features
FLAGS
ROUND_OPT
@@ -1072,9 +1077,10 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
DEPENDS
- libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.nearest_integer_operations
libc.src.__support.macros.properties.cpu_features
+ libc.src.__support.macros.properties.types
FLAGS
ROUND_OPT
)
@@ -1362,12 +1368,15 @@ add_entrypoint_object(
.expxf16
libc.hdr.errno_macros
libc.hdr.fenv_macros
+ libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.multiply_add
+ libc.src.__support.FPUtil.nearest_integer
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.rounding_mode
- libc.src.__support.macros.attributes
libc.src.__support.macros.optimization
COMPILE_OPTIONS
-O3
@@ -1442,6 +1451,7 @@ add_entrypoint_object(
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
@@ -1545,6 +1555,7 @@ add_entrypoint_object(
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.CPP.array
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
@@ -1617,6 +1628,7 @@ add_entrypoint_object(
.expxf16
libc.hdr.errno_macros
libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
diff --git a/libc/src/math/generic/ceilf16.cpp b/libc/src/math/generic/ceilf16.cpp
index 8af31c6623a02a..9d89efc5311d18 100644
--- a/libc/src/math/generic/ceilf16.cpp
+++ b/libc/src/math/generic/ceilf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/ceilf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, ceilf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_ceilf(x));
+ return fputil::cast<float16>(__builtin_ceilf(x));
#else
return fputil::ceil(x);
#endif
diff --git a/libc/src/math/generic/exp10f16.cpp b/libc/src/math/generic/exp10f16.cpp
index 9959f7450b591f..1c5966c1f1c126 100644
--- a/libc/src/math/generic/exp10f16.cpp
+++ b/libc/src/math/generic/exp10f16.cpp
@@ -14,6 +14,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
@@ -118,13 +119,13 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) {
switch (x_u) {
case 0x3c00U: // x = 1.0f16
- return static_cast<float16>(10.0);
+ return fputil::cast<float16>(10.0);
case 0x4000U: // x = 2.0f16
- return static_cast<float16>(100.0);
+ return fputil::cast<float16>(100.0);
case 0x4200U: // x = 3.0f16
- return static_cast<float16>(1'000.0);
+ return fputil::cast<float16>(1'000.0);
case 0x4400U: // x = 4.0f16
- return static_cast<float16>(10'000.0);
+ return fputil::cast<float16>(10'000.0);
}
}
@@ -164,7 +165,7 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
// > 1 + x * P;
float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f,
0x1.04b434p+1f, 0x1.2bcf9ep+0f);
- return static_cast<float16>(exp2_hi_mid * exp10_lo);
+ return fputil::cast<float16>(exp2_hi_mid * exp10_lo);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/exp2f16.cpp b/libc/src/math/generic/exp2f16.cpp
index 66b79567040053..3c4310259b1df9 100644
--- a/libc/src/math/generic/exp2f16.cpp
+++ b/libc/src/math/generic/exp2f16.cpp
@@ -14,6 +14,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
@@ -121,7 +122,7 @@ LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) {
// > 1 + x * P;
float exp2_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.62e43p-1f, 0x1.ec0aa6p-3f,
0x1.c6b4a6p-5f);
- return static_cast<float16>(exp2_hi_mid * exp2_lo);
+ return fputil::cast<float16>(exp2_hi_mid * exp2_lo);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/expf16.cpp b/libc/src/math/generic/expf16.cpp
index 7ffdbd5191008a..0548ef3932ae92 100644
--- a/libc/src/math/generic/expf16.cpp
+++ b/libc/src/math/generic/expf16.cpp
@@ -13,6 +13,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/common.h"
@@ -103,7 +104,7 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
// > display = hexadecimal;
// > P = fpminimax(expm1(x)/x, 2, [|SG...|], [-2^-5, 2^-5]);
// > 1 + x * P;
- return static_cast<float16>(
+ return fputil::cast<float16>(
fputil::polyeval(xf, 0x1p+0f, 0x1p+0f, 0x1.0004p-1f, 0x1.555778p-3f));
}
}
@@ -113,7 +114,7 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
// exp(x) = exp(hi + mid) * exp(lo)
auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
- return static_cast<float16>(exp_hi_mid * exp_lo);
+ return fputil::cast<float16>(exp_hi_mid * exp_lo);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/expm1f16.cpp b/libc/src/math/generic/expm1f16.cpp
index 0facdc510e4287..4ce0efd1f461bb 100644
--- a/libc/src/math/generic/expm1f16.cpp
+++ b/libc/src/math/generic/expm1f16.cpp
@@ -13,6 +13,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/rounding_mode.h"
@@ -99,7 +100,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
FPBits::one(Sign::NEG).get_val());
// When x <= -0x1.0ap+3, round(expm1(x), HP, RN) = -0x1.ffcp-1.
return fputil::round_result_slightly_down(
- static_cast<float16>(-0x1.ffcp-1));
+ fputil::cast<float16>(-0x1.ffcp-1));
}
// When 0 < |x| <= 2^(-3).
@@ -114,7 +115,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
// > display = hexadecimal;
// > P = fpminimax(expm1(x)/x, 4, [|SG...|], [-2^-3, 2^-3]);
// > x * P;
- return static_cast<float16>(
+ return fputil::cast<float16>(
xf * fputil::polyeval(xf, 0x1p+0f, 0x1.fffff8p-2f, 0x1.555556p-3f,
0x1.55905ep-5f, 0x1.1124c2p-7f));
}
@@ -126,7 +127,7 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
// exp(x) = exp(hi + mid) * exp(lo)
auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
// expm1(x) = exp(hi + mid) * exp(lo) - 1
- return static_cast<float16>(fputil::multiply_add(exp_hi_mid, exp_lo, -1.0f));
+ return fputil::cast<float16>(fputil::multiply_add(exp_hi_mid, exp_lo, -1.0f));
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/floorf16.cpp b/libc/src/math/generic/floorf16.cpp
index 3092048f5ab061..361b22729f642e 100644
--- a/libc/src/math/generic/floorf16.cpp
+++ b/libc/src/math/generic/floorf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/floorf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, floorf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_floorf(x));
+ return fputil::cast<float16>(__builtin_floorf(x));
#else
return fputil::floor(x);
#endif
diff --git a/libc/src/math/generic/rintf16.cpp b/libc/src/math/generic/rintf16.cpp
index 3a53dd28e3d109..aefdcbea770644 100644
--- a/libc/src/math/generic/rintf16.cpp
+++ b/libc/src/math/generic/rintf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/rintf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, rintf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_rintf(x));
+ return fputil::cast<float16>(__builtin_rintf(x));
#else
return fputil::round_using_current_rounding_mode(x);
#endif
diff --git a/libc/src/math/generic/roundevenf16.cpp b/libc/src/math/generic/roundevenf16.cpp
index c3dbd779b97395..fdcd968bc9b874 100644
--- a/libc/src/math/generic/roundevenf16.cpp
+++ b/libc/src/math/generic/roundevenf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/roundevenf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, roundevenf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_ROUNDEVEN) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_roundevenf(x));
+ return fputil::cast<float16>(__builtin_roundevenf(x));
#else
return fputil::round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
#endif
diff --git a/libc/src/math/generic/roundf16.cpp b/libc/src/math/generic/roundf16.cpp
index a5e2b44fbd54bd..9adfb52ed27c67 100644
--- a/libc/src/math/generic/roundf16.cpp
+++ b/libc/src/math/generic/roundf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/roundf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, roundf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_ROUND) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_roundf(x));
+ return fputil::cast<float16>(__builtin_roundf(x));
#else
return fputil::round(x);
#endif
diff --git a/libc/src/math/generic/truncf16.cpp b/libc/src/math/generic/truncf16.cpp
index 31b1214a9a0e4b..4d37e6560a965b 100644
--- a/libc/src/math/generic/truncf16.cpp
+++ b/libc/src/math/generic/truncf16.cpp
@@ -8,6 +8,7 @@
#include "src/math/truncf16.h"
#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/cpu_features.h"
@@ -17,7 +18,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float16, truncf16, (float16 x)) {
#if defined(__LIBC_USE_BUILTIN_CEIL_FLOOR_RINT_TRUNC) && \
defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
- return static_cast<float16>(__builtin_truncf(x));
+ return fputil::cast<float16>(__builtin_truncf(x));
#else
return fputil::trunc(x);
#endif
diff --git a/libc/test/src/math/smoke/AddTest.h b/libc/test/src/math/smoke/AddTest.h
index 0b7e395a22d4cd..4474845055fe9a 100644
--- a/libc/test/src/math/smoke/AddTest.h
+++ b/libc/test/src/math/smoke/AddTest.h
@@ -34,32 +34,33 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using AddFunc = OutType (*)(InType, InType);
void test_special_numbers(AddFunc func) {
- EXPECT_FP_IS_NAN(func(aNaN, aNaN));
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);
+ EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN));
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID);
InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
- EXPECT_FP_IS_NAN(func(qnan_42, zero));
- EXPECT_FP_IS_NAN(func(zero, qnan_42));
+ EXPECT_FP_IS_NAN(func(qnan_42, in.zero));
+ EXPECT_FP_IS_NAN(func(in.zero, qnan_42));
- EXPECT_FP_EQ(inf, func(inf, zero));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, zero));
- EXPECT_FP_EQ(inf, func(inf, neg_zero));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, neg_zero));
+ EXPECT_FP_EQ(inf, func(in.inf, in.zero));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero));
+ EXPECT_FP_EQ(inf, func(in.inf, in.neg_zero));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.neg_zero));
}
void test_invalid_operations(AddFunc func) {
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, neg_inf), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID);
}
void test_range_errors(AddFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf,
+ func(in.neg_max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -73,10 +74,11 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, neg_max_normal),
+ func(in.neg_max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
@@ -89,9 +91,11 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf,
+ func(in.neg_max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -105,11 +109,11 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, neg_max_normal),
+ func(in.neg_max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
@@ -124,7 +128,7 @@ class AddTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
void test_inexact_results(AddFunc func) {
- func(InType(1.0), min_denormal);
+ func(InType(1.0), in.min_denormal);
EXPECT_FP_EXCEPTION(FE_INEXACT);
}
};
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 7271e933b9311d..1ded60b78597ae 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -398,6 +398,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.dfmal
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -410,6 +411,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.dfmaf128
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -1057,6 +1059,7 @@ add_fp_unittest(
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.expf16
+ libc.src.__support.FPUtil.cast
)
add_fp_unittest(
@@ -1093,6 +1096,7 @@ add_fp_unittest(
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.exp2f16
+ libc.src.__support.FPUtil.cast
)
add_fp_unittest(
@@ -1140,6 +1144,7 @@ add_fp_unittest(
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.exp10f16
+ libc.src.__support.FPUtil.cast
)
add_fp_unittest(
@@ -3308,6 +3313,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.fmaf
+ libc.src.__support.macros.properties.types
FLAGS
FMA_OPT__ONLY
)
@@ -3322,6 +3328,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.fma
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -3359,6 +3366,7 @@ add_fp_unittest(
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.expm1f16
+ libc.src.__support.FPUtil.cast
)
add_fp_unittest(
@@ -4335,6 +4343,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.f16fma
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4347,6 +4356,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.f16fmaf
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4359,6 +4369,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.f16fmal
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4371,6 +4382,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.f16fmaf128
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4473,6 +4485,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.ffma
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4485,6 +4498,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.ffmal
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
@@ -4497,6 +4511,7 @@ add_fp_unittest(
FmaTest.h
DEPENDS
libc.src.math.ffmaf128
+ libc.src.__support.macros.properties.types
)
add_fp_unittest(
diff --git a/libc/test/src/math/smoke/DivTest.h b/libc/test/src/math/smoke/DivTest.h
index 666179628c55ff..60e7a8adc9eba3 100644
--- a/libc/test/src/math/smoke/DivTest.h
+++ b/libc/test/src/math/smoke/DivTest.h
@@ -28,45 +28,47 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using InFPBits = typename InConstants::FPBits;
using InStorageType = typename InConstants::StorageType;
+ InConstants in;
+
public:
using DivFunc = OutType (*)(InType, InType);
void test_special_numbers(DivFunc func) {
- EXPECT_FP_IS_NAN(func(aNaN, aNaN));
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);
+ EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN));
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID);
InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
- EXPECT_FP_IS_NAN(func(qnan_42, zero));
- EXPECT_FP_IS_NAN(func(zero, qnan_42));
+ EXPECT_FP_IS_NAN(func(qnan_42, in.zero));
+ EXPECT_FP_IS_NAN(func(in.zero, qnan_42));
- EXPECT_FP_EQ(inf, func(inf, zero));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, zero));
- EXPECT_FP_EQ(neg_inf, func(inf, neg_zero));
- EXPECT_FP_EQ(inf, func(neg_inf, neg_zero));
+ EXPECT_FP_EQ(inf, func(in.inf, in.zero));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero));
+ EXPECT_FP_EQ(neg_inf, func(in.inf, in.neg_zero));
+ EXPECT_FP_EQ(inf, func(in.neg_inf, in.neg_zero));
}
void test_division_by_zero(DivFunc func) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), zero), FE_DIVBYZERO);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(-1.0), zero),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO);
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(-1.0), in.zero),
FE_DIVBYZERO);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(1.0), neg_zero),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(InType(1.0), in.neg_zero),
FE_DIVBYZERO);
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), zero), FE_DIVBYZERO);
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(InType(1.0), in.zero), FE_DIVBYZERO);
}
void test_invalid_operations(DivFunc func) {
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(zero, zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_zero, zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(zero, neg_zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_zero, neg_zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.zero, in.neg_zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_zero, in.neg_zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, neg_inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, neg_inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_inf), FE_INVALID);
EXPECT_MATH_ERRNO(EDOM);
}
@@ -74,64 +76,72 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using namespace LIBC_NAMESPACE::fputil::testing;
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, min_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, min_denormal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf,
+ func(in.neg_max_normal, in.min_denormal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, func(neg_min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, min_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.min_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, min_denormal),
+ func(in.neg_max_normal, in.min_denormal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, func(neg_min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, min_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.min_normal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, min_denormal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf,
+ func(in.neg_max_normal, in.min_denormal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
- func(neg_min_denormal, max_normal),
+ func(in.neg_min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, min_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.min_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, min_denormal),
+ func(in.neg_max_normal, in.min_denormal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal, func(min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
+ func(in.min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero, func(neg_min_denormal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
+ func(in.neg_min_denormal, in.max_normal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
diff --git a/libc/test/src/math/smoke/FModTest.h b/libc/test/src/math/smoke/FModTest.h
index 0a4227da83f81d..ad9688fc01e7c1 100644
--- a/libc/test/src/math/smoke/FModTest.h
+++ b/libc/test/src/math/smoke/FModTest.h
@@ -108,61 +108,61 @@ class FmodTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
TEST_SPECIAL(T(3.0), neg_inf, T(3.0), false, 0);
TEST_SPECIAL(zero, aNaN, aNaN, false, 0);
- TEST_SPECIAL(zero, -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(zero, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(neg_zero, aNaN, aNaN, false, 0);
- TEST_SPECIAL(neg_zero, -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(neg_zero, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(T(1.0), aNaN, aNaN, false, 0);
- TEST_SPECIAL(T(1.0), -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(T(1.0), neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(inf, aNaN, aNaN, false, 0);
- TEST_SPECIAL(inf, -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(inf, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(neg_inf, aNaN, aNaN, false, 0);
- TEST_SPECIAL(neg_inf, -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(neg_inf, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(zero, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(zero, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(zero, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_zero, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(neg_zero, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_zero, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(T(1.0), sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(T(1.0), -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(T(1.0), neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(inf, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(inf, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(inf, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(neg_inf, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(neg_inf, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_inf, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(aNaN, zero, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, zero, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, zero, aNaN, false, 0);
TEST_SPECIAL(aNaN, neg_zero, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, neg_zero, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, neg_zero, aNaN, false, 0);
TEST_SPECIAL(aNaN, T(1.0), aNaN, false, 0);
- TEST_SPECIAL(-aNaN, T(1.0), aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, T(1.0), aNaN, false, 0);
TEST_SPECIAL(aNaN, inf, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, inf, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, inf, aNaN, false, 0);
TEST_SPECIAL(aNaN, neg_inf, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, neg_inf, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, neg_inf, aNaN, false, 0);
TEST_SPECIAL(sNaN, zero, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, zero, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, zero, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, neg_zero, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, neg_zero, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, neg_zero, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, T(1.0), aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, T(1.0), aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, T(1.0), aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, inf, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, inf, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, inf, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, neg_inf, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, neg_inf, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, neg_inf, aNaN, false, FE_INVALID);
TEST_SPECIAL(aNaN, aNaN, aNaN, false, 0);
- TEST_SPECIAL(aNaN, -aNaN, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, aNaN, aNaN, false, 0);
- TEST_SPECIAL(-aNaN, -aNaN, aNaN, false, 0);
+ TEST_SPECIAL(aNaN, neg_aNaN, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, aNaN, aNaN, false, 0);
+ TEST_SPECIAL(neg_aNaN, neg_aNaN, aNaN, false, 0);
TEST_SPECIAL(aNaN, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(aNaN, -sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-aNaN, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-aNaN, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(aNaN, neg_sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_aNaN, sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_aNaN, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, aNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(sNaN, -aNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, aNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, -aNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(sNaN, neg_aNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, aNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, neg_aNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(sNaN, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(sNaN, -sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, sNaN, aNaN, false, FE_INVALID);
- TEST_SPECIAL(-sNaN, -sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(sNaN, neg_sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, sNaN, aNaN, false, FE_INVALID);
+ TEST_SPECIAL(neg_sNaN, neg_sNaN, aNaN, false, FE_INVALID);
TEST_SPECIAL(T(6.5), T(2.25), T(2.0), false, 0);
TEST_SPECIAL(T(-6.5), T(2.25), T(-2.0), false, 0);
diff --git a/libc/test/src/math/smoke/FmaTest.h b/libc/test/src/math/smoke/FmaTest.h
index bf6d06d698fde5..41093422d51b2e 100644
--- a/libc/test/src/math/smoke/FmaTest.h
+++ b/libc/test/src/math/smoke/FmaTest.h
@@ -9,6 +9,9 @@
#ifndef LLVM_LIBC_TEST_SRC_MATH_FMATEST_H
#define LLVM_LIBC_TEST_SRC_MATH_FMATEST_H
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/macros/properties/types.h"
#include "test/UnitTest/FEnvSafeTest.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
@@ -37,6 +40,11 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
OutConstants out;
InConstants in;
+ const InType in_out_min_normal =
+ LIBC_NAMESPACE::fputil::cast<InType>(out.min_normal);
+ const InType in_out_min_denormal =
+ LIBC_NAMESPACE::fputil::cast<InType>(out.min_denormal);
+
public:
using FmaFunc = OutType (*)(InType, InType, InType);
@@ -52,7 +60,7 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
// Test underflow rounding up.
EXPECT_FP_EQ(OutFPBits(OutStorageType(2)).get_val(),
- func(OutType(0.5), out.min_denormal, out.min_denormal));
+ func(InType(0.5), in_out_min_denormal, in_out_min_denormal));
if constexpr (sizeof(OutType) < sizeof(InType)) {
EXPECT_FP_EQ(out.zero,
@@ -63,8 +71,9 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
OutType v = OutFPBits(static_cast<OutStorageType>(OUT_MIN_NORMAL_U +
OutStorageType(1)))
.get_val();
- EXPECT_FP_EQ(v, func(OutType(1) / OutType(OUT_MIN_NORMAL_U << 1), v,
- out.min_normal));
+ EXPECT_FP_EQ(v, func(InType(1) / InType(OUT_MIN_NORMAL_U << 1),
+ LIBC_NAMESPACE::fputil::cast<InType>(v),
+ in_out_min_normal));
if constexpr (sizeof(OutType) < sizeof(InType)) {
InFPBits tmp = InFPBits::one();
@@ -74,12 +83,21 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
InType v = InFPBits(static_cast<InStorageType>(IN_MIN_NORMAL_U +
InStorageType(1)))
.get_val();
- EXPECT_FP_EQ(out.min_normal, func(reciprocal_value, v, out.min_normal));
+ EXPECT_FP_EQ(out.min_normal,
+ func(reciprocal_value, v, in_out_min_normal));
}
// Test overflow.
OutType z = out.max_normal;
- EXPECT_FP_EQ_ALL_ROUNDING(OutType(0.75) * z, func(InType(1.75), z, -z));
+ InType in_z = LIBC_NAMESPACE::fputil::cast<InType>(out.max_normal);
+#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+ // Rounding modes other than the default might not be usable with float16.
+ if constexpr (LIBC_NAMESPACE::cpp::is_same_v<OutType, float16>)
+ EXPECT_FP_EQ(OutType(0.75) * z, func(InType(1.75), in_z, -in_z));
+ else
+#endif
+ EXPECT_FP_EQ_ALL_ROUNDING(OutType(0.75) * z,
+ func(InType(1.75), in_z, -in_z));
// Exact cancellation.
EXPECT_FP_EQ_ROUNDING_NEAREST(
diff --git a/libc/test/src/math/smoke/ModfTest.h b/libc/test/src/math/smoke/ModfTest.h
index 6226e5d55f40cc..24cfb1152c2e5f 100644
--- a/libc/test/src/math/smoke/ModfTest.h
+++ b/libc/test/src/math/smoke/ModfTest.h
@@ -97,7 +97,7 @@ class ModfTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
T integral;
T frac = func(x, &integral);
- ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(frac) < 1.0l);
+ ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(frac) < T(1.0));
ASSERT_TRUE(LIBC_NAMESPACE::fputil::trunc(x) == integral);
ASSERT_TRUE(integral + frac == x);
}
diff --git a/libc/test/src/math/smoke/MulTest.h b/libc/test/src/math/smoke/MulTest.h
index 0c847e39687b72..c409122397b1d7 100644
--- a/libc/test/src/math/smoke/MulTest.h
+++ b/libc/test/src/math/smoke/MulTest.h
@@ -34,22 +34,22 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using MulFunc = OutType (*)(InType, InType);
void test_special_numbers(MulFunc func) {
- EXPECT_FP_IS_NAN(func(aNaN, aNaN));
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);
+ EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN));
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID);
InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
- EXPECT_FP_IS_NAN(func(qnan_42, zero));
- EXPECT_FP_IS_NAN(func(zero, qnan_42));
+ EXPECT_FP_IS_NAN(func(qnan_42, in.zero));
+ EXPECT_FP_IS_NAN(func(in.zero, qnan_42));
- EXPECT_FP_EQ(inf, func(inf, InType(1.0)));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, InType(1.0)));
- EXPECT_FP_EQ(neg_inf, func(inf, InType(-1.0)));
- EXPECT_FP_EQ(inf, func(neg_inf, InType(-1.0)));
+ EXPECT_FP_EQ(inf, func(in.inf, InType(1.0)));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, InType(1.0)));
+ EXPECT_FP_EQ(neg_inf, func(in.inf, InType(-1.0)));
+ EXPECT_FP_EQ(inf, func(in.neg_inf, InType(-1.0)));
- EXPECT_FP_EQ_ALL_ROUNDING(zero, func(zero, zero));
- EXPECT_FP_EQ_ALL_ROUNDING(zero, func(neg_zero, neg_zero));
- EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(zero, neg_zero));
- EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero, zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, func(in.zero, in.zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, func(in.neg_zero, in.neg_zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.zero, in.neg_zero));
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(in.neg_zero, in.zero));
EXPECT_FP_EQ_ALL_ROUNDING(OutType(1.0), func(1.0, 1.0));
EXPECT_FP_EQ_ALL_ROUNDING(OutType(15.0), func(3.0, 5.0));
@@ -58,20 +58,21 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
void test_invalid_operations(MulFunc func) {
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, neg_zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, zero), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, neg_zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.neg_zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.zero), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_zero), FE_INVALID);
}
void test_range_errors(MulFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf,
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -85,10 +86,11 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, max_normal),
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
@@ -101,9 +103,11 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf,
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -117,11 +121,11 @@ class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, max_normal),
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
diff --git a/libc/test/src/math/smoke/NextTowardTest.h b/libc/test/src/math/smoke/NextTowardTest.h
index 5992273d919012..61528f71305db0 100644
--- a/libc/test/src/math/smoke/NextTowardTest.h
+++ b/libc/test/src/math/smoke/NextTowardTest.h
@@ -43,6 +43,8 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
const T neg_zero = FPBits::zero(Sign::NEG).get_val();
const T nan = FPBits::quiet_nan().get_val();
+ const long double to_inf = ToFPBits::inf(Sign::POS).get_val();
+ const long double to_neg_inf = ToFPBits::inf(Sign::NEG).get_val();
const long double to_zero = ToFPBits::zero().get_val();
const long double to_neg_zero = ToFPBits::zero(Sign::NEG).get_val();
const long double to_nan = ToFPBits::quiet_nan().get_val();
@@ -134,7 +136,7 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
- result = func(x, inf);
+ result = func(x, to_inf);
expected_bits = min_normal + 1;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
@@ -145,7 +147,7 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ_WITH_UNDERFLOW(result, expected);
- result = func(x, -inf);
+ result = func(x, to_neg_inf);
expected_bits = FPBits::SIGN_MASK + min_normal + 1;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
@@ -156,14 +158,14 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
expected_bits = max_normal - 1;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
- ASSERT_FP_EQ_WITH_OVERFLOW(func(x, inf), inf);
+ ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_inf), inf);
x = -x;
result = func(x, 0);
expected_bits = FPBits::SIGN_MASK + max_normal - 1;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
- ASSERT_FP_EQ_WITH_OVERFLOW(func(x, -inf), -inf);
+ ASSERT_FP_EQ_WITH_OVERFLOW(func(x, to_neg_inf), neg_inf);
// 'from' is infinity.
x = inf;
@@ -171,14 +173,14 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
expected_bits = max_normal;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
- ASSERT_FP_EQ(func(x, inf), inf);
+ ASSERT_FP_EQ(func(x, to_inf), inf);
x = neg_inf;
result = func(x, 0);
expected_bits = FPBits::SIGN_MASK + max_normal;
expected = LIBC_NAMESPACE::cpp::bit_cast<T>(expected_bits);
ASSERT_FP_EQ(result, expected);
- ASSERT_FP_EQ(func(x, neg_inf), neg_inf);
+ ASSERT_FP_EQ(func(x, to_neg_inf), neg_inf);
// 'from' is a power of 2.
x = T(32.0);
diff --git a/libc/test/src/math/smoke/SqrtTest.h b/libc/test/src/math/smoke/SqrtTest.h
index ce9f2f85b4604a..b5eaee22fc79dd 100644
--- a/libc/test/src/math/smoke/SqrtTest.h
+++ b/libc/test/src/math/smoke/SqrtTest.h
@@ -15,15 +15,21 @@ class SqrtTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
DECLARE_SPECIAL_CONSTANTS(OutType)
+ struct InConstants {
+ DECLARE_SPECIAL_CONSTANTS(InType)
+ };
+
+ InConstants in;
+
public:
typedef OutType (*SqrtFunc)(InType);
void test_special_numbers(SqrtFunc func) {
- ASSERT_FP_EQ(aNaN, func(aNaN));
- ASSERT_FP_EQ(inf, func(inf));
- ASSERT_FP_EQ(aNaN, func(neg_inf));
- ASSERT_FP_EQ(zero, func(zero));
- ASSERT_FP_EQ(neg_zero, func(neg_zero));
+ ASSERT_FP_EQ(aNaN, func(in.aNaN));
+ ASSERT_FP_EQ(inf, func(in.inf));
+ ASSERT_FP_EQ(aNaN, func(in.neg_inf));
+ ASSERT_FP_EQ(zero, func(in.zero));
+ ASSERT_FP_EQ(neg_zero, func(in.neg_zero));
ASSERT_FP_EQ(aNaN, func(InType(-1.0)));
ASSERT_FP_EQ(OutType(1.0), func(InType(1.0)));
ASSERT_FP_EQ(OutType(2.0), func(InType(4.0)));
diff --git a/libc/test/src/math/smoke/SubTest.h b/libc/test/src/math/smoke/SubTest.h
index 9ee4220b382085..b6ad7770a90598 100644
--- a/libc/test/src/math/smoke/SubTest.h
+++ b/libc/test/src/math/smoke/SubTest.h
@@ -33,32 +33,32 @@ class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
using SubFunc = OutType (*)(InType, InType);
void test_special_numbers(SubFunc func) {
- EXPECT_FP_IS_NAN(func(aNaN, aNaN));
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);
+ EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN));
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID);
InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
- EXPECT_FP_IS_NAN(func(qnan_42, zero));
- EXPECT_FP_IS_NAN(func(zero, qnan_42));
+ EXPECT_FP_IS_NAN(func(qnan_42, in.zero));
+ EXPECT_FP_IS_NAN(func(in.zero, qnan_42));
- EXPECT_FP_EQ(inf, func(inf, zero));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, zero));
- EXPECT_FP_EQ(inf, func(inf, neg_zero));
- EXPECT_FP_EQ(neg_inf, func(neg_inf, neg_zero));
+ EXPECT_FP_EQ(inf, func(in.inf, in.zero));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero));
+ EXPECT_FP_EQ(inf, func(in.inf, in.neg_zero));
+ EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.neg_zero));
}
void test_invalid_operations(SubFunc func) {
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, inf), FE_INVALID);
- EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, neg_inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.inf), FE_INVALID);
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_inf), FE_INVALID);
}
void test_range_errors(SubFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;
if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -73,10 +73,11 @@ class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, max_normal),
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(zero,
@@ -90,9 +91,10 @@ class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
+ func(in.max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(neg_max_normal, max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
@@ -107,11 +109,11 @@ class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
- EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, neg_max_normal),
+ EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.neg_max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
- func(neg_max_normal, max_normal),
+ func(in.neg_max_normal, in.max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
@@ -126,7 +128,7 @@ class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}
void test_inexact_results(SubFunc func) {
- func(InType(1.0), min_denormal);
+ func(InType(1.0), in.min_denormal);
EXPECT_FP_EXCEPTION(FE_INEXACT);
}
};
diff --git a/libc/test/src/math/smoke/exp10f16_test.cpp b/libc/test/src/math/smoke/exp10f16_test.cpp
index 006dfafa8aa141..1c4ef2aa08a70a 100644
--- a/libc/test/src/math/smoke/exp10f16_test.cpp
+++ b/libc/test/src/math/smoke/exp10f16_test.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/exp10f16.h"
#include "test/UnitTest/FPMatcher.h"
@@ -26,15 +27,14 @@ TEST_F(LlvmLibcExp10f16Test, SpecialNumbers) {
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::exp10f16(inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(zero),
- LIBC_NAMESPACE::exp10f16(neg_inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::exp10f16(neg_inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::exp10f16(zero));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::exp10f16(neg_zero));
EXPECT_MATH_ERRNO(0);
}
@@ -47,7 +47,8 @@ TEST_F(LlvmLibcExp10f16Test, Overflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- inf, LIBC_NAMESPACE::exp10f16(static_cast<float16>(5.0)), FE_OVERFLOW);
+ inf, LIBC_NAMESPACE::exp10f16(LIBC_NAMESPACE::fputil::cast<float16>(5.0)),
+ FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
@@ -59,7 +60,8 @@ TEST_F(LlvmLibcExp10f16Test, Underflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- zero, LIBC_NAMESPACE::exp10f16(static_cast<float16>(-8.0)),
+ zero,
+ LIBC_NAMESPACE::exp10f16(LIBC_NAMESPACE::fputil::cast<float16>(-8.0)),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
diff --git a/libc/test/src/math/smoke/exp2f16_test.cpp b/libc/test/src/math/smoke/exp2f16_test.cpp
index cd87e6134557a5..f69b33a3cf37fe 100644
--- a/libc/test/src/math/smoke/exp2f16_test.cpp
+++ b/libc/test/src/math/smoke/exp2f16_test.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/exp2f16.h"
#include "test/UnitTest/FPMatcher.h"
@@ -26,15 +27,14 @@ TEST_F(LlvmLibcExp2f16Test, SpecialNumbers) {
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::exp2f16(inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(zero),
- LIBC_NAMESPACE::exp2f16(neg_inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::exp2f16(neg_inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::exp2f16(zero));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::exp2f16(neg_zero));
EXPECT_MATH_ERRNO(0);
}
@@ -47,7 +47,8 @@ TEST_F(LlvmLibcExp2f16Test, Overflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- inf, LIBC_NAMESPACE::exp2f16(static_cast<float16>(16.0)), FE_OVERFLOW);
+ inf, LIBC_NAMESPACE::exp2f16(LIBC_NAMESPACE::fputil::cast<float16>(16.0)),
+ FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
@@ -59,7 +60,8 @@ TEST_F(LlvmLibcExp2f16Test, Underflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- zero, LIBC_NAMESPACE::exp2f16(static_cast<float16>(-25.0)),
+ zero,
+ LIBC_NAMESPACE::exp2f16(LIBC_NAMESPACE::fputil::cast<float16>(-25.0)),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
diff --git a/libc/test/src/math/smoke/expf16_test.cpp b/libc/test/src/math/smoke/expf16_test.cpp
index 969870fe247bc2..ab745a3cf6f563 100644
--- a/libc/test/src/math/smoke/expf16_test.cpp
+++ b/libc/test/src/math/smoke/expf16_test.cpp
@@ -8,6 +8,7 @@
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/expf16.h"
#include "test/UnitTest/FPMatcher.h"
@@ -27,15 +28,14 @@ TEST_F(LlvmLibcExpf16Test, SpecialNumbers) {
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::expf16(inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(zero),
- LIBC_NAMESPACE::expf16(neg_inf));
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::expf16(neg_inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::expf16(zero));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(1.0f),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(1.0f),
LIBC_NAMESPACE::expf16(neg_zero));
EXPECT_MATH_ERRNO(0);
}
@@ -48,7 +48,8 @@ TEST_F(LlvmLibcExpf16Test, Overflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- inf, LIBC_NAMESPACE::expf16(static_cast<float16>(12.0)), FE_OVERFLOW);
+ inf, LIBC_NAMESPACE::expf16(LIBC_NAMESPACE::fputil::cast<float16>(12.0)),
+ FE_OVERFLOW);
EXPECT_MATH_ERRNO(ERANGE);
}
@@ -60,7 +61,8 @@ TEST_F(LlvmLibcExpf16Test, Underflow) {
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(
- zero, LIBC_NAMESPACE::expf16(static_cast<float16>(-18.0)),
+ zero,
+ LIBC_NAMESPACE::expf16(LIBC_NAMESPACE::fputil::cast<float16>(-18.0)),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
diff --git a/libc/test/src/math/smoke/expm1f16_test.cpp b/libc/test/src/math/smoke/expm1f16_test.cpp
index 3bdbaad2279416..f297c5dfc3c7e1 100644
--- a/libc/test/src/math/smoke/expm1f16_test.cpp
+++ b/libc/test/src/math/smoke/expm1f16_test.cpp
@@ -8,6 +8,7 @@
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/expm1f16.h"
#include "test/UnitTest/FPMatcher.h"
@@ -27,7 +28,7 @@ TEST_F(LlvmLibcExpm1f16Test, SpecialNumbers) {
EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::expm1f16(inf));
EXPECT_MATH_ERRNO(0);
- EXPECT_FP_EQ_ALL_ROUNDING(static_cast<float16>(-1.0),
+ EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::expm1f16(neg_inf));
EXPECT_MATH_ERRNO(0);
@@ -46,7 +47,7 @@ TEST_F(LlvmLibcExpm1f16Test, Overflow) {
EXPECT_MATH_ERRNO(ERANGE);
// round(16 * log(2), HP, RN);
- float16 x = static_cast<float16>(0x1.63p+3);
+ float16 x = LIBC_NAMESPACE::fputil::cast<float16>(0x1.63p+3);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(inf, LIBC_NAMESPACE::expm1f16(x),
FE_OVERFLOW | FE_INEXACT);
@@ -68,41 +69,44 @@ TEST_F(LlvmLibcExpm1f16Test, Overflow) {
TEST_F(LlvmLibcExpm1f16Test, ResultNearNegOne) {
LIBC_NAMESPACE::libc_errno = 0;
- EXPECT_FP_EQ_WITH_EXCEPTION(static_cast<float16>(-1.0),
+ EXPECT_FP_EQ_WITH_EXCEPTION(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::expm1f16(neg_max_normal),
FE_INEXACT);
// round(-11 * log(2), HP, RN);
- float16 x = static_cast<float16>(-0x1.e8p+2);
+ float16 x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.e8p+2);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
- static_cast<float16>(-0x1.ffcp-1), LIBC_NAMESPACE::expm1f16(x),
- FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
+ LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(static_cast<float16>(-0x1.ffcp-1),
- LIBC_NAMESPACE::expm1f16(x),
- FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
+ LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
+ LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
- static_cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x),
+ FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
- static_cast<float16>(-0x1.ffcp-1), LIBC_NAMESPACE::expm1f16(x),
- FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
+ LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
- x = static_cast<float16>(-0x1.0a4p+3);
+ x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.0a4p+3);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
- static_cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x),
+ FE_INEXACT);
- EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(static_cast<float16>(-0x1.ffcp-1),
- LIBC_NAMESPACE::expm1f16(x),
- FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
+ LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
+ LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
- static_cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-1.0), LIBC_NAMESPACE::expm1f16(x),
+ FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
- static_cast<float16>(-0x1.ffcp-1), LIBC_NAMESPACE::expm1f16(x),
- FE_INEXACT);
+ LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
+ LIBC_NAMESPACE::expm1f16(x), FE_INEXACT);
}
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index be0415d0956fa4..cebf9082271ec5 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -11,6 +11,7 @@ if(LIBC_TESTS_CAN_USE_MPFR)
libc.src.__support.CPP.stringstream
libc.src.__support.CPP.string_view
libc.src.__support.CPP.type_traits
+ libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fpbits_str
LibcTest.unit
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 7ce6a70d093169..27ff1f7190ef95 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -13,6 +13,7 @@
#include "src/__support/CPP/string_view.h"
#include "src/__support/CPP/stringstream.h"
#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/fpbits_str.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"
@@ -683,7 +684,7 @@ template <> long double MPFRNumber::as<long double>() const {
template <> float16 MPFRNumber::as<float16>() const {
// TODO: Either prove that this cast won't cause double-rounding errors, or
// find a better way to get a float16.
- return static_cast<float16>(mpfr_get_d(value, mpfr_rounding));
+ return fputil::cast<float16>(mpfr_get_d(value, mpfr_rounding));
}
#endif
>From 5e6d18c7ceccfe053805fcef07a21001231202f4 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Tue, 20 Aug 2024 19:40:42 +0200
Subject: [PATCH 2/2] Fix CMake target dependencies
---
libc/src/__support/FPUtil/CMakeLists.txt | 2 ++
libc/src/__support/FPUtil/generic/CMakeLists.txt | 1 +
2 files changed, 3 insertions(+)
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 90901549946f42..522b4afefd48d6 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -92,11 +92,13 @@ add_header_library(
HDRS
except_value_utils.h
DEPENDS
+ .cast
.fp_bits
.fenv_impl
.rounding_mode
libc.src.__support.CPP.optional
libc.src.__support.macros.optimization
+ libc.src.__support.macros.properties.cpu_features
libc.src.__support.macros.properties.types
)
diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index b6f58f3fab571a..60434d6f6f11ab 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -68,6 +68,7 @@ add_header_library(
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.attributes
+ libc.src.__support.macros.optimization
)
add_header_library(
More information about the libc-commits
mailing list