diff options
Diffstat (limited to 'zahl.h')
| -rw-r--r-- | zahl.h | 251 |
1 files changed, 2 insertions, 249 deletions
@@ -12,21 +12,10 @@ #include <stdint.h> #include <limits.h> - - -#ifndef ZAHL_INLINE -# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define ZAHL_INLINE static inline -# else -# define ZAHL_INLINE static -# endif -#endif +#include "zahl-internals.h" -/* You should pretend like this typedef does not exist. */ -typedef uint64_t zahl_char_t; - /* This structure should be considered opaque. */ typedef struct { int sign; @@ -185,242 +174,6 @@ void zperror(const char *); /* Identical to perror(3p) except it sup -/* ------------------------------- Implementations of inline functions. ------------------------------- */ - - -#if defined(__GNUC__) || defined(__clang__) -# define ZAHL_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -# define ZAHL_LIKELY(expr) __builtin_expect(!!(expr), 1) -#else -# define ZAHL_UNLIKELY(expr) (expr) -# define ZAHL_LIKELY(expr) (expr) -#endif - - -ZAHL_INLINE void zinit(z_t a) { a->alloced = 0; a->chars = 0; } -ZAHL_INLINE int zeven(z_t a) { return !a->sign || !(a->chars[0] & 1); } -ZAHL_INLINE int zodd(z_t a) { return a->sign && (a->chars[0] & 1); } -ZAHL_INLINE int zeven_nonzero(z_t a) { return !(a->chars[0] & 1); } -ZAHL_INLINE int zodd_nonzero(z_t a) { return (a->chars[0] & 1); } -ZAHL_INLINE int zzero(z_t a) { return !a->sign; } -ZAHL_INLINE int zsignum(z_t a) { return a->sign; } -ZAHL_INLINE void zabs(z_t a, z_t b) { if (a != b) zset(a, b); a->sign = !!a->sign; } -ZAHL_INLINE void zneg(z_t a, z_t b) { if (a != b) zset(a, b); a->sign = -a->sign; } - - -ZAHL_INLINE void -zswap(z_t a, z_t b) -{ - z_t t; - t->sign = a->sign; - a->sign = b->sign; - b->sign = t->sign; - t->used = b->used; - b->used = a->used; - a->used = t->used; - t->alloced = a->alloced; - a->alloced = b->alloced; - b->alloced = t->alloced; - t->chars = b->chars; - b->chars = a->chars; - a->chars = t->chars; -} - - -ZAHL_INLINE void -zseti(z_t a, int64_t b) -{ - if (ZAHL_UNLIKELY(b >= 0)) { - zsetu(a, (uint64_t)b); - } else { - zsetu(a, (uint64_t)-b); - a->sign = -1; - } -} - - -ZAHL_INLINE size_t -zlsb(z_t a) -{ -#if defined(__GNUC__) || defined(__clang__) - size_t i = 0; - if (ZAHL_UNLIKELY(zzero(a))) - return SIZE_MAX; - for (; !a->chars[i]; i++); - i *= 8 * sizeof(zahl_char_t); - i += (size_t)__builtin_ctzll(a->chars[i]); - return i; -#else - size_t i = 0; - zahl_char_t x; - if (ZAHL_UNLIKELY(zzero(a))) - return SIZE_MAX; - for (; !a->chars[i]; i++); - i *= 8 * sizeof(zahl_char_t); - x = ~(a->chars[i]); - for (; x & 1; x >>= 1, i++); - return i; -#endif -} - - -ZAHL_INLINE size_t -zbits(z_t a) -{ -#if defined(__GNUC__) || defined(__clang__) - size_t rc; - if (ZAHL_UNLIKELY(zzero(a))) - return 1; - while (!a->chars[a->used - 1]) a->used--; /* TODO should not be necessary */ - rc = a->used * 8 * sizeof(zahl_char_t); - rc -= (size_t)__builtin_clzll(a->chars[a->used - 1]); - return rc; -#else - size_t rc; - zahl_char_t x; - if (ZAHL_UNLIKELY(zzero(a))) - return 1; - while (!a->chars[a->used - 1]) a->used--; /* TODO should not be necessary */ - x = a->chars[a->used - 1]; - rc = (a->used - 1) * 8 * sizeof(zahl_char_t); - for (; x; x >>= 1, rc++); - return rc; -#endif -} - - -ZAHL_INLINE int -zcmpmag(z_t a, z_t b) -{ - size_t i, j; - if (ZAHL_UNLIKELY(zzero(a))) - return -!zzero(b); - if (ZAHL_UNLIKELY(zzero(b))) - return 1; - i = a->used - 1; - j = b->used - 1; -#if 0 /* TODO this should be sufficient. */ - if (i != j) - return (i > j) * 2 - 1; -#else - for (; i > j; i--) { - if (a->chars[i]) - return +1; - a->used--; - } - for (; j > i; j--) { - if (b->chars[j]) - return -1; - b->used--; - } -#endif - for (; i && a->chars[i] == b->chars[i]; i--); - return a->chars[i] < b->chars[i] ? -1 : a->chars[i] > b->chars[i]; -} - - -ZAHL_INLINE int -zcmp(z_t a, z_t b) -{ - if (zsignum(a) != zsignum(b)) - return zsignum(a) < zsignum(b) ? -1 : zsignum(a) > zsignum(b); - return zsignum(a) * zcmpmag(a, b); -} - - -ZAHL_INLINE int -zcmpu(z_t a, uint64_t b) -{ - extern z_t libzahl_tmp_cmp; - if (ZAHL_UNLIKELY(!b)) - return zsignum(a); - if (ZAHL_UNLIKELY(zsignum(a) <= 0)) - return -1; - libzahl_tmp_cmp->chars[0] = b; - return zcmpmag(a, libzahl_tmp_cmp); -} - - -ZAHL_INLINE int -zcmpi(z_t a, int64_t b) -{ - extern z_t libzahl_tmp_cmp; - if (ZAHL_UNLIKELY(!b)) - return zsignum(a); - if (ZAHL_UNLIKELY(zzero(a))) - return ZAHL_LIKELY(b < 0) ? 1 : -1; - if (ZAHL_LIKELY(b < 0)) { - if (zsignum(a) > 0) - return +1; - libzahl_tmp_cmp->chars[0] = (uint64_t)-b; - return -zcmpmag(a, libzahl_tmp_cmp); - } else { - if (zsignum(a) < 0) - return -1; - libzahl_tmp_cmp->chars[0] = b; - return +zcmpmag(a, libzahl_tmp_cmp); - } -} - - -void zbset_impl_set(z_t a, z_t b, size_t bit); -void zbset_impl_clear(z_t a, z_t b, size_t bit); -void zbset_impl_flip(z_t a, z_t b, size_t bit); -ZAHL_INLINE void -zbset(z_t a, z_t b, size_t bit, int action) -{ - if (ZAHL_UNLIKELY(a != b)) - zset(a, b); - -#if defined(__GNUC__) || defined(__clang__) - if (__builtin_constant_p(action) && __builtin_constant_p(bit)) { - zahl_char_t mask = 1; - if (zzero(a) || bit >> 6 >= a->used) { - if (!action) - return; - goto fallback; - } - mask <<= bit & 63; - if (action > 0) { - a->chars[bit >> 6] |= mask; - return; - } else if (action < 0) { - a->chars[bit >> 6] ^= mask; - } else { - a->chars[bit >> 6] &= ~mask; - } - for (; a->used && !a->chars[a->used - 1]; a->used--); - if (!a->used) - a->sign = 0; - return; - } -fallback: -#endif - - if (action > 0) { - zbset_impl_set(a, b, bit); - } else if (action < 0) { - zbset_impl_flip(a, b, bit); - } else { - zbset_impl_clear(a, b, bit); - } -} - - -ZAHL_INLINE int -zbtest(z_t a, size_t bit) -{ - size_t chars; - if (ZAHL_UNLIKELY(zzero(a))) - return 0; - - chars = bit >> 6; - if (ZAHL_UNLIKELY(chars >= a->used)) - return 0; - - bit &= 63; - return (a->chars[chars] >> bit) & 1; -} - +#include "zahl-inlines.h" #endif |
