1 //===-- Common header for helpers to set exceptional values -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
11 
12 #include "FEnvImpl.h"
13 #include "FPBits.h"
14 
15 namespace __llvm_libc {
16 
17 namespace fputil {
18 
19 template <typename T, int N> struct ExceptionalValues {
20   using UIntType = typename FPBits<T>::UIntType;
21   static constexpr int SIZE = N;
22   // Input bits.
23   UIntType inputs[SIZE];
24   // Output bits contains 4 values:
25   //   output[i][0]: output bits corresponding to FE_TOWARDZERO
26   //   output[i][1]: offset for FE_UPWARD
27   //   output[i][2]: offset for FE_DOWNWARD
28   //   output[i][3]: offset for FE_TONEAREST
29   UIntType outputs[SIZE][4];
30 };
31 
32 template <typename T, int N> struct ExceptionChecker {
33   using UIntType = typename FPBits<T>::UIntType;
34   using FPBits = FPBits<T>;
35   using ExceptionalValues = ExceptionalValues<T, N>;
36 
check_odd_funcExceptionChecker37   static bool check_odd_func(const ExceptionalValues &ExceptVals,
38                              UIntType x_abs, bool sign, T &result) {
39     for (int i = 0; i < N; ++i) {
40       if (unlikely(x_abs == ExceptVals.inputs[i])) {
41         UIntType out_bits = ExceptVals.outputs[i][0]; // FE_TOWARDZERO
42         switch (fputil::get_round()) {
43         case FE_UPWARD:
44           out_bits +=
45               sign ? ExceptVals.outputs[i][2] : ExceptVals.outputs[i][1];
46           break;
47         case FE_DOWNWARD:
48           out_bits +=
49               sign ? ExceptVals.outputs[i][1] : ExceptVals.outputs[i][2];
50           break;
51         case FE_TONEAREST:
52           out_bits += ExceptVals.outputs[i][3];
53           break;
54         }
55         result = FPBits(out_bits).get_val();
56         if (sign)
57           result = -result;
58 
59         return true;
60       }
61     }
62     return false;
63   }
64 };
65 
66 } // namespace fputil
67 
68 } // namespace __llvm_libc
69 
70 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
71