Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- Utility class to manipulate fixed point numbers. --*- 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_FIXED_POINT_FX_REP_H |
10 | #define LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_REP_H |
11 | |
12 | #include "include/llvm-libc-macros/stdfix-macros.h" |
13 | #include "src/__support/CPP/type_traits.h" |
14 | #include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR |
15 | #include "src/__support/macros/config.h" |
16 | |
17 | #include <stdint.h> |
18 | |
19 | #ifdef LIBC_COMPILER_HAS_FIXED_POINT |
20 | |
21 | namespace LIBC_NAMESPACE_DECL { |
22 | namespace fixed_point { |
23 | |
24 | namespace internal { |
25 | |
26 | template <int Bits> struct Storage { |
27 | static_assert(Bits > 0 && Bits <= 64, "Bits has to be between 1 and 64."); |
28 | using Type = typename cpp::conditional_t< |
29 | (Bits <= 8), uint8_t, |
30 | typename cpp::conditional_t< |
31 | (Bits <= 16 && Bits > 8), uint16_t, |
32 | typename cpp::conditional_t<(Bits <= 32 && Bits > 16), uint32_t, |
33 | uint64_t>>>; |
34 | }; |
35 | |
36 | } // namespace internal |
37 | |
38 | template <typename T> struct FXRep; |
39 | |
40 | template <> struct FXRep<short fract> { |
41 | using Type = short _Fract; |
42 | |
43 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
44 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
45 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT; |
46 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
47 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
48 | |
49 | LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; } |
50 | LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; } |
51 | LIBC_INLINE static constexpr Type ZERO() { return 0.0HR; } |
52 | LIBC_INLINE static constexpr Type EPS() { return SFRACT_EPSILON; } |
53 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HR; } |
54 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HR; } |
55 | |
56 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
57 | using CompType = cpp::make_signed_t<StorageType>; |
58 | }; |
59 | |
60 | template <> struct FXRep<unsigned short fract> { |
61 | using Type = unsigned short fract; |
62 | |
63 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
64 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
65 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT; |
66 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
67 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
68 | |
69 | LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; } |
70 | LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; } |
71 | LIBC_INLINE static constexpr Type ZERO() { return 0.0UHR; } |
72 | LIBC_INLINE static constexpr Type EPS() { return USFRACT_EPSILON; } |
73 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHR; } |
74 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHR; } |
75 | |
76 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
77 | using CompType = cpp::make_unsigned_t<StorageType>; |
78 | }; |
79 | |
80 | template <> struct FXRep<fract> { |
81 | using Type = fract; |
82 | |
83 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
84 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
85 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT; |
86 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
87 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
88 | |
89 | LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; } |
90 | LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; } |
91 | LIBC_INLINE static constexpr Type ZERO() { return 0.0R; } |
92 | LIBC_INLINE static constexpr Type EPS() { return FRACT_EPSILON; } |
93 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5R; } |
94 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25R; } |
95 | |
96 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
97 | using CompType = cpp::make_signed_t<StorageType>; |
98 | }; |
99 | |
100 | template <> struct FXRep<unsigned fract> { |
101 | using Type = unsigned fract; |
102 | |
103 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
104 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
105 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT; |
106 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
107 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
108 | |
109 | LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; } |
110 | LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; } |
111 | LIBC_INLINE static constexpr Type ZERO() { return 0.0UR; } |
112 | LIBC_INLINE static constexpr Type EPS() { return UFRACT_EPSILON; } |
113 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UR; } |
114 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UR; } |
115 | |
116 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
117 | using CompType = cpp::make_unsigned_t<StorageType>; |
118 | }; |
119 | |
120 | template <> struct FXRep<long fract> { |
121 | using Type = long fract; |
122 | |
123 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
124 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
125 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT; |
126 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
127 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
128 | |
129 | LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; } |
130 | LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; } |
131 | LIBC_INLINE static constexpr Type ZERO() { return 0.0LR; } |
132 | LIBC_INLINE static constexpr Type EPS() { return LFRACT_EPSILON; } |
133 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LR; } |
134 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LR; } |
135 | |
136 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
137 | using CompType = cpp::make_signed_t<StorageType>; |
138 | }; |
139 | |
140 | template <> struct FXRep<unsigned long fract> { |
141 | using Type = unsigned long fract; |
142 | |
143 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
144 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0; |
145 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT; |
146 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
147 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
148 | |
149 | LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; } |
150 | LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; } |
151 | LIBC_INLINE static constexpr Type ZERO() { return 0.0ULR; } |
152 | LIBC_INLINE static constexpr Type EPS() { return ULFRACT_EPSILON; } |
153 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULR; } |
154 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULR; } |
155 | |
156 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
157 | using CompType = cpp::make_unsigned_t<StorageType>; |
158 | }; |
159 | |
160 | template <> struct FXRep<short accum> { |
161 | using Type = short accum; |
162 | |
163 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
164 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = SACCUM_IBIT; |
165 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT; |
166 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
167 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
168 | |
169 | LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; } |
170 | LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; } |
171 | LIBC_INLINE static constexpr Type ZERO() { return 0.0HK; } |
172 | LIBC_INLINE static constexpr Type EPS() { return SACCUM_EPSILON; } |
173 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HK; } |
174 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HK; } |
175 | |
176 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
177 | using CompType = cpp::make_signed_t<StorageType>; |
178 | }; |
179 | |
180 | template <> struct FXRep<unsigned short accum> { |
181 | using Type = unsigned short accum; |
182 | |
183 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
184 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = USACCUM_IBIT; |
185 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT; |
186 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
187 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
188 | |
189 | LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; } |
190 | LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; } |
191 | LIBC_INLINE static constexpr Type ZERO() { return 0.0UHK; } |
192 | LIBC_INLINE static constexpr Type EPS() { return USACCUM_EPSILON; } |
193 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHK; } |
194 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHK; } |
195 | |
196 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
197 | using CompType = cpp::make_unsigned_t<StorageType>; |
198 | }; |
199 | |
200 | template <> struct FXRep<accum> { |
201 | using Type = accum; |
202 | |
203 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
204 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ACCUM_IBIT; |
205 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT; |
206 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
207 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
208 | |
209 | LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; } |
210 | LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; } |
211 | LIBC_INLINE static constexpr Type ZERO() { return 0.0K; } |
212 | LIBC_INLINE static constexpr Type EPS() { return ACCUM_EPSILON; } |
213 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5K; } |
214 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25K; } |
215 | |
216 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
217 | using CompType = cpp::make_signed_t<StorageType>; |
218 | }; |
219 | |
220 | template <> struct FXRep<unsigned accum> { |
221 | using Type = unsigned accum; |
222 | |
223 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
224 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT; |
225 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT; |
226 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
227 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
228 | |
229 | LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; } |
230 | LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; } |
231 | LIBC_INLINE static constexpr Type ZERO() { return 0.0UK; } |
232 | LIBC_INLINE static constexpr Type EPS() { return UACCUM_EPSILON; } |
233 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UK; } |
234 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UK; } |
235 | |
236 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
237 | using CompType = cpp::make_unsigned_t<StorageType>; |
238 | }; |
239 | |
240 | template <> struct FXRep<long accum> { |
241 | using Type = long accum; |
242 | |
243 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; |
244 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = LACCUM_IBIT; |
245 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT; |
246 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
247 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
248 | |
249 | LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; } |
250 | LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; } |
251 | LIBC_INLINE static constexpr Type ZERO() { return 0.0LK; } |
252 | LIBC_INLINE static constexpr Type EPS() { return LACCUM_EPSILON; } |
253 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LK; } |
254 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LK; } |
255 | |
256 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
257 | using CompType = cpp::make_signed_t<StorageType>; |
258 | }; |
259 | |
260 | template <> struct FXRep<unsigned long accum> { |
261 | using Type = unsigned long accum; |
262 | |
263 | LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0; |
264 | LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ULACCUM_IBIT; |
265 | LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT; |
266 | LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN; |
267 | LIBC_INLINE_VAR static constexpr int TOTAL_LEN = SIGN_LEN + VALUE_LEN; |
268 | |
269 | LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; } |
270 | LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; } |
271 | LIBC_INLINE static constexpr Type ZERO() { return 0.0ULK; } |
272 | LIBC_INLINE static constexpr Type EPS() { return ULACCUM_EPSILON; } |
273 | LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULK; } |
274 | LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULK; } |
275 | |
276 | using StorageType = typename internal::Storage<TOTAL_LEN>::Type; |
277 | using CompType = cpp::make_unsigned_t<StorageType>; |
278 | }; |
279 | |
280 | template <> struct FXRep<short sat fract> : FXRep<short fract> {}; |
281 | template <> struct FXRep<sat fract> : FXRep<fract> {}; |
282 | template <> struct FXRep<long sat fract> : FXRep<long fract> {}; |
283 | template <> |
284 | struct FXRep<unsigned short sat fract> : FXRep<unsigned short fract> {}; |
285 | template <> struct FXRep<unsigned sat fract> : FXRep<unsigned fract> {}; |
286 | template <> |
287 | struct FXRep<unsigned long sat fract> : FXRep<unsigned long fract> {}; |
288 | |
289 | template <> struct FXRep<short sat accum> : FXRep<short accum> {}; |
290 | template <> struct FXRep<sat accum> : FXRep<accum> {}; |
291 | template <> struct FXRep<long sat accum> : FXRep<long accum> {}; |
292 | template <> |
293 | struct FXRep<unsigned short sat accum> : FXRep<unsigned short accum> {}; |
294 | template <> struct FXRep<unsigned sat accum> : FXRep<unsigned accum> {}; |
295 | template <> |
296 | struct FXRep<unsigned long sat accum> : FXRep<unsigned long accum> {}; |
297 | |
298 | } // namespace fixed_point |
299 | } // namespace LIBC_NAMESPACE_DECL |
300 | |
301 | #endif // LIBC_COMPILER_HAS_FIXED_POINT |
302 | |
303 | #endif // LLVM_LIBC_SRC___SUPPORT_FIXED_POINT_FX_REP_H |
304 |
Warning: This file is not a C or C++ file. It does not have highlighting.