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