• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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