[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