diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-04-07 16:04:07 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-04-07 16:04:07 +0200 |
| commit | 8d82bea597a2969db0780e3142437ea91929613f (patch) | |
| tree | 71d9dbf04a53e22eef9433c0ae09cf83ae3997e8 /zahl-inlines.h | |
| parent | zptest: use DEFAULT_RANDOM (diff) | |
| download | libzahl-8d82bea597a2969db0780e3142437ea91929613f.tar.gz libzahl-8d82bea597a2969db0780e3142437ea91929613f.tar.bz2 libzahl-8d82bea597a2969db0780e3142437ea91929613f.tar.xz | |
Split out zahl-inlines.h zahl-internals.h from zahl.h to hide uninteresting stuff
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'zahl-inlines.h')
| -rw-r--r-- | zahl-inlines.h | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/zahl-inlines.h b/zahl-inlines.h new file mode 100644 index 0000000..8ffa6cb --- /dev/null +++ b/zahl-inlines.h @@ -0,0 +1,198 @@ +/* See LICENSE file for copyright and license details. */ + +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) { ZAHL_SET(a, b); a->sign = !!a->sign; } +ZAHL_INLINE void zneg(z_t a, z_t b) { ZAHL_SET(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); + ZAHL_SET_SIGNUM(a, -1); + } +} + + +ZAHL_INLINE size_t +zlsb(z_t a) +{ + size_t i = 0; + if (ZAHL_UNLIKELY(zzero(a))) + return SIZE_MAX; + for (; !a->chars[i]; i++); + i *= 8 * sizeof(zahl_char_t); + ZAHL_ADD_CTZ(i, a->chars[i]); + return i; +} + + +ZAHL_INLINE size_t +zbits(z_t a) +{ + 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); + ZAHL_SUB_CLZ(rc, a->chars[a->used - 1]); + return rc; +} + + +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] = (zahl_char_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); + +#ifdef ZAHL_CONST_P + if (ZAHL_CONST_P(action) && ZAHL_CONST_P(bit)) { + zahl_char_t mask = 1; + if (zzero(a) || ZAHL_FLOOR_BITS_TO_CHARS(bit) >= a->used) { + if (!action) + return; + goto fallback; + } + mask <<= ZAHL_BITS_IN_LAST_CHAR(bit); + if (action > 0) { + a->chars[ZAHL_FLOOR_BITS_TO_CHARS(bit)] |= mask; + return; + } else if (action < 0) { + a->chars[ZAHL_FLOOR_BITS_TO_CHARS(bit)] ^= mask; + } else { + a->chars[ZAHL_FLOOR_BITS_TO_CHARS(bit)] &= ~mask; + } + ZAHL_TRIM_AND_ZERO(a); + 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 = ZAHL_FLOOR_BITS_TO_CHARS(bit); + if (ZAHL_UNLIKELY(chars >= a->used)) + return 0; + + bit &= ZAHL_BITS_IN_LAST_CHAR(bit); + return (a->chars[chars] >> bit) & 1; +} |
