libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

internals.h (4450B)


      1 /* See LICENSE file for copyright and license details. */
      2 
      3 #ifndef ZAHL_INLINE
      4 # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
      5 #  define ZAHL_INLINE  static inline
      6 # else
      7 #  define ZAHL_INLINE  static
      8 # endif
      9 #endif
     10 
     11 
     12 #if defined(__GNUC__) || defined(__clang__)
     13 # define ZAHL_LIKELY(expr)                __builtin_expect(!!(expr), 1)
     14 # define ZAHL_UNLIKELY(expr)              __builtin_expect(!!(expr), 0)
     15 # define ZAHL_CONST_P(value)              __builtin_constant_p(value)
     16 #else
     17 # define ZAHL_LIKELY(expr)                (expr)
     18 # define ZAHL_UNLIKELY(expr)              (expr)
     19 #endif
     20 
     21 
     22 #if defined(__GNUC__) && !defined(__clang__)
     23 # define ZAHL_O0     __attribute__((__optimize__("O0")))
     24 # define ZAHL_O1     __attribute__((__optimize__("O1")))
     25 # define ZAHL_O2     __attribute__((__optimize__("O2")))
     26 # define ZAHL_O3     __attribute__((__optimize__("O3")))
     27 # define ZAHL_Ofast  __attribute__((__optimize__("Ofast")))
     28 # define ZAHL_Os     __attribute__((__optimize__("Os")))
     29 # define ZAHL_Oz     __attribute__((__optimize__("Os")))
     30 #elif defined(__clang__)
     31 # define ZAHL_O0     __attribute__((__optnone__))
     32 # define ZAHL_O1     /* Don't know how. */
     33 # define ZAHL_O2     /* Don't know how. */
     34 # define ZAHL_O3     /* Don't know how. */
     35 # define ZAHL_Ofast  /* Don't know how. */
     36 # define ZAHL_Os     /* Don't know how. */
     37 # define ZAHL_Oz     /* Don't know how. */
     38 #else
     39 # define ZAHL_O0     /* Don't know how. */
     40 # define ZAHL_O1     /* Don't know how. */
     41 # define ZAHL_O2     /* Don't know how. */
     42 # define ZAHL_O3     /* Don't know how. */
     43 # define ZAHL_Ofast  /* Don't know how. */
     44 # define ZAHL_Os     /* Don't know how. */
     45 # define ZAHL_Oz     /* Don't know how. */
     46 #endif
     47 /* Mostly ZAHL_O2, but sometimes ZAHL_O3, are useful.
     48  * But note, often it optimal to not use any of them. */
     49 
     50 
     51 #define ZAHL_BITS_PER_CHAR                64
     52 #define ZAHL_LB_BITS_PER_CHAR             6
     53 #define ZAHL_CHAR_MAX                     UINT64_MAX
     54 #define ZAHL_FLUFF                        4
     55 /* Note: These cannot be changed willy-nilly, some code depends
     56  * on them, be cause being flexible would just be too painful. */
     57 
     58 
     59 #define ZAHL_FLOOR_BITS_TO_CHARS(bits)    ((bits) >> ZAHL_LB_BITS_PER_CHAR)
     60 #define ZAHL_CEILING_BITS_TO_CHARS(bits)  (((bits) + (ZAHL_BITS_PER_CHAR - 1)) >> ZAHL_LB_BITS_PER_CHAR)
     61 #define ZAHL_BITS_IN_LAST_CHAR(bits)      ((bits) & (ZAHL_BITS_PER_CHAR - 1))
     62 #define ZAHL_TRUNCATE_TO_CHAR(bits)       ((bits) & ~(size_t)(ZAHL_BITS_PER_CHAR - 1))
     63 
     64 
     65 #define ZAHL_SET_SIGNUM(a, signum)        ((a)->sign = (signum))
     66 #define ZAHL_SET(a, b)                    do { if ((a) != (b)) zset(a, b); } while (0)
     67 #define ZAHL_ENSURE_SIZE(a, n)            do { if ((a)->alloced < (n)) libzahl_realloc(a, (n)); } while (0)
     68 #define ZAHL_TRIM(a)                      for (; (a)->used && !(a)->chars[(a)->used - 1]; (a)->used--)
     69 #define ZAHL_TRIM_NONZERO(a)              for (; !(a)->chars[(a)->used - 1]; (a)->used--)
     70 #define ZAHL_TRIM_AND_ZERO(a)             do { ZAHL_TRIM(a); if (!(a)->used) ZAHL_SET_SIGNUM(a, 0); } while (0)
     71 #define ZAHL_TRIM_AND_SIGN(a, s)          do { ZAHL_TRIM(a); ZAHL_SET_SIGNUM(a, (a)->used ? (s) : 0); } while (0)
     72 #define ZAHL_SWAP(a, b, t, m)             ((t)->m = (a)->m, (a)->m = (b)->m, (b)->m = (t)->m)
     73 
     74 
     75 #if defined(__GNUC__) || defined(__clang__)
     76 # if ZAHL_CHAR_MAX == LONG_MAX
     77 #  define ZAHL_ADD_CTZ(r, x)  ((r) += (size_t)__builtin_ctzl(x))
     78 #  define ZAHL_SUB_CLZ(r, x)  ((r) -= (size_t)__builtin_clzl(x))
     79 # else
     80 #  define ZAHL_ADD_CTZ(r, x)  ((r) += (size_t)__builtin_ctzll(x))
     81 #  define ZAHL_SUB_CLZ(r, x)  ((r) -= (size_t)__builtin_clzll(x))
     82 # endif
     83 #else
     84 # define ZAHL_ADD_CTZ(r, x)                                   \
     85 	do {                                                  \
     86 		zahl_char_t zahl_x__ = (x);                   \
     87 		for (; zahl_x__ & 1; zahl_x__ >>= 1, (r)++);  \
     88 	} while (0)
     89 # define ZAHL_SUB_CLZ(r, x)                               \
     90 	do {                                              \
     91 		zahl_char_t zahl_x__ = (x);               \
     92 		(r) -= 8 * sizeof(zahl_char_t);           \
     93 		for (; zahl_x__; zahl_x__ >>= 1, (r)++);  \
     94 	} while (0)
     95 #endif
     96 
     97 
     98 typedef uint64_t zahl_char_t;
     99 
    100 struct zahl {
    101         int sign;
    102 #if INT_MAX != LONG_MAX
    103 	int padding__;
    104 #endif
    105         size_t used;
    106         size_t alloced;
    107         zahl_char_t *chars;
    108 };
    109 
    110 
    111 extern struct zahl libzahl_tmp_div[1];
    112 extern struct zahl libzahl_tmp_mod[1];
    113 
    114 
    115 void libzahl_realloc(struct zahl *, size_t);
    116 
    117 #include "memory.h"