commit 92be5631d8e319babf5cca49f53ea5e692c54793
Author: Mattias Andrée <maandree_AT_kth.se>
AuthorDate: Tue Mar 15 00:20:00 2016 +0100
Commit: Mattias Andrée <maandree_AT_kth.se>
CommitDate: Tue Mar 15 00:20:00 2016 +0100
Optimisations
Signed-off-by: Mattias Andrée <maandree_AT_kth.se>
diff --git a/Makefile b/Makefile
index c340bf6..c256d4c 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -8,11 +8,6 @@ FUN =\
zadd\
zand\
zbset\
- zbtest\
- zcmp\
- zcmpi\
- zcmpmag\
- zcmpu\
zdiv\
zdivmod\
zerror\
_AT_@ -61,7 +56,12 @@ INLINE_FUN =\
zneg\
zlsb\
zbits\
- zseti
+ zseti\
+ zcmp\
+ zcmpi\
+ zcmpmag\
+ zcmpu\
+ zbtest
OBJ = $(FUN:=.o) allocator.o
MAN3 = $(FUN:=.3) $(INLINE_FUN:=.3)
diff --git a/TODO b/TODO
index a71124e..23edfbf 100644
--- a/TODO
+++ b/TODO
_AT_@ -3,3 +3,8 @@ It uses optimised division algorithm that requires that d|n.
Add zsets_radix
Add zstr_radix
+Add zranddist value based on % for fitness to bound
+
+Test big endian
+Test always having used > 0 for zero
+ Test negative/non-negative instead of sign
diff --git a/src/zadd.c b/src/zadd.c
index 2d42684..557ec6f 100644
--- a/src/zadd.c
+++ b/src/zadd.c
_AT_@ -21,8 +21,8 @@ zadd_impl(z_t a, z_t b, size_t n)
a->used = i;
}
-inline void
-zadd_unsigned(z_t a, z_t b, z_t c)
+static inline void
+libzahl_zadd_unsigned(z_t a, z_t b, z_t c)
{
size_t size, n;
_AT_@ -66,6 +66,12 @@ zadd_unsigned(z_t a, z_t b, z_t c)
}
void
+zadd_unsigned(z_t a, z_t b, z_t c)
+{
+ libzahl_zadd_unsigned(a, b, c);
+}
+
+void
zadd(z_t a, z_t b, z_t c)
{
if (unlikely(zzero(b))) {
_AT_@ -74,7 +80,7 @@ zadd(z_t a, z_t b, z_t c)
SET(a, b);
} else if (unlikely(znegative(b))) {
if (znegative(c)) {
- zadd_unsigned(a, b, c);
+ libzahl_zadd_unsigned(a, b, c);
SET_SIGNUM(a, -zsignum(a));
} else {
zsub_unsigned(a, c, b);
_AT_@ -82,6 +88,6 @@ zadd(z_t a, z_t b, z_t c)
} else if (unlikely(znegative(c))) {
zsub_unsigned(a, b, c);
} else {
- zadd_unsigned(a, b, c);
+ libzahl_zadd_unsigned(a, b, c);
}
}
diff --git a/src/zbset.c b/src/zbset.c
index 2874238..cc7b2b0 100644
--- a/src/zbset.c
+++ b/src/zbset.c
_AT_@ -2,38 +2,45 @@
#include "internals.h"
-void
-zbset(z_t a, z_t b, size_t bit, int action)
-{
- zahl_char_t mask = 1;
- size_t chars;
-
- chars = FLOOR_BITS_TO_CHARS(bit);
- bit = BITS_IN_LAST_CHAR(bit);
- mask <<= bit;
+#define PROLOGUE(MAY_INCREASE)\
+ zahl_char_t mask = 1;\
+ size_t chars = FLOOR_BITS_TO_CHARS(bit);\
+ if (MAY_INCREASE) {\
+ if (zzero(a)) {\
+ a->used = 0;\
+ SET_SIGNUM(a, 1);\
+ }\
+ if (unlikely(chars >= a->used)) {\
+ ENSURE_SIZE(a, chars + 1);\
+ zmemset(a->chars + a->used, 0, chars + 1 - a->used);\
+ a->used = chars + 1;\
+ }\
+ } else if (unlikely(chars >= a->used)) {\
+ return;\
+ }\
+ bit = BITS_IN_LAST_CHAR(bit);\
+ mask <<= bit
- SET(a, b);
- if (action) {
- if (zzero(a)) {
- a->used = 0;
- SET_SIGNUM(a, 1);
- }
- if (a->used <= chars) {
- ENSURE_SIZE(a, chars + 1);
- zmemset(a->chars + a->used, 0, chars + 1 - a->used);
- a->used = chars + 1;
- }
- }
+void
+zbset_impl_set(z_t a, z_t b, size_t bit)
+{
+ PROLOGUE(1);
+ a->chars[chars] |= mask;
+}
- if (action > 0) {
- a->chars[chars] |= mask;
- return;
- } else if (action < 0) {
- a->chars[chars] ^= mask;
- } else if (chars < a->used) {
- a->chars[chars] &= ~mask;
- }
+void
+zbset_impl_clear(z_t a, z_t b, size_t bit)
+{
+ PROLOGUE(0);
+ a->chars[chars] &= ~mask;
+ TRIM_AND_ZERO(a);
+}
+void
+zbset_impl_flip(z_t a, z_t b, size_t bit)
+{
+ PROLOGUE(1);
+ a->chars[chars] ^= mask;
TRIM_AND_ZERO(a);
}
diff --git a/src/zbtest.c b/src/zbtest.c
deleted file mode 100644
index a97e714..0000000
--- a/src/zbtest.c
+++ /dev/null
_AT_@ -1,18 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "internals.h"
-
-
-int
-zbtest(z_t a, size_t bit)
-{
- size_t chars;
- if (zzero(a))
- return 0;
-
- chars = FLOOR_BITS_TO_CHARS(bit);
- if (chars >= a->used)
- return 0;
-
- bit = BITS_IN_LAST_CHAR(bit);
- return (a->chars[chars] >> bit) & 1;
-}
diff --git a/src/zcmp.c b/src/zcmp.c
deleted file mode 100644
index 55caa6b..0000000
--- a/src/zcmp.c
+++ /dev/null
_AT_@ -1,11 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "internals.h"
-
-
-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);
-}
diff --git a/src/zcmpi.c b/src/zcmpi.c
deleted file mode 100644
index 71391b1..0000000
--- a/src/zcmpi.c
+++ /dev/null
_AT_@ -1,14 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "internals.h"
-
-
-int
-zcmpi(z_t a, int64_t b)
-{
- if (unlikely(!b))
- return zsignum(a);
- if (unlikely(zzero(a)))
- return b > 0 ? -1 : b < 0;
- zseti(libzahl_tmp_cmp, b);
- return zcmp(a, libzahl_tmp_cmp);
-}
diff --git a/src/zcmpmag.c b/src/zcmpmag.c
deleted file mode 100644
index 5594502..0000000
--- a/src/zcmpmag.c
+++ /dev/null
_AT_@ -1,29 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "internals.h"
-
-
-int
-zcmpmag(z_t a, z_t b)
-{
- size_t i, j;
- if (unlikely(zzero(a)))
- return -!zzero(b);
- if (unlikely(zzero(b)))
- return 1;
- i = a->used - 1;
- j = b->used - 1;
- for (; i > j; i--) {
- if (a->chars[i])
- return +1;
- a->used--;
- }
- for (; j > i; j--) {
- if (b->chars[j])
- return -1;
- b->used--;
- }
- for (; i; i--)
- if (a->chars[i] != b->chars[i])
- return (a->chars[i] > b->chars[i]) * 2 - 1;
- return a->chars[0] < b->chars[0] ? -1 : a->chars[0] > b->chars[0];
-}
diff --git a/src/zcmpu.c b/src/zcmpu.c
deleted file mode 100644
index 8bba692..0000000
--- a/src/zcmpu.c
+++ /dev/null
_AT_@ -1,14 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include "internals.h"
-
-
-int
-zcmpu(z_t a, uint64_t b)
-{
- if (unlikely(!b))
- return zsignum(a);
- if (unlikely(zsignum(a) <= 0))
- return -1;
- zsetu(libzahl_tmp_cmp, b);
- return zcmp(a, libzahl_tmp_cmp);
-}
diff --git a/src/zlsh.c b/src/zlsh.c
index 42894e0..1c9fd8f 100644
--- a/src/zlsh.c
+++ b/src/zlsh.c
_AT_@ -6,22 +6,18 @@ void
zlsh(z_t a, z_t b, size_t bits)
{
size_t i, chars, cbits;
- zahl_char_t carry[] = {0, 0};
+ zahl_char_t carry = 0, tcarry;
if (unlikely(zzero(b))) {
SET_SIGNUM(a, 0);
return;
}
- if (unlikely(!bits)) {
- SET(a, b);
- return;
- }
chars = FLOOR_BITS_TO_CHARS(bits);
bits = BITS_IN_LAST_CHAR(bits);
cbits = BITS_PER_CHAR - bits;
- ENSURE_SIZE(a, b->used + chars);
+ ENSURE_SIZE(a, b->used + chars + 1);
if (likely(a == b))
zmemmove(a->chars + chars, b->chars, b->used);
else
_AT_@ -31,15 +27,13 @@ zlsh(z_t a, z_t b, size_t bits)
if (likely(bits)) { /* This if statement is very important in C. */
for (i = chars; i < a->used; i++) {
- carry[~i & 1] = a->chars[i] >> cbits;
+ tcarry = a->chars[i] >> cbits;
a->chars[i] <<= bits;
- a->chars[i] |= carry[i & 1];
- }
- if (carry[i & 1]) {
- ENSURE_SIZE(a, a->used + 1);
- a->chars[i] = carry[i & 1];
- a->used++;
+ a->chars[i] |= carry;
+ carry = tcarry;
}
+ if (carry)
+ a->chars[a->used++] = carry;
}
SET_SIGNUM(a, zsignum(b));
diff --git a/src/zsetup.c b/src/zsetup.c
index 151f2f6..921e509 100644
--- a/src/zsetup.c
+++ b/src/zsetup.c
_AT_@ -31,7 +31,7 @@ zsetup(jmp_buf env)
memset(libzahl_pool_alloc, 0, sizeof(libzahl_pool_alloc));
#define X(x)\
- zinit(x);
+ zinit(x), zsetu(x, 1);
LIST_TEMPS;
#undef X
#define X(x, f, v)\
diff --git a/src/zsub.c b/src/zsub.c
index c8057b5..b3f12f2 100644
--- a/src/zsub.c
+++ b/src/zsub.c
_AT_@ -25,8 +25,8 @@ zsub_impl(z_t a, z_t b, size_t n)
}
}
-inline void
-zsub_unsigned(z_t a, z_t b, z_t c)
+static inline void
+libzahl_zsub_unsigned(z_t a, z_t b, z_t c)
{
int magcmp;
size_t n;
_AT_@ -71,6 +71,12 @@ zsub_unsigned(z_t a, z_t b, z_t c)
}
void
+zsub_unsigned(z_t a, z_t b, z_t c)
+{
+ libzahl_zsub_unsigned(a, b, c);
+}
+
+void
zsub(z_t a, z_t b, z_t c)
{
if (unlikely(zzero(b))) {
_AT_@ -79,7 +85,7 @@ zsub(z_t a, z_t b, z_t c)
SET(a, b);
} else if (unlikely(znegative(b))) {
if (znegative(c)) {
- zsub_unsigned(a, c, b);
+ libzahl_zsub_unsigned(a, c, b);
} else {
zadd_unsigned(a, b, c);
SET_SIGNUM(a, -zsignum(a));
_AT_@ -87,6 +93,6 @@ zsub(z_t a, z_t b, z_t c)
} else if (znegative(c)) {
zadd_unsigned(a, b, c);
} else {
- zsub_unsigned(a, b, c);
+ libzahl_zsub_unsigned(a, b, c);
}
}
diff --git a/zahl.h b/zahl.h
index 9a03b26..e700dc7 100644
--- a/zahl.h
+++ b/zahl.h
_AT_@ -92,10 +92,10 @@ ZAHL_INLINE void zseti(z_t, int64_t); /* a := b */
/* Comparison functions. */
-int zcmp(z_t, z_t); /* signum (a - b) */
-int zcmpu(z_t, uint64_t); /* signum (a - b) */
-int zcmpi(z_t, int64_t); /* signum (a - b) */
-int zcmpmag(z_t, z_t); /* signum (|a| - |b|) */
+ZAHL_INLINE int zcmp(z_t, z_t); /* signum (a - b) */
+ZAHL_INLINE int zcmpu(z_t, uint64_t); /* signum (a - b) */
+ZAHL_INLINE int zcmpi(z_t, int64_t); /* signum (a - b) */
+ZAHL_INLINE int zcmpmag(z_t, z_t); /* signum (|a| - |b|) */
/* Arithmetic functions. */
_AT_@ -130,13 +130,13 @@ 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) */
-int zbtest(z_t, size_t); /* (a >> b) & 1 */
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 */
/* If d > 0: a := b | (1 << c), if d = 0: a := b & ~(1 << c), if d < 0: a := b ^ (1 << c) */
-void zbset(z_t, z_t, size_t, int);
+ZAHL_INLINE void zbset(z_t, z_t, size_t, int);
/* Number theory. */
_AT_@ -280,5 +280,138 @@ zbits(z_t a)
}
+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;
+}
+
#endif
Received on Tue Mar 15 2016 - 00:20:10 CET
This archive was generated by hypermail 2.3.0
: Tue Mar 15 2016 - 00:24:19 CET