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
20namespace LIBC_NAMESPACE::fixed_point {
21
22namespace internal {
23
24template <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
36template <typename T> struct FXRep;
37
38template <> 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
58template <> 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
78template <> 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
98template <> 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
118template <> 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
138template <> 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
158template <> 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
178template <> 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
198template <> 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
218template <> 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
238template <> 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
258template <> 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
278template <> struct FXRep<short sat fract> : FXRep<short fract> {};
279template <> struct FXRep<sat fract> : FXRep<fract> {};
280template <> struct FXRep<long sat fract> : FXRep<long fract> {};
281template <>
282struct FXRep<unsigned short sat fract> : FXRep<unsigned short fract> {};
283template <> struct FXRep<unsigned sat fract> : FXRep<unsigned fract> {};
284template <>
285struct FXRep<unsigned long sat fract> : FXRep<unsigned long fract> {};
286
287template <> struct FXRep<short sat accum> : FXRep<short accum> {};
288template <> struct FXRep<sat accum> : FXRep<accum> {};
289template <> struct FXRep<long sat accum> : FXRep<long accum> {};
290template <>
291struct FXRep<unsigned short sat accum> : FXRep<unsigned short accum> {};
292template <> struct FXRep<unsigned sat accum> : FXRep<unsigned accum> {};
293template <>
294struct 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

source code of libc/src/__support/fixed_point/fx_rep.h