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"