Warning: This file is not a C or C++ file. It does not have highlighting.

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#include "cast.h"
15#include "rounding_mode.h"
16#include "src/__support/CPP/optional.h"
17#include "src/__support/macros/config.h"
18#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
19#include "src/__support/macros/properties/cpu_features.h"
20#include "src/__support/macros/properties/types.h"
21
22namespace LIBC_NAMESPACE_DECL {
23
24namespace fputil {
25
26// This file contains utility functions and classes to manage exceptional values
27// when there are many of them.
28//
29// Example usage:
30//
31// Define list of exceptional inputs and outputs:
32// static constexpr int N = ...; // Number of exceptional values.
33// static constexpr fputil::ExceptValues<StorageType, N> Excepts {
34// <list of input bits, output bits and offsets>
35// };
36//
37// Check for exceptional inputs:
38// if (auto r = Excepts.lookup(x_bits); LIBC_UNLIKELY(r.has_value()))
39// return r.value();
40
41template <typename T, size_t N> struct ExceptValues {
42 static_assert(cpp::is_floating_point_v<T>, "Must be a floating point type.");
43
44 using StorageType = typename FPBits<T>::StorageType;
45
46 struct Mapping {
47 StorageType input;
48 StorageType rnd_towardzero_result;
49 StorageType rnd_upward_offset;
50 StorageType rnd_downward_offset;
51 StorageType rnd_tonearest_offset;
52 };
53
54 Mapping values[N];
55
56 LIBC_INLINE constexpr cpp::optional<T> lookup(StorageType x_bits) const {
57 for (size_t i = 0; i < N; ++i) {
58 if (LIBC_UNLIKELY(x_bits == values[i].input)) {
59 StorageType out_bits = values[i].rnd_towardzero_result;
60 switch (fputil::quick_get_round()) {
61 case FE_UPWARD:
62 out_bits += values[i].rnd_upward_offset;
63 break;
64 case FE_DOWNWARD:
65 out_bits += values[i].rnd_downward_offset;
66 break;
67 case FE_TONEAREST:
68 out_bits += values[i].rnd_tonearest_offset;
69 break;
70 }
71 return FPBits<T>(out_bits).get_val();
72 }
73 }
74 return cpp::nullopt;
75 }
76
77 LIBC_INLINE constexpr cpp::optional<T> lookup_odd(StorageType x_abs,
78 bool sign) const {
79 for (size_t i = 0; i < N; ++i) {
80 if (LIBC_UNLIKELY(x_abs == values[i].input)) {
81 StorageType out_bits = values[i].rnd_towardzero_result;
82 switch (fputil::quick_get_round()) {
83 case FE_UPWARD:
84 if (sign)
85 out_bits += values[i].rnd_downward_offset;
86 else
87 out_bits += values[i].rnd_upward_offset;
88 break;
89 case FE_DOWNWARD:
90 // Use conditionals instead of ternary operator to work around gcc's
91 // -Wconversion false positive bug:
92 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101537
93 if (sign)
94 out_bits += values[i].rnd_upward_offset;
95 else
96 out_bits += values[i].rnd_downward_offset;
97 break;
98 case FE_TONEAREST:
99 out_bits += values[i].rnd_tonearest_offset;
100 break;
101 }
102 T result = FPBits<T>(out_bits).get_val();
103 if (sign)
104 result = -result;
105
106 return result;
107 }
108 }
109 return cpp::nullopt;
110 }
111};
112
113// Helper functions to set results for exceptional cases.
114template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
115 volatile T tmp = value_rn;
116 tmp -= FPBits<T>::min_normal().get_val();
117 return tmp;
118}
119
120template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
121 volatile T tmp = value_rn;
122 tmp += FPBits<T>::min_normal().get_val();
123 return tmp;
124}
125
126#if defined(LIBC_TYPES_HAS_FLOAT16) && \
127 !defined(LIBC_TARGET_CPU_HAS_FAST_FLOAT16_OPS)
128template <> LIBC_INLINE float16 round_result_slightly_down(float16 value_rn) {
129 volatile float tmp = value_rn;
130 tmp -= FPBits<float16>::min_normal().get_val();
131 return cast<float16>(tmp);
132}
133
134template <> LIBC_INLINE float16 round_result_slightly_up(float16 value_rn) {
135 volatile float tmp = value_rn;
136 tmp += FPBits<float16>::min_normal().get_val();
137 return cast<float16>(tmp);
138}
139#endif
140
141} // namespace fputil
142
143} // namespace LIBC_NAMESPACE_DECL
144
145#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_EXCEPT_VALUE_UTILS_H
146

Warning: This file is not a C or C++ file. It does not have highlighting.

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of libc/src/__support/FPUtil/except_value_utils.h