xref: /f-stack/freebsd/sys/qmath.h (revision 22ce4aff)
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