master
1/*-
2 * Copyright (c) 2018 Netflix, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * Data types and APIs for fixed-point math based on the "Q" number format.
29 *
30 * Author: Lawrence Stewart <lstewart@netflix.com>
31 *
32 * The 3 LSBs of all base data types are reserved for embedded control data:
33 * bits 1-2 specify the radix point shift index i.e. 00,01,10,11 == 1,2,3,4
34 * bit 3 specifies the radix point shift index multiplier as 2 (0) or 16 (1)
35 *
36 * This scheme can therefore represent Q numbers with [2,4,6,8,16,32,48,64] bits
37 * of precision after the binary radix point. The number of bits available for
38 * the integral component depends on the underlying storage type chosen.
39 */
40
41#ifndef _SYS_QMATH_H_
42#define _SYS_QMATH_H_
43
44#include <machine/_stdint.h>
45
46typedef int8_t s8q_t;
47typedef uint8_t u8q_t;
48typedef int16_t s16q_t;
49typedef uint16_t u16q_t;
50typedef int32_t s32q_t;
51typedef uint32_t u32q_t;
52typedef int64_t s64q_t;
53typedef uint64_t u64q_t;
54/* typedef int128_t s128q_t; Not yet */
55/* typedef uint128_t u128q_t; Not yet */
56typedef s64q_t smaxq_t;
57typedef u64q_t umaxq_t;
58
59#if defined(__GNUC__) && !defined(__clang__)
60/* Ancient GCC hack to de-const, remove when GCC4 is removed. */
61#define Q_BT(q) __typeof(1 * q)
62#else
63/* The underlying base type of 'q'. */
64#define Q_BT(q) __typeof(q)
65#endif
66
67/* Type-cast variable 'v' to the same underlying type as 'q'. */
68#define Q_TC(q, v) ((__typeof(q))(v))
69
70/* Number of total bits associated with the data type underlying 'q'. */
71#define Q_NTBITS(q) ((uint32_t)(sizeof(q) << 3))
72
73/* Number of LSBs reserved for control data. */
74#define Q_NCBITS ((uint32_t)3)
75
76/* Number of control-encoded bits reserved for fractional component data. */
77#define Q_NFCBITS(q) \
78 ((uint32_t)(((Q_GCRAW(q) & 0x3) + 1) << ((Q_GCRAW(q) & 0x4) ? 4 : 1)))
79
80/* Min/max number of bits that can be reserved for fractional component data. */
81#define Q_MINNFBITS(q) ((uint32_t)(2))
82#define Q_MAXNFBITS(q) ((uint32_t)(Q_NTBITS(q) - Q_SIGNED(q) - Q_NCBITS))
83
84/*
85 * Number of bits actually reserved for fractional component data. This can be
86 * less than the value returned by Q_NFCBITS() as we treat any excess
87 * control-encoded number of bits for the underlying data type as meaning all
88 * available bits are reserved for fractional component data i.e. zero int bits.
89 */
90#define Q_NFBITS(q) \
91 (Q_NFCBITS(q) > Q_MAXNFBITS(q) ? Q_MAXNFBITS(q) : Q_NFCBITS(q))
92
93/* Number of bits available for integer component data. */
94#define Q_NIBITS(q) ((uint32_t)(Q_NTBITS(q) - Q_RPSHFT(q) - Q_SIGNED(q)))
95
96/* The radix point offset relative to the LSB. */
97#define Q_RPSHFT(q) (Q_NCBITS + Q_NFBITS(q))
98
99/* The sign bit offset relative to the LSB. */
100#define Q_SIGNSHFT(q) (Q_NTBITS(q) - 1)
101
102/* Set the sign bit to 0 ('isneg' is F) or 1 ('isneg' is T). */
103#define Q_SSIGN(q, isneg) \
104 ((q) = ((Q_SIGNED(q) && (isneg)) ? (q) | (1ULL << Q_SIGNSHFT(q)) : \
105 (q) & ~(1ULL << Q_SIGNSHFT(q))))
106
107/* Manipulate the 'q' bits holding control/sign data. */
108#define Q_CRAWMASK(q) 0x7ULL
109#define Q_SRAWMASK(q) (1ULL << Q_SIGNSHFT(q))
110#define Q_GCRAW(q) ((q) & Q_CRAWMASK(q))
111#define Q_GCVAL(q) Q_GCRAW(q)
112#define Q_SCVAL(q, cv) ((q) = ((q) & ~Q_CRAWMASK(q)) | (cv))
113
114/* Manipulate the 'q' bits holding combined integer/fractional data. */
115#define Q_IFRAWMASK(q) \
116 Q_TC(q, Q_SIGNED(q) ? ~(Q_SRAWMASK(q) | Q_CRAWMASK(q)) : ~Q_CRAWMASK(q))
117#define Q_IFMAXVAL(q) Q_TC(q, Q_IFRAWMASK(q) >> Q_NCBITS)
118#define Q_IFMINVAL(q) Q_TC(q, Q_SIGNED(q) ? -Q_IFMAXVAL(q) : 0)
119#define Q_IFVALIMASK(q) Q_TC(q, ~Q_IFVALFMASK(q))
120#define Q_IFVALFMASK(q) Q_TC(q, (1ULL << Q_NFBITS(q)) - 1)
121#define Q_GIFRAW(q) Q_TC(q, (q) & Q_IFRAWMASK(q))
122#define Q_GIFABSVAL(q) Q_TC(q, Q_GIFRAW(q) >> Q_NCBITS)
123#define Q_GIFVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GIFABSVAL(q) : Q_GIFABSVAL(q))
124#define Q_SIFVAL(q, ifv) \
125 ((q) = ((q) & (~(Q_SRAWMASK(q) | Q_IFRAWMASK(q)))) | \
126 (Q_TC(q, Q_ABS(ifv)) << Q_NCBITS) | \
127 (Q_LTZ(ifv) ? 1ULL << Q_SIGNSHFT(q) : 0))
128#define Q_SIFVALS(q, iv, fv) \
129 ((q) = ((q) & (~(Q_SRAWMASK(q) | Q_IFRAWMASK(q)))) | \
130 (Q_TC(q, Q_ABS(iv)) << Q_RPSHFT(q)) | \
131 (Q_TC(q, Q_ABS(fv)) << Q_NCBITS) | \
132 (Q_LTZ(iv) || Q_LTZ(fv) ? 1ULL << Q_SIGNSHFT(q) : 0))
133
134/* Manipulate the 'q' bits holding integer data. */
135#define Q_IRAWMASK(q) Q_TC(q, Q_IFRAWMASK(q) & ~Q_FRAWMASK(q))
136#define Q_IMAXVAL(q) Q_TC(q, Q_IRAWMASK(q) >> Q_RPSHFT(q))
137#define Q_IMINVAL(q) Q_TC(q, Q_SIGNED(q) ? -Q_IMAXVAL(q) : 0)
138#define Q_GIRAW(q) Q_TC(q, (q) & Q_IRAWMASK(q))
139#define Q_GIABSVAL(q) Q_TC(q, Q_GIRAW(q) >> Q_RPSHFT(q))
140#define Q_GIVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GIABSVAL(q) : Q_GIABSVAL(q))
141#define Q_SIVAL(q, iv) \
142 ((q) = ((q) & ~(Q_SRAWMASK(q) | Q_IRAWMASK(q))) | \
143 (Q_TC(q, Q_ABS(iv)) << Q_RPSHFT(q)) | \
144 (Q_LTZ(iv) ? 1ULL << Q_SIGNSHFT(q) : 0))
145
146/* Manipulate the 'q' bits holding fractional data. */
147#define Q_FRAWMASK(q) Q_TC(q, ((1ULL << Q_NFBITS(q)) - 1) << Q_NCBITS)
148#define Q_FMAXVAL(q) Q_TC(q, Q_FRAWMASK(q) >> Q_NCBITS)
149#define Q_GFRAW(q) Q_TC(q, (q) & Q_FRAWMASK(q))
150#define Q_GFABSVAL(q) Q_TC(q, Q_GFRAW(q) >> Q_NCBITS)
151#define Q_GFVAL(q) Q_TC(q, Q_LTZ(q) ? -Q_GFABSVAL(q) : Q_GFABSVAL(q))
152#define Q_SFVAL(q, fv) \
153 ((q) = ((q) & ~(Q_SRAWMASK(q) | Q_FRAWMASK(q))) | \
154 (Q_TC(q, Q_ABS(fv)) << Q_NCBITS) | \
155 (Q_LTZ(fv) ? 1ULL << Q_SIGNSHFT(q) : 0))
156
157/*
158 * Calculate the number of bits required per 'base' digit, rounding up or down
159 * for non power-of-two bases.
160 */
161#define Q_BITSPERBASEDOWN(base) (flsll(base) - 1)
162#define Q_BITSPERBASEUP(base) (flsll(base) - (__builtin_popcountll(base) == 1))
163#define Q_BITSPERBASE(base, rnd) Q_BITSPERBASE##rnd(base)
164
165/*
166 * Upper bound number of digits required to render 'nbits' worth of integer
167 * component bits with numeric base 'base'. Overestimates for power-of-two
168 * bases.
169 */
170#define Q_NIBITS2NCHARS(nbits, base) \
171({ \
172 int _bitsperbase = Q_BITSPERBASE(base, DOWN); \
173 (((nbits) + _bitsperbase - 1) / _bitsperbase); \
174})
175
176#define Q_NFBITS2NCHARS(nbits, base) (nbits)
177
178/*
179 * Maximum number of chars required to render 'q' as a C-string of base 'base'.
180 * Includes space for sign, radix point and NUL-terminator.
181 */
182#define Q_MAXSTRLEN(q, base) \
183 (2 + Q_NIBITS2NCHARS(Q_NIBITS(q), base) + \
184 Q_NFBITS2NCHARS(Q_NFBITS(q), base) + Q_SIGNED(q))
185
186/* Yield the next char from integer bits. */
187#define Q_IBITS2CH(q, bits, base) \
188({ \
189 __typeof(bits) _tmp = (bits) / (base); \
190 int _idx = (bits) - (_tmp * (base)); \
191 (bits) = _tmp; \
192 "0123456789abcdef"[_idx]; \
193})
194
195/* Yield the next char from fractional bits. */
196#define Q_FBITS2CH(q, bits, base) \
197({ \
198 int _carry = 0, _idx, _nfbits = Q_NFBITS(q), _shift = 0; \
199 /* \
200 * Normalise enough MSBs to yield the next digit, multiply by the \
201 * base, and truncate residual fractional bits post multiplication. \
202 */ \
203 if (_nfbits > Q_BITSPERBASEUP(base)) { \
204 /* Break multiplication into two steps to ensure no overflow. */\
205 _shift = _nfbits >> 1; \
206 _carry = (((bits) & ((1ULL << _shift) - 1)) * (base)) >> _shift;\
207 } \
208 _idx = ((((bits) >> _shift) * (base)) + _carry) >> (_nfbits - _shift);\
209 (bits) *= (base); /* With _idx computed, no overflow concern. */ \
210 (bits) &= (1ULL << _nfbits) - 1; /* Exclude residual int bits. */ \
211 "0123456789abcdef"[_idx]; \
212})
213
214/*
215 * Render the C-string representation of 'q' into 's'. Returns a pointer to the
216 * final '\0' to allow for easy calculation of the rendered length and easy
217 * appending to the C-string.
218 */
219#define Q_TOSTR(q, prec, base, s, slen) \
220({ \
221 char *_r, *_s = s; \
222 int _i; \
223 if (Q_LTZ(q) && ((ptrdiff_t)(slen)) > 0) \
224 *_s++ = '-'; \
225 Q_BT(q) _part = Q_GIABSVAL(q); \
226 _r = _s; \
227 do { \
228 /* Render integer chars in reverse order. */ \
229 if ((_s - (s)) < ((ptrdiff_t)(slen))) \
230 *_s++ = Q_IBITS2CH(q, _part, base); \
231 else \
232 _r = NULL; \
233 } while (_part > 0 && _r != NULL); \
234 if (!((_s - (s)) < ((ptrdiff_t)(slen)))) \
235 _r = NULL; \
236 _i = (_s - _r) >> 1; /* N digits requires int(N/2) swaps. */ \
237 while (_i-- > 0 && _r != NULL) { \
238 /* Work from middle out to reverse integer chars. */ \
239 *_s = *(_r + _i); /* Stash LHS char temporarily. */ \
240 *(_r + _i) = *(_s - _i - 1); /* Copy RHS char to LHS. */\
241 *(_s - _i - 1) = *_s; /* Copy LHS char to RHS. */ \
242 } \
243 _i = (prec); \
244 if (_i != 0 && _r != NULL) { \
245 if ((_s - (s)) < ((ptrdiff_t)(slen))) \
246 *_s++ = '.'; \
247 else \
248 _r = NULL; \
249 _part = Q_GFABSVAL(q); \
250 if (_i < 0 || _i > (int)Q_NFBITS(q)) \
251 _i = Q_NFBITS(q); \
252 while (_i-- > 0 && _r != NULL) { \
253 /* Render fraction chars in correct order. */ \
254 if ((_s - (s)) < ((ptrdiff_t)(slen))) \
255 *_s++ = Q_FBITS2CH(q, _part, base); \
256 else \
257 _r = NULL; \
258 } \
259 } \
260 if ((_s - (s)) < ((ptrdiff_t)(slen)) && _r != NULL) \
261 *_s = '\0'; \
262 else { \
263 _r = NULL; \
264 if (((ptrdiff_t)(slen)) > 0) \
265 *(s) = '\0'; \
266 } \
267 /* Return a pointer to the '\0' or NULL on overflow. */ \
268 (_r != NULL ? _s : _r); \
269})
270
271/* Left shift an integral value to align with the int bits of 'q'. */
272#define Q_SHL(q, iv) \
273 (Q_LTZ(iv) ? -(int64_t)(Q_ABS(iv) << Q_NFBITS(q)) : \
274 Q_TC(q, iv) << Q_NFBITS(q))
275
276/* Calculate the relative fractional precision between 'a' and 'b' in bits. */
277#define Q_RELPREC(a, b) ((int)Q_NFBITS(a) - (int)Q_NFBITS(b))
278
279/*
280 * Determine control bits for the desired 'rpshft' radix point shift. Rounds up
281 * to the nearest valid shift supported by the encoding scheme.
282 */
283#define Q_CTRLINI(rpshft) \
284 (((rpshft) <= 8) ? (((rpshft) - 1) >> 1) : (0x4 | (((rpshft) - 1) >> 4)))
285
286/*
287 * Convert decimal fractional value 'dfv' to its binary-encoded representation
288 * with 'nfbits' of binary precision. 'dfv' must be passed as a preprocessor
289 * literal to preserve leading zeroes. The returned result can be used to set a
290 * Q number's fractional bits e.g. using Q_SFVAL().
291 */
292#define Q_DFV2BFV(dfv, nfbits) \
293({ \
294 uint64_t _bfv = 0, _thresh = 5, _tmp = dfv; \
295 int _i = sizeof(""#dfv) - 1; \
296 /* \
297 * Compute decimal threshold to determine which \
298 * conversion rounds will yield a binary 1. \
299 */ \
300 while (--_i > 0) {_thresh *= 10;} \
301 _i = (nfbits) - 1; \
302 while (_i >= 0) { \
303 if (_thresh <= _tmp) { \
304 _bfv |= 1ULL << _i; \
305 _tmp = _tmp - _thresh; \
306 } \
307 _i--; _tmp <<= 1; \
308 } \
309 _bfv; \
310})
311
312/*
313 * Initialise 'q' with raw integer value 'iv', decimal fractional value 'dfv',
314 * and radix point shift 'rpshft'. Must be done in two steps in case 'iv'
315 * depends on control bits being set e.g. when passing Q_INTMAX(q) as 'iv'.
316 */
317#define Q_INI(q, iv, dfv, rpshft) \
318({ \
319 (*(q)) = Q_CTRLINI(rpshft); \
320 Q_SIFVALS(*(q), iv, Q_DFV2BFV(dfv, Q_NFBITS(*(q)))); \
321})
322
323/* Test if 'a' and 'b' fractional precision is the same (T) or not (F). */
324#define Q_PRECEQ(a, b) (Q_NFBITS(a) == Q_NFBITS(b))
325
326/* Test if 'n' is a signed type (T) or not (F). Works with any numeric type. */
327#define Q_SIGNED(n) (Q_TC(n, -1) < 0)
328
329/*
330 * Test if 'n' is negative. Works with any numeric type that uses the MSB as the
331 * sign bit, and also works with Q numbers.
332 */
333#define Q_LTZ(n) (Q_SIGNED(n) && ((n) & Q_SRAWMASK(n)))
334
335/*
336 * Return absolute value of 'n'. Works with any standard numeric type that uses
337 * the MSB as the sign bit, and is signed/unsigned type safe.
338 * Does not work with Q numbers; use Q_QABS() instead.
339 */
340#define Q_ABS(n) (Q_LTZ(n) ? -(n) : (n))
341
342/*
343 * Return an absolute value interpretation of 'q'.
344 */
345#define Q_QABS(q) (Q_SIGNED(q) ? (q) & ~Q_SRAWMASK(q) : (q))
346
347/* Convert 'q' to float or double representation. */
348#define Q_Q2F(q) ((float)Q_GIFVAL(q) / (float)(1ULL << Q_NFBITS(q)))
349#define Q_Q2D(q) ((double)Q_GIFVAL(q) / (double)(1ULL << Q_NFBITS(q)))
350
351/* Numerically compare 'a' and 'b' as whole numbers using provided operators. */
352#define Q_QCMPQ(a, b, intcmp, fraccmp) \
353 ((Q_GIVAL(a) intcmp Q_GIVAL(b)) || \
354 ((Q_GIVAL(a) == Q_GIVAL(b)) && (Q_GFVAL(a) fraccmp Q_GFVAL(b))))
355
356/* Test if 'a' is numerically less than 'b' (T) or not (F). */
357#define Q_QLTQ(a, b) Q_QCMPQ(a, b, <, <)
358
359/* Test if 'a' is numerically less than or equal to 'b' (T) or not (F). */
360#define Q_QLEQ(a, b) Q_QCMPQ(a, b, <, <=)
361
362/* Test if 'a' is numerically greater than 'b' (T) or not (F). */
363#define Q_QGTQ(a, b) Q_QCMPQ(a, b, >, >)
364
365/* Test if 'a' is numerically greater than or equal to 'b' (T) or not (F). */
366#define Q_QGEQ(a, b) Q_QCMPQ(a, b, >, >=)
367
368/* Test if 'a' is numerically equal to 'b' (T) or not (F). */
369#define Q_QEQ(a, b) Q_QCMPQ(a, b, ==, ==)
370
371/* Test if 'a' is numerically not equal to 'b' (T) or not (F). */
372#define Q_QNEQ(a, b) Q_QCMPQ(a, b, !=, !=)
373
374/* Returns the numerically larger of 'a' and 'b'. */
375#define Q_QMAXQ(a, b) (Q_GT(a, b) ? (a) : (b))
376
377/* Returns the numerically smaller of 'a' and 'b'. */
378#define Q_QMINQ(a, b) (Q_LT(a, b) ? (a) : (b))
379
380/*
381 * Test if 'a' can be represented by 'b' with full accuracy (T) or not (F).
382 * The type casting has to be done to a's type so that any truncation caused by
383 * the casts will not affect the logic.
384 */
385#define Q_QCANREPQ(a, b) \
386 ((((Q_LTZ(a) && Q_SIGNED(b)) || !Q_LTZ(a)) && \
387 Q_GIABSVAL(a) <= Q_TC(a, Q_IMAXVAL(b)) && \
388 Q_GFABSVAL(a) <= Q_TC(a, Q_FMAXVAL(b))) ? \
389 0 : EOVERFLOW)
390
391/* Test if raw integer value 'i' can be represented by 'q' (T) or not (F). */
392#define Q_QCANREPI(q, i) \
393 ((((Q_LTZ(i) && Q_SIGNED(q)) || !Q_LTZ(i)) && \
394 Q_ABS(i) <= Q_TC(i, Q_IMAXVAL(q))) ? 0 : EOVERFLOW)
395
396/*
397 * Returns a Q variable debug format string with appropriate modifiers and
398 * padding relevant to the underlying Q data type.
399 */
400#define Q_DEBUGFMT_(prefmt, postfmt, mod, hexpad) \
401 prefmt \
402 /* Var name + address. */ \
403 "\"%s\"@%p" \
404 /* Data type. */ \
405 "\n\ttype=%c%dq_t, " \
406 /* Qm.n notation; 'm' = # int bits, 'n' = # frac bits. */ \
407 "Qm.n=Q%d.%d, " \
408 /* Radix point shift relative to the underlying data type's LSB. */ \
409 "rpshft=%d, " \
410 /* Min/max integer values which can be represented. */ \
411 "imin=0x%0" #mod "x, " \
412 "imax=0x%0" #mod "x" \
413 /* Raw hex dump of all bits. */ \
414 "\n\tqraw=0x%0" #hexpad #mod "x" \
415 /* Bit masks for int/frac/ctrl bits. */ \
416 "\n\timask=0x%0" #hexpad #mod "x, " \
417 "fmask=0x%0" #hexpad #mod "x, " \
418 "cmask=0x%0" #hexpad #mod "x, " \
419 "ifmask=0x%0" #hexpad #mod "x" \
420 /* Hex dump of masked int bits; 'iraw' includes shift */ \
421 "\n\tiraw=0x%0" #hexpad #mod "x, " \
422 "iabsval=0x%" #mod "x, " \
423 "ival=0x%" #mod "x" \
424 /* Hex dump of masked frac bits; 'fraw' includes shift */ \
425 "\n\tfraw=0x%0" #hexpad #mod "x, " \
426 "fabsval=0x%" #mod "x, " \
427 "fval=0x%" #mod "x" \
428 "%s" \
429 postfmt
430
431#define Q_DEBUGFMT(q, prefmt, postfmt) \
432 sizeof(q) == 8 ? Q_DEBUGFMT_(prefmt, postfmt, j, 16) : \
433 sizeof(q) == 4 ? Q_DEBUGFMT_(prefmt, postfmt, , 8) : \
434 sizeof(q) == 2 ? Q_DEBUGFMT_(prefmt, postfmt, h, 4) : \
435 sizeof(q) == 1 ? Q_DEBUGFMT_(prefmt, postfmt, hh, 2) : \
436 prefmt "\"%s\"@%p: invalid" postfmt \
437
438/*
439 * Returns a format string and data suitable for printf-like rendering
440 * e.g. Print to console with a trailing newline: printf(Q_DEBUG(q, "", "\n"));
441 */
442#define Q_DEBUG(q, prefmt, postfmt, incfmt) \
443 Q_DEBUGFMT(q, prefmt, postfmt) \
444 , #q \
445 , &(q) \
446 , Q_SIGNED(q) ? 's' : 'u' \
447 , Q_NTBITS(q) \
448 , Q_NIBITS(q) \
449 , Q_NFBITS(q) \
450 , Q_RPSHFT(q) \
451 , Q_IMINVAL(q) \
452 , Q_IMAXVAL(q) \
453 , (q) \
454 , Q_IRAWMASK(q) \
455 , Q_FRAWMASK(q) \
456 , Q_TC(q, Q_CRAWMASK(q)) \
457 , Q_IFRAWMASK(q) \
458 , Q_GIRAW(q) \
459 , Q_GIABSVAL(q) \
460 , Q_GIVAL(q) \
461 , Q_GFRAW(q) \
462 , Q_GFABSVAL(q) \
463 , Q_GFVAL(q) \
464 , (incfmt) ? Q_DEBUGFMT(q, "\nfmt:", "") : "" \
465
466/*
467 * If precision differs, attempt to normalise to the greater precision that
468 * preserves the integer component of both 'a' and 'b'.
469 */
470#define Q_NORMPREC(a, b) \
471({ \
472 int _perr = 0, _relprec = Q_RELPREC(*(a), b); \
473 if (_relprec != 0) \
474 _perr = ERANGE; /* XXXLAS: Do precision normalisation! */\
475 _perr; \
476})
477
478/* Clone r's control bits and int/frac value into 'l'. */
479#define Q_QCLONEQ(l, r) \
480({ \
481 Q_BT(*(l)) _l = Q_GCVAL(r); \
482 int _err = Q_QCANREPQ(r, _l); \
483 if (!_err) { \
484 *(l) = _l; \
485 Q_SIFVAL(*(l), Q_GIFVAL(r)); \
486 } \
487 _err; \
488})
489
490/* Copy r's int/frac vals into 'l', retaining 'l's precision and signedness. */
491#define Q_QCPYVALQ(l, r) \
492({ \
493 int _err = Q_QCANREPQ(r, *(l)); \
494 if (!_err) \
495 Q_SIFVALS(*(l), Q_GIVAL(r), Q_GFVAL(r)); \
496 _err; \
497})
498
499#define Q_QADDSUBQ(a, b, eop) \
500({ \
501 int _aserr; \
502 if ((_aserr = Q_NORMPREC(a, b))) while (0); /* NOP */ \
503 else if ((eop) == '+') { \
504 if (Q_IFMAXVAL(*(a)) - Q_GIFABSVAL(b) < Q_GIFVAL(*(a))) \
505 _aserr = EOVERFLOW; /* [+/-a + +b] > max(a) */ \
506 else \
507 Q_SIFVAL(*(a), Q_GIFVAL(*(a)) + Q_TC(*(a), \
508 Q_GIFABSVAL(b))); \
509 } else { /* eop == '-' */ \
510 if (Q_IFMINVAL(*(a)) + Q_GIFABSVAL(b) > Q_GIFVAL(*(a))) \
511 _aserr = EOVERFLOW; /* [+/-a - +b] < min(a) */ \
512 else \
513 Q_SIFVAL(*(a), Q_GIFVAL(*(a)) - Q_TC(*(a), \
514 Q_GIFABSVAL(b))); \
515 } \
516 _aserr; \
517})
518#define Q_QADDQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '-' : '+'))
519#define Q_QSUBQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '+' : '-'))
520
521#define Q_QDIVQ(a, b) \
522({ \
523 int _err; \
524 if ((_err = Q_NORMPREC(a, b))) while (0); /* NOP */ \
525 else if (Q_GIFABSVAL(b) == 0 || (!Q_SIGNED(*(a)) && Q_LTZ(b))) \
526 _err = EINVAL; /* Divide by zero or cannot represent. */\
527 /* XXXLAS: Handle overflow. */ \
528 else if (Q_GIFABSVAL(*(a)) != 0) { /* Result expected. */ \
529 Q_SIFVAL(*(a), \
530 ((Q_GIVAL(*(a)) << Q_NFBITS(*(a))) / Q_GIFVAL(b)) + \
531 (Q_GFVAL(b) == 0 ? 0 : \
532 ((Q_GFVAL(*(a)) << Q_NFBITS(*(a))) / Q_GFVAL(b)))); \
533 } \
534 _err; \
535})
536
537#define Q_QMULQ(a, b) \
538({ \
539 int _mulerr; \
540 if ((_mulerr = Q_NORMPREC(a, b))) while (0); /* NOP */ \
541 else if (!Q_SIGNED(*(a)) && Q_LTZ(b)) \
542 _mulerr = EINVAL; \
543 else if (Q_GIFABSVAL(b) != 0 && \
544 Q_IFMAXVAL(*(a)) / Q_GIFABSVAL(b) < Q_GIFABSVAL(*(a))) \
545 _mulerr = EOVERFLOW; \
546 else \
547 Q_SIFVAL(*(a), (Q_GIFVAL(*(a)) * Q_GIFVAL(b)) >> \
548 Q_NFBITS(*(a))); \
549 _mulerr; \
550})
551
552#define Q_QCPYVALI(q, i) \
553({ \
554 int _err = Q_QCANREPI(*(q), i); \
555 if (!_err) \
556 Q_SIFVAL(*(q), Q_SHL(*(q), i)); \
557 _err; \
558})
559
560#define Q_QADDSUBI(q, i, eop) \
561({ \
562 int _aserr = 0; \
563 if (Q_NTBITS(*(q)) < (uint32_t)flsll(Q_ABS(i))) \
564 _aserr = EOVERFLOW; /* i cannot fit in q's type. */ \
565 else if ((eop) == '+') { \
566 if (Q_IMAXVAL(*(q)) - Q_TC(*(q), Q_ABS(i)) < \
567 Q_GIVAL(*(q))) \
568 _aserr = EOVERFLOW; /* [+/-q + +i] > max(q) */ \
569 else \
570 Q_SIFVAL(*(q), Q_GIFVAL(*(q)) + \
571 Q_SHL(*(q), Q_ABS(i))); \
572 } else { /* eop == '-' */ \
573 if (Q_IMINVAL(*(q)) + Q_ABS(i) > Q_GIVAL(*(q))) \
574 _aserr = EOVERFLOW; /* [+/-q - +i] < min(q) */ \
575 else \
576 Q_SIFVAL(*(q), Q_GIFVAL(*(q)) - \
577 Q_SHL(*(q), Q_ABS(i))); \
578 } \
579 _aserr; \
580})
581#define Q_QADDI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '-' : '+'))
582#define Q_QSUBI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '+' : '-'))
583
584#define Q_QDIVI(q, i) \
585({ \
586 int _diverr = 0; \
587 if ((i) == 0 || (!Q_SIGNED(*(q)) && Q_LTZ(i))) \
588 _diverr = EINVAL; /* Divide by zero or cannot represent. */\
589 else if (Q_GIFABSVAL(*(q)) != 0) { /* Result expected. */ \
590 Q_SIFVAL(*(q), Q_GIFVAL(*(q)) / Q_TC(*(q), i)); \
591 if (Q_GIFABSVAL(*(q)) == 0) \
592 _diverr = ERANGE; /* q underflow. */ \
593 } \
594 _diverr; \
595})
596
597#define Q_QMULI(q, i) \
598({ \
599 int _mulerr = 0; \
600 if (!Q_SIGNED(*(q)) && Q_LTZ(i)) \
601 _mulerr = EINVAL; /* Cannot represent. */ \
602 else if ((i) != 0 && Q_IFMAXVAL(*(q)) / Q_TC(*(q), Q_ABS(i)) < \
603 Q_GIFABSVAL(*(q))) \
604 _mulerr = EOVERFLOW; \
605 else \
606 Q_SIFVAL(*(q), Q_GIFVAL(*(q)) * Q_TC(*(q), i)); \
607 _mulerr; \
608})
609
610#define Q_QFRACI(q, in, id) \
611({ \
612 uint64_t _tmp; \
613 int _err = 0; \
614 if ((id) == 0) \
615 _err = EINVAL; /* Divide by zero. */ \
616 else if ((in) == 0) \
617 Q_SIFVAL(*(q), in); \
618 else if ((_tmp = Q_ABS(in)) > (UINT64_MAX >> Q_RPSHFT(*(q)))) \
619 _err = EOVERFLOW; /* _tmp overflow. */ \
620 else { \
621 _tmp = Q_SHL(*(q), _tmp) / Q_ABS(id); \
622 if (Q_QCANREPI(*(q), _tmp & Q_IFVALIMASK(*(q)))) \
623 _err = EOVERFLOW; /* q overflow. */ \
624 else { \
625 Q_SIFVAL(*(q), _tmp); \
626 Q_SSIGN(*(q), (Q_LTZ(in) && !Q_LTZ(id)) || \
627 (!Q_LTZ(in) && Q_LTZ(id))); \
628 if (_tmp == 0) \
629 _err = ERANGE; /* q underflow. */ \
630 } \
631 } \
632 _err; \
633})
634
635#endif /* _SYS_QMATH_H_ */