(wrong string) ée

From: <git_AT_suckless.org>
Date: Sun, 13 Mar 2016 23:58:34 +0100 (CET)

commit 5b10b24044b3350a19ab3d3c0b37b5e9c12365b1
Author: Mattias Andrée <maandree_AT_kth.se>
AuthorDate: Sun Mar 13 23:54:56 2016 +0100
Commit: Mattias Andrée <maandree_AT_kth.se>
CommitDate: Sun Mar 13 23:54:56 2016 +0100

    Multiple changes:
    
    1) Compile test with -O0, it takes too long otherwise.
    
    2) Add error codes: ZERROR_0_POW_0, ZERROR_0_DIV_0, ZERROR_DIV_0, ZERROR_NEGATIVE.
    
    3) Add workaround for a bug in clang (src/allocator.c).
    
    4) Cleanups.
    
    5) Minor optimisations.
    
    6) Add inclusion guard for zahl.h.
    
    Signed-off-by: Mattias Andrée <maandree_AT_kth.se>

diff --git a/Makefile b/Makefile
index 60dda0a..80d3aa7 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -80,7 +80,7 @@ test-random.c: test-generate.py
         ./test-generate.py > test-random.c
 
 test: test.c libzahl.a test-random.c
- $(CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) -o $_AT_ test.c libzahl.a
+ $(CC) $(LDFLAGS) $(CFLAGS:--O*) -O0 $(CPPFLAGS) -o $_AT_ test.c libzahl.a
 
 ifndef BENCHMARK_LIB
 benchmark: bench/benchmark.c libzahl.a
diff --git a/man/zerror.3 b/man/zerror.3
index 837b3df..8bc0e53 100644
--- a/man/zerror.3
+++ b/man/zerror.3
_AT_@ -37,5 +37,48 @@ The error is stored in
 (The error may not be stored in
 .I errno
 until this function is called.)
+.TP
+.B ZERROR_0_POW_0
+An attempt to calculate the zeroth power of zero was made.
+This is on indeterminate form and cannot be calculated.
+The closest matching
+.I errno
+value is
+.BR EDOM .
+.TP
+.B ZERROR_0_DIV_0
+An attempt to divide zero by zero was made.
+This is on indeterminate form and cannot be calculated.
+The closest matching
+.I errno
+value is
+.BR EDOM .
+.TP
+.B ZERROR_DIV_0
+An attempt to divide a non-zero value by zero was made.
+This is undefined and cannot be calculated.
+This occurs if a divisor or a modulator is zero, or if
+zero is raised to a negative number.
+The closest matching
+.I errno
+value is
+.BR EDOM .
+.TP
+.B ZERROR_NEGATIVE
+A function argument that must not be negative was negative.
+The closest matching
+.I errno
+values is
+.B EDOM
+and
+.BR EINVAL .
+.SH RETURN VALUE
+.B zerror
+returns the error that caused libzahl a function to fail.
+.SH NOTES
+.I errno
+is only set if
+.B ZERROR_ERRNO_SET
+is returned.
 .SH SEE ALSO
 .BR zperror (3)
diff --git a/src/allocator.c b/src/allocator.c
index 33c8677..41ce9ed 100644
--- a/src/allocator.c
+++ b/src/allocator.c
_AT_@ -1,27 +1,47 @@
 /* See LICENSE file for copyright and license details. */
 #include "internals.h"
+#include <stdio.h>
+
+
+/* Find r such that r is a minimal power of 2 ≥ n. */
+#define NEXT_2POW(n)\
+ do if (likely((n & (~n + 1)) != n)) {\
+ size_t x;\
+ n |= n >> 1;\
+ n |= n >> 2;\
+ n |= n >> 4;\
+ for (i = sizeof(n), x = 8; i; i >>= 1, x <<= 1)\
+ n |= n >> x;\
+ n += 1;\
+ } while (0)
+
+
+#if defined(__clang__)
+static inline __attribute__((optnone)) size_t
+clang_warkaround_next_2pow(size_t need)
+{
+ size_t i;
+ NEXT_2POW(need);
+ return need;
+}
+#endif
 
 
 void
 libzahl_realloc(z_t a, size_t need)
 {
- size_t i, x;
+ size_t i;
         zahl_char_t *new;
 
- /* Find n such that n is a minimal power of 2 ≥ need. */
- if ((need & (~need + 1)) != need) {
- need |= need >> 1;
- need |= need >> 2;
- need |= need >> 4;
- for (i = sizeof(need), x = 8; i; i >>= 1, x <<= 1)
- need |= need >> x;
- need += 1;
- }
+#if defined(__clang__)
+ need = clang_warkaround_next_2pow(need);
+#else
+ NEXT_2POW(need);
+#endif
 
- for (i = 0, x = need; x; x >>= 1)
- i += 1;
+ i = libzahl_msb_nz_zu(need);
 
- if (libzahl_pool_n[i]) {
+ if (likely(libzahl_pool_n[i])) {
                 libzahl_pool_n[i]--;
                 new = libzahl_pool[i][libzahl_pool_n[i]];
                 zmemcpy(new, a->chars, a->alloced);
_AT_@ -32,7 +52,7 @@ libzahl_realloc(z_t a, size_t need)
                 if (!a->chars) {
                         if (!errno) /* sigh... */
                                 errno = ENOMEM;
- FAILURE(errno);
+ libzahl_failure(errno);
                 }
         }
         a->alloced = need;
diff --git a/src/internals.h b/src/internals.h
index 2a947dd..c1153ea 100644
--- a/src/internals.h
+++ b/src/internals.h
_AT_@ -4,6 +4,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <limits.h>
 
 #define BITS_PER_CHAR 64
 #define LB_BITS_PER_CHAR 6
_AT_@ -60,13 +61,14 @@ extern size_t libzahl_pool_n[sizeof(size_t) * 8];
 extern size_t libzahl_pool_alloc[sizeof(size_t) * 8];
 
 #if defined(__GNUC__) || defined(__clang__)
-# define EXPECT(value, expected) __builtin_expect(value, expected)
+# define likely(value) __builtin_expect(!!(value), 1)
+# define unlikely(value) __builtin_expect(!!(value), 0)
 #else
-# define EXPECT(value, expected) (value)
+# define likely(value) (value)
+# define unlikely(value) (value)
 #endif
 
-#define FAILURE(error) (libzahl_error = (error), longjmp(libzahl_jmp_buf, 1))
-#define zmemmove(d, s, n) memmove((d), (s), (n) * sizeof(zahl_char_t))
+#define libzahl_failure(error) (libzahl_error = (error), longjmp(libzahl_jmp_buf, 1))
 #define SET_SIGNUM(a, signum) ((a)->sign = (signum))
 #define SET(a, b) do { if ((a) != (b)) zset(a, b); } while (0)
 #define ENSURE_SIZE(a, n) do { if ((a)->alloced < (n)) libzahl_realloc(a, (n)); } while (0)
_AT_@ -74,6 +76,16 @@ extern size_t libzahl_pool_alloc[sizeof(size_t) * 8];
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 #define TRIM(a) for (; (a)->used && !(a)->chars[(a)->used - 1]; (a)->used--)
 #define TRIM_NONZERO(a) for (; !(a)->chars[(a)->used - 1]; (a)->used--)
+#define TRIM_AND_ZERO(a) do { TRIM(a); if (!(a)->used) SET_SIGNUM(a, 0); } while (0)
+#define znegative(a) (zsignum(a) < 0)
+#define znegative1(a, b) ((zsignum(a) | zsignum(b)) < 0)
+#define znegative2(a, b) ((zsignum(a) & zsignum(b)) < 0)
+#define zpositive(a) (zsignum(a) > 0)
+#define zpositive1(a, b) (zpositive(a) + zpositive(b) > 0)
+#define zpositive2(a, b) (zsignum(a) + zsignum(b) == 2)
+#define zzero1(a, b) (zzero(a) + zzero(b) > 0)
+#define zzero2(a, b) (!(zsignum(a) | zsignum(b)))
+#define zmemmove(d, s, n) memmove((d), (s), (n) * sizeof(zahl_char_t))
 
 void libzahl_realloc(z_t a, size_t need);
 
_AT_@ -90,3 +102,39 @@ zmemset(zahl_char_t *a, register zahl_char_t v, register size_t n)
         while (n--)
                 a[n] = v;
 }
+
+/*
+ * libzahl_msb_nz_zu
+ * ^^^ ^^ ^^
+ * | | |
+ * | | \- size_t parameter
+ * | \- non-zero input
+ * \- most significant bit
+ */
+
+#if SIZE_MAX == ULONG_MAX
+# define libzahl_msb_nz_zu(x) libzahl_msb_nz_lu(x)
+#else
+# define libzahl_msb_nz_zu(x) libzahl_msb_nz_llu(x)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# define libzahl_msb_nz_lu(x) (8 * sizeof(unsigned long int) - (size_t)__builtin_clzl(x));
+# define libzahl_msb_nz_llu(x) (8 * sizeof(unsigned long long int) - (size_t)__builtin_clzll(x));
+#else
+static inline size_t
+libzahl_msb_nz_lu(unsigned long int x)
+{
+ size_t r = 0;
+ for (; x; x >>= 1, r++);
+ return r;
+}
+
+static inline size_t
+libzahl_msb_nz_llu(unsigned long long int x)
+{
+ size_t r = 0;
+ for (; x; x >>= 1, r++);
+ return r;
+}
+#endif
diff --git a/src/zadd.c b/src/zadd.c
index ec17ca4..9891b00 100644
--- a/src/zadd.c
+++ b/src/zadd.c
_AT_@ -9,10 +9,10 @@ zadd_unsigned(z_t a, z_t b, z_t c)
         uint32_t carry[] = {0, 0};
         zahl_char_t *addend;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 zabs(a, c);
                 return;
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 zabs(a, b);
                 return;
         }
_AT_@ -29,7 +29,7 @@ zadd_unsigned(z_t a, z_t b, z_t c)
                         zmemset(a->chars + a->used, 0, n - a->used);
                 }
                 addend = c->chars;
- } else if (EXPECT(a == c, 0)) {
+ } else if (unlikely(a == c)) {
                 if (a->used < b->used) {
                         n = b->used;
                         zmemset(a->chars + a->used, 0, n - a->used);
_AT_@ -67,15 +67,15 @@ zadd_unsigned(z_t a, z_t b, z_t c)
 void
 zadd(z_t a, z_t b, z_t c)
 {
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET(a, c);
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 SET(a, b);
- } else if (EXPECT(b == c, 0)) {
+ } else if (unlikely(b == c)) {
                 zlsh(a, b, 1);
- } else if (EXPECT((zsignum(b) | zsignum(c)) < 0, 0)) {
- if (zsignum(b) < 0) {
- if (zsignum(c) < 0) {
+ } else if (unlikely(znegative1(b, c))) {
+ if (znegative(b)) {
+ if (znegative(c)) {
                                 zadd_unsigned(a, b, c);
                                 SET_SIGNUM(a, -zsignum(a));
                         } else {
diff --git a/src/zand.c b/src/zand.c
index 65a8962..119f66c 100644
--- a/src/zand.c
+++ b/src/zand.c
_AT_@ -7,7 +7,7 @@ zand(z_t a, z_t b, z_t c)
 {
         size_t n;
 
- if (EXPECT(zzero(b) || zzero(c), 0)) {
+ if (unlikely(zzero1(b, c))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
_AT_@ -24,7 +24,7 @@ found_highest:
         if (a == b) {
                 while (n--)
                         a->chars[n] &= c->chars[n];
- } else if (EXPECT(a == c, 0)) {
+ } else if (unlikely(a == c)) {
                 while (n--)
                         a->chars[n] &= b->chars[n];
         } else {
_AT_@ -33,5 +33,5 @@ found_highest:
                 while (n--)
                         a->chars[n] &= b->chars[n];
         }
- SET_SIGNUM(a, (zsignum(b) > 0 || zsignum(c) > 0) * 2 - 1);
+ SET_SIGNUM(a, zpositive1(b, c) * 2 - 1);
 }
diff --git a/src/zbset.c b/src/zbset.c
index 33252c1..2874238 100644
--- a/src/zbset.c
+++ b/src/zbset.c
_AT_@ -35,7 +35,5 @@ zbset(z_t a, z_t b, size_t bit, int action)
                 a->chars[chars] &= ~mask;
         }
 
- TRIM(a);
- if (!a->used)
- SET_SIGNUM(a, 0);
+ TRIM_AND_ZERO(a);
 }
diff --git a/src/zcmpi.c b/src/zcmpi.c
index 52fbaf9..54abcd9 100644
--- a/src/zcmpi.c
+++ b/src/zcmpi.c
_AT_@ -5,9 +5,9 @@
 int
 zcmpi(z_t a, long long int b)
 {
- if (EXPECT(!b, 0))
+ if (unlikely(!b))
                 return zsignum(a);
- if (EXPECT(zzero(a), 0))
+ 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
index 59cc415..5594502 100644
--- a/src/zcmpmag.c
+++ b/src/zcmpmag.c
_AT_@ -6,9 +6,9 @@ int
 zcmpmag(z_t a, z_t b)
 {
         size_t i, j;
- if (EXPECT(zzero(a), 0))
+ if (unlikely(zzero(a)))
                 return -!zzero(b);
- if (EXPECT(zzero(b), 0))
+ if (unlikely(zzero(b)))
                 return 1;
         i = a->used - 1;
         j = b->used - 1;
diff --git a/src/zcmpu.c b/src/zcmpu.c
index 7da7f9a..40e33b6 100644
--- a/src/zcmpu.c
+++ b/src/zcmpu.c
_AT_@ -5,9 +5,9 @@
 int
 zcmpu(z_t a, unsigned long long int b)
 {
- if (EXPECT(!b, 0))
+ if (unlikely(!b))
                 return zsignum(a);
- if (EXPECT(zsignum(a) <= 0, 0))
+ if (unlikely(zsignum(a) <= 0))
                 return -1;
         zsetu(libzahl_tmp_cmp, b);
         return zcmp(a, libzahl_tmp_cmp);
diff --git a/src/zdivmod.c b/src/zdivmod.c
index c77e34a..55d0e06 100644
--- a/src/zdivmod.c
+++ b/src/zdivmod.c
_AT_@ -15,19 +15,19 @@ zdivmod(z_t a, z_t b, z_t c, z_t d)
 
         sign = zsignum(c) * zsignum(d);
 
- if (EXPECT(!sign, 0)) {
+ if (unlikely(!sign)) {
                 if (zzero(c)) {
                         if (zzero(d)) {
- FAILURE(EDOM); /* Indeterminate form: 0 divided by 0 */
+ libzahl_failure(-ZERROR_0_DIV_0);
                         } else {
                                 SET_SIGNUM(a, 0);
                                 SET_SIGNUM(b, 0);
                         }
                 } else {
- FAILURE(EDOM); /* Undefined form: Division by 0 */
+ libzahl_failure(-ZERROR_DIV_0);
                 }
                 return;
- } else if (EXPECT((cmpmag = zcmpmag(c, d)) <= 0, 0)) {
+ } else if (unlikely((cmpmag = zcmpmag(c, d)) <= 0)) {
                   if (cmpmag == 0) {
                         zseti(a, sign);
                         SET_SIGNUM(b, 0);
diff --git a/src/zerror.c b/src/zerror.c
index c59b092..e4ed427 100644
--- a/src/zerror.c
+++ b/src/zerror.c
_AT_@ -2,6 +2,13 @@
 #include "internals.h"
 
 
+#define LIST_ERRORS\
+ X(ZERROR_0_POW_0, "indeterminate form: 0:th power of 0")\
+ X(ZERROR_0_DIV_0, "indeterminate form: 0 divided by 0")\
+ X(ZERROR_DIV_0, "undefined result: division by 0")\
+ X(ZERROR_NEGATIVE, "argument must be non-negative")
+
+
 enum zerror
 zerror(const char **desc)
 {
_AT_@ -10,10 +17,16 @@ zerror(const char **desc)
                         *desc = strerror(libzahl_error);
                 errno = libzahl_error;
                 return ZERROR_ERRNO_SET;
- } else {
- /* Current, we should not be able to get here. */
- if (desc)
+ }
+
+ if (desc) {
+ switch (-libzahl_error) {
+#define X(V, D) case V: *desc = D; break;
+ LIST_ERRORS
+#undef X
+ default:
                         abort();
- return -libzahl_error;
+ }
         }
+ return -libzahl_error;
 }
diff --git a/src/zfree.c b/src/zfree.c
index 2a1680a..5048048 100644
--- a/src/zfree.c
+++ b/src/zfree.c
_AT_@ -5,15 +5,13 @@
 void
 zfree(z_t a)
 {
- size_t i = 0, x, j;
+ size_t i, x, j;
         zahl_char_t **new;
 
- if (!a->chars)
+ if (unlikely(!a->chars))
                 return;
 
- for (x = a->alloced; x; x >>= 1)
- i += 1;
-
+ i = libzahl_msb_nz_zu(a->alloced);
         j = libzahl_pool_n[i]++;
 
         if (j == libzahl_pool_alloc[i]) {
diff --git a/src/zgcd.c b/src/zgcd.c
index 9b1d451..7c6f2bc 100644
--- a/src/zgcd.c
+++ b/src/zgcd.c
_AT_@ -16,22 +16,22 @@ zgcd(z_t a, z_t b, z_t c)
         zahl_char_t uv, bit;
         int neg;
 
- if (EXPECT(!zcmp(b, c), 0)) {
+ if (unlikely(!zcmp(b, c))) {
                 SET(a, b);
                 return;
         }
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET(a, c);
                 return;
         }
- if (EXPECT(zzero(c), 0)) {
+ if (unlikely(zzero(c))) {
                 SET(a, b);
                 return;
         }
 
         zabs(u, b);
         zabs(v, c);
- neg = zsignum(b) < 0 && zsignum(c) < 0;
+ neg = znegative2(b, c);
 
         min = MIN(u->used, v->used);
         for (; i < min; i++) {
diff --git a/src/zload.c b/src/zload.c
index 03bcbb9..877c95e 100644
--- a/src/zload.c
+++ b/src/zload.c
_AT_@ -8,7 +8,7 @@ zload(z_t a, const void *buffer)
         const char *buf = buffer;
         a->sign = *((const int *)buf), buf += sizeof(int);
         a->used = *((const size_t *)buf), buf += sizeof(size_t);
- if (EXPECT(!!a->sign, 1)) {
+ if (likely(a->sign)) {
                 ENSURE_SIZE(a, a->used);
                 zmemcpy(a->chars, (const zahl_char_t *)buf, a->used);
         }
diff --git a/src/zlsh.c b/src/zlsh.c
index 3daa01d..42894e0 100644
--- a/src/zlsh.c
+++ b/src/zlsh.c
_AT_@ -8,11 +8,11 @@ zlsh(z_t a, z_t b, size_t bits)
         size_t i, chars, cbits;
         zahl_char_t carry[] = {0, 0};
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
- if (EXPECT(!bits, 0)) {
+ if (unlikely(!bits)) {
                 SET(a, b);
                 return;
         }
_AT_@ -22,14 +22,14 @@ zlsh(z_t a, z_t b, size_t bits)
         cbits = BITS_PER_CHAR - bits;
 
         ENSURE_SIZE(a, b->used + chars);
- if (EXPECT(a == b, 1))
+ if (likely(a == b))
                 zmemmove(a->chars + chars, b->chars, b->used);
         else
                 zmemcpy(a->chars + chars, b->chars, b->used);
         zmemset(a->chars, 0, chars);
         a->used = b->used + chars;
 
- if (EXPECT(bits, 1)) { /* This if statement is very important in C. */
+ 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;
                         a->chars[i] <<= bits;
diff --git a/src/zmodmul.c b/src/zmodmul.c
index bb0aa03..26d1178 100644
--- a/src/zmodmul.c
+++ b/src/zmodmul.c
_AT_@ -6,7 +6,7 @@ void
 zmodmul(z_t a, z_t b, z_t c, z_t d)
 {
         /* TODO Montgomery modular multiplication */
- if (EXPECT(a == d, 0)) {
+ if (unlikely(a == d)) {
                 zset(libzahl_tmp_modmul, d);
                 zmul(a, b, c);
                 zmod(a, a, libzahl_tmp_modmul);
diff --git a/src/zmodpow.c b/src/zmodpow.c
index ed87ac5..9e002ff 100644
--- a/src/zmodpow.c
+++ b/src/zmodpow.c
_AT_@ -12,22 +12,22 @@ zmodpow(z_t a, z_t b, z_t c, z_t d)
         size_t i, j, n, bits;
         zahl_char_t x;
 
- if (EXPECT(zsignum(c) <= 0, 0)) {
+ if (unlikely(zsignum(c) <= 0)) {
                 if (zzero(c)) {
                         if (zzero(b))
- FAILURE(EDOM); /* Indeterminate form: 0:th power of 0 */
+ libzahl_failure(-ZERROR_0_POW_0);
                         else if (zzero(d))
- FAILURE(EDOM); /* Undefined form: Division by 0 */
+ libzahl_failure(-ZERROR_DIV_0);
                         zsetu(a, 1);
- } else if (zzero(b) || zzero(d)) {
- FAILURE(EDOM); /* Undefined form: Division by 0 */
+ } else if (zzero1(b, d)) {
+ libzahl_failure(-ZERROR_DIV_0);
                 } else {
                         SET_SIGNUM(a, 0);
                 }
                 return;
- } else if (EXPECT(zzero(d), 0)) {
- FAILURE(EDOM); /* Undefined form: Division by 0 */
- } else if (EXPECT(zzero(b), 0)) {
+ } else if (unlikely(zzero(d))) {
+ libzahl_failure(-ZERROR_DIV_0);
+ } else if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/zmodpowu.c b/src/zmodpowu.c
index 6dcb6b7..c9c8af5 100644
--- a/src/zmodpowu.c
+++ b/src/zmodpowu.c
_AT_@ -8,17 +8,17 @@
 void
 zmodpowu(z_t a, z_t b, unsigned long long int c, z_t d)
 {
- if (EXPECT(!c, 0)) {
+ if (unlikely(!c)) {
                 if (zzero(b))
- FAILURE(EDOM); /* Indeterminate form: 0:th power of 0 */
+ libzahl_failure(-ZERROR_0_POW_0);
                 else if (zzero(d))
- FAILURE(EDOM); /* Undefined form: Division by 0 */
+ libzahl_failure(-ZERROR_DIV_0);
                 else
                         zsetu(a, 1);
                 return;
- } else if (EXPECT(zzero(d), 0)) {
- FAILURE(EDOM); /* Undefined form: Division by 0 */
- } else if (EXPECT(zzero(b), 0)) {
+ } else if (unlikely(zzero(d))) {
+ libzahl_failure(-ZERROR_DIV_0);
+ } else if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/zmodsqr.c b/src/zmodsqr.c
index bdf0ea2..4eb6e51 100644
--- a/src/zmodsqr.c
+++ b/src/zmodsqr.c
_AT_@ -6,7 +6,7 @@ void
 zmodsqr(z_t a, z_t b, z_t c)
 {
         /* TODO What is the fastest way to do zmodsqr? */
- if (EXPECT(a == c, 0)) {
+ if (unlikely(a == c)) {
                 zset(libzahl_tmp_modsqr, c);
                 zsqr(a, b);
                 zmod(a, a, libzahl_tmp_modsqr);
diff --git a/src/zmul.c b/src/zmul.c
index c2cca10..ae02844 100644
--- a/src/zmul.c
+++ b/src/zmul.c
_AT_@ -22,7 +22,7 @@ zmul(z_t a, z_t b, z_t c)
         b_sign = zsignum(b);
         c_sign = zsignum(c);
 
- if (EXPECT(!b_sign || !c_sign, 0)) {
+ if (unlikely(!b_sign || !c_sign)) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/znot.c b/src/znot.c
index e1b114c..bebc55b 100644
--- a/src/znot.c
+++ b/src/znot.c
_AT_@ -7,7 +7,7 @@ znot(z_t a, z_t b)
 {
         size_t bits, i;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
_AT_@ -22,7 +22,5 @@ znot(z_t a, z_t b)
         if (bits)
                 a->chars[a->used - 1] &= ((zahl_char_t)1 << bits) - 1;
 
- TRIM(a);
- if (!a->used)
- SET_SIGNUM(a, 0);
+ TRIM_AND_ZERO(a);
 }
diff --git a/src/zor.c b/src/zor.c
index b67f5b3..4e7a2dc 100644
--- a/src/zor.c
+++ b/src/zor.c
_AT_@ -7,13 +7,13 @@ zor(z_t a, z_t b, z_t c)
 {
         size_t n, m;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 if (zzero(c))
                         SET_SIGNUM(a, 0);
                 else
                         SET(a, c);
                 return;
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 SET(a, b);
                 return;
         }
_AT_@ -28,7 +28,7 @@ zor(z_t a, z_t b, z_t c)
                         zmemcpy(a->chars + n, c->chars + n, m - n);
                 while (n--)
                         a->chars[n] |= c->chars[n];
- } else if (EXPECT(a == c, 0)) {
+ } else if (unlikely(a == c)) {
                 if (c->used < b->used)
                         zmemcpy(a->chars + n, b->chars + n, m - n);
                 while (n--)
_AT_@ -44,5 +44,5 @@ zor(z_t a, z_t b, z_t c)
         }
 
         a->used = m;
- SET_SIGNUM(a, (zsignum(b) > 0 && zsignum(c) > 0) * 2 - 1);
+ SET_SIGNUM(a, zpositive2(b, c) * 2 - 1);
 }
diff --git a/src/zperror.c b/src/zperror.c
index 37bd5c7..5d5d11a 100644
--- a/src/zperror.c
+++ b/src/zperror.c
_AT_@ -11,7 +11,11 @@ zperror(const char *prefix)
                 errno = libzahl_error;
                 perror(prefix);
         } else {
- /* Current, we should not be able to get here. */
- abort();
+ const char *desc;
+ zerror(&desc);
+ if (prefix && *prefix)
+ fprintf(stderr, "%s: %s\n", prefix, desc);
+ else
+ fprintf(stderr, "%s\n", desc);
         }
 }
diff --git a/src/zpow.c b/src/zpow.c
index 9eb5724..81f8098 100644
--- a/src/zpow.c
+++ b/src/zpow.c
_AT_@ -17,18 +17,18 @@ zpow(z_t a, z_t b, z_t c)
         size_t i, j, n, bits;
         zahl_char_t x;
 
- if (EXPECT(zsignum(c) <= 0, 0)) {
+ if (unlikely(zsignum(c) <= 0)) {
                 if (zzero(c)) {
                         if (zzero(b))
- FAILURE(EDOM); /* Indeterminate form: 0:th power of 0 */
+ libzahl_failure(-ZERROR_0_POW_0);
                         zsetu(a, 1);
                 } else if (zzero(b)) {
- FAILURE(EDOM); /* Undefined form: Division by 0 */
+ libzahl_failure(-ZERROR_DIV_0);
                 } else {
                         SET_SIGNUM(a, 0);
                 }
                 return;
- } else if (EXPECT(zzero(b), 0)) {
+ } else if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/zpowu.c b/src/zpowu.c
index 67cdc58..c4a2a64 100644
--- a/src/zpowu.c
+++ b/src/zpowu.c
_AT_@ -7,12 +7,12 @@
 void
 zpowu(z_t a, z_t b, unsigned long long int c)
 {
- if (EXPECT(!c, 0)) {
+ if (unlikely(!c)) {
                 if (zzero(b))
- FAILURE(EDOM); /* Indeterminate form: 0:th power of 0 */
+ libzahl_failure(-ZERROR_0_POW_0);
                 zsetu(a, 1);
                 return;
- } else if (EXPECT(zzero(b), 0)) {
+ } else if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/zptest.c b/src/zptest.c
index d6fa80d..005a2bd 100644
--- a/src/zptest.c
+++ b/src/zptest.c
_AT_@ -17,7 +17,7 @@ zptest(z_t witness, z_t n, int t)
 
         size_t i, r;
 
- if (EXPECT(zcmpu(n, 3) <= 0, 0)) {
+ if (unlikely(zcmpu(n, 3) <= 0)) {
                 if (zcmpu(n, 1) <= 0) {
                         if (witness)
                                 SET(witness, n);
_AT_@ -26,7 +26,7 @@ zptest(z_t witness, z_t n, int t)
                         return PRIME;
                 }
         }
- if (EXPECT(zeven(n), 0)) {
+ if (unlikely(zeven(n))) {
                 if (witness)
                         SET(witness, n);
                 return NONPRIME;
diff --git a/src/zrand.c b/src/zrand.c
index 48d4802..64fa7ed 100644
--- a/src/zrand.c
+++ b/src/zrand.c
_AT_@ -27,7 +27,7 @@ zrand_get_random_bits(z_t r, size_t bits, int fd)
         for (n = chars * sizeof(zahl_char_t); n;) {
                 read_just = read(fd, buf + read_total, n);
                 if (read_just < 0)
- FAILURE(errno);
+ libzahl_failure(errno);
                 read_total += (size_t)read_just;
                 n -= (size_t)read_just;
         }
_AT_@ -62,22 +62,22 @@ zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
                 pathname = SECURE_RANDOM_PATHNAME;
                 break;
         default:
- abort();
+ libzahl_failure(EINVAL);
         }
 
- if (EXPECT(zzero(n), 0)) {
+ if (unlikely(zzero(n))) {
                 SET_SIGNUM(r, 0);
                 return;
         }
 
         fd = open(pathname, O_RDONLY);
         if (fd < 0)
- FAILURE(errno);
+ libzahl_failure(errno);
 
         switch (dist) {
         case QUASIUNIFORM:
- if (EXPECT(zsignum(n) < 0, 0))
- FAILURE(EDOM); /* n must be non-negative. */
+ if (unlikely(znegative(n)))
+ libzahl_failure(-ZERROR_NEGATIVE);
                 bits = zbits(n);
                 zrand_get_random_bits(r, bits, fd);
                 zadd(r, r, libzahl_const_1);
_AT_@ -86,8 +86,8 @@ zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
                 break;
 
         case UNIFORM:
- if (EXPECT(zsignum(n) < 0, 0))
- FAILURE(EDOM); /* n must be non-negative. */
+ if (unlikely(znegative(n)))
+ libzahl_failure(-ZERROR_NEGATIVE);
                 bits = zbits(n);
                 do
                         zrand_get_random_bits(r, bits, fd);
_AT_@ -95,7 +95,7 @@ zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
                 break;
 
         default:
- abort();
+ libzahl_failure(EINVAL);
         }
 
         close(fd);
diff --git a/src/zrsh.c b/src/zrsh.c
index cc83ae5..163919d 100644
--- a/src/zrsh.c
+++ b/src/zrsh.c
_AT_@ -7,14 +7,14 @@ zrsh(z_t a, z_t b, size_t bits)
 {
         size_t i, chars, cbits;
 
- if (EXPECT(!bits, 0)) {
+ if (unlikely(!bits)) {
                 SET(a, b);
                 return;
         }
 
         chars = FLOOR_BITS_TO_CHARS(bits);
 
- if (EXPECT(zzero(b) || chars >= b->used || zbits(b) <= bits, 0)) {
+ if (unlikely(zzero(b) || chars >= b->used || zbits(b) <= bits)) {
                 SET_SIGNUM(a, 0);
                 return;
         }
_AT_@ -22,16 +22,16 @@ zrsh(z_t a, z_t b, size_t bits)
         bits = BITS_IN_LAST_CHAR(bits);
         cbits = BITS_PER_CHAR - bits;
 
- if (EXPECT(chars, 1) && EXPECT(a == b, 1)) {
+ if (likely(chars) && likely(a == b)) {
                 a->used -= chars;
                 zmemmove(a->chars, a->chars + chars, a->used);
- } else if (EXPECT(a != b, 0)) {
+ } else if (unlikely(a != b)) {
                 a->used = b->used - chars;
                 ENSURE_SIZE(a, a->used);
                 zmemcpy(a->chars, b->chars + chars, a->used);
         }
 
- if (EXPECT(bits, 0)) { /* This if statement is very important in C. */
+ if (unlikely(bits)) { /* This if statement is very important in C. */
                 a->chars[0] >>= bits;
                 for (i = 1; i < a->used; i++) {
                         a->chars[i - 1] |= a->chars[i] << cbits;
diff --git a/src/zsave.c b/src/zsave.c
index 07d43fa..8b08f2a 100644
--- a/src/zsave.c
+++ b/src/zsave.c
_AT_@ -9,7 +9,7 @@ zsave(z_t a, void *buffer)
                 char *buf = buffer;
                 *((int *)buf) = a->sign, buf += sizeof(int);
                 *((size_t *)buf) = a->used, buf += sizeof(size_t);
- if (EXPECT(!zzero(a), 1))
+ if (likely(!zzero(a)))
                         zmemcpy((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/src/zset.c b/src/zset.c
index 9bb2778..b0188fc 100644
--- a/src/zset.c
+++ b/src/zset.c
_AT_@ -5,7 +5,7 @@
 void
 zset(z_t a, z_t b)
 {
- if (EXPECT(b->sign == 0, 0)) {
+ if (unlikely(b->sign == 0)) {
                 a->sign = 0;
         } else {
                 a->sign = b->sign;
diff --git a/src/zseti.c b/src/zseti.c
index d3514fb..e1116b6 100644
--- a/src/zseti.c
+++ b/src/zseti.c
_AT_@ -5,7 +5,7 @@
 void
 zseti(z_t a, long long int b)
 {
- if (EXPECT(b >= 0, 0)) {
+ if (unlikely(b >= 0)) {
                 zsetu(a, (unsigned long long int)b);
         } else {
                 zsetu(a, (unsigned long long int)-b);
diff --git a/src/zsets.c b/src/zsets.c
index 24ca082..bddc9ec 100644
--- a/src/zsets.c
+++ b/src/zsets.c
_AT_@ -13,12 +13,12 @@ zsets(z_t a, const char *str)
 
         str += neg || (*str == '+');
 
- if (EXPECT(!*str, 0)) {
+ if (unlikely(!*str)) {
                 errno = EINVAL;
                 return -1;
         }
         for (str_end = str; *str_end; str_end++) {
- if (EXPECT(!isdigit(*str_end), 0)) {
+ if (unlikely(!isdigit(*str_end))) {
                         errno = EINVAL;
                         return -1;
                 }
diff --git a/src/zsplit.c b/src/zsplit.c
index 68810d2..ab2dc78 100644
--- a/src/zsplit.c
+++ b/src/zsplit.c
_AT_@ -5,13 +5,13 @@
 void
 zsplit(z_t high, z_t low, z_t a, size_t delim)
 {
- if (EXPECT(zzero(a), 0)) {
+ if (unlikely(zzero(a))) {
                 SET_SIGNUM(high, 0);
                 SET_SIGNUM(low, 0);
                 return;
         }
 
- if (EXPECT(high == a, 0)) {
+ if (unlikely(high == a)) {
                 ztrunc(low, a, delim);
                 zrsh(high, a, delim);
         } else {
diff --git a/src/zsqr.c b/src/zsqr.c
index 9601eb6..bd03128 100644
--- a/src/zsqr.c
+++ b/src/zsqr.c
_AT_@ -13,7 +13,7 @@ zsqr(z_t a, z_t b)
         z_t z0, z1, z2, high, low;
         int sign;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
diff --git a/src/zstr.c b/src/zstr.c
index 81a9674..dfcdf23 100644
--- a/src/zstr.c
+++ b/src/zstr.c
_AT_@ -16,16 +16,12 @@ char *
 zstr(z_t a, char *b)
 {
         char buf[19 + 1];
- size_t n, len;
+ size_t n, len, neg;
         char overridden = 0;
- int neg;
 
         if (zzero(a)) {
- if (!b) {
- b = malloc(2);
- if (!b)
- FAILURE(errno);
- }
+ if (!b && !(b = malloc(2)))
+ libzahl_failure(errno);
                 b[0] = '0';
                 b[1] = 0;
                 return b;
_AT_@ -33,13 +29,10 @@ zstr(z_t a, char *b)
 
         n = zstr_length(a, 10);
 
- if (!b) {
- b = malloc(n + 1);
- if (!b)
- FAILURE(errno);
- }
+ if (!b && !(b = malloc(n + 1)))
+ libzahl_failure(errno);
 
- neg = zsignum(a) < 0;
+ neg = znegative(a);
         zabs(num, a);
         b[0] = '-';
         b += neg;
diff --git a/src/zsub.c b/src/zsub.c
index bf918da..e769e32 100644
--- a/src/zsub.c
+++ b/src/zsub.c
_AT_@ -10,11 +10,11 @@ zsub_unsigned(z_t a, z_t b, z_t c)
         size_t i, n;
         int magcmp;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 zabs(a, c);
                 zneg(a, a);
                 return;
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 zabs(a, b);
                 return;
         }
_AT_@ -61,15 +61,15 @@ zsub_unsigned(z_t a, z_t b, z_t c)
 void
 zsub(z_t a, z_t b, z_t c)
 {
- if (EXPECT(b == c, 0)) {
+ if (unlikely(b == c)) {
                 SET_SIGNUM(a, 0);
- } else if (EXPECT(zzero(b), 0)) {
+ } else if (unlikely(zzero(b))) {
                 zneg(a, c);
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 SET(a, b);
- } else if (EXPECT((zsignum(b) | zsignum(c)) < 0, 0)) {
- if (zsignum(b) < 0) {
- if (zsignum(c) < 0) {
+ } else if (unlikely(znegative1(b, c))) {
+ if (znegative(b)) {
+ if (znegative(c)) {
                                 zsub_unsigned(a, c, b);
                         } else {
                                 zadd_unsigned(a, b, c);
diff --git a/src/ztrunc.c b/src/ztrunc.c
index 7dcafd9..91d2a92 100644
--- a/src/ztrunc.c
+++ b/src/ztrunc.c
_AT_@ -8,7 +8,7 @@ ztrunc(z_t a, z_t b, size_t bits)
         zahl_char_t mask = 1;
         size_t chars;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 SET_SIGNUM(a, 0);
                 return;
         }
_AT_@ -16,14 +16,14 @@ ztrunc(z_t a, z_t b, size_t bits)
         chars = CEILING_BITS_TO_CHARS(bits);
         a->sign = b->sign;
         a->used = MIN(chars, b->used);
- if (EXPECT(a->used < chars, 0))
+ if (unlikely(a->used < chars))
                 bits = 0;
- if (EXPECT(a != b, 1)) {
+ if (likely(a != b)) {
                 ENSURE_SIZE(a, a->used);
                 zmemcpy(a->chars, b->chars, a->used);
         }
         bits = BITS_IN_LAST_CHAR(bits);
- if (EXPECT(!!bits, 1)) {
+ if (likely(bits)) {
                 mask <<= bits;
                 mask -= 1;
                 a->chars[a->used - 1] &= mask;
diff --git a/src/zxor.c b/src/zxor.c
index da56a24..876591a 100644
--- a/src/zxor.c
+++ b/src/zxor.c
_AT_@ -7,13 +7,13 @@ zxor(z_t a, z_t b, z_t c)
 {
         size_t n, m;
 
- if (EXPECT(zzero(b), 0)) {
+ if (unlikely(zzero(b))) {
                 if (zzero(c))
                         SET_SIGNUM(a, 0);
                 else
                         SET(a, c);
                 return;
- } else if (EXPECT(zzero(c), 0)) {
+ } else if (unlikely(zzero(c))) {
                 SET(a, b);
                 return;
         }
_AT_@ -28,7 +28,7 @@ zxor(z_t a, z_t b, z_t c)
                         zmemcpy(a->chars + n, c->chars + n, m - n);
                 while (n--)
                         a->chars[n] ^= c->chars[n];
- } else if (EXPECT(a == c, 0)) {
+ } else if (unlikely(a == c)) {
                 if (c->used < b->used)
                         zmemcpy(a->chars + n, b->chars + n, m - n);
                 while (n--)
diff --git a/test.c b/test.c
index 624abb0..c4f146c 100644
--- a/test.c
+++ b/test.c
_AT_@ -112,7 +112,7 @@ main(void)
         assert(zodd(_2), == 0);
         assert(zzero(_2), == 0);
         assert(zsignum(_2), == 1);
-
+
         assert((zneg(_2, _2), zsignum(_2)), == -1); zneg(_2, _2);
         assert(zsignum(_2), == 1);
 
diff --git a/zahl.h b/zahl.h
index 89fc6f8..d051bc1 100644
--- a/zahl.h
+++ b/zahl.h
_AT_@ -3,6 +3,9 @@
 /* Warning: libzahl is not thread-safe. */
 /* Caution: Do not use libzahl for cryptographic applications, use a specialised library. */
 
+#ifndef ZAHL_H
+#define ZAHL_H
+
 
 #include <stddef.h>
 #include <setjmp.h>
_AT_@ -27,7 +30,11 @@ enum zranddev { FAST_RANDOM = 0, SECURE_RANDOM };
 enum zranddist { QUASIUNIFORM = 0, UNIFORM };
 
 enum zerror {
- ZERROR_ERRNO_SET = 0
+ ZERROR_ERRNO_SET = 0, /* Please refer to errno. */
+ ZERROR_0_POW_0, /* Indeterminate form: 0:th power of 0. (Translatable to EDOM.) */
+ ZERROR_0_DIV_0, /* Indeterminate form: 0 divided by 0. (Translatable to EDOM.) */
+ ZERROR_DIV_0, /* Undefined result: Division by 0. (Translatable to EDOM.) */
+ ZERROR_NEGATIVE /* Argument must be non-negative. (Translatable to EDOM or EINVAL.) */
 };
 
 
_AT_@ -160,7 +167,7 @@ zlsb(z_t a)
                 return SIZE_MAX;
         for (; !a->chars[i]; i++);
         i *= 8 * sizeof(zahl_char_t);
- i += __builtin_ctzll(a->chars[i]);
+ i += (size_t)__builtin_ctzll(a->chars[i]);
         return i;
 }
 #else
_AT_@ -190,7 +197,7 @@ zbits(z_t 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 -= __builtin_clzll(a->chars[a->used - 1]);
+ rc -= (size_t)__builtin_clzll(a->chars[a->used - 1]);
         return rc;
 }
 #else
_AT_@ -208,3 +215,6 @@ zbits(z_t a)
         return rc;
 }
 #endif
+
+
+#endif
Received on Sun Mar 13 2016 - 23:58:34 CET

This archive was generated by hypermail 2.3.0 : Mon Mar 14 2016 - 00:00:28 CET