internals.h - libzahl - big integer library
(HTM) git clone git://git.suckless.org/libzahl
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) 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"