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 "rounding_mode.h"
15 #include "src/__support/CPP/optional.h"
16 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
18 namespace __llvm_libc
{
22 // This file contains utility functions and classes to manage exceptional values
23 // when there are many of them.
27 // Define list of exceptional inputs and outputs:
28 // static constexpr int N = ...; // Number of exceptional values.
29 // static constexpr fputil::ExceptValues<UIntType, N> Excepts {
30 // <list of input bits, output bits and offsets>
33 // Check for exceptional inputs:
34 // if (auto r = Excepts.lookup(x_bits); LIBC_UNLIKELY(r.has_value()))
37 template <typename T
, size_t N
> struct ExceptValues
{
38 static_assert(cpp::is_floating_point_v
<T
>, "Must be a floating point type.");
40 using UIntType
= typename FPBits
<T
>::UIntType
;
44 UIntType rnd_towardzero_result
;
45 UIntType rnd_upward_offset
;
46 UIntType rnd_downward_offset
;
47 UIntType rnd_tonearest_offset
;
52 LIBC_INLINE
constexpr cpp::optional
<T
> lookup(UIntType x_bits
) const {
53 for (size_t i
= 0; i
< N
; ++i
) {
54 if (LIBC_UNLIKELY(x_bits
== values
[i
].input
)) {
55 UIntType out_bits
= values
[i
].rnd_towardzero_result
;
56 switch (fputil::quick_get_round()) {
58 out_bits
+= values
[i
].rnd_upward_offset
;
61 out_bits
+= values
[i
].rnd_downward_offset
;
64 out_bits
+= values
[i
].rnd_tonearest_offset
;
67 return FPBits
<T
>(out_bits
).get_val();
73 LIBC_INLINE
constexpr cpp::optional
<T
> lookup_odd(UIntType x_abs
,
75 for (size_t i
= 0; i
< N
; ++i
) {
76 if (LIBC_UNLIKELY(x_abs
== values
[i
].input
)) {
77 UIntType out_bits
= values
[i
].rnd_towardzero_result
;
78 switch (fputil::quick_get_round()) {
80 out_bits
+= sign
? values
[i
].rnd_downward_offset
81 : values
[i
].rnd_upward_offset
;
84 out_bits
+= sign
? values
[i
].rnd_upward_offset
85 : values
[i
].rnd_downward_offset
;
88 out_bits
+= values
[i
].rnd_tonearest_offset
;
91 T result
= FPBits
<T
>(out_bits
).get_val();
102 // Helper functions to set results for exceptional cases.
103 LIBC_INLINE
float round_result_slightly_down(float value_rn
) {
104 volatile float tmp
= value_rn
;
105 tmp
= tmp
- 0x1.0p
-100f
;
109 LIBC_INLINE
float round_result_slightly_up(float value_rn
) {
110 volatile float tmp
= value_rn
;
111 tmp
= tmp
+ 0x1.0p
-100f
;
115 } // namespace fputil
117 } // namespace __llvm_libc
119 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H