| 1 | /*- |
| 2 | * Copyright (c) 2018-2024 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 | |
| 46 | typedef int8_t		s8q_t; |
| 47 | typedef uint8_t		u8q_t; |
| 48 | typedef int16_t		s16q_t; |
| 49 | typedef uint16_t	u16q_t; |
| 50 | typedef int32_t		s32q_t; |
| 51 | typedef uint32_t	u32q_t; |
| 52 | typedef int64_t		s64q_t; |
| 53 | typedef uint64_t	u64q_t; |
| 54 | /* typedef int128_t	s128q_t; Not yet */ |
| 55 | /* typedef uint128_t	u128q_t; Not yet */ |
| 56 | typedef	s64q_t		smaxq_t; |
| 57 | typedef	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 (0) or not |
| 382 | * (EOVERFLOW). If 'b' has fewer integer and/or fractional bits than 'a', |
| 383 | * the integer and fractional values stored in 'a' must fit in the available |
| 384 | * number of integer and fractional bits in 'b'. |
| 385 | */ |
| 386 | #define	Q_QCANREPQ(a, b) (( \ |
| 387 | (!Q_LTZ(a) || Q_SIGNED(b)) \ |
| 388 | && ( Q_NIBITS(a) <= Q_NIBITS(b) \ |
| 389 | || 0 == (Q_GIABSVAL(a) & (~Q_TC(a, 0) << Q_NIBITS(b)))) \ |
| 390 | && ( Q_NFBITS(a) <= Q_NFBITS(b) \ |
| 391 | || 0 == (Q_GFABSVAL(a) & ~(~Q_TC(a, 0) << (Q_NFBITS(a) - Q_NFBITS(b))))) \ |
| 392 | ) ? 0 : EOVERFLOW) |
| 393 | |
| 394 | /* Test if raw integer value 'i' can be represented by 'q' (T) or not (F). */ |
| 395 | #define	Q_QCANREPI(q, i) \ |
| 396 | ((((Q_LTZ(i) && Q_SIGNED(q)) || !Q_LTZ(i)) && \ |
| 397 | Q_ABS(i) <= Q_TC(i, Q_IMAXVAL(q))) ? 0 : EOVERFLOW) |
| 398 | |
| 399 | /* |
| 400 | * Returns a Q variable debug format string with appropriate modifiers and |
| 401 | * padding relevant to the underlying Q data type. |
| 402 | */ |
| 403 | #define	Q_DEBUGFMT_(prefmt, postfmt, mod, hexpad)			\ |
| 404 | prefmt								\ |
| 405 | /* Var name + address. */						\ |
| 406 | "\"%s\"@%p"								\ |
| 407 | /* Data type. */							\ |
| 408 | "\n\ttype=%c%dq_t, "						\ |
| 409 | /* Qm.n notation; 'm' = # int bits, 'n' = # frac bits. */		\ |
| 410 | "Qm.n=Q%d.%d, "							\ |
| 411 | /* Radix point shift relative to the underlying data type's LSB. */	\ |
| 412 | "rpshft=%d, "							\ |
| 413 | /* Min/max integer values which can be represented. */		\ |
| 414 | "imin=0x%0" #mod "x, "						\ |
| 415 | "imax=0x%0" #mod "x"						\ |
| 416 | /* Raw hex dump of all bits. */					\ |
| 417 | "\n\tqraw=0x%0" #hexpad #mod "x"					\ |
| 418 | /* Bit masks for int/frac/ctrl bits. */				\ |
| 419 | "\n\timask=0x%0" #hexpad #mod "x, "					\ |
| 420 | "fmask=0x%0" #hexpad #mod "x, "					\ |
| 421 | "cmask=0x%0" #hexpad #mod "x, "					\ |
| 422 | "ifmask=0x%0" #hexpad #mod "x"					\ |
| 423 | /* Hex dump of masked int bits; 'iraw' includes shift */		\ |
| 424 | "\n\tiraw=0x%0" #hexpad #mod "x, "					\ |
| 425 | "iabsval=0x%" #mod "x, "						\ |
| 426 | "ival=0x%" #mod "x"					\ |
| 427 | /* Hex dump of masked frac bits; 'fraw' includes shift */		\ |
| 428 | "\n\tfraw=0x%0" #hexpad #mod "x, "					\ |
| 429 | "fabsval=0x%" #mod "x, "						\ |
| 430 | "fval=0x%" #mod "x"							\ |
| 431 | "%s"								\ |
| 432 | postfmt |
| 433 | |
| 434 | #define	Q_DEBUGFMT(q, prefmt, postfmt)					\ |
| 435 | sizeof(q) == 8 ? Q_DEBUGFMT_(prefmt, postfmt, j, 16)	:	\ |
| 436 | sizeof(q) == 4 ? Q_DEBUGFMT_(prefmt, postfmt, , 8)	:	\ |
| 437 | sizeof(q) == 2 ? Q_DEBUGFMT_(prefmt, postfmt, h, 4)	:	\ |
| 438 | sizeof(q) == 1 ? Q_DEBUGFMT_(prefmt, postfmt, hh, 2)	:	\ |
| 439 | prefmt "\"%s\"@%p: invalid" postfmt				\ |
| 440 | |
| 441 | /* |
| 442 | * Returns a format string and data suitable for printf-like rendering |
| 443 | * e.g. Print to console with a trailing newline: printf(Q_DEBUG(q, "", "\n")); |
| 444 | */ |
| 445 | #define	Q_DEBUG(q, prefmt, postfmt, incfmt)				\ |
| 446 | Q_DEBUGFMT(q, prefmt, postfmt)					\ |
| 447 | , #q								\ |
| 448 | , &(q)								\ |
| 449 | , Q_SIGNED(q) ? 's' : 'u'						\ |
| 450 | , Q_NTBITS(q)							\ |
| 451 | , Q_NIBITS(q)							\ |
| 452 | , Q_NFBITS(q)							\ |
| 453 | , Q_RPSHFT(q)							\ |
| 454 | , Q_IMINVAL(q)							\ |
| 455 | , Q_IMAXVAL(q)							\ |
| 456 | , (q)								\ |
| 457 | , Q_IRAWMASK(q)							\ |
| 458 | , Q_FRAWMASK(q)							\ |
| 459 | , Q_TC(q, Q_CRAWMASK(q))						\ |
| 460 | , Q_IFRAWMASK(q)							\ |
| 461 | , Q_GIRAW(q)							\ |
| 462 | , Q_GIABSVAL(q)							\ |
| 463 | , Q_GIVAL(q)							\ |
| 464 | , Q_GFRAW(q)							\ |
| 465 | , Q_GFABSVAL(q)							\ |
| 466 | , Q_GFVAL(q)							\ |
| 467 | , (incfmt) ? Q_DEBUGFMT(q, "\nfmt:", "") : ""			\ |
| 468 | |
| 469 | /* |
| 470 | * If precision differs, attempt to normalise to the greater precision that |
| 471 | * preserves the integer component of both 'a' and 'b'. |
| 472 | */ |
| 473 | #define	Q_NORMPREC(a, b)						\ |
| 474 | ({									\ |
| 475 | 	int _perr = 0, _relprec = Q_RELPREC(*(a), b);			\ |
| 476 | 	if (_relprec != 0)						\ |
| 477 | 		_perr = ERANGE; /* XXXLAS: Do precision normalisation! */\ |
| 478 | 	_perr;								\ |
| 479 | }) |
| 480 | |
| 481 | /* Clone r's control bits and int/frac value into 'l'. */ |
| 482 | #define	Q_QCLONEQ(l, r)							\ |
| 483 | ({									\ |
| 484 | 	Q_BT(*(l)) _l = Q_GCVAL(r);					\ |
| 485 | 	int _err = Q_QCANREPQ(r, _l);					\ |
| 486 | 	if (!_err) {							\ |
| 487 | 		*(l) = _l;						\ |
| 488 | 		Q_SIFVAL(*(l), Q_GIFVAL(r));				\ |
| 489 | 	}								\ |
| 490 | 	_err;								\ |
| 491 | }) |
| 492 | |
| 493 | /* Copy r's int/frac vals into 'l', retaining 'l's precision and signedness. */ |
| 494 | #define	Q_QCPYVALQ(l, r)						\ |
| 495 | ({									\ |
| 496 | 	int _err = Q_QCANREPQ(r, *(l));					\ |
| 497 | 	if (!_err)							\ |
| 498 | 		Q_SIFVALS(*(l), Q_GIVAL(r), Q_GFVAL(r));		\ |
| 499 | 	_err;								\ |
| 500 | }) |
| 501 | |
| 502 | #define	Q_QADDSUBQ(a, b, eop)						\ |
| 503 | ({									\ |
| 504 | 	int _aserr;							\ |
| 505 | 	if ((_aserr = Q_NORMPREC(a, b))) while (0); /* NOP */		\ |
| 506 | 	else if ((eop) == '+') {					\ |
| 507 | 		if (Q_IFMAXVAL(*(a)) - Q_GIFABSVAL(b) < Q_GIFVAL(*(a)))	\ |
| 508 | 			_aserr = EOVERFLOW; /* [+/-a + +b] > max(a) */	\ |
| 509 | 		else							\ |
| 510 | 			Q_SIFVAL(*(a), Q_GIFVAL(*(a)) + Q_TC(*(a),	\ |
| 511 | 			 Q_GIFABSVAL(b)));				\ |
| 512 | 	} else { /* eop == '-' */					\ |
| 513 | 		if (Q_IFMINVAL(*(a)) + Q_GIFABSVAL(b) > Q_GIFVAL(*(a)))	\ |
| 514 | 			_aserr = EOVERFLOW; /* [+/-a - +b] < min(a) */	\ |
| 515 | 		else							\ |
| 516 | 			Q_SIFVAL(*(a), Q_GIFVAL(*(a)) - Q_TC(*(a),	\ |
| 517 | 			 Q_GIFABSVAL(b)));				\ |
| 518 | 	}								\ |
| 519 | 	_aserr;								\ |
| 520 | }) |
| 521 | #define	Q_QADDQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '-' : '+')) |
| 522 | #define	Q_QSUBQ(a, b) Q_QADDSUBQ(a, b, (Q_LTZ(b) ? '+' : '-')) |
| 523 | |
| 524 | #define	Q_QDIVQ(a, b)							\ |
| 525 | ({									\ |
| 526 | 	int _err;							\ |
| 527 | 	if ((_err = Q_NORMPREC(a, b))) while (0); /* NOP */		\ |
| 528 | 	else if (Q_GIFABSVAL(b) == 0 || (!Q_SIGNED(*(a)) && Q_LTZ(b)))	\ |
| 529 | 		_err = EINVAL; /* Divide by zero or cannot represent. */\ |
| 530 | 	/* XXXLAS: Handle overflow. */					\ |
| 531 | 	else if (Q_GIFABSVAL(*(a)) != 0) { /* Result expected. */	\ |
| 532 | 		Q_SIFVAL(*(a),						\ |
| 533 | 		 ((Q_GIVAL(*(a)) << Q_NFBITS(*(a))) / Q_GIFVAL(b)) +	\ |
| 534 | 		 (Q_GFVAL(b) == 0 ? 0 :				\ |
| 535 | 		 ((Q_GFVAL(*(a)) << Q_NFBITS(*(a))) / Q_GFVAL(b))));	\ |
| 536 | 	}								\ |
| 537 | 	_err;								\ |
| 538 | }) |
| 539 | |
| 540 | #define	Q_QMULQ(a, b)							\ |
| 541 | ({									\ |
| 542 | 	int _mulerr;							\ |
| 543 | 	if ((_mulerr = Q_NORMPREC(a, b))) while (0); /* NOP */		\ |
| 544 | 	else if (!Q_SIGNED(*(a)) && Q_LTZ(b))				\ |
| 545 | 		_mulerr = EINVAL;					\ |
| 546 | 	else if (Q_GIFABSVAL(b) != 0 &&					\ |
| 547 | 	 Q_IFMAXVAL(*(a)) / Q_GIFABSVAL(b) < Q_GIFABSVAL(*(a)))	\ |
| 548 | 		_mulerr = EOVERFLOW;					\ |
| 549 | 	else								\ |
| 550 | 		Q_SIFVAL(*(a), (Q_GIFVAL(*(a)) * Q_GIFVAL(b)) >>	\ |
| 551 | 		 Q_NFBITS(*(a)));					\ |
| 552 | 	_mulerr;							\ |
| 553 | }) |
| 554 | |
| 555 | #define	Q_QCPYVALI(q, i)						\ |
| 556 | ({									\ |
| 557 | 	int _err = Q_QCANREPI(*(q), i);					\ |
| 558 | 	if (!_err)							\ |
| 559 | 		Q_SIFVAL(*(q), Q_SHL(*(q), i));				\ |
| 560 | 	_err;								\ |
| 561 | }) |
| 562 | |
| 563 | #define	Q_QADDSUBI(q, i, eop)						\ |
| 564 | ({									\ |
| 565 | 	int _aserr = 0;							\ |
| 566 | 	if (Q_NTBITS(*(q)) < (uint32_t)flsll(Q_ABS(i)))			\ |
| 567 | 		_aserr = EOVERFLOW; /* i cannot fit in q's type. */	\ |
| 568 | 	else if ((eop) == '+') {					\ |
| 569 | 		if (Q_IMAXVAL(*(q)) - Q_TC(*(q), Q_ABS(i)) <		\ |
| 570 | 		 Q_GIVAL(*(q)))					\ |
| 571 | 			_aserr = EOVERFLOW; /* [+/-q + +i] > max(q) */	\ |
| 572 | 		else							\ |
| 573 | 			Q_SIFVAL(*(q), Q_GIFVAL(*(q)) +			\ |
| 574 | 			 Q_SHL(*(q), Q_ABS(i)));			\ |
| 575 | 	} else { /* eop == '-' */					\ |
| 576 | 		if (Q_IMINVAL(*(q)) + Q_ABS(i) > Q_GIVAL(*(q)))		\ |
| 577 | 			_aserr = EOVERFLOW; /* [+/-q - +i] < min(q) */	\ |
| 578 | 		else							\ |
| 579 | 			Q_SIFVAL(*(q), Q_GIFVAL(*(q)) -			\ |
| 580 | 			 Q_SHL(*(q), Q_ABS(i)));			\ |
| 581 | 	}								\ |
| 582 | 	_aserr;								\ |
| 583 | }) |
| 584 | #define	Q_QADDI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '-' : '+')) |
| 585 | #define	Q_QSUBI(q, i) Q_QADDSUBI(q, i, (Q_LTZ(i) ? '+' : '-')) |
| 586 | |
| 587 | #define	Q_QDIVI(q, i)							\ |
| 588 | ({									\ |
| 589 | 	int _diverr = 0;						\ |
| 590 | 	if ((i) == 0 || (!Q_SIGNED(*(q)) && Q_LTZ(i)))			\ |
| 591 | 		_diverr = EINVAL; /* Divide by zero or cannot represent. */\ |
| 592 | 	else if (Q_GIFABSVAL(*(q)) != 0) { /* Result expected. */	\ |
| 593 | 		Q_SIFVAL(*(q), Q_GIFVAL(*(q)) / Q_TC(*(q), i));		\ |
| 594 | 		if (Q_GIFABSVAL(*(q)) == 0)				\ |
| 595 | 			_diverr = ERANGE; /* q underflow. */		\ |
| 596 | 	}								\ |
| 597 | 	_diverr;							\ |
| 598 | }) |
| 599 | |
| 600 | #define	Q_QMULI(q, i)							\ |
| 601 | ({									\ |
| 602 | 	int _mulerr = 0;						\ |
| 603 | 	if (!Q_SIGNED(*(q)) && Q_LTZ(i))				\ |
| 604 | 		_mulerr = EINVAL; /* Cannot represent. */		\ |
| 605 | 	else if ((i) != 0 && Q_IFMAXVAL(*(q)) / Q_TC(*(q), Q_ABS(i)) <	\ |
| 606 | 	 Q_GIFABSVAL(*(q)))						\ |
| 607 | 		_mulerr = EOVERFLOW;					\ |
| 608 | 	else								\ |
| 609 | 		Q_SIFVAL(*(q), Q_GIFVAL(*(q)) * Q_TC(*(q), i));		\ |
| 610 | 	_mulerr;							\ |
| 611 | }) |
| 612 | |
| 613 | #define	Q_QFRACI(q, in, id)						\ |
| 614 | ({									\ |
| 615 | 	uint64_t _tmp;							\ |
| 616 | 	int _err = 0;							\ |
| 617 | 	if ((id) == 0)							\ |
| 618 | 		_err = EINVAL; /* Divide by zero. */			\ |
| 619 | 	else if ((in) == 0)						\ |
| 620 | 		Q_SIFVAL(*(q), in);					\ |
| 621 | 	else if ((_tmp = Q_ABS(in)) > (UINT64_MAX >> Q_RPSHFT(*(q))))	\ |
| 622 | 		_err = EOVERFLOW; /* _tmp overflow. */			\ |
| 623 | 	else {								\ |
| 624 | 		_tmp = Q_SHL(*(q), _tmp) / Q_ABS(id);			\ |
| 625 | 		if (Q_QCANREPI(*(q), _tmp & Q_IFVALIMASK(*(q))))	\ |
| 626 | 			_err = EOVERFLOW; /* q overflow. */		\ |
| 627 | 		else {							\ |
| 628 | 			Q_SIFVAL(*(q), _tmp);				\ |
| 629 | 			Q_SSIGN(*(q), (Q_LTZ(in) && !Q_LTZ(id)) ||	\ |
| 630 | 			 (!Q_LTZ(in) && Q_LTZ(id)));			\ |
| 631 | 			if (_tmp == 0)					\ |
| 632 | 				_err = ERANGE; /* q underflow. */	\ |
| 633 | 		}							\ |
| 634 | 	}								\ |
| 635 | 	_err;								\ |
| 636 | }) |
| 637 | |
| 638 | #endif	/* _SYS_QMATH_H_ */ |