libfxd 0.2.dev
A fixed-point library for C++.
Loading...
Searching...
No Matches
except.hpp
Go to the documentation of this file.
1/*
2 * libfxd - a fixed-point library for C++
3 *
4 * Copyright 2023 Daniel K. O.
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef LIBFXD_EXCEPT_HPP
9#define LIBFXD_EXCEPT_HPP
10
11#include <concepts>
12#include <cstdlib>
13#include <stdexcept>
14
15#include "concepts.hpp"
16#include "error.hpp"
17
18#include "detail/safe.hpp"
19#include "detail/safe-div.hpp"
20#include "detail/safe-mul.hpp"
21
22
24namespace fxd::except {
25
26
36 [[noreturn]]
37 inline
38 void
40 {
41 switch (e) {
43 throw std::underflow_error{"underflow"};
44 case error::overflow:
45 throw std::overflow_error{"overflow"};
47 throw std::invalid_argument{"not a number"};
48 default:
49 throw std::logic_error{"unknown error"};
50 }
51 }
52
53
54#define WRAP(expr) \
55 do { \
56 auto result = detail::safe::expr; \
57 if (!result) \
58 except(result.error()); \
59 return *result; \
60 } while (false)
61
62
69 template<fixed_point Fxd,
70 std::integral I>
71 constexpr
72 Fxd
73 from_raw(I val)
74 {
75 WRAP(from_raw<Fxd>(val));
76 }
77
78
80 template<fixed_point Dst,
81 std::convertible_to<Dst> Src>
82 constexpr
83 Dst
84 make_fixed(Src src)
85 {
86 WRAP(make_fixed<Dst>(src));
87 }
88
89
91 template<int Int, int Frac,
92 typename Raw = detail::select_int_t<Int + Frac>,
93 std::convertible_to<fixed<Int, Frac, Raw>> Src>
94 constexpr
96 make_fixed(Src src)
97 {
98 using Dst = fixed<Int, Frac, Raw>;
99 return except::make_fixed<Dst>(src);
100 }
101
102
104 template<int Int, int Frac,
105 typename Raw = detail::select_uint_t<Int + Frac>,
106 std::convertible_to<fixed<Int, Frac, Raw>> Src>
107 constexpr
109 make_ufixed(Src src)
110 {
111 using Dst = fixed<Int, Frac, Raw>;
112 return except::make_fixed<Dst>(src);
113 }
114
115
117 template<fixed_point Dst,
118 fixed_point Src>
119 constexpr
120 Dst
121 fixed_cast(Src src)
122 {
123 WRAP(fixed_cast<Dst>(src));
124 }
125
126
128 template<int Int, int Frac,
129 typename Raw = detail::select_int_t<Int + Frac>,
130 fixed_point Src>
131 constexpr
133 fixed_cast(Src src)
134 {
135 using Dst = fixed<Int, Frac, Raw>;
136 return except::fixed_cast<Dst>(src);
137 }
138
139
141 template<int Int, int Frac,
142 typename Raw = detail::select_uint_t<Int + Frac>,
143 fixed_point Src>
144 constexpr
146 ufixed_cast(Src src)
147 {
148 using Dst = fixed<Int, Frac, Raw>;
149 return except::fixed_cast<Dst>(src);
150 }
151
152
154 template<std::integral I,
155 fixed_point Fxd>
156 I
157 to_int(Fxd f)
158 {
159 WRAP(to_int<I>(f));
160 }
161
162
164 template<fixed_point Fxd>
165 constexpr
166 detail::select_int_for<Fxd::int_bits, typename Fxd::raw_type>
167 to_int(Fxd f)
168 {
169 using I = detail::select_int_for<Fxd::int_bits, typename Fxd::raw_type>;
170 return except::to_int<I>(f);
171 }
172
173
175 template<fixed_point Dst,
176 std::convertible_to<Dst> Src>
177 constexpr
178 Dst&
179 assign(Dst& dst,
180 Src src)
181 {
182 return dst = except::make_fixed<Dst>(src);
183 }
184
185
187 template<fixed_point Fxd>
188 constexpr
189 Fxd&
190 pre_inc(Fxd& f)
191 {
192 auto result = detail::safe::incremented(f);
193 if (!result)
194 except(result.error());
195 return f = *result;
196 }
197
198
200 template<fixed_point Fxd>
201 constexpr
202 Fxd
203 post_inc(Fxd& f)
204 {
205 Fxd old_f = f;
207 return old_f;
208 }
209
210
212 template<fixed_point Fxd>
213 constexpr
214 Fxd&
215 pre_dec(Fxd& f)
216 {
217 auto result = detail::safe::decremented(f);
218 if (!result)
219 except(result.error());
220 return f = *result;
221 }
222
223
225 template<fixed_point Fxd>
226 constexpr
227 Fxd
228 post_dec(Fxd& f)
229 {
230 Fxd old_f = f;
232 return old_f;
233 }
234
235
237 template<fixed_point Fxd>
238 constexpr
239 Fxd
240 negate(Fxd f)
241 {
242 WRAP(negate(f));
243 }
244
245
247 template<fixed_point Fxd>
248 constexpr
249 Fxd
250 add(Fxd a,
251 Fxd b)
252 {
253 WRAP(add(a, b));
254 }
255
256
258 template<fixed_point Fxd>
259 constexpr
260 Fxd
261 sub(Fxd a,
262 Fxd b)
263 {
264 WRAP(sub(a, b));
265 }
266
267
269 namespace down {
270
272 template<fixed_point Fxd>
273 constexpr
274 Fxd
275 div(Fxd a,
276 Fxd b)
277 {
278 WRAP(down::div(a, b));
279 }
280
281
283 template<fixed_point Fxd>
284 constexpr
285 Fxd
286 mul(Fxd a,
287 Fxd b)
288 {
289 WRAP(down::mul(a, b));
290 }
291
292 } // namespace down
293
294
296 namespace up {
297
299 template<fixed_point Fxd>
300 constexpr
301 Fxd
302 div(Fxd a,
303 Fxd b)
304 {
305 WRAP(up::div(a, b));
306 }
307
308
310 template<fixed_point Fxd>
311 constexpr
312 Fxd
313 mul(Fxd a,
314 Fxd b)
315 {
316 WRAP(up::mul(a, b));
317 }
318
319 } // namespace up
320
321
323 inline
324 namespace zero {
325
327 template<fixed_point Fxd>
328 constexpr
329 Fxd
330 div(Fxd a,
331 Fxd b)
332 {
333 WRAP(zero::div(a, b));
334 }
335
336
338 template<fixed_point Fxd>
339 constexpr
340 Fxd
341 mul(Fxd a,
342 Fxd b)
343 {
344 WRAP(zero::mul(a, b));
345 }
346
347 } // namespace zero
348
349
351 template<fixed_point Fxd>
352 constexpr
353 Fxd
354 abs(Fxd f)
355 {
356 WRAP(abs(f));
357 }
358
359
360#undef WRAP
361
362
363} // namespace fxd::except
364
365
366#endif
Concept to match any fxd::fixed
Definition: concepts.hpp:19
#define WRAP(expr)
Definition: except.hpp:54
constexpr Fxd mul(Fxd a, Fxd b)
Multiply rounding down, throw on overflow.
Definition: except.hpp:286
constexpr Fxd div(Fxd a, Fxd b)
Divide rounding down, throw on overflow.
Definition: except.hpp:275
constexpr Fxd mul(Fxd a, Fxd b)
Multiply rounding up, throw on overflow.
Definition: except.hpp:313
constexpr Fxd div(Fxd a, Fxd b)
Divide rounding up, throw on overflow.
Definition: except.hpp:302
constexpr Fxd mul(Fxd a, Fxd b)
Multiply rounding to zero, throw on overflow.
Definition: except.hpp:341
constexpr Fxd div(Fxd a, Fxd b)
Divide rounding to zero, throw on overflow.
Definition: except.hpp:330
Throw on overflow.
Definition: except.hpp:24
constexpr Fxd abs(Fxd f)
Same as fxd::abs(), throw on overflow.
Definition: except.hpp:354
constexpr Fxd & pre_dec(Fxd &f)
Pre-decrement (--f), throw on overflow.
Definition: except.hpp:215
constexpr fixed< Int, Frac, Raw > ufixed_cast(Src src)
Convenience overload (unsigned version).
Definition: except.hpp:146
constexpr Fxd negate(Fxd f)
Negate, throw on overflow.
Definition: except.hpp:240
constexpr Fxd post_dec(Fxd &f)
Post-decrement (f--), throw on overflow.
Definition: except.hpp:228
constexpr Dst make_fixed(Src src)
Construct from numerical value, throw on overflow.
Definition: except.hpp:84
constexpr Fxd add(Fxd a, Fxd b)
Add, throw on overflow.
Definition: except.hpp:250
constexpr Dst & assign(Dst &dst, Src src)
Assignment, throw on overflow.
Definition: except.hpp:179
constexpr Fxd sub(Fxd a, Fxd b)
Subtract, throw on overflow.
Definition: except.hpp:261
void except(error e)
Error handler that throws exceptions on error.
Definition: except.hpp:39
constexpr Fxd from_raw(I val)
Construct from raw value, throw on overflow.
Definition: except.hpp:73
constexpr Fxd post_inc(Fxd &f)
Post-increment (f++), throw on overflow.
Definition: except.hpp:203
constexpr Fxd & pre_inc(Fxd &f)
Pre-increment (++f), throw on overflow.
Definition: except.hpp:190
constexpr fixed< Int, Frac, Raw > make_ufixed(Src src)
Convenience overload (unsigned version).
Definition: except.hpp:109
constexpr Dst fixed_cast(Src src) noexcept
Convert a fixed point to a different type of fixed point.
Definition: casting.hpp:28
constexpr I to_int(Fxd f) noexcept
Convert to integer.
Definition: conversions.hpp:45
error
Error values reported by fxd::expect function.
Definition: error.hpp:14
The fixed-point class template.
Definition: fixed.hpp:38