The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/sys/qmath.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 58cbd961b3014353c8e0e3e4055bea7f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.