[libc-commits] [libc] a4d48e3 - [libc][NFC] Use cpp::optional for checking exceptional values of math functions.
Tue Ly via libc-commits
libc-commits at lists.llvm.org
Thu Sep 1 14:39:35 PDT 2022
Author: Tue Ly
Date: 2022-09-01T17:39:12-04:00
New Revision: a4d48e3b0b66cacb8c42be8421608f7efd170c24
URL: https://github.com/llvm/llvm-project/commit/a4d48e3b0b66cacb8c42be8421608f7efd170c24
DIFF: https://github.com/llvm/llvm-project/commit/a4d48e3b0b66cacb8c42be8421608f7efd170c24.diff
LOG: [libc][NFC] Use cpp::optional for checking exceptional values of math functions.
Update the utility functions for checking exceptional values of math
functions to use cpp::optional return values.
Reviewed By: sivachandra
Differential Revision: https://reviews.llvm.org/D133134
Added:
Modified:
libc/src/__support/FPUtil/CMakeLists.txt
libc/src/__support/FPUtil/except_value_utils.h
libc/src/math/generic/cosf.cpp
libc/src/math/generic/tanf.cpp
Removed:
################################################################################
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 5a66139524a8..a3b085040a3d 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -102,6 +102,7 @@ add_header_library(
DEPENDS
.fp_bits
.fenv_impl
+ libc.src.__support.CPP.optional
)
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index a8a9ba865fb7..684647c2547a 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -11,55 +11,88 @@
#include "FEnvImpl.h"
#include "FPBits.h"
+#include "src/__support/CPP/optional.h"
namespace __llvm_libc {
namespace fputil {
-template <typename T, int N> struct ExceptionalValues {
- using UIntType = typename FPBits<T>::UIntType;
- static constexpr int SIZE = N;
- // Input bits.
- UIntType inputs[SIZE];
- // Output bits contains 4 values:
- // output[i][0]: output bits corresponding to FE_TOWARDZERO
- // output[i][1]: offset for FE_UPWARD
- // output[i][2]: offset for FE_DOWNWARD
- // output[i][3]: offset for FE_TONEAREST
- UIntType outputs[SIZE][4];
-};
+// This file contains utility functions and classes to manage exceptional values
+// when there are many of them.
+//
+// Example usage:
+//
+// Define list of exceptional inputs and outputs:
+// static constexpr int N = ...; // Number of exceptional values.
+// static constexpr fputil::ExceptValues<UIntType, N> Excepts {
+// <list of input bits, output bits and offsets>
+// };
+//
+// Check for exceptional inputs:
+// if (auto r = Excepts.lookup(x_bits); unlikely(r.has_value()))
+// return r.value();
+
+template <typename T, size_t N> struct ExceptValues {
+ static_assert(cpp::is_floating_point_v<T>, "Must be a floating point type.");
-template <typename T, int N> struct ExceptionChecker {
using UIntType = typename FPBits<T>::UIntType;
- using FPBits = FPBits<T>;
- using ExceptionalValues = ExceptionalValues<T, N>;
- static bool check_odd_func(const ExceptionalValues &ExceptVals,
- UIntType x_abs, bool sign, T &result) {
- for (int i = 0; i < N; ++i) {
- if (unlikely(x_abs == ExceptVals.inputs[i])) {
- UIntType out_bits = ExceptVals.outputs[i][0]; // FE_TOWARDZERO
+ struct Mapping {
+ UIntType input;
+ UIntType rnd_towardzero_result;
+ UIntType rnd_upward_offset;
+ UIntType rnd_downward_offset;
+ UIntType rnd_tonearest_offset;
+ };
+
+ Mapping values[N];
+
+ constexpr cpp::optional<T> lookup(UIntType x_bits) const {
+ for (size_t i = 0; i < N; ++i) {
+ if (unlikely(x_bits == values[i].input)) {
+ UIntType out_bits = values[i].rnd_towardzero_result;
+ switch (fputil::get_round()) {
+ case FE_UPWARD:
+ out_bits += values[i].rnd_upward_offset;
+ break;
+ case FE_DOWNWARD:
+ out_bits += values[i].rnd_downward_offset;
+ break;
+ case FE_TONEAREST:
+ out_bits += values[i].rnd_tonearest_offset;
+ break;
+ }
+ return FPBits<T>(out_bits).get_val();
+ }
+ }
+ return cpp::nullopt;
+ }
+
+ constexpr cpp::optional<T> lookup_odd(UIntType x_abs, bool sign) const {
+ for (size_t i = 0; i < N; ++i) {
+ if (unlikely(x_abs == values[i].input)) {
+ UIntType out_bits = values[i].rnd_towardzero_result;
switch (fputil::get_round()) {
case FE_UPWARD:
- out_bits +=
- sign ? ExceptVals.outputs[i][2] : ExceptVals.outputs[i][1];
+ out_bits += sign ? values[i].rnd_downward_offset
+ : values[i].rnd_upward_offset;
break;
case FE_DOWNWARD:
- out_bits +=
- sign ? ExceptVals.outputs[i][1] : ExceptVals.outputs[i][2];
+ out_bits += sign ? values[i].rnd_upward_offset
+ : values[i].rnd_downward_offset;
break;
case FE_TONEAREST:
- out_bits += ExceptVals.outputs[i][3];
+ out_bits += values[i].rnd_tonearest_offset;
break;
}
- result = FPBits(out_bits).get_val();
+ T result = FPBits<T>(out_bits).get_val();
if (sign)
result = -result;
- return true;
+ return result;
}
}
- return false;
+ return cpp::nullopt;
}
};
diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp
index 58f499ff5afe..ebccc99dab04 100644
--- a/libc/src/math/generic/cosf.cpp
+++ b/libc/src/math/generic/cosf.cpp
@@ -20,27 +20,23 @@
namespace __llvm_libc {
// Exceptional cases for cosf.
-static constexpr int COSF_EXCEPTS = 6;
+static constexpr size_t N_EXCEPTS = 6;
-static constexpr fputil::ExceptionalValues<float, COSF_EXCEPTS> CosfExcepts{
- /* inputs */ {
- 0x55325019, // x = 0x1.64a032p43
- 0x5922aa80, // x = 0x1.4555p51
- 0x5aa4542c, // x = 0x1.48a858p54
- 0x5f18b878, // x = 0x1.3170fp63
- 0x6115cb11, // x = 0x1.2b9622p67
- 0x7beef5ef, // x = 0x1.ddebdep120
- },
- /* outputs (RZ, RU offset, RD offset, RN offset) */
- {
- {0x3f4ea5d2, 1, 0, 0}, // x = 0x1.64a032p43, cos(x) = 0x1.9d4ba4p-1 (RZ)
- {0x3f08aebe, 1, 0, 1}, // x = 0x1.4555p51, cos(x) = 0x1.115d7cp-1 (RZ)
- {0x3efa40a4, 1, 0, 0}, // x = 0x1.48a858p54, cos(x) = 0x1.f48148p-2 (RZ)
- {0x3f7f14bb, 1, 0, 0}, // x = 0x1.3170fp63, cos(x) = 0x1.fe2976p-1 (RZ)
- {0x3f78142e, 1, 0, 1}, // x = 0x1.2b9622p67, cos(x) = 0x1.f0285cp-1 (RZ)
- {0x3f08a21c, 1, 0,
- 0}, // x = 0x1.ddebdep120, cos(x) = 0x1.114438p-1 (RZ)
- }};
+static constexpr fputil::ExceptValues<float, N_EXCEPTS> COSF_EXCEPTS{{
+ // (inputs, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x1.64a032p43, cos(x) = 0x1.9d4ba4p-1 (RZ)
+ {0x55325019, 0x3f4ea5d2, 1, 0, 0},
+ // x = 0x1.4555p51, cos(x) = 0x1.115d7cp-1 (RZ)
+ {0x5922aa80, 0x3f08aebe, 1, 0, 1},
+ // x = 0x1.48a858p54, cos(x) = 0x1.f48148p-2 (RZ)
+ {0x5aa4542c, 0x3efa40a4, 1, 0, 0},
+ // x = 0x1.3170fp63, cos(x) = 0x1.fe2976p-1 (RZ)
+ {0x5f18b878, 0x3f7f14bb, 1, 0, 0},
+ // x = 0x1.2b9622p67, cos(x) = 0x1.f0285cp-1 (RZ)
+ {0x6115cb11, 0x3f78142e, 1, 0, 1},
+ // x = 0x1.ddebdep120, cos(x) = 0x1.114438p-1 (RZ)
+ {0x7beef5ef, 0x3f08a21c, 1, 0, 0},
+}};
LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
@@ -110,12 +106,8 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
#endif // LIBC_TARGET_HAS_FMA
}
- using ExceptChecker = typename fputil::ExceptionChecker<float, COSF_EXCEPTS>;
- {
- float result;
- if (ExceptChecker::check_odd_func(CosfExcepts, x_abs, false, result))
- return result;
- }
+ if (auto r = COSF_EXCEPTS.lookup(x_abs); unlikely(r.has_value()))
+ return r.value();
// x is inf or nan.
if (unlikely(x_abs >= 0x7f80'0000U)) {
diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp
index 42a2d49f45ee..601939a65c7f 100644
--- a/libc/src/math/generic/tanf.cpp
+++ b/libc/src/math/generic/tanf.cpp
@@ -56,29 +56,23 @@ static constexpr double TAN_K_PI_OVER_32[32] = {
};
// Exceptional cases for tanf.
-static constexpr int TANF_EXCEPTS = 6;
-
-static constexpr fputil::ExceptionalValues<float, TANF_EXCEPTS> TanfExcepts{
- /* inputs */ {
- 0x531d744c, // x = 0x1.3ae898p39
- 0x57d7b0ed, // x = 0x1.af61dap48
- 0x65ee8695, // x = 0x1.dd0d2ap76
- 0x6798fe4f, // x = 0x1.31fc9ep80
- 0x6ad36709, // x = 0x1.a6ce12p86
- 0x72b505bb, // x = 0x1.6a0b76p102
- },
- /* outputs (RZ, RU offset, RD offset, RN offset) */
- {
- {0x4591ea1e, 1, 0, 1}, // x = 0x1.3ae898p39, tan(x) = 0x1.23d43cp12 (RZ)
- {0x3eb068e3, 1, 0, 1}, // x = 0x1.af61dap48, tan(x) = 0x1.60d1c6p-2 (RZ)
- {0xcaa32f8e, 0, 1,
- 0}, // x = 0x1.dd0d2ap76, tan(x) = -0x1.465f1cp22 (RZ)
- {0x461e09f7, 1, 0, 0}, // x = 0x1.31fc9ep80, tan(x) = 0x1.3c13eep13 (RZ)
- {0xbf62b097, 0, 1,
- 0}, // x = 0x1.a6ce12p86, tan(x) = -0x1.c5612ep-1 (RZ)
- {0xbff2150f, 0, 1,
- 0}, // x = 0x1.6a0b76p102, tan(x) = -0x1.e42a1ep0 (RZ)
- }};
+static constexpr size_t N_EXCEPTS = 6;
+
+static constexpr fputil::ExceptValues<float, N_EXCEPTS> TANF_EXCEPTS{{
+ // (inputs, RZ output, RU offset, RD offset, RN offset)
+ // x = 0x1.3ae898p39, tan(x) = 0x1.23d43cp12 (RZ)
+ {0x531d744c, 0x4591ea1e, 1, 0, 1},
+ // x = 0x1.af61dap48, tan(x) = 0x1.60d1c6p-2 (RZ)
+ {0x57d7b0ed, 0x3eb068e3, 1, 0, 1},
+ // x = 0x1.dd0d2ap76, tan(x) = -0x1.465f1cp22 (RZ)
+ {0x65ee8695, 0xcaa32f8e, 0, 1, 0},
+ // x = 0x1.31fc9ep80, tan(x) = 0x1.3c13eep13 (RZ)
+ {0x6798fe4f, 0x461e09f7, 1, 0, 0},
+ // x = 0x1.a6ce12p86, tan(x) = -0x1.c5612ep-1 (RZ)
+ {0x6ad36709, 0xbf62b097, 0, 1, 0},
+ // x = 0x1.6a0b76p102, tan(x) = -0x1.e42a1ep0 (RZ)
+ {0x72b505bb, 0xbff2150f, 0, 1, 0},
+}};
LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
@@ -200,14 +194,9 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
k = small_range_reduction(xd, y);
} else {
- using ExceptChecker =
- typename fputil::ExceptionChecker<float, TANF_EXCEPTS>;
- {
- float result;
- if (ExceptChecker::check_odd_func(TanfExcepts, x_abs, x_sign <= 0.0,
- result))
- return result;
- }
+ if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign <= 0.0);
+ unlikely(r.has_value()))
+ return r.value();
fputil::FPBits<float> x_bits(x_abs);
k = large_range_reduction(xd, x_bits.get_exponent(), y);
More information about the libc-commits
mailing list