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