aboutsummaryrefslogtreecommitdiffstats
path: root/zahl
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--zahl-inlines.h68
-rw-r--r--zahl-internals.h19
-rw-r--r--zahl.h15
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;
+}
diff --git a/zahl.h b/zahl.h
index f3d3d69..1e27882 100644
--- a/zahl.h
+++ b/zahl.h
@@ -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