[libc-commits] [libc] [llvm] [libc][math][c23] Add {, u}fromfp{, x}{, f, l, f128} functions (PR #86003)
via libc-commits
libc-commits at lists.llvm.org
Fri Mar 22 13:43:58 PDT 2024
- Previous message: [libc-commits] [libc] [llvm] [libc][math][c23] Add {, u}fromfp{, x}{, f, l, f128} functions (PR #86003)
- Next message: [libc-commits] [libc] [llvm] [libc][math][c23] Add {, u}fromfp{, x}{, f, l, f128} functions (PR #86003)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
https://github.com/overmighty updated https://github.com/llvm/llvm-project/pull/86003
>From 6cc24c159cde5ac478b8a12b447cb7be229d584c Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Wed, 20 Mar 2024 20:40:55 +0000
Subject: [PATCH 1/5] [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128} functions
Fixes #85279.
---
libc/config/linux/x86_64/entrypoints.txt | 16 +
libc/docs/math/index.rst | 32 ++
libc/include/llvm-libc-macros/math-macros.h | 6 +
libc/spec/stdc.td | 26 +
.../FPUtil/NearestIntegerOperations.h | 90 +++-
libc/src/math/CMakeLists.txt | 20 +
libc/src/math/fromfp.h | 18 +
libc/src/math/fromfpf.h | 18 +
libc/src/math/fromfpf128.h | 20 +
libc/src/math/fromfpl.h | 18 +
libc/src/math/fromfpx.h | 18 +
libc/src/math/fromfpxf.h | 18 +
libc/src/math/fromfpxf128.h | 20 +
libc/src/math/fromfpxl.h | 18 +
libc/src/math/generic/CMakeLists.txt | 196 ++++++++
libc/src/math/generic/fromfp.cpp | 19 +
libc/src/math/generic/fromfpf.cpp | 19 +
libc/src/math/generic/fromfpf128.cpp | 20 +
libc/src/math/generic/fromfpl.cpp | 20 +
libc/src/math/generic/fromfpx.cpp | 19 +
libc/src/math/generic/fromfpxf.cpp | 19 +
libc/src/math/generic/fromfpxf128.cpp | 20 +
libc/src/math/generic/fromfpxl.cpp | 20 +
libc/src/math/generic/ufromfp.cpp | 19 +
libc/src/math/generic/ufromfpf.cpp | 19 +
libc/src/math/generic/ufromfpf128.cpp | 20 +
libc/src/math/generic/ufromfpl.cpp | 20 +
libc/src/math/generic/ufromfpx.cpp | 19 +
libc/src/math/generic/ufromfpxf.cpp | 19 +
libc/src/math/generic/ufromfpxf128.cpp | 20 +
libc/src/math/generic/ufromfpxl.cpp | 20 +
libc/src/math/ufromfp.h | 18 +
libc/src/math/ufromfpf.h | 18 +
libc/src/math/ufromfpf128.h | 20 +
libc/src/math/ufromfpl.h | 18 +
libc/src/math/ufromfpx.h | 18 +
libc/src/math/ufromfpxf.h | 18 +
libc/src/math/ufromfpxf128.h | 20 +
libc/src/math/ufromfpxl.h | 18 +
libc/test/UnitTest/CMakeLists.txt | 1 +
libc/test/UnitTest/FPMatcher.h | 9 +-
libc/test/src/math/smoke/CMakeLists.txt | 192 ++++++++
libc/test/src/math/smoke/FromfpTest.h | 338 +++++++++++++
libc/test/src/math/smoke/FromfpxTest.h | 452 ++++++++++++++++++
libc/test/src/math/smoke/UfromfpTest.h | 288 +++++++++++
libc/test/src/math/smoke/UfromfpxTest.h | 353 ++++++++++++++
libc/test/src/math/smoke/fromfp_test.cpp | 13 +
libc/test/src/math/smoke/fromfpf128_test.cpp | 13 +
libc/test/src/math/smoke/fromfpf_test.cpp | 13 +
libc/test/src/math/smoke/fromfpl_test.cpp | 13 +
libc/test/src/math/smoke/fromfpx_test.cpp | 13 +
libc/test/src/math/smoke/fromfpxf128_test.cpp | 13 +
libc/test/src/math/smoke/fromfpxf_test.cpp | 13 +
libc/test/src/math/smoke/fromfpxl_test.cpp | 13 +
libc/test/src/math/smoke/ufromfp_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpf128_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpf_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpl_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpx_test.cpp | 13 +
.../test/src/math/smoke/ufromfpxf128_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpxf_test.cpp | 13 +
libc/test/src/math/smoke/ufromfpxl_test.cpp | 13 +
.../libc/test/UnitTest/BUILD.bazel | 1 +
63 files changed, 2821 insertions(+), 15 deletions(-)
create mode 100644 libc/src/math/fromfp.h
create mode 100644 libc/src/math/fromfpf.h
create mode 100644 libc/src/math/fromfpf128.h
create mode 100644 libc/src/math/fromfpl.h
create mode 100644 libc/src/math/fromfpx.h
create mode 100644 libc/src/math/fromfpxf.h
create mode 100644 libc/src/math/fromfpxf128.h
create mode 100644 libc/src/math/fromfpxl.h
create mode 100644 libc/src/math/generic/fromfp.cpp
create mode 100644 libc/src/math/generic/fromfpf.cpp
create mode 100644 libc/src/math/generic/fromfpf128.cpp
create mode 100644 libc/src/math/generic/fromfpl.cpp
create mode 100644 libc/src/math/generic/fromfpx.cpp
create mode 100644 libc/src/math/generic/fromfpxf.cpp
create mode 100644 libc/src/math/generic/fromfpxf128.cpp
create mode 100644 libc/src/math/generic/fromfpxl.cpp
create mode 100644 libc/src/math/generic/ufromfp.cpp
create mode 100644 libc/src/math/generic/ufromfpf.cpp
create mode 100644 libc/src/math/generic/ufromfpf128.cpp
create mode 100644 libc/src/math/generic/ufromfpl.cpp
create mode 100644 libc/src/math/generic/ufromfpx.cpp
create mode 100644 libc/src/math/generic/ufromfpxf.cpp
create mode 100644 libc/src/math/generic/ufromfpxf128.cpp
create mode 100644 libc/src/math/generic/ufromfpxl.cpp
create mode 100644 libc/src/math/ufromfp.h
create mode 100644 libc/src/math/ufromfpf.h
create mode 100644 libc/src/math/ufromfpf128.h
create mode 100644 libc/src/math/ufromfpl.h
create mode 100644 libc/src/math/ufromfpx.h
create mode 100644 libc/src/math/ufromfpxf.h
create mode 100644 libc/src/math/ufromfpxf128.h
create mode 100644 libc/src/math/ufromfpxl.h
create mode 100644 libc/test/src/math/smoke/FromfpTest.h
create mode 100644 libc/test/src/math/smoke/FromfpxTest.h
create mode 100644 libc/test/src/math/smoke/UfromfpTest.h
create mode 100644 libc/test/src/math/smoke/UfromfpxTest.h
create mode 100644 libc/test/src/math/smoke/fromfp_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpf128_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpf_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpl_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpx_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpxf128_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpxf_test.cpp
create mode 100644 libc/test/src/math/smoke/fromfpxl_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfp_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpf128_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpf_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpl_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpx_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpxf128_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpxf_test.cpp
create mode 100644 libc/test/src/math/smoke/ufromfpxl_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 8b1cd3fb105271..de741e218a3727 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -387,6 +387,12 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
+ libc.src.math.fromfp
+ libc.src.math.fromfpf
+ libc.src.math.fromfpl
+ libc.src.math.fromfpx
+ libc.src.math.fromfpxf
+ libc.src.math.fromfpxl
libc.src.math.hypot
libc.src.math.hypotf
libc.src.math.ilogb
@@ -471,6 +477,12 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.trunc
libc.src.math.truncf
libc.src.math.truncl
+ libc.src.math.ufromfp
+ libc.src.math.ufromfpf
+ libc.src.math.ufromfpl
+ libc.src.math.ufromfpx
+ libc.src.math.ufromfpxf
+ libc.src.math.ufromfpxl
)
if(LIBC_TYPES_HAS_FLOAT128)
@@ -485,6 +497,8 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.fminf128
libc.src.math.fmodf128
libc.src.math.frexpf128
+ libc.src.math.fromfpf128
+ libc.src.math.fromfpxf128
libc.src.math.ilogbf128
libc.src.math.ldexpf128
libc.src.math.llogbf128
@@ -502,6 +516,8 @@ if(LIBC_TYPES_HAS_FLOAT128)
libc.src.math.roundf128
libc.src.math.sqrtf128
libc.src.math.truncf128
+ libc.src.math.ufromfpf128
+ libc.src.math.ufromfpxf128
)
endif()
diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst
index d337d060fb5dd9..fa604faaec2ff0 100644
--- a/libc/docs/math/index.rst
+++ b/libc/docs/math/index.rst
@@ -181,6 +181,22 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| frexpf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfp | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpf | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpl | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpf128 | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpx | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpxf | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpxl | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| fromfpxf128 | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| ilogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| ilogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | |
@@ -339,6 +355,22 @@ Basic Operations
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
| truncf128 | |check| | |check| | | |check| | | | | | | | | |
+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfp | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpf | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpl | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpf128 | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpx | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpxf | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpxl | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
+| ufromfpxf128 | |check| | | | | | | | | | | | |
++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+
Higher Math Functions
diff --git a/libc/include/llvm-libc-macros/math-macros.h b/libc/include/llvm-libc-macros/math-macros.h
index 2605535b927d76..03c7a823e6e96b 100644
--- a/libc/include/llvm-libc-macros/math-macros.h
+++ b/libc/include/llvm-libc-macros/math-macros.h
@@ -17,6 +17,12 @@
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
+#define FP_INT_UPWARD 0
+#define FP_INT_DOWNWARD 1
+#define FP_INT_TOWARDZERO 2
+#define FP_INT_TONEARESTFROMZERO 3
+#define FP_INT_TONEAREST 4
+
#define MATH_ERRNO 1
#define MATH_ERREXCEPT 2
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 3e58e3b8864566..a8b365fec1e9ea 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -352,6 +352,12 @@ def StdC : StandardSpec<"stdc"> {
Macro<"INFINITY">,
Macro<"NAN">,
+ Macro<"FP_INT_UPWARD">,
+ Macro<"FP_INT_DOWNWARD">,
+ Macro<"FP_INT_TOWARDZERO">,
+ Macro<"FP_INT_TONEARESTFROMZERO">,
+ Macro<"FP_INT_TONEAREST">,
+
Macro<"FP_ILOGB0">,
Macro<"FP_ILOGBNAN">,
@@ -414,6 +420,26 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"frexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>,
GuardedFunctionSpec<"frexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">,
+ FunctionSpec<"fromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+
+ FunctionSpec<"fromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"fromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+
+ FunctionSpec<"ufromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+
+ FunctionSpec<"ufromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ FunctionSpec<"ufromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+
FunctionSpec<"hypot", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index e890e38ba4ae7d..cef612f9263529 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -141,7 +141,7 @@ LIBC_INLINE T round(T x) {
}
template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE T round_using_current_rounding_mode(T x) {
+LIBC_INLINE constexpr T round_using_specific_rounding_mode(T x, int rnd) {
using StorageType = typename FPBits<T>::StorageType;
FPBits<T> bits(x);
@@ -151,7 +151,6 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
bool is_neg = bits.is_neg();
int exponent = bits.get_exponent();
- int rounding_mode = quick_get_round();
// If the exponent is greater than the most negative mantissa
// exponent, then x is already an integer.
@@ -159,20 +158,23 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
return x;
if (exponent <= -1) {
- switch (rounding_mode) {
- case FE_DOWNWARD:
+ switch (rnd) {
+ case FP_INT_DOWNWARD:
return is_neg ? T(-1.0) : T(0.0);
- case FE_UPWARD:
+ case FP_INT_UPWARD:
return is_neg ? T(-0.0) : T(1.0);
- case FE_TOWARDZERO:
+ case FP_INT_TOWARDZERO:
return is_neg ? T(-0.0) : T(0.0);
- case FE_TONEAREST:
+ case FP_INT_TONEARESTFROMZERO:
+ if (exponent < -1)
+ return is_neg ? T(-0.0) : T(0.0); // abs(x) < 0.5
+ return is_neg ? T(-1.0) : T(1.0); // abs(x) >= 0.5
+ case FP_INT_TONEAREST:
+ default:
if (exponent <= -2 || bits.get_mantissa() == 0)
return is_neg ? T(-0.0) : T(0.0); // abs(x) <= 0.5
else
return is_neg ? T(-1.0) : T(1.0); // abs(x) > 0.5
- default:
- __builtin_unreachable();
}
}
@@ -194,14 +196,19 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
StorageType trunc_is_odd =
new_bits.get_mantissa() & (StorageType(1) << trim_size);
- switch (rounding_mode) {
- case FE_DOWNWARD:
+ switch (rnd) {
+ case FP_INT_DOWNWARD:
return is_neg ? trunc_value - T(1.0) : trunc_value;
- case FE_UPWARD:
+ case FP_INT_UPWARD:
return is_neg ? trunc_value : trunc_value + T(1.0);
- case FE_TOWARDZERO:
+ case FP_INT_TOWARDZERO:
return trunc_value;
- case FE_TONEAREST:
+ case FP_INT_TONEARESTFROMZERO:
+ if (trim_value >= half_value)
+ return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0);
+ return trunc_value;
+ case FP_INT_TONEAREST:
+ default:
if (trim_value > half_value) {
return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0);
} else if (trim_value == half_value) {
@@ -214,11 +221,66 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
} else {
return trunc_value;
}
+ }
+}
+
+template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
+LIBC_INLINE T round_using_current_rounding_mode(T x) {
+ int rounding_mode = quick_get_round();
+
+ switch (rounding_mode) {
+ case FE_DOWNWARD:
+ return round_using_specific_rounding_mode(x, FP_INT_DOWNWARD);
+ case FE_UPWARD:
+ return round_using_specific_rounding_mode(x, FP_INT_UPWARD);
+ case FE_TOWARDZERO:
+ return round_using_specific_rounding_mode(x, FP_INT_TOWARDZERO);
+ case FE_TONEAREST:
+ return round_using_specific_rounding_mode(x, FP_INT_TONEAREST);
default:
__builtin_unreachable();
}
}
+template <bool IsSigned, typename T,
+ cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
+LIBC_INLINE constexpr T fromfp(T x, int rnd, unsigned int width) {
+ if (width == 0U)
+ return FPBits<T>::quiet_nan().get_val();
+
+ T rounded_value = round_using_specific_rounding_mode(x, rnd);
+
+ if constexpr (IsSigned) {
+ // T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
+ if (width - 1 > FPBits<T>::EXP_BIAS)
+ return rounded_value;
+ if (rounded_value < -T(1U << (width - 1U)))
+ return FPBits<T>::quiet_nan().get_val();
+ if (rounded_value > T((1U << (width - 1U)) - 1U))
+ return FPBits<T>::quiet_nan().get_val();
+ return rounded_value;
+ }
+
+ if (rounded_value < T(0.0))
+ return FPBits<T>::quiet_nan().get_val();
+ // T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
+ if (width <= FPBits<T>::EXP_BIAS && rounded_value > T(1U << width) - 1U)
+ return FPBits<T>::quiet_nan().get_val();
+ return rounded_value;
+}
+
+template <bool IsSigned, typename T,
+ cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
+LIBC_INLINE constexpr T fromfpx(T x, int rnd, unsigned int width) {
+ T rounded_value = fromfp<IsSigned>(x, rnd, width);
+ FPBits<T> bits(rounded_value);
+
+ if (!bits.is_nan() && rounded_value != x)
+ raise_except_if_required(FE_INEXACT);
+
+ return rounded_value;
+}
+
namespace internal {
template <typename F, typename I,
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 5e2e6e699d0e0c..2f1d65780013f8 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -127,6 +127,16 @@ add_math_entrypoint_object(frexpf)
add_math_entrypoint_object(frexpl)
add_math_entrypoint_object(frexpf128)
+add_math_entrypoint_object(fromfp)
+add_math_entrypoint_object(fromfpf)
+add_math_entrypoint_object(fromfpl)
+add_math_entrypoint_object(fromfpf128)
+
+add_math_entrypoint_object(fromfpx)
+add_math_entrypoint_object(fromfpxf)
+add_math_entrypoint_object(fromfpxl)
+add_math_entrypoint_object(fromfpxf128)
+
add_math_entrypoint_object(hypot)
add_math_entrypoint_object(hypotf)
@@ -267,3 +277,13 @@ add_math_entrypoint_object(trunc)
add_math_entrypoint_object(truncf)
add_math_entrypoint_object(truncl)
add_math_entrypoint_object(truncf128)
+
+add_math_entrypoint_object(ufromfp)
+add_math_entrypoint_object(ufromfpf)
+add_math_entrypoint_object(ufromfpl)
+add_math_entrypoint_object(ufromfpf128)
+
+add_math_entrypoint_object(ufromfpx)
+add_math_entrypoint_object(ufromfpxf)
+add_math_entrypoint_object(ufromfpxl)
+add_math_entrypoint_object(ufromfpxf128)
diff --git a/libc/src/math/fromfp.h b/libc/src/math/fromfp.h
new file mode 100644
index 00000000000000..d3de2dd3460832
--- /dev/null
+++ b/libc/src/math/fromfp.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfp ------------------------*- 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_FROMFP_H
+#define LLVM_LIBC_SRC_MATH_FROMFP_H
+
+namespace LIBC_NAMESPACE {
+
+double fromfp(double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFP_H
diff --git a/libc/src/math/fromfpf.h b/libc/src/math/fromfpf.h
new file mode 100644
index 00000000000000..11d432148d0189
--- /dev/null
+++ b/libc/src/math/fromfpf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfpf -----------------------*- 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_FROMFPF_H
+#define LLVM_LIBC_SRC_MATH_FROMFPF_H
+
+namespace LIBC_NAMESPACE {
+
+float fromfpf(float x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPF_H
diff --git a/libc/src/math/fromfpf128.h b/libc/src/math/fromfpf128.h
new file mode 100644
index 00000000000000..5f85fde570a0fb
--- /dev/null
+++ b/libc/src/math/fromfpf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for fromfpf128 --------------------*- 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_FROMFPF128_H
+#define LLVM_LIBC_SRC_MATH_FROMFPF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 fromfpf128(float128 x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPF128_H
diff --git a/libc/src/math/fromfpl.h b/libc/src/math/fromfpl.h
new file mode 100644
index 00000000000000..dd8e1eebdea994
--- /dev/null
+++ b/libc/src/math/fromfpl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfpl -----------------------*- 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_FROMFPL_H
+#define LLVM_LIBC_SRC_MATH_FROMFPL_H
+
+namespace LIBC_NAMESPACE {
+
+long double fromfpl(long double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPL_H
diff --git a/libc/src/math/fromfpx.h b/libc/src/math/fromfpx.h
new file mode 100644
index 00000000000000..3fc96e1e648b93
--- /dev/null
+++ b/libc/src/math/fromfpx.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfpx -----------------------*- 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_FROMFPX_H
+#define LLVM_LIBC_SRC_MATH_FROMFPX_H
+
+namespace LIBC_NAMESPACE {
+
+double fromfpx(double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPX_H
diff --git a/libc/src/math/fromfpxf.h b/libc/src/math/fromfpxf.h
new file mode 100644
index 00000000000000..b55bc4c7513951
--- /dev/null
+++ b/libc/src/math/fromfpxf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfpxf ----------------------*- 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_FROMFPXF_H
+#define LLVM_LIBC_SRC_MATH_FROMFPXF_H
+
+namespace LIBC_NAMESPACE {
+
+float fromfpxf(float x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPXF_H
diff --git a/libc/src/math/fromfpxf128.h b/libc/src/math/fromfpxf128.h
new file mode 100644
index 00000000000000..88932646cdcc9f
--- /dev/null
+++ b/libc/src/math/fromfpxf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for fromfpxf128 -------------------*- 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_FROMFPXF128_H
+#define LLVM_LIBC_SRC_MATH_FROMFPXF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 fromfpxf128(float128 x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPXF128_H
diff --git a/libc/src/math/fromfpxl.h b/libc/src/math/fromfpxl.h
new file mode 100644
index 00000000000000..545288834b8f33
--- /dev/null
+++ b/libc/src/math/fromfpxl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fromfpxl ----------------------*- 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_FROMFPXL_H
+#define LLVM_LIBC_SRC_MATH_FROMFPXL_H
+
+namespace LIBC_NAMESPACE {
+
+long double fromfpxl(long double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_FROMFPXL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 176c32e47768df..e8eb36acc93035 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2025,6 +2025,202 @@ add_entrypoint_object(
-O3
)
+add_entrypoint_object(
+ fromfp
+ SRCS
+ fromfp.cpp
+ HDRS
+ ../fromfp.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpf
+ SRCS
+ fromfpf.cpp
+ HDRS
+ ../fromfpf.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpl
+ SRCS
+ fromfpl.cpp
+ HDRS
+ ../fromfpl.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpf128
+ SRCS
+ fromfpf128.cpp
+ HDRS
+ ../fromfpf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpx
+ SRCS
+ fromfpx.cpp
+ HDRS
+ ../fromfpx.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpxf
+ SRCS
+ fromfpxf.cpp
+ HDRS
+ ../fromfpxf.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpxl
+ SRCS
+ fromfpxl.cpp
+ HDRS
+ ../fromfpxl.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ fromfpxf128
+ SRCS
+ fromfpxf128.cpp
+ HDRS
+ ../fromfpxf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfp
+ SRCS
+ ufromfp.cpp
+ HDRS
+ ../ufromfp.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpf
+ SRCS
+ ufromfpf.cpp
+ HDRS
+ ../ufromfpf.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpl
+ SRCS
+ ufromfpl.cpp
+ HDRS
+ ../ufromfpl.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpf128
+ SRCS
+ ufromfpf128.cpp
+ HDRS
+ ../ufromfpf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpx
+ SRCS
+ ufromfpx.cpp
+ HDRS
+ ../ufromfpx.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpxf
+ SRCS
+ ufromfpxf.cpp
+ HDRS
+ ../ufromfpxf.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpxl
+ SRCS
+ ufromfpxl.cpp
+ HDRS
+ ../ufromfpxl.h
+ DEPENDS
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
+add_entrypoint_object(
+ ufromfpxf128
+ SRCS
+ ufromfpxf128.cpp
+ HDRS
+ ../ufromfpxf128.h
+ DEPENDS
+ libc.src.__support.macros.properties.types
+ libc.src.__support.FPUtil.nearest_integer
+ COMPILE_OPTIONS
+ -O3
+)
+
#TODO: Add errno include to the hyperbolic functions.
add_object_library(
explogxf
diff --git a/libc/src/math/generic/fromfp.cpp b/libc/src/math/generic/fromfp.cpp
new file mode 100644
index 00000000000000..ba3f0a133cbcb9
--- /dev/null
+++ b/libc/src/math/generic/fromfp.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fromfp 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/fromfp.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, fromfp, (double x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpf.cpp b/libc/src/math/generic/fromfpf.cpp
new file mode 100644
index 00000000000000..fd058a13201c90
--- /dev/null
+++ b/libc/src/math/generic/fromfpf.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fromfpf 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/fromfpf.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, fromfpf, (float x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpf128.cpp b/libc/src/math/generic/fromfpf128.cpp
new file mode 100644
index 00000000000000..440a5da756932b
--- /dev/null
+++ b/libc/src/math/generic/fromfpf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fromfpf128 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/fromfpf128.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, fromfpf128,
+ (float128 x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpl.cpp b/libc/src/math/generic/fromfpl.cpp
new file mode 100644
index 00000000000000..ee3abeaf98f856
--- /dev/null
+++ b/libc/src/math/generic/fromfpl.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fromfpl 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/fromfpl.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, fromfpl,
+ (long double x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpx.cpp b/libc/src/math/generic/fromfpx.cpp
new file mode 100644
index 00000000000000..b9e7e4a7aa1262
--- /dev/null
+++ b/libc/src/math/generic/fromfpx.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fromfpx 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/fromfpx.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, fromfpx, (double x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpxf.cpp b/libc/src/math/generic/fromfpxf.cpp
new file mode 100644
index 00000000000000..1473499244d318
--- /dev/null
+++ b/libc/src/math/generic/fromfpxf.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of fromfpxf 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/fromfpxf.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, fromfpxf, (float x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpxf128.cpp b/libc/src/math/generic/fromfpxf128.cpp
new file mode 100644
index 00000000000000..5d930d22ae5eb1
--- /dev/null
+++ b/libc/src/math/generic/fromfpxf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fromfpxf128 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/fromfpxf128.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, fromfpxf128,
+ (float128 x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/fromfpxl.cpp b/libc/src/math/generic/fromfpxl.cpp
new file mode 100644
index 00000000000000..c3db055246f227
--- /dev/null
+++ b/libc/src/math/generic/fromfpxl.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of fromfpxl 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/fromfpxl.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, fromfpxl,
+ (long double x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfp.cpp b/libc/src/math/generic/ufromfp.cpp
new file mode 100644
index 00000000000000..15800d67fd8d38
--- /dev/null
+++ b/libc/src/math/generic/ufromfp.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ufromfp 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/ufromfp.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, ufromfp, (double x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpf.cpp b/libc/src/math/generic/ufromfpf.cpp
new file mode 100644
index 00000000000000..898446ec45aa21
--- /dev/null
+++ b/libc/src/math/generic/ufromfpf.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ufromfpf 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/ufromfpf.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, ufromfpf, (float x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpf128.cpp b/libc/src/math/generic/ufromfpf128.cpp
new file mode 100644
index 00000000000000..cc728f35551ca6
--- /dev/null
+++ b/libc/src/math/generic/ufromfpf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ufromfpf128 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/ufromfpf128.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, ufromfpf128,
+ (float128 x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpl.cpp b/libc/src/math/generic/ufromfpl.cpp
new file mode 100644
index 00000000000000..bd353e9ebbb566
--- /dev/null
+++ b/libc/src/math/generic/ufromfpl.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ufromfpl 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/ufromfpl.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, ufromfpl,
+ (long double x, int rnd, unsigned int width)) {
+ return fputil::fromfp</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpx.cpp b/libc/src/math/generic/ufromfpx.cpp
new file mode 100644
index 00000000000000..5ad95ff3061ebd
--- /dev/null
+++ b/libc/src/math/generic/ufromfpx.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ufromfpx 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/ufromfpx.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(double, ufromfpx, (double x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpxf.cpp b/libc/src/math/generic/ufromfpxf.cpp
new file mode 100644
index 00000000000000..7c878489e8d254
--- /dev/null
+++ b/libc/src/math/generic/ufromfpxf.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ufromfpxf 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/ufromfpxf.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, ufromfpxf, (float x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpxf128.cpp b/libc/src/math/generic/ufromfpxf128.cpp
new file mode 100644
index 00000000000000..57c290365e693b
--- /dev/null
+++ b/libc/src/math/generic/ufromfpxf128.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ufromfpxf128 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/ufromfpxf128.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float128, ufromfpxf128,
+ (float128 x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/generic/ufromfpxl.cpp b/libc/src/math/generic/ufromfpxl.cpp
new file mode 100644
index 00000000000000..9a8ba7aa5b91de
--- /dev/null
+++ b/libc/src/math/generic/ufromfpxl.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ufromfpxl 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/ufromfpxl.h"
+#include "src/__support/FPUtil/NearestIntegerOperations.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long double, ufromfpxl,
+ (long double x, int rnd, unsigned int width)) {
+ return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/math/ufromfp.h b/libc/src/math/ufromfp.h
new file mode 100644
index 00000000000000..f4667486440c2e
--- /dev/null
+++ b/libc/src/math/ufromfp.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfp -----------------------*- 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_UFROMFP_H
+#define LLVM_LIBC_SRC_MATH_UFROMFP_H
+
+namespace LIBC_NAMESPACE {
+
+double ufromfp(double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFP_H
diff --git a/libc/src/math/ufromfpf.h b/libc/src/math/ufromfpf.h
new file mode 100644
index 00000000000000..40c6773d143e8f
--- /dev/null
+++ b/libc/src/math/ufromfpf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfpf ----------------------*- 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_UFROMFPF_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPF_H
+
+namespace LIBC_NAMESPACE {
+
+float ufromfpf(float x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPF_H
diff --git a/libc/src/math/ufromfpf128.h b/libc/src/math/ufromfpf128.h
new file mode 100644
index 00000000000000..785fa82becbcd5
--- /dev/null
+++ b/libc/src/math/ufromfpf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ufromfpf128 -------------------*- 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_UFROMFPF128_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 ufromfpf128(float128 x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPF128_H
diff --git a/libc/src/math/ufromfpl.h b/libc/src/math/ufromfpl.h
new file mode 100644
index 00000000000000..f05a77dc2f103d
--- /dev/null
+++ b/libc/src/math/ufromfpl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfpl ----------------------*- 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_UFROMFPL_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPL_H
+
+namespace LIBC_NAMESPACE {
+
+long double ufromfpl(long double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPL_H
diff --git a/libc/src/math/ufromfpx.h b/libc/src/math/ufromfpx.h
new file mode 100644
index 00000000000000..79c413af968a5f
--- /dev/null
+++ b/libc/src/math/ufromfpx.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfpx ----------------------*- 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_UFROMFPX_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPX_H
+
+namespace LIBC_NAMESPACE {
+
+double ufromfpx(double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPX_H
diff --git a/libc/src/math/ufromfpxf.h b/libc/src/math/ufromfpxf.h
new file mode 100644
index 00000000000000..f6bd8f7d59959b
--- /dev/null
+++ b/libc/src/math/ufromfpxf.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfpxf ---------------------*- 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_UFROMFPXF_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPXF_H
+
+namespace LIBC_NAMESPACE {
+
+float ufromfpxf(float x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPXF_H
diff --git a/libc/src/math/ufromfpxf128.h b/libc/src/math/ufromfpxf128.h
new file mode 100644
index 00000000000000..f3b43ff54f37c7
--- /dev/null
+++ b/libc/src/math/ufromfpxf128.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ufromfpxf128 ------------------*- 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_UFROMFPXF128_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPXF128_H
+
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE {
+
+float128 ufromfpxf128(float128 x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPXF128_H
diff --git a/libc/src/math/ufromfpxl.h b/libc/src/math/ufromfpxl.h
new file mode 100644
index 00000000000000..180b8f93d21876
--- /dev/null
+++ b/libc/src/math/ufromfpxl.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for ufromfpxl ---------------------*- 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_UFROMFPXL_H
+#define LLVM_LIBC_SRC_MATH_UFROMFPXL_H
+
+namespace LIBC_NAMESPACE {
+
+long double ufromfpxl(long double x, int rnd, unsigned int width);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_MATH_UFROMFPXL_H
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index f7a6f4a91fabcf..d830d22bb540e9 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -118,6 +118,7 @@ add_unittest_framework_library(
DEPENDS
LibcTest
libc.test.UnitTest.string_utils
+ libc.src.__support.CPP.array
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.fpbits_str
libc.src.__support.FPUtil.fenv_impl
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index ee618a623efe19..f8cbc23b6dd089 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H
#define LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H
+#include "src/__support/CPP/array.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
@@ -105,7 +106,13 @@ template <typename T> struct FPTest : public Test {
const T neg_max_normal = FPBits::max_normal(Sign::NEG).get_val(); \
const T min_denormal = FPBits::min_subnormal(Sign::POS).get_val(); \
const T neg_min_denormal = FPBits::min_subnormal(Sign::NEG).get_val(); \
- const T max_denormal = FPBits::max_subnormal().get_val();
+ const T max_denormal = FPBits::max_subnormal().get_val(); \
+ static constexpr LIBC_NAMESPACE::cpp::array<int, 5> \
+ MATH_ROUNDING_DIRECTIONS = { \
+ FP_INT_UPWARD, FP_INT_DOWNWARD, \
+ FP_INT_TOWARDZERO, FP_INT_TONEARESTFROMZERO, \
+ FP_INT_TONEAREST, \
+ };
#define EXPECT_FP_EQ(expected, actual) \
EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher< \
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 85dacce3b21dca..56d864e7808310 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -839,6 +839,198 @@ add_fp_unittest(
libc.src.math.frexpf128
)
+add_fp_unittest(
+ fromfp_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfp_test.cpp
+ HDRS
+ FromfpTest.h
+ DEPENDS
+ libc.src.math.fromfp
+)
+
+add_fp_unittest(
+ fromfpf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpf_test.cpp
+ HDRS
+ FromfpTest.h
+ DEPENDS
+ libc.src.math.fromfpf
+)
+
+add_fp_unittest(
+ fromfpl_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpl_test.cpp
+ HDRS
+ FromfpTest.h
+ DEPENDS
+ libc.src.math.fromfpl
+)
+
+add_fp_unittest(
+ fromfpf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpf128_test.cpp
+ HDRS
+ FromfpTest.h
+ DEPENDS
+ libc.src.math.fromfpf128
+)
+
+add_fp_unittest(
+ fromfpx_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpx_test.cpp
+ HDRS
+ FromfpxTest.h
+ DEPENDS
+ libc.src.math.fromfpx
+)
+
+add_fp_unittest(
+ fromfpxf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpxf_test.cpp
+ HDRS
+ FromfpxTest.h
+ DEPENDS
+ libc.src.math.fromfpxf
+)
+
+add_fp_unittest(
+ fromfpxl_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpxl_test.cpp
+ HDRS
+ FromfpxTest.h
+ DEPENDS
+ libc.src.math.fromfpxl
+)
+
+add_fp_unittest(
+ fromfpxf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ fromfpxf128_test.cpp
+ HDRS
+ FromfpxTest.h
+ DEPENDS
+ libc.src.math.fromfpxf128
+)
+
+add_fp_unittest(
+ ufromfp_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfp_test.cpp
+ HDRS
+ UfromfpTest.h
+ DEPENDS
+ libc.src.math.ufromfp
+)
+
+add_fp_unittest(
+ ufromfpf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpf_test.cpp
+ HDRS
+ UfromfpTest.h
+ DEPENDS
+ libc.src.math.ufromfpf
+)
+
+add_fp_unittest(
+ ufromfpl_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpl_test.cpp
+ HDRS
+ UfromfpTest.h
+ DEPENDS
+ libc.src.math.ufromfpl
+)
+
+add_fp_unittest(
+ ufromfpf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpf128_test.cpp
+ HDRS
+ UfromfpTest.h
+ DEPENDS
+ libc.src.math.ufromfpf128
+)
+
+add_fp_unittest(
+ ufromfpx_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpx_test.cpp
+ HDRS
+ UfromfpxTest.h
+ DEPENDS
+ libc.src.math.ufromfpx
+)
+
+add_fp_unittest(
+ ufromfpxf_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpxf_test.cpp
+ HDRS
+ UfromfpxTest.h
+ DEPENDS
+ libc.src.math.ufromfpxf
+)
+
+add_fp_unittest(
+ ufromfpxl_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpxl_test.cpp
+ HDRS
+ UfromfpxTest.h
+ DEPENDS
+ libc.src.math.ufromfpxl
+)
+
+add_fp_unittest(
+ ufromfpxf128_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ ufromfpxf128_test.cpp
+ HDRS
+ UfromfpxTest.h
+ DEPENDS
+ libc.src.math.ufromfpxf128
+)
+
add_fp_unittest(
ilogb_test
SUITE
diff --git a/libc/test/src/math/smoke/FromfpTest.h b/libc/test/src/math/smoke/FromfpTest.h
new file mode 100644
index 00000000000000..dd61c928065cd9
--- /dev/null
+++ b/libc/test/src/math/smoke/FromfpTest.h
@@ -0,0 +1,338 @@
+//===-- Utility class to test different flavors of fromfp -------*- 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 LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef T (*FromfpFunc)(T, int, unsigned int);
+
+ void testSpecialNumbersNonzeroWidth(FromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
+ EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U));
+ }
+ }
+
+ void testSpecialNumbersZeroWidth(FromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U));
+ }
+ }
+
+ void testRoundedNumbersWithinRange(FromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.0), rnd, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 12U));
+ }
+ }
+
+ void testRoundedNumbersOutsideRange(FromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 11U));
+ }
+ }
+
+ void testFractionsUpwardWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.115), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.3), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.75), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.32), FP_INT_UPWARD, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_UPWARD, 5U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_UPWARD, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.65), FP_INT_UPWARD, 5U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_UPWARD, 12U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96), FP_INT_UPWARD, 12U));
+ }
+
+ void testFractionsUpwardOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.115), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U));
+ }
+
+ void testFractionsDownwardWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.115), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.3), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_DOWNWARD, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 5U));
+ EXPECT_FP_EQ(T(-11.0), func(T(-10.32), FP_INT_DOWNWARD, 5U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 5U));
+ EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_DOWNWARD, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 12U));
+ EXPECT_FP_EQ(T(-1235.0), func(T(-1234.38), FP_INT_DOWNWARD, 12U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 12U));
+ EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_DOWNWARD, 12U));
+ }
+
+ void testFractionsDownwardOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U));
+ }
+
+ void testFractionsTowardZeroWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.75), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TOWARDZERO, 5U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.65), FP_INT_TOWARDZERO, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TOWARDZERO, 12U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96), FP_INT_TOWARDZERO, 12U));
+ }
+
+ void testFractionsTowardZeroOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U));
+ }
+
+ void testFractionsToNearestFromZeroWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TONEARESTFROMZERO, 5U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 5U));
+ EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_TONEARESTFROMZERO, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 12U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 12U));
+ EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 12U));
+ }
+
+ void testFractionsToNearestFromZeroOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U));
+ }
+
+ void testFractionsToNearestWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEAREST, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TONEAREST, 5U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEAREST, 5U));
+ EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_TONEAREST, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TONEAREST, 12U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 12U));
+ EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_TONEAREST, 12U));
+
+ EXPECT_FP_EQ(T(2.0), func(T(2.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-2.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(2.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-2.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(3.0), func(T(2.75), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(-3.0), func(T(-2.75), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(5.0), func(T(5.3), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(-5.0), func(T(-5.3), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.5), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(-6.0), func(T(-5.5), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.75), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(-6.0), func(T(-5.75), FP_INT_TONEAREST, 4U));
+ }
+
+ void testFractionsToNearestOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U));
+ }
+};
+
+#define LIST_FROMFP_TESTS(T, func) \
+ using LlvmLibcFromfpTest = FromfpTestTemplate<T>; \
+ TEST_F(LlvmLibcFromfpTest, SpecialNumbersNonzeroWidth) { \
+ testSpecialNumbersNonzeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, SpecialNumbersZeroWidth) { \
+ testSpecialNumbersZeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, RoundedNumbersWithinRange) { \
+ testRoundedNumbersWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, RoundedNumbersOutsideRange) { \
+ testRoundedNumbersOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsUpwardWithinRange) { \
+ testFractionsUpwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsUpwardOutsideRange) { \
+ testFractionsUpwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsDownwardWithinRange) { \
+ testFractionsDownwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsDownwardOutsideRange) { \
+ testFractionsDownwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsTowardZeroWithinRange) { \
+ testFractionsTowardZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsTowardZeroOutsideRange) { \
+ testFractionsTowardZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestFromZeroWithinRange) { \
+ testFractionsToNearestFromZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestFromZeroOutsideRange) { \
+ testFractionsToNearestFromZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestWithinRange) { \
+ testFractionsToNearestWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestOutsideRange) { \
+ testFractionsToNearestOutsideRange(&func); \
+ }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H
diff --git a/libc/test/src/math/smoke/FromfpxTest.h b/libc/test/src/math/smoke/FromfpxTest.h
new file mode 100644
index 00000000000000..0c5300236f7493
--- /dev/null
+++ b/libc/test/src/math/smoke/FromfpxTest.h
@@ -0,0 +1,452 @@
+//===-- Utility class to test different flavors of fromfpx ------*- 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 LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef T (*FromfpxFunc)(T, int, unsigned int);
+
+ void testSpecialNumbersNonzeroWidth(FromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
+ EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U));
+ }
+ }
+
+ void testSpecialNumbersZeroWidth(FromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U));
+ }
+ }
+
+ void testRoundedNumbersWithinRange(FromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U));
+ EXPECT_FP_EQ(T(-10.0), func(T(-10.0), rnd, 5U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 12U));
+ EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 12U));
+ }
+ }
+
+ void testRoundedNumbersOutsideRange(FromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 11U));
+ }
+ }
+
+ void testFractionsUpwardWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.5), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.115), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.3), FP_INT_UPWARD, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_UPWARD, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.5), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_UPWARD, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.75), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.32), FP_INT_UPWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.32), FP_INT_UPWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_UPWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.65), FP_INT_UPWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.38), FP_INT_UPWARD, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.96), FP_INT_UPWARD, 12U), FE_INEXACT);
+ }
+
+ void testFractionsUpwardOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.115), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U));
+ }
+
+ void testFractionsDownwardWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.5), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.115), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.715), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.3), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.5), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.75), FP_INT_DOWNWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.32), FP_INT_DOWNWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.65), FP_INT_DOWNWARD, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1235.0), func(T(-1234.38), FP_INT_DOWNWARD, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1235.0), func(T(-1234.96), FP_INT_DOWNWARD, 12U), FE_INEXACT);
+ }
+
+ void testFractionsDownwardOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U));
+ }
+
+ void testFractionsTowardZeroWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.75), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-10.0), func(T(-10.32), FP_INT_TOWARDZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-10.0), func(T(-10.65), FP_INT_TOWARDZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.38), FP_INT_TOWARDZERO, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.96), FP_INT_TOWARDZERO, 12U), FE_INEXACT);
+ }
+
+ void testFractionsTowardZeroOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U));
+ }
+
+ void testFractionsToNearestFromZeroWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1.0), func(T(-0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1.0), func(T(-0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1.0), func(T(-1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-10.0), func(T(-10.32), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-11.0), func(T(-10.65), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1235.0), func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 12U),
+ FE_INEXACT);
+ }
+
+ void testFractionsToNearestFromZeroOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U));
+ }
+
+ void testFractionsToNearestWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.715), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.5), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.75), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TONEAREST, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.32), FP_INT_TONEAREST, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_TONEAREST, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.65), FP_INT_TONEAREST, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.38), FP_INT_TONEAREST, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 12U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1235.0), func(T(-1234.96), FP_INT_TONEAREST, 12U), FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.3), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-2.3), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.5), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-2.5), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(3.0), func(T(2.75), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-3.0), func(T(-2.75), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(5.0), func(T(5.3), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-5.0), func(T(-5.3), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.5), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-6.0), func(T(-5.5), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.75), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-6.0), func(T(-5.75), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ }
+
+ void testFractionsToNearestOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U));
+ }
+};
+
+#define LIST_FROMFPX_TESTS(T, func) \
+ using LlvmLibcFromfpxTest = FromfpxTestTemplate<T>; \
+ TEST_F(LlvmLibcFromfpxTest, SpecialNumbersNonzeroWidth) { \
+ testSpecialNumbersNonzeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, SpecialNumbersZeroWidth) { \
+ testSpecialNumbersZeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, RoundedNumbersWithinRange) { \
+ testRoundedNumbersWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, RoundedNumbersOutsideRange) { \
+ testRoundedNumbersOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsUpwardWithinRange) { \
+ testFractionsUpwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsUpwardOutsideRange) { \
+ testFractionsUpwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsDownwardWithinRange) { \
+ testFractionsDownwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsDownwardOutsideRange) { \
+ testFractionsDownwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsTowardZeroWithinRange) { \
+ testFractionsTowardZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsTowardZeroOutsideRange) { \
+ testFractionsTowardZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFromZeroWithinRange) { \
+ testFractionsToNearestFromZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFromZeroOutsideRange) { \
+ testFractionsToNearestFromZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestWithinRange) { \
+ testFractionsToNearestWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestOutsideRange) { \
+ testFractionsToNearestOutsideRange(&func); \
+ }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H
diff --git a/libc/test/src/math/smoke/UfromfpTest.h b/libc/test/src/math/smoke/UfromfpTest.h
new file mode 100644
index 00000000000000..763b2770adf158
--- /dev/null
+++ b/libc/test/src/math/smoke/UfromfpTest.h
@@ -0,0 +1,288 @@
+//===-- Utility class to test different flavors of ufromfp ------*- 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 LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef T (*UfromfpFunc)(T, int, unsigned int);
+
+ void testSpecialNumbersNonzeroWidth(UfromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
+ EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U));
+ }
+ }
+
+ void testSpecialNumbersZeroWidth(UfromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U));
+ }
+ }
+
+ void testRoundedNumbersWithinRange(UfromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U));
+ }
+ }
+
+ void testRoundedNumbersOutsideRange(UfromfpFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 32U));
+ }
+ }
+
+ void testFractionsUpwardWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.115), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.3), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_UPWARD, 2U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.32), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_UPWARD, 4U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 11U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 11U));
+ }
+
+ void testFractionsUpwardOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U));
+ }
+
+ void testFractionsDownwardWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 11U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 11U));
+ }
+
+ void testFractionsDownwardOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U));
+ }
+
+ void testFractionsTowardZeroWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 11U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 11U));
+ }
+
+ void testFractionsTowardZeroOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U));
+ }
+
+ void testFractionsToNearestFromZeroWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U));
+ }
+
+ void testFractionsToNearestFromZeroOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U));
+ }
+
+ void testFractionsToNearestWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEAREST, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 11U));
+ EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 11U));
+
+ EXPECT_FP_EQ(T(2.0), func(T(2.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(2.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(3.0), func(T(2.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(T(5.0), func(T(5.3), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.5), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.75), FP_INT_TONEAREST, 3U));
+ }
+
+ void testFractionsToNearestOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U));
+ }
+};
+
+#define LIST_UFROMFP_TESTS(T, func) \
+ using LlvmLibcUfromfpTest = UfromfpTestTemplate<T>; \
+ TEST_F(LlvmLibcUfromfpTest, SpecialNumbersNonzeroWidth) { \
+ testSpecialNumbersNonzeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, SpecialNumbersZeroWidth) { \
+ testSpecialNumbersZeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, RoundedNumbersWithinRange) { \
+ testRoundedNumbersWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, RoundedNumbersOutsideRange) { \
+ testRoundedNumbersOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsUpwardWithinRange) { \
+ testFractionsUpwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsUpwardOutsideRange) { \
+ testFractionsUpwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsDownwardWithinRange) { \
+ testFractionsDownwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsDownwardOutsideRange) { \
+ testFractionsDownwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsTowardZeroWithinRange) { \
+ testFractionsTowardZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsTowardZeroOutsideRange) { \
+ testFractionsTowardZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFromZeroWithinRange) { \
+ testFractionsToNearestFromZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFromZeroOutsideRange) { \
+ testFractionsToNearestFromZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestWithinRange) { \
+ testFractionsToNearestWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestOutsideRange) { \
+ testFractionsToNearestOutsideRange(&func); \
+ }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H
diff --git a/libc/test/src/math/smoke/UfromfpxTest.h b/libc/test/src/math/smoke/UfromfpxTest.h
new file mode 100644
index 00000000000000..de11c0d8fcebf7
--- /dev/null
+++ b/libc/test/src/math/smoke/UfromfpxTest.h
@@ -0,0 +1,353 @@
+//===-- Utility class to test different flavors of ufromfpx -----*- 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 LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H
+#define LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+template <typename T>
+class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
+
+ DECLARE_SPECIAL_CONSTANTS(T)
+
+public:
+ typedef T (*UfromfpxFunc)(T, int, unsigned int);
+
+ void testSpecialNumbersNonzeroWidth(UfromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
+ EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 32U));
+ }
+ }
+
+ void testSpecialNumbersZeroWidth(UfromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(inf, rnd, 0U));
+ EXPECT_FP_EQ(aNaN, func(neg_inf, rnd, 0U));
+
+ EXPECT_FP_EQ(aNaN, func(aNaN, rnd, 0U));
+ }
+ }
+
+ void testRoundedNumbersWithinRange(UfromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U));
+ EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U));
+ }
+ }
+
+ void testRoundedNumbersOutsideRange(UfromfpxFunc func) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.0), rnd, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.0), rnd, 32U));
+ }
+ }
+
+ void testFractionsUpwardWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.5), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.115), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.3), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_UPWARD, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.32), FP_INT_UPWARD, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_UPWARD, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 11U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 11U),
+ FE_INEXACT);
+ }
+
+ void testFractionsUpwardOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(1.3), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_UPWARD, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U));
+ }
+
+ void testFractionsDownwardWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 11U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 11U), FE_INEXACT);
+ }
+
+ void testFractionsDownwardOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U));
+ }
+
+ void testFractionsTowardZeroWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 11U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 11U), FE_INEXACT);
+ }
+
+ void testFractionsTowardZeroOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U));
+ }
+
+ void testFractionsToNearestFromZeroWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INEXACT);
+ }
+
+ void testFractionsToNearestFromZeroOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U));
+ }
+
+ void testFractionsToNearestWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TONEAREST, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_TONEAREST, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 11U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 11U), FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.3), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.5), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(3.0), func(T(2.75), FP_INT_TONEAREST, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(5.0), func(T(5.3), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.5), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.75), FP_INT_TONEAREST, 3U),
+ FE_INEXACT);
+ }
+
+ void testFractionsToNearestOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U));
+ }
+};
+
+#define LIST_UFROMFPX_TESTS(T, func) \
+ using LlvmLibcUfromfpxTest = UfromfpxTestTemplate<T>; \
+ TEST_F(LlvmLibcUfromfpxTest, SpecialNumbersNonzeroWidth) { \
+ testSpecialNumbersNonzeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, SpecialNumbersZeroWidth) { \
+ testSpecialNumbersZeroWidth(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, RoundedNumbersWithinRange) { \
+ testRoundedNumbersWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, RoundedNumbersOutsideRange) { \
+ testRoundedNumbersOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsUpwardWithinRange) { \
+ testFractionsUpwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsUpwardOutsideRange) { \
+ testFractionsUpwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsDownwardWithinRange) { \
+ testFractionsDownwardWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsDownwardOutsideRange) { \
+ testFractionsDownwardOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsTowardZeroWithinRange) { \
+ testFractionsTowardZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsTowardZeroOutsideRange) { \
+ testFractionsTowardZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFromZeroWithinRange) { \
+ testFractionsToNearestFromZeroWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFromZeroOutsideRange) { \
+ testFractionsToNearestFromZeroOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestWithinRange) { \
+ testFractionsToNearestWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestOutsideRange) { \
+ testFractionsToNearestOutsideRange(&func); \
+ }
+
+#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H
diff --git a/libc/test/src/math/smoke/fromfp_test.cpp b/libc/test/src/math/smoke/fromfp_test.cpp
new file mode 100644
index 00000000000000..147a9df9afcff9
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfp_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfp ----------------------------------------------===//
+//
+// 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 "FromfpTest.h"
+
+#include "src/math/fromfp.h"
+
+LIST_FROMFP_TESTS(double, LIBC_NAMESPACE::fromfp)
diff --git a/libc/test/src/math/smoke/fromfpf128_test.cpp b/libc/test/src/math/smoke/fromfpf128_test.cpp
new file mode 100644
index 00000000000000..288aadb359bfe0
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpf128 ------------------------------------------===//
+//
+// 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 "FromfpTest.h"
+
+#include "src/math/fromfpf128.h"
+
+LIST_FROMFP_TESTS(float128, LIBC_NAMESPACE::fromfpf128)
diff --git a/libc/test/src/math/smoke/fromfpf_test.cpp b/libc/test/src/math/smoke/fromfpf_test.cpp
new file mode 100644
index 00000000000000..63f3f624716e53
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpf ---------------------------------------------===//
+//
+// 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 "FromfpTest.h"
+
+#include "src/math/fromfpf.h"
+
+LIST_FROMFP_TESTS(float, LIBC_NAMESPACE::fromfpf)
diff --git a/libc/test/src/math/smoke/fromfpl_test.cpp b/libc/test/src/math/smoke/fromfpl_test.cpp
new file mode 100644
index 00000000000000..c0072768870b71
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpl ---------------------------------------------===//
+//
+// 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 "FromfpTest.h"
+
+#include "src/math/fromfpl.h"
+
+LIST_FROMFP_TESTS(long double, LIBC_NAMESPACE::fromfpl)
diff --git a/libc/test/src/math/smoke/fromfpx_test.cpp b/libc/test/src/math/smoke/fromfpx_test.cpp
new file mode 100644
index 00000000000000..10b1eee726e1fe
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpx_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpx ---------------------------------------------===//
+//
+// 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 "FromfpxTest.h"
+
+#include "src/math/fromfpx.h"
+
+LIST_FROMFPX_TESTS(double, LIBC_NAMESPACE::fromfpx)
diff --git a/libc/test/src/math/smoke/fromfpxf128_test.cpp b/libc/test/src/math/smoke/fromfpxf128_test.cpp
new file mode 100644
index 00000000000000..2839bed30cb7c7
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpxf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpxf128 -----------------------------------------===//
+//
+// 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 "FromfpxTest.h"
+
+#include "src/math/fromfpxf128.h"
+
+LIST_FROMFPX_TESTS(float128, LIBC_NAMESPACE::fromfpxf128)
diff --git a/libc/test/src/math/smoke/fromfpxf_test.cpp b/libc/test/src/math/smoke/fromfpxf_test.cpp
new file mode 100644
index 00000000000000..42e47aba40ae7b
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpxf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpxf --------------------------------------------===//
+//
+// 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 "FromfpxTest.h"
+
+#include "src/math/fromfpxf.h"
+
+LIST_FROMFPX_TESTS(float, LIBC_NAMESPACE::fromfpxf)
diff --git a/libc/test/src/math/smoke/fromfpxl_test.cpp b/libc/test/src/math/smoke/fromfpxl_test.cpp
new file mode 100644
index 00000000000000..cbe8d750ff2a6f
--- /dev/null
+++ b/libc/test/src/math/smoke/fromfpxl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for fromfpxl --------------------------------------------===//
+//
+// 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 "FromfpxTest.h"
+
+#include "src/math/fromfpxl.h"
+
+LIST_FROMFPX_TESTS(long double, LIBC_NAMESPACE::fromfpxl)
diff --git a/libc/test/src/math/smoke/ufromfp_test.cpp b/libc/test/src/math/smoke/ufromfp_test.cpp
new file mode 100644
index 00000000000000..ff47621124006a
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfp_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfp ---------------------------------------------===//
+//
+// 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 "UfromfpTest.h"
+
+#include "src/math/ufromfp.h"
+
+LIST_UFROMFP_TESTS(double, LIBC_NAMESPACE::ufromfp)
diff --git a/libc/test/src/math/smoke/ufromfpf128_test.cpp b/libc/test/src/math/smoke/ufromfpf128_test.cpp
new file mode 100644
index 00000000000000..9ba3034f6e61fd
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpf128 -----------------------------------------===//
+//
+// 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 "UfromfpTest.h"
+
+#include "src/math/ufromfpf128.h"
+
+LIST_UFROMFP_TESTS(float128, LIBC_NAMESPACE::ufromfpf128)
diff --git a/libc/test/src/math/smoke/ufromfpf_test.cpp b/libc/test/src/math/smoke/ufromfpf_test.cpp
new file mode 100644
index 00000000000000..2913b31e20bda3
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpf --------------------------------------------===//
+//
+// 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 "UfromfpTest.h"
+
+#include "src/math/ufromfpf.h"
+
+LIST_UFROMFP_TESTS(float, LIBC_NAMESPACE::ufromfpf)
diff --git a/libc/test/src/math/smoke/ufromfpl_test.cpp b/libc/test/src/math/smoke/ufromfpl_test.cpp
new file mode 100644
index 00000000000000..8976056756e45f
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpl --------------------------------------------===//
+//
+// 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 "UfromfpTest.h"
+
+#include "src/math/ufromfpl.h"
+
+LIST_UFROMFP_TESTS(long double, LIBC_NAMESPACE::ufromfpl)
diff --git a/libc/test/src/math/smoke/ufromfpx_test.cpp b/libc/test/src/math/smoke/ufromfpx_test.cpp
new file mode 100644
index 00000000000000..3bb45e428f2866
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpx_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpx --------------------------------------------===//
+//
+// 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 "UfromfpxTest.h"
+
+#include "src/math/ufromfpx.h"
+
+LIST_UFROMFPX_TESTS(double, LIBC_NAMESPACE::ufromfpx)
diff --git a/libc/test/src/math/smoke/ufromfpxf128_test.cpp b/libc/test/src/math/smoke/ufromfpxf128_test.cpp
new file mode 100644
index 00000000000000..6defaf7fee3dd0
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpxf128_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpxf128 ----------------------------------------===//
+//
+// 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 "UfromfpxTest.h"
+
+#include "src/math/ufromfpxf128.h"
+
+LIST_UFROMFPX_TESTS(float128, LIBC_NAMESPACE::ufromfpxf128)
diff --git a/libc/test/src/math/smoke/ufromfpxf_test.cpp b/libc/test/src/math/smoke/ufromfpxf_test.cpp
new file mode 100644
index 00000000000000..862fd4c2cdac65
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpxf_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpxf -------------------------------------------===//
+//
+// 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 "UfromfpxTest.h"
+
+#include "src/math/ufromfpxf.h"
+
+LIST_UFROMFPX_TESTS(float, LIBC_NAMESPACE::ufromfpxf)
diff --git a/libc/test/src/math/smoke/ufromfpxl_test.cpp b/libc/test/src/math/smoke/ufromfpxl_test.cpp
new file mode 100644
index 00000000000000..b6b93b38e6be2c
--- /dev/null
+++ b/libc/test/src/math/smoke/ufromfpxl_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for ufromfpxl -------------------------------------------===//
+//
+// 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 "UfromfpxTest.h"
+
+#include "src/math/ufromfpxl.h"
+
+LIST_UFROMFPX_TESTS(long double, LIBC_NAMESPACE::ufromfpxl)
diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
index 2a0c071f228683..d2087a3d528f44 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
@@ -76,6 +76,7 @@ libc_support_library(
deps = [
":LibcUnitTest",
":string_utils",
+ "//libc:__support_cpp_array",
"//libc:__support_cpp_bit",
"//libc:__support_cpp_bitset",
"//libc:__support_cpp_span",
>From 3b2d2eb8107743afad7821ee35d7e8c200a52fd0 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Thu, 21 Mar 2024 11:53:08 +0000
Subject: [PATCH 2/5] fixup! [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128}
functions
---
libc/spec/stdc.td | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index a8b365fec1e9ea..7407ead17711aa 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -423,22 +423,22 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"fromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"fromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"fromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"fromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"fromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"fromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"fromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"fromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"fromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"ufromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"ufromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"ufromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"ufromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"ufromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"ufromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
FunctionSpec<"ufromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
- FunctionSpec<"ufromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>,
+ GuardedFunctionSpec<"ufromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">,
FunctionSpec<"hypot", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
>From bfd4fa9bb420f80193f6b89418a3e5006c0e4a90 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Thu, 21 Mar 2024 19:00:30 +0000
Subject: [PATCH 3/5] fixup! [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128}
functions
---
libc/docs/dev/undefined_behavior.rst | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst
index 50e8bdde89ddd6..1c916f6505f645 100644
--- a/libc/docs/dev/undefined_behavior.rst
+++ b/libc/docs/dev/undefined_behavior.rst
@@ -81,3 +81,11 @@ The C standard does not specify behavior for ``printf("%s", NULL)``. We will
print the string literal ``(null)`` unless using the
``LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS`` option described in :ref:`printf
behavior<printf_behavior>`.
+
+Unknown Math Rounding Direction
+-------------------------------
+The C standard states that if the value of the ``rnd`` argument of the
+``fromfp``, ``ufromfp``, ``fromfpx`` and ``ufromfpx`` functions is not equal to
+the value of a math rounding direction macro, the direction of rounding is
+unspecified. LLVM's libc chooses to use the ``FP_INT_TONEAREST`` rounding
+direction in this case.
>From 7d8234f93313630e53ccdacba87b49d0e1311801 Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Thu, 21 Mar 2024 19:12:00 +0000
Subject: [PATCH 4/5] fixup! [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128}
functions
---
libc/test/UnitTest/FPMatcher.h | 7 +-
libc/test/src/math/smoke/FromfpTest.h | 86 ++++++++++++++-
libc/test/src/math/smoke/FromfpxTest.h | 134 +++++++++++++++++++++++-
libc/test/src/math/smoke/UfromfpTest.h | 68 +++++++++++-
libc/test/src/math/smoke/UfromfpxTest.h | 92 +++++++++++++++-
5 files changed, 368 insertions(+), 19 deletions(-)
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index f8cbc23b6dd089..f4553eac5c8a57 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -107,11 +107,12 @@ template <typename T> struct FPTest : public Test {
const T min_denormal = FPBits::min_subnormal(Sign::POS).get_val(); \
const T neg_min_denormal = FPBits::min_subnormal(Sign::NEG).get_val(); \
const T max_denormal = FPBits::max_subnormal().get_val(); \
- static constexpr LIBC_NAMESPACE::cpp::array<int, 5> \
- MATH_ROUNDING_DIRECTIONS = { \
+ static constexpr int UNKNOWN_MATH_ROUNDING_DIRECTION = 99; \
+ static constexpr LIBC_NAMESPACE::cpp::array<int, 6> \
+ MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN = { \
FP_INT_UPWARD, FP_INT_DOWNWARD, \
FP_INT_TOWARDZERO, FP_INT_TONEARESTFROMZERO, \
- FP_INT_TONEAREST, \
+ FP_INT_TONEAREST, UNKNOWN_MATH_ROUNDING_DIRECTION, \
};
#define EXPECT_FP_EQ(expected, actual) \
diff --git a/libc/test/src/math/smoke/FromfpTest.h b/libc/test/src/math/smoke/FromfpTest.h
index dd61c928065cd9..2d4c4c5314c9dd 100644
--- a/libc/test/src/math/smoke/FromfpTest.h
+++ b/libc/test/src/math/smoke/FromfpTest.h
@@ -21,7 +21,7 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
typedef T (*FromfpFunc)(T, int, unsigned int);
void testSpecialNumbersNonzeroWidth(FromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
@@ -33,7 +33,7 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testSpecialNumbersZeroWidth(FromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
@@ -45,7 +45,7 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersWithinRange(FromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U));
EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U));
@@ -56,7 +56,7 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersOutsideRange(FromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U));
EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U));
EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U));
@@ -288,6 +288,78 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U));
EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U));
}
+
+ void testFractionsToNearestFallbackWithinRange(FromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(-1.0), func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U));
+ EXPECT_FP_EQ(T(-10.0),
+ func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U));
+ EXPECT_FP_EQ(T(-11.0),
+ func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U));
+ EXPECT_FP_EQ(T(1234.0),
+ func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U));
+ EXPECT_FP_EQ(T(-1234.0),
+ func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U));
+ EXPECT_FP_EQ(T(1235.0),
+ func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U));
+ EXPECT_FP_EQ(T(-1235.0),
+ func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U));
+
+ EXPECT_FP_EQ(T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(-2.0), func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(-3.0), func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(-5.0), func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(-6.0), func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(-6.0), func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ }
+
+ void testFractionsToNearestFallbackOutsideRange(FromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ }
};
#define LIST_FROMFP_TESTS(T, func) \
@@ -333,6 +405,12 @@ class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
} \
TEST_F(LlvmLibcFromfpTest, FractionsToNearestOutsideRange) { \
testFractionsToNearestOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestFallbackWithinRange) { \
+ testFractionsToNearestFallbackWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpTest, FractionsToNearestFallbackOutsideRange) { \
+ testFractionsToNearestFallbackOutsideRange(&func); \
}
#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H
diff --git a/libc/test/src/math/smoke/FromfpxTest.h b/libc/test/src/math/smoke/FromfpxTest.h
index 0c5300236f7493..b3c14c7c09ba07 100644
--- a/libc/test/src/math/smoke/FromfpxTest.h
+++ b/libc/test/src/math/smoke/FromfpxTest.h
@@ -21,7 +21,7 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
typedef T (*FromfpxFunc)(T, int, unsigned int);
void testSpecialNumbersNonzeroWidth(FromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
@@ -33,7 +33,7 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testSpecialNumbersZeroWidth(FromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
@@ -45,7 +45,7 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersWithinRange(FromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U));
EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U));
EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U));
@@ -56,7 +56,7 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersOutsideRange(FromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(T(1.0), rnd, 1U));
EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 4U));
EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 4U));
@@ -402,6 +402,126 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U));
EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U));
}
+
+ void testFractionsToNearestFallbackWithinRange(FromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1.0), func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1.0), func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-10.0), func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-11.0), func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1234.0), func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-1235.0), func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U),
+ FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-2.0), func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-3.0), func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-5.0), func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-6.0), func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-6.0), func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U),
+ FE_INEXACT);
+ }
+
+ void testFractionsToNearestFallbackOutsideRange(FromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ }
};
#define LIST_FROMFPX_TESTS(T, func) \
@@ -447,6 +567,12 @@ class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
} \
TEST_F(LlvmLibcFromfpxTest, FractionsToNearestOutsideRange) { \
testFractionsToNearestOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFallbackWithinRange) { \
+ testFractionsToNearestFallbackWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFallbackOutsideRange) { \
+ testFractionsToNearestFallbackOutsideRange(&func); \
}
#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H
diff --git a/libc/test/src/math/smoke/UfromfpTest.h b/libc/test/src/math/smoke/UfromfpTest.h
index 763b2770adf158..e753fc489cdea7 100644
--- a/libc/test/src/math/smoke/UfromfpTest.h
+++ b/libc/test/src/math/smoke/UfromfpTest.h
@@ -21,7 +21,7 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
typedef T (*UfromfpFunc)(T, int, unsigned int);
void testSpecialNumbersNonzeroWidth(UfromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
@@ -33,7 +33,7 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testSpecialNumbersZeroWidth(UfromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
@@ -45,7 +45,7 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersWithinRange(UfromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U));
EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U));
@@ -53,7 +53,7 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersOutsideRange(UfromfpFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U));
EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U));
EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U));
@@ -238,6 +238,60 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U));
EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U));
}
+
+ void testFractionsToNearestFallbackWithinRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U));
+ EXPECT_FP_EQ(T(1234.0),
+ func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+ EXPECT_FP_EQ(T(1235.0),
+ func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U));
+
+ EXPECT_FP_EQ(T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ }
+
+ void testFractionsToNearestFallbackOutsideRange(UfromfpFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ }
};
#define LIST_UFROMFP_TESTS(T, func) \
@@ -283,6 +337,12 @@ class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test {
} \
TEST_F(LlvmLibcUfromfpTest, FractionsToNearestOutsideRange) { \
testFractionsToNearestOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFallbackWithinRange) { \
+ testFractionsToNearestFallbackWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFallbackOutsideRange) { \
+ testFractionsToNearestFallbackOutsideRange(&func); \
}
#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H
diff --git a/libc/test/src/math/smoke/UfromfpxTest.h b/libc/test/src/math/smoke/UfromfpxTest.h
index de11c0d8fcebf7..47bf32c80f1705 100644
--- a/libc/test/src/math/smoke/UfromfpxTest.h
+++ b/libc/test/src/math/smoke/UfromfpxTest.h
@@ -21,7 +21,7 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
typedef T (*UfromfpxFunc)(T, int, unsigned int);
void testSpecialNumbersNonzeroWidth(UfromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(zero, func(zero, rnd, 32U));
EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U));
@@ -33,7 +33,7 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testSpecialNumbersZeroWidth(UfromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(zero, rnd, 0U));
EXPECT_FP_EQ(aNaN, func(neg_zero, rnd, 0U));
@@ -45,7 +45,7 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersWithinRange(UfromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U));
EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U));
EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U));
@@ -53,7 +53,7 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
}
void testRoundedNumbersOutsideRange(UfromfpxFunc func) {
- for (int rnd : MATH_ROUNDING_DIRECTIONS) {
+ for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) {
EXPECT_FP_EQ(aNaN, func(T(-1.0), rnd, 32U));
EXPECT_FP_EQ(aNaN, func(T(10.0), rnd, 3U));
EXPECT_FP_EQ(aNaN, func(T(-10.0), rnd, 32U));
@@ -303,6 +303,84 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
EXPECT_FP_EQ(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U));
EXPECT_FP_EQ(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U));
}
+
+ void testFractionsToNearestFallbackWithinRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1234.0), func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U),
+ FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(1235.0), func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U),
+ FE_INEXACT);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ EXPECT_FP_EQ_WITH_EXCEPTION(
+ T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT);
+ }
+
+ void testFractionsToNearestFallbackOutsideRange(UfromfpxFunc func) {
+ EXPECT_FP_EQ(aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U));
+ EXPECT_FP_EQ(aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U));
+ EXPECT_FP_EQ(aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+
+ EXPECT_FP_EQ(aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U));
+ EXPECT_FP_EQ(aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ EXPECT_FP_EQ(aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U));
+ EXPECT_FP_EQ(aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U));
+ }
};
#define LIST_UFROMFPX_TESTS(T, func) \
@@ -348,6 +426,12 @@ class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test {
} \
TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestOutsideRange) { \
testFractionsToNearestOutsideRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackWithinRange) { \
+ testFractionsToNearestFallbackWithinRange(&func); \
+ } \
+ TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackOutsideRange) { \
+ testFractionsToNearestFallbackOutsideRange(&func); \
}
#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H
>From ac71b02a2bef0356b1420e4f2323f3a29d4401cf Mon Sep 17 00:00:00 2001
From: OverMighty <its.overmighty at gmail.com>
Date: Fri, 22 Mar 2024 20:43:28 +0000
Subject: [PATCH 5/5] fixup! [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128}
functions
---
libc/docs/dev/undefined_behavior.rst | 2 +-
libc/src/math/generic/CMakeLists.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst
index 1c916f6505f645..c97a539ca8da45 100644
--- a/libc/docs/dev/undefined_behavior.rst
+++ b/libc/docs/dev/undefined_behavior.rst
@@ -84,7 +84,7 @@ behavior<printf_behavior>`.
Unknown Math Rounding Direction
-------------------------------
-The C standard states that if the value of the ``rnd`` argument of the
+The C23 standard states that if the value of the ``rnd`` argument of the
``fromfp``, ``ufromfp``, ``fromfpx`` and ``ufromfpx`` functions is not equal to
the value of a math rounding direction macro, the direction of rounding is
unspecified. LLVM's libc chooses to use the ``FP_INT_TONEAREST`` rounding
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index e8eb36acc93035..5198e9c58a98f1 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2071,7 +2071,7 @@ add_entrypoint_object(
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.nearest_integer
COMPILE_OPTIONS
- -O3
+ -O3
)
add_entrypoint_object(
- Previous message: [libc-commits] [libc] [llvm] [libc][math][c23] Add {, u}fromfp{, x}{, f, l, f128} functions (PR #86003)
- Next message: [libc-commits] [libc] [llvm] [libc][math][c23] Add {, u}fromfp{, x}{, f, l, f128} functions (PR #86003)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the libc-commits
mailing list