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