diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-04-29 21:54:39 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-04-29 21:55:15 +0200 |
| commit | 4bba6e7176632b4d760ba9362a1515552471d741 (patch) | |
| tree | edd86d32b0867990bf953568164800391b769589 /zahl | |
| parent | refsheet: fix type of second parameter for zseti, zsetu, zcmpi, and zcmpu (diff) | |
| download | libzahl-4bba6e7176632b4d760ba9362a1515552471d741.tar.gz libzahl-4bba6e7176632b4d760ba9362a1515552471d741.tar.bz2 libzahl-4bba6e7176632b4d760ba9362a1515552471d741.tar.xz | |
Some optimisations, fix refsheet, and disable const/pure attributes in gmp in benchmark
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | zahl-inlines.h | 68 | ||||
| -rw-r--r-- | zahl-internals.h | 19 | ||||
| -rw-r--r-- | zahl.h | 15 |
3 files changed, 80 insertions, 22 deletions
diff --git a/zahl-inlines.h b/zahl-inlines.h index 7c06270..abea865 100644 --- a/zahl-inlines.h +++ b/zahl-inlines.h @@ -14,19 +14,12 @@ 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) { + /* Almost three times faster than the naïve method. */ 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_SWAP(a, b, t, sign); + ZAHL_SWAP(b, a, t, used); + ZAHL_SWAP(a, b, t, alloced); + ZAHL_SWAP(b, a, t, chars); } @@ -42,6 +35,20 @@ zseti(z_t a, int64_t b) } +ZAHL_INLINE void +zsetu(z_t a, uint64_t b) +{ + if (!b) { + ZAHL_SET_SIGNUM(a, 0); + return; + } + ZAHL_ENSURE_SIZE(a, 1); + ZAHL_SET_SIGNUM(a, 1); + a->chars[0] = (zahl_char_t)b; + a->used = 1; +} + + ZAHL_INLINE size_t zlsb(z_t a) { @@ -140,10 +147,6 @@ zcmpi(z_t a, int64_t b) } -void zbset_impl_set(z_t a, size_t bit); -void zbset_impl_clear(z_t a, size_t bit); -void zbset_impl_flip(z_t a, size_t bit); - ZAHL_INLINE void zbset(z_t a, z_t b, size_t bit, int action) { @@ -174,11 +177,11 @@ fallback: #endif if (action > 0) - zbset_impl_set(a, bit); + zbset_ll_set(a, bit); else if (action < 0) - zbset_impl_flip(a, bit); + zbset_ll_flip(a, bit); else - zbset_impl_clear(a, bit); + zbset_ll_clear(a, bit); } @@ -196,3 +199,30 @@ zbtest(z_t a, size_t bit) bit &= ZAHL_BITS_IN_LAST_CHAR(bit); return (a->chars[chars] >> bit) & 1; } + + +ZAHL_INLINE void +zsplit(z_t high, z_t low, z_t a, size_t delim) +{ + if (ZAHL_UNLIKELY(high == a)) { + ztrunc(low, a, delim); + zrsh(high, a, delim); + } else { + zrsh(high, a, delim); + ztrunc(low, a, delim); + } +} + + +ZAHL_INLINE size_t +zsave(z_t a, void *buffer) +{ + if (ZAHL_LIKELY(buffer)) { + char *buf = buffer; + *((int *)buf) = a->sign, buf += sizeof(int); + *((size_t *)buf) = a->used, buf += sizeof(size_t); + if (ZAHL_LIKELY(!zzero(a))) + libzahl_memcpy((zahl_char_t *)buf, a->chars, a->used); + } + return sizeof(int) + sizeof(size_t) + (zzero(a) ? 0 : a->used * sizeof(zahl_char_t)); +} diff --git a/zahl-internals.h b/zahl-internals.h index 9d6df24..4adbdfe 100644 --- a/zahl-internals.h +++ b/zahl-internals.h @@ -32,10 +32,12 @@ #define ZAHL_SET_SIGNUM(a, signum) ((a)->sign = (signum)) #define ZAHL_SET(a, b) do { if ((a) != (b)) zset(a, b); } while (0) +#define ZAHL_ENSURE_SIZE(a, n) do { if ((a)->alloced < (n)) libzahl_realloc(a, (n)); } while (0) #define ZAHL_TRIM(a) for (; (a)->used && !(a)->chars[(a)->used - 1]; (a)->used--) #define ZAHL_TRIM_NONZERO(a) for (; !(a)->chars[(a)->used - 1]; (a)->used--) #define ZAHL_TRIM_AND_ZERO(a) do { ZAHL_TRIM(a); if (!(a)->used) ZAHL_SET_SIGNUM(a, 0); } while (0) #define ZAHL_TRIM_AND_SIGN(a, s) do { ZAHL_TRIM(a); ZAHL_SET_SIGNUM(a, (a)->used ? (s) : 0); } while (0) +#define ZAHL_SWAP(a, b, t, m) ((t)->m = (a)->m, (a)->m = (b)->m, (b)->m = (t)->m) #if defined(__GNUC__) || defined(__clang__) @@ -72,3 +74,20 @@ struct zahl { size_t alloced; zahl_char_t *chars; }; + + +void libzahl_realloc(struct zahl *, size_t); + +static inline void +libzahl_memcpy(zahl_char_t *restrict d, const zahl_char_t *restrict s, register size_t n) +{ + while (n--) + d[n] = s[n]; +} + +static inline void +libzahl_memset(zahl_char_t *a, register zahl_char_t v, register size_t n) +{ + while (n--) + a[n] = v; +} @@ -66,14 +66,14 @@ void zunsetup(void); /* Free resources used by libzahl */ ZAHL_INLINE void zinit(z_t); /* Prepare a for use. */ ZAHL_INLINE void zswap(z_t, z_t); /* (a, b) := (b, a) */ void zfree(z_t); /* Free resources in a. */ -size_t zsave(z_t, void *); /* Store a into b (if !!b), and return number of written bytes. */ +ZAHL_INLINE size_t zsave(z_t, void *); /* Store a into b (if !!b), and return number of written bytes. */ size_t zload(z_t, const void *); /* Restore a from b, and return number of read bytes. */ /* Assignment functions. */ void zset(z_t, z_t); /* a := b */ -void zsetu(z_t, uint64_t); /* a := b */ +ZAHL_INLINE void zsetu(z_t, uint64_t); /* a := b */ ZAHL_INLINE void zseti(z_t, int64_t); /* a := b */ /* Comparison functions. */ @@ -119,7 +119,8 @@ void znot(z_t, z_t); /* a := ~b */ void zlsh(z_t, z_t, size_t); /* a := b << c */ void zrsh(z_t, z_t, size_t); /* a := b >> c */ void ztrunc(z_t, z_t, size_t); /* a := b & ((1 << c) - 1) */ -void zsplit(z_t, z_t, z_t, size_t); /* a := c >> d, b := c - (a << d) */ +ZAHL_INLINE void zsplit(z_t, z_t, z_t, size_t); + /* a := c >> d, b := c - (a << d) */ ZAHL_INLINE int zbtest(z_t, size_t); /* (a >> b) & 1 */ ZAHL_INLINE size_t zlsb(z_t); /* Index of first set bit, SIZE_MAX if none are set. */ ZAHL_INLINE size_t zbits(z_t); /* ⌊log₂ |a|⌋ + 1, 1 if a = 0 */ @@ -165,6 +166,14 @@ void zperror(const char *); /* Identical to perror(3p) except it sup +/* Low-level functions. [Do not count on these to be retained between different versions of libzahl.] */ + +void zbset_ll_set(z_t, size_t); /* zbset(a, a, b, 1) */ +void zbset_ll_clear(z_t, size_t); /* zbset(a, a, b, 0) */ +void zbset_ll_flip(z_t, size_t); /* zbset(a, a, b, -1) */ + + + #include "zahl-inlines.h" #endif |
