xref: /aosp_15_r20/external/llvm-libc/src/__support/fixed_point/fx_rep.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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 TOTAL_LEN =
47       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
67       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
87       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
107       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
127       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
147       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
167       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
187       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
207       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
227       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
247       SIGN_LEN + INTEGRAL_LEN + FRACTION_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 TOTAL_LEN =
267       SIGN_LEN + INTEGRAL_LEN + FRACTION_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