1 //===-- Common header for helpers to set exceptional values -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
10 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
14 #include "src/__support/CPP/optional.h"
15 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
17 namespace __llvm_libc
{
21 // This file contains utility functions and classes to manage exceptional values
22 // when there are many of them.
26 // Define list of exceptional inputs and outputs:
27 // static constexpr int N = ...; // Number of exceptional values.
28 // static constexpr fputil::ExceptValues<UIntType, N> Excepts {
29 // <list of input bits, output bits and offsets>
32 // Check for exceptional inputs:
33 // if (auto r = Excepts.lookup(x_bits); LIBC_UNLIKELY(r.has_value()))
36 template <typename T
, size_t N
> struct ExceptValues
{
37 static_assert(cpp::is_floating_point_v
<T
>, "Must be a floating point type.");
39 using UIntType
= typename FPBits
<T
>::UIntType
;
43 UIntType rnd_towardzero_result
;
44 UIntType rnd_upward_offset
;
45 UIntType rnd_downward_offset
;
46 UIntType rnd_tonearest_offset
;
51 LIBC_INLINE
constexpr cpp::optional
<T
> lookup(UIntType x_bits
) const {
52 for (size_t i
= 0; i
< N
; ++i
) {
53 if (LIBC_UNLIKELY(x_bits
== values
[i
].input
)) {
54 UIntType out_bits
= values
[i
].rnd_towardzero_result
;
55 switch (fputil::get_round()) {
57 out_bits
+= values
[i
].rnd_upward_offset
;
60 out_bits
+= values
[i
].rnd_downward_offset
;
63 out_bits
+= values
[i
].rnd_tonearest_offset
;
66 return FPBits
<T
>(out_bits
).get_val();
72 LIBC_INLINE
constexpr cpp::optional
<T
> lookup_odd(UIntType x_abs
,
74 for (size_t i
= 0; i
< N
; ++i
) {
75 if (LIBC_UNLIKELY(x_abs
== values
[i
].input
)) {
76 UIntType out_bits
= values
[i
].rnd_towardzero_result
;
77 switch (fputil::get_round()) {
79 out_bits
+= sign
? values
[i
].rnd_downward_offset
80 : values
[i
].rnd_upward_offset
;
83 out_bits
+= sign
? values
[i
].rnd_upward_offset
84 : values
[i
].rnd_downward_offset
;
87 out_bits
+= values
[i
].rnd_tonearest_offset
;
90 T result
= FPBits
<T
>(out_bits
).get_val();
101 // Helper functions to set results for exceptional cases.
102 LIBC_INLINE
float round_result_slightly_down(float value_rn
) {
103 volatile float tmp
= value_rn
;
104 tmp
= tmp
- 0x1.0p
-100f
;
108 LIBC_INLINE
float round_result_slightly_up(float value_rn
) {
109 volatile float tmp
= value_rn
;
110 tmp
= tmp
+ 0x1.0p
-100f
;
114 } // namespace fputil
116 } // namespace __llvm_libc
118 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H