From b282259711af7b295cb80a12880bcd8e0d1fcefa Mon Sep 17 00:00:00 2001 From: OverMighty Date: Mon, 25 Mar 2024 14:26:22 +0000 Subject: [PATCH] [libc][math][c23] Add {,u}fromfp{,x}{,f,l,f128} functions (#86003) Fixes #85279. cc @lntue --- libc/config/linux/x86_64/entrypoints.txt | 16 + libc/docs/dev/undefined_behavior.rst | 8 + libc/docs/math/index.rst | 32 + libc/include/llvm-libc-macros/math-macros.h | 6 + libc/spec/stdc.td | 26 + .../FPUtil/NearestIntegerOperations.h | 94 ++- 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 | 10 +- libc/test/src/math/smoke/CMakeLists.txt | 192 ++++++ libc/test/src/math/smoke/FromfpTest.h | 416 +++++++++++++ libc/test/src/math/smoke/FromfpxTest.h | 578 ++++++++++++++++++ libc/test/src/math/smoke/UfromfpTest.h | 348 +++++++++++ libc/test/src/math/smoke/UfromfpxTest.h | 437 +++++++++++++ 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 + 64 files changed, 3181 insertions(+), 16 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/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst index 50e8bdde89ddd6..c97a539ca8da45 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`. + +Unknown Math Rounding Direction +------------------------------- +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 +direction in this case. 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..7407ead17711aa 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, [ArgSpec, ArgSpec]>, GuardedFunctionSpec<"frexpf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"fromfp", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"fromfpf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"fromfpl", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"fromfpf128", RetValSpec, [ArgSpec, ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fromfpx", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"fromfpxf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"fromfpxl", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"fromfpxf128", RetValSpec, [ArgSpec, ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"ufromfp", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"ufromfpf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"ufromfpl", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"ufromfpf128", RetValSpec, [ArgSpec, ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"ufromfpx", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"ufromfpxf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"ufromfpxl", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"ufromfpxf128", RetValSpec, [ArgSpec, ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"hypot", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"hypotf", RetValSpec, [ArgSpec, ArgSpec]>, diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h index e890e38ba4ae7d..579584076b1258 100644 --- a/libc/src/__support/FPUtil/NearestIntegerOperations.h +++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h @@ -140,8 +140,9 @@ LIBC_INLINE T round(T x) { } } -template , int> = 0> -LIBC_INLINE T round_using_current_rounding_mode(T x) { +template +LIBC_INLINE constexpr cpp::enable_if_t, T> +round_using_specific_rounding_mode(T x, int rnd) { using StorageType = typename FPBits::StorageType; FPBits bits(x); @@ -151,7 +152,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 +159,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 +197,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 +222,67 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) { } else { return trunc_value; } + } +} + +template +LIBC_INLINE cpp::enable_if_t, 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 +LIBC_INLINE constexpr cpp::enable_if_t, T> +fromfp(T x, int rnd, unsigned int width) { + if (width == 0U) + return FPBits::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::EXP_BIAS) + return rounded_value; + if (rounded_value < -T(1U << (width - 1U))) + return FPBits::quiet_nan().get_val(); + if (rounded_value > T((1U << (width - 1U)) - 1U)) + return FPBits::quiet_nan().get_val(); + return rounded_value; + } + + if (rounded_value < T(0.0)) + return FPBits::quiet_nan().get_val(); + // T can't hold a finite number >= 2.0 * 2^EXP_BIAS. + if (width <= FPBits::EXP_BIAS && rounded_value > T(1U << width) - 1U) + return FPBits::quiet_nan().get_val(); + return rounded_value; +} + +template +LIBC_INLINE constexpr cpp::enable_if_t, T> +fromfpx(T x, int rnd, unsigned int width) { + T rounded_value = fromfp(x, rnd, width); + FPBits bits(rounded_value); + + if (!bits.is_nan() && rounded_value != x) + raise_except_if_required(FE_INEXACT); + + return rounded_value; +} + namespace internal { template (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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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..f4553eac5c8a57 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,14 @@ template 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 int UNKNOWN_MATH_ROUNDING_DIRECTION = 99; \ + static constexpr LIBC_NAMESPACE::cpp::array \ + MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN = { \ + FP_INT_UPWARD, FP_INT_DOWNWARD, \ + FP_INT_TOWARDZERO, FP_INT_TONEARESTFROMZERO, \ + FP_INT_TONEAREST, UNKNOWN_MATH_ROUNDING_DIRECTION, \ + }; #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..2d4c4c5314c9dd --- /dev/null +++ b/libc/test/src/math/smoke/FromfpTest.h @@ -0,0 +1,416 @@ +//===-- 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 +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_INCLUDING_UNKNOWN) { + 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_INCLUDING_UNKNOWN) { + 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_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)); + 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_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)); + 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)); + } + + 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) \ + using LlvmLibcFromfpTest = FromfpTestTemplate; \ + 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); \ + } \ + 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 new file mode 100644 index 00000000000000..b3c14c7c09ba07 --- /dev/null +++ b/libc/test/src/math/smoke/FromfpxTest.h @@ -0,0 +1,578 @@ +//===-- 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 +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_INCLUDING_UNKNOWN) { + 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_INCLUDING_UNKNOWN) { + 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_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)); + 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_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)); + 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)); + } + + 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) \ + using LlvmLibcFromfpxTest = FromfpxTestTemplate; \ + 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); \ + } \ + 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 new file mode 100644 index 00000000000000..e753fc489cdea7 --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpTest.h @@ -0,0 +1,348 @@ +//===-- 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 +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_INCLUDING_UNKNOWN) { + 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_INCLUDING_UNKNOWN) { + 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_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)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpFunc func) { + 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)); + 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)); + } + + 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) \ + using LlvmLibcUfromfpTest = UfromfpTestTemplate; \ + 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); \ + } \ + 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 new file mode 100644 index 00000000000000..47bf32c80f1705 --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpxTest.h @@ -0,0 +1,437 @@ +//===-- 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 +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_INCLUDING_UNKNOWN) { + 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_INCLUDING_UNKNOWN) { + 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_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)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpxFunc func) { + 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)); + 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)); + } + + 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) \ + using LlvmLibcUfromfpxTest = UfromfpxTestTemplate; \ + 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); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackWithinRange) { \ + testFractionsToNearestFallbackWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackOutsideRange) { \ + testFractionsToNearestFallbackOutsideRange(&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",