commit aff09967d194d062ae8d83c0fbe1edf158804ef9
parent 0a7e36380717fe926d43ab30ef6162db9bd71723
Author: Mattias Andrée <maandree@kth.se>
Date: Fri, 4 Mar 2016 10:45:10 +0100
Clean up, fix a few bugs, and add a test
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
20 files changed, 792 insertions(+), 49 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,3 +3,4 @@
*.su
*.a
*.so
+/test
diff --git a/Makefile b/Makefile
@@ -56,7 +56,7 @@ FUN =\
OBJ = $(FUN:=.o)
MAN = $(foreach F,$(FUN),man/$(F).3) man/libzahl.7
-all: libzahl.a
+all: libzahl.a test
%.o: src/%.c $(HDR) config.mk
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
@@ -65,7 +65,10 @@ libzahl.a: $(OBJ)
$(AR) rc $@ $?
$(RANLIB) $@
+test: test.c libzahl.a
+ $(CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) -o $@ $^
+
clean:
- -rm -- *.o *.su *.a *.so 2>/dev/null
+ -rm -- *.o *.su *.a *.so test 2>/dev/null
.PHONY: all clean
diff --git a/src/internals.h b/src/internals.h
@@ -62,7 +62,8 @@ extern int libzahl_set_up;
#define zmemcmp(a, b, n) memcmp(a, b, (n) * sizeof(zahl_char_t))
#define SET_SIGNUM(a, signum) ((a)->sign = (signum))
-#define SET(a, b) do { if (a != b) zset(a, b); } while (0)
+#define SET(a, b) do { if ((a) != (b)) zset(a, b); } while (0)
+#define ENSURE_SIZE(a, n) do { if ((a)->alloced < (n)) zahl_realloc(a, (n)); } while (0)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
diff --git a/src/zadd.c b/src/zadd.c
@@ -15,8 +15,7 @@ zadd_unsigned(z_t a, z_t b, z_t c)
}
size = MAX(b->used, c->used);
- if (a->alloced < size + 1)
- zahl_realloc(a, size + 1);
+ ENSURE_SIZE(a, size + 1);
a->chars[size] = 0;
n = b->used + c->used - size;
diff --git a/src/zand.c b/src/zand.c
@@ -28,8 +28,7 @@ found_highest:
while (n--)
a->chars[n] &= b->chars[n];
} else {
- if (a->alloced < a->used)
- zahl_realloc(a, a->used);
+ ENSURE_SIZE(a, a->used);
zmemcpy(a->chars, c->chars, a->used);
while (n--)
a->chars[n] &= b->chars[n];
diff --git a/src/zbset.c b/src/zbset.c
@@ -5,12 +5,12 @@
void
zbset(z_t a, z_t b, size_t bit, int action)
{
- zahl_char_t x = 1;
+ zahl_char_t mask = 1;
size_t chars;
chars = FLOOR_BITS_TO_CHARS(bit);
bit = BITS_IN_LAST_CHAR(bit);
- x <<= bit;
+ mask <<= bit;
SET(a, b);
@@ -20,19 +20,19 @@ zbset(z_t a, z_t b, size_t bit, int action)
SET_SIGNUM(a, 1);
}
if (a->used <= chars) {
- if (a->alloced <= chars)
- zahl_realloc(a, chars + 1);
- zmemset(a->chars + a->used, 0, chars - a->used + 1);
+ ENSURE_SIZE(a, chars + 1);
+ zmemset(a->chars + a->used, 0, chars + 1 - a->used);
+ a->used = chars + 1;
}
}
if (action > 0) {
- a->chars[chars] |= x;
+ a->chars[chars] |= mask;
return;
} else if (action < 0) {
- a->chars[chars] ^= x;
- } else if (a->used > chars) {
- a->chars[chars] &= ~x;
+ a->chars[chars] ^= mask;
+ } else if (chars < a->used) {
+ a->chars[chars] &= ~mask;
}
while (a->used && !a->chars[a->used - 1])
diff --git a/src/zload.c b/src/zload.c
@@ -6,11 +6,12 @@ size_t
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);
- a->alloced = *((const size_t *)buf), buf += sizeof(size_t);
- if (a->alloced)
- zahl_realloc(a, a->alloced);
+ size_t alloced;
+ a->sign = *((const int *)buf), buf += sizeof(int);
+ a->used = *((const size_t *)buf), buf += sizeof(size_t);
+ alloced = *((const size_t *)buf), buf += sizeof(size_t);
+ if (alloced)
+ ENSURE_SIZE(a, alloced);
else
a->chars = 0;
if (!zzero(a))
diff --git a/src/zlsh.c b/src/zlsh.c
@@ -22,8 +22,7 @@ zlsh(z_t a, z_t b, size_t bits)
cbits = BITS_PER_CHAR - 1 - bits;
a->used = b->used + chars;
- if (a->alloced < a->used)
- zahl_realloc(a, a->used);
+ ENSURE_SIZE(a, a->used);
if (a == b)
zmemmove(a->chars + chars, b->chars, a->used);
else
@@ -36,8 +35,7 @@ zlsh(z_t a, z_t b, size_t bits)
a->chars[i] |= carry[i & 1];
}
if (carry[i & 1]) {
- if (a->alloced == a->used)
- zahl_realloc(a, a->alloced << 1);
+ ENSURE_SIZE(a, a->alloced << 1);
a->chars[i] = carry[i & 1];
a->used++;
}
diff --git a/src/zmodpow.c b/src/zmodpow.c
@@ -42,7 +42,7 @@ zmodpow(z_t a, z_t b, z_t c, z_t d)
zset(td, d);
zsetu(a, 1);
- for (i = 0; i < n; i++) {
+ for (i = 0; i < n; i++) { /* Remember, n is floored. */
x = tc->chars[i];
for (j = BITS_PER_CHAR; j--; x >>= 1) {
if (x & 1)
@@ -50,4 +50,10 @@ zmodpow(z_t a, z_t b, z_t c, z_t d)
zmodsqr(tb, tb, td);
}
}
+ x = tc->chars[i];
+ for (; x; x >>= 1) {
+ if (x & 1)
+ zmodmul(a, a, tb, td);
+ zmodsqr(tb, tb, td);
+ }
}
diff --git a/src/zmul.c b/src/zmul.c
@@ -24,7 +24,7 @@ zmul(z_t a, z_t b, z_t c)
b_sign = zsignum(b);
c_sign = zsignum(c);
- if (m <= 16 && m2 <= 16) {
+ if (m <= BITS_PER_CHAR / 2 && m2 <= BITS_PER_CHAR / 2) {
zsetu(a, b->chars[0] * c->chars[0]);
SET_SIGNUM(a, b_sign * c_sign);
return;
diff --git a/src/zor.c b/src/zor.c
@@ -21,8 +21,7 @@ zor(z_t a, z_t b, z_t c)
m = MAX(b->used, c->used);
n = b->used + c->used - m;
- if (a->alloced < m)
- zahl_realloc(a, m);
+ ENSURE_SIZE(a, m);
if (a == b) {
zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
diff --git a/src/zpow.c b/src/zpow.c
@@ -37,7 +37,7 @@ zpow(z_t a, z_t b, z_t c)
zset(tc, c);
zsetu(a, 1);
- for (i = 0; i < n; i++) {
+ for (i = 0; i < n; i++) { /* Remember, n is floored. */
x = tc->chars[i];
for (j = BITS_PER_CHAR; j--; x >>= 1) {
if (x & 1)
@@ -45,4 +45,10 @@ zpow(z_t a, z_t b, z_t c)
zsqr(tb, tb);
}
}
+ x = tc->chars[i];
+ for (; x; x >>= 1) {
+ if (x & 1)
+ zmul(a, a, tb);
+ zsqr(tb, tb);
+ }
}
diff --git a/src/zrand.c b/src/zrand.c
@@ -16,15 +16,16 @@
static void
zrand_get_random_bits(z_t r, size_t bits, int fd)
{
- size_t read_total, n, chars = CEILING_BITS_TO_CHARS(bits);
+ size_t read_total = 0, n, chars = CEILING_BITS_TO_CHARS(bits);
ssize_t read_just;
- uint32_t mask = 1;
+ zahl_char_t mask = 1;
+ char *buf;
- if (r->alloced < chars)
- zahl_realloc(r, chars);
+ ENSURE_SIZE(r, chars);
+ buf = (char *)(r->chars);
- for (n = chars << LB_BITS_PER_CHAR; n;) {
- read_just = read(fd, (char *)(r->chars) + read_total, n);
+ for (n = chars * sizeof(zahl_char_t); n;) {
+ read_just = read(fd, buf + read_total, n);
if (read_just < 0)
FAILURE_JUMP();
read_total += (size_t)read_just;
@@ -75,6 +76,10 @@ zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
switch (dist) {
case QUASIUNIFORM:
+ if (zsignum(n) < 0) {
+ errno = EDOM; /* n must be non-negative. */
+ FAILURE_JUMP();
+ }
bits = zbits(n);
zrand_get_random_bits(r, bits, fd);
zadd(r, r, libzahl_const_1);
@@ -83,10 +88,14 @@ zrand(z_t r, enum zranddev dev, enum zranddist dist, z_t n)
break;
case UNIFORM:
+ if (zsignum(n) < 0) {
+ errno = EDOM; /* n must be non-negative. */
+ FAILURE_JUMP();
+ }
bits = zbits(n);
do
zrand_get_random_bits(r, bits, fd);
- while (zcmp(r, n) > 0);
+ while (zcmpmag(r, n) > 0);
break;
default:
diff --git a/src/zrsh.c b/src/zrsh.c
@@ -27,8 +27,7 @@ zrsh(z_t a, z_t b, size_t bits)
zmemmove(a->chars, a->chars + chars, a->used);
} else if (a != b) {
a->used = b->used - chars;
- if (a->alloced < a->used)
- zahl_realloc(a, a->used);
+ ENSURE_SIZE(a, a->used);
zmemcpy(a->chars, b->chars + chars, a->used);
}
diff --git a/src/zset.c b/src/zset.c
@@ -8,8 +8,7 @@ zset(z_t a, z_t b)
if (zzero(b)) {
SET_SIGNUM(a, 0);
} else {
- if (a->alloced < b->alloced)
- zahl_realloc(a, b->alloced);
+ ENSURE_SIZE(a, b->alloced);
a->sign = b->sign;
a->used = b->used;
zmemcpy(a->chars, b->chars, b->used);
diff --git a/src/zsetu.c b/src/zsetu.c
@@ -11,8 +11,7 @@ zsetu(z_t a, unsigned long long int b)
SET_SIGNUM(a, 0);
return;
}
- if (a->alloced < SIZE_MULTIPLE(b, *(a->chars)))
- zahl_realloc(a, SIZE_MULTIPLE(b, *(a->chars)));
+ ENSURE_SIZE(a, SIZE_MULTIPLE(b, *(a->chars)));
SET_SIGNUM(a, 1);
a->used = 0;
while (b) {
diff --git a/src/zsqr.c b/src/zsqr.c
@@ -20,7 +20,7 @@ zsqr(z_t a, z_t b)
m2 = zbits(b);
- if (m2 <= 16) {
+ if (m2 <= BITS_PER_CHAR / 2) {
zsetu(a, b->chars[0] * b->chars[0]);
SET_SIGNUM(a, 1);
return;
diff --git a/src/ztrunc.c b/src/ztrunc.c
@@ -18,9 +18,10 @@ ztrunc(z_t a, z_t b, size_t bits)
a->used = MIN(chars, b->used);
if (a->used < chars)
bits = 0;
- if (a->alloced < b->alloced)
- zahl_realloc(a, b->alloced);
- zmemcpy(a->chars, b->chars, a->used);
+ if (a != b) {
+ ENSURE_SIZE(a, b->alloced);
+ zmemcpy(a->chars, b->chars, a->used);
+ }
bits = BITS_IN_LAST_CHAR(bits);
if (bits) {
mask <<= bits;
diff --git a/src/zxor.c b/src/zxor.c
@@ -26,8 +26,7 @@ zxor(z_t a, z_t b, z_t c)
return;
}
- if (a->alloced < m)
- zahl_realloc(a, m);
+ ENSURE_SIZE(a, m);
if (a == b) {
zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
diff --git a/test.c b/test.c
@@ -0,0 +1,724 @@
+/* See LICENSE file for copyright and license details. */
+#include "zahl.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define assert(expr, expected)\
+ do {\
+ int got = (expr);\
+ if (!(got expected)) {\
+ fprintf(stderr,\
+ "Failure at line %i: %s, expected %s, but got %i.\n",\
+ __LINE__, #expr, #expected, got);\
+ return 1;\
+ }\
+ } while (0)
+
+#define assert_zu(expr, expected)\
+ do {\
+ size_t got = (expr);\
+ if (got != (expected)) {\
+ fprintf(stderr,\
+ "Failure at line %i: %s, expected %zu, but got %zu.\n",\
+ __LINE__, #expr, (size_t)(expected), got);\
+ return 1;\
+ }\
+ } while (0)
+
+#define assert_s(expr, expected)\
+ do {\
+ const char *got = (expr);\
+ if (strcmp(got, expected)) {\
+ fprintf(stderr,\
+ "Failure at line %i: %s, expected %s, but got %s.\n",\
+ __LINE__, #expr, expected, got);\
+ return 1;\
+ }\
+ } while (0)
+
+int
+main(void)
+{
+ /* static because otherwise it would have to be volatile yeilding a lot of stupid
+ * warnings. auto variables are not guaranteed to be readable after a long jump. */
+ static z_t a, b, c, d, _0, _1, _2, _3;
+
+ jmp_buf env;
+ char buf[1000];
+ int ret = 0;
+ size_t n;
+
+ if (setjmp(env)) {
+ ret = 1;
+ goto done;
+ }
+
+ zsetup(env);
+ zinit(a), zinit(b), zinit(c), zinit(d), zinit(_0), zinit(_1), zinit(_2), zinit(_3);
+
+ zsetu(_0, 0);
+ zsetu(_1, 1);
+ zsetu(_2, 2);
+ zsetu(_3, 3);
+
+ assert(zeven(_0), == 1);
+ assert(zodd(_0), == 0);
+ assert(zzero(_0), == 1);
+ assert(zsignum(_0), == 0);
+ assert(zeven(_1), == 0);
+ assert(zodd(_1), == 1);
+ assert(zzero(_1), == 0);
+ assert(zsignum(_1), == 1);
+ assert(zeven(_2), == 1);
+ assert(zodd(_2), == 0);
+ assert(zzero(_2), == 0);
+ assert(zsignum(_2), == 1);
+
+ zswap(_1, _2);
+ assert(zeven(_2), == 0);
+ assert(zodd(_2), == 1);
+ assert(zzero(_2), == 0);
+ assert(zsignum(_2), == 1);
+ assert(zeven(_1), == 1);
+ assert(zodd(_1), == 0);
+ assert(zzero(_1), == 0);
+ assert(zsignum(_1), == 1);
+ zswap(_2, _1);
+ assert(zeven(_1), == 0);
+ assert(zodd(_1), == 1);
+ assert(zzero(_1), == 0);
+ assert(zsignum(_1), == 1);
+ assert(zeven(_2), == 1);
+ 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);
+
+ assert(zcmp(_0, _0), == 0);
+ assert(zcmp(_1, _1), == 0);
+ assert(zcmp(_0, _1), < 0);
+ assert(zcmp(_1, _0), > 0);
+ assert(zcmp(_1, _2), < 0);
+ assert(zcmp(_2, _1), > 0);
+ assert(zcmp(_0, _2), < 0);
+ assert(zcmp(_2, _0), > 0);
+
+ zbset(a, _0, 0, 1);
+ assert(zcmp(a, _1), == 0);
+ zbset(a, a, 1, 1);
+ assert(zcmp(a, _3), == 0);
+ zbset(a, a, 0, 0);
+ assert(zcmp(a, _2), == 0);
+ zbset(a, a, 0, 0);
+ assert(zcmp(a, _2), == 0);
+ zbset(a, a, 0, -1);
+ assert(zcmp(a, _3), == 0);
+ zbset(a, a, 0, -1);
+ assert(zcmp(a, _2), == 0);
+
+ zadd(a, _0, _1);
+ assert(zsignum(a), == 1);
+ assert(zcmp(a, _1), == 0);
+ assert(zcmpi(a, 1), == 0);
+ assert(zcmpu(a, 1), == 0);
+ zneg(a, a);
+ assert(zsignum(a), == -1);
+ assert(zcmp(a, _1), < 0);
+ assert(zcmpi(a, 1), < 0);
+ assert(zcmpu(a, 1), < 0);
+ zadd(a, _2, _0);
+ assert(zsignum(a), == 1);
+ assert(zcmp(a, _2), == 0);
+ assert(zcmpi(a, 2), == 0);
+ assert(zcmpu(a, 2), == 0);
+ zneg(a, a);
+ assert(zsignum(a), == -1);
+ assert(zcmp(a, _2), < 0);
+ assert(zcmpi(a, 2), < 0);
+ assert(zcmpu(a, 2), < 0);
+ assert(zsignum(_1), == 1);
+ zadd(a, _1, _1);
+ assert(zsignum(a), == 1);
+ assert(zcmp(a, _2), == 0);
+ assert(zcmpi(a, 2), == 0);
+ assert(zcmpu(a, 2), == 0);
+ zset(b, _1);
+ zadd(a, b, _1);
+ assert(zsignum(a), == 1);
+ assert(zcmp(a, _2), == 0);
+ assert(zcmpi(a, 2), == 0);
+ assert(zcmpu(a, 2), == 0);
+ zneg(a, a);
+ zset(b, _2);
+ zneg(b, b);
+ assert(zsignum(a), == -1);
+ assert(zcmp(a, b), == 0);
+ assert(zcmp(a, _2), < 0);
+ assert(zcmpmag(a, b), == 0);
+ assert(zcmpmag(a, _2), == 0);
+ assert(zcmpi(a, 2), < 0);
+ assert(zcmpu(a, 2), < 0);
+ assert(zcmpi(a, -2), == 0);
+ assert((zneg(_2, _2), zcmp(a, _2)), == 0); zneg(_2, _2);
+ zadd(a, _1, _2);
+ assert(zsignum(a), == 1);
+ assert(zcmp(a, _2), > 0);
+ assert(zcmpi(a, 2), > 0);
+ assert(zcmpu(a, 2), > 0);
+ zneg(a, a);
+ zset(b, _2);
+ zneg(b, b);
+ assert(zsignum(a), == -1);
+ assert(zcmpmag(a, _2), > 0);
+ assert(zcmpmag(a, b), > 0);
+ assert(zcmp(a, b), < 0);
+ assert(zcmp(a, _2), < 0);
+ assert(zcmpi(a, 2), < 0);
+ assert(zcmpu(a, 2), < 0);
+ assert(zcmpi(a, -2), < 0);
+ assert((zneg(_2, _2), zcmp(a, _2)), < 0); zneg(_2, _2);
+ zneg(b, _3);
+ assert(zcmp(a, b), == 0);
+
+ zsub(a, _2, _1);
+ assert(zcmpmag(_2, _1), > 0);
+ assert(zcmpmag(_2, _0), > 0);
+ assert(zcmpmag(_1, _0), > 0);
+ zsub(b, _1, _2);
+ assert(zcmpmag(_2, _0), > 0);
+ assert(zcmpmag(_1, _0), > 0);
+ assert(zcmpmag(_2, _1), > 0);
+ assert(zcmpmag(a, b), == 0);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, b), > 0);
+ assert(zcmp(a, _1), == 0);
+ assert(zcmp(b, _1), < 0);
+ zsub(a, _1, _1);
+ assert(zcmp(a, _0), == 0);
+ zseti(b, 0);
+ zsetu(c, 0);
+ zsub(a, b, c);
+ assert(zcmp(a, _0), == 0);
+ assert(zcmpmag(_2, _1), > 0);
+ assert(zcmp(_2, _1), > 0);
+ zsub(a, _2, _1);
+ assert(zsignum(a), == 1);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), == 0);
+ zsub(a, a, _1);
+ assert(zcmp(a, _0), == 0);
+ zsub(a, a, _0);
+ assert(zcmp(a, _0), == 0);
+ zsub(a, _1, _2);
+ assert(zcmp(a, _1), < 0);
+ assert(zcmpmag(a, _1), == 0);
+ zabs(a, a);
+ assert(zcmp(a, _1), == 0);
+ zabs(a, a);
+ assert(zcmp(a, _1), == 0);
+ zabs(a, _1);
+ assert(zcmp(a, _1), == 0);
+ zabs(a, _0);
+ assert(zcmp(a, _0), == 0);
+
+ zseti(b, -1);
+ zseti(c, -2);
+ zadd(a, _0, b);
+ assert(zcmp(a, _0), < 0);
+ assert(zcmpi(a, -1), == 0);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), < 0);
+ zadd(a, b, _0);
+ assert(zcmp(a, _0), < 0);
+ assert(zcmpi(a, -1), == 0);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), < 0);
+ zadd(a, b, c);
+ assert(zcmp(a, c), < 0);
+ assert(zcmpmag(a, _2), > 0);
+ zadd(a, c, b);
+ assert(zcmp(a, c), < 0);
+ assert(zcmpmag(a, _2), > 0);
+ zadd(a, b, _1);
+ assert(zcmp(a, _0), == 0);
+ assert(zcmpmag(a, _0), == 0);
+ zadd(a, _1, b);
+ assert(zcmp(a, _0), == 0);
+ assert(zcmpmag(a, _0), == 0);
+
+ zneg(b, _1);
+ zneg(c, _2);
+ zsub(a, _0, b);
+ assert(zcmp(a, _1), == 0);
+ zsub(a, b, _0);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), < 0);
+ zsub(a, b, c);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), == 0);
+ zsub(a, c, b);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), < 0);
+ zsub(a, b, _1);
+ assert(zcmpmag(a, _2), == 0);
+ assert(zcmp(a, _2), < 0);
+ assert(zcmp(a, c), == 0);
+ zsub(a, _1, b);
+ assert(zcmp(b, _1), < 0);
+ assert(zcmpmag(b, _1), == 0);
+ assert(zcmp(a, _2), == 0);
+
+ zsetu(a, 1000);
+ zsetu(b, 0);
+ assert(zcmp(a, b), != 0);
+ n = zsave(a, buf);
+ assert(n, > 0);
+ assert_zu(zload(b, buf), n);
+ assert(zcmp(a, b), == 0);
+
+ zneg(b, _1);
+ zneg(c, _2);
+
+ assert((zadd_unsigned(a, b, c), zcmp(a, _3)), == 0);
+ assert((zadd_unsigned(a, b, c), zcmp(a, _3)), == 0);
+ assert((zadd_unsigned(a, b, _2), zcmp(a, _3)), == 0);
+ assert((zadd_unsigned(a, _1, c), zcmp(a, _3)), == 0);
+
+ assert((zsub_unsigned(a, _2, _1), zcmp(a, _1)), == 0);
+ assert((zsub_unsigned(a, _2, b), zcmp(a, _1)), == 0);
+ assert((zsub_unsigned(a, c, _1), zcmp(a, _1)), == 0);
+ assert((zsub_unsigned(a, c, b), zcmp(a, _1)), == 0);
+
+ assert((zsub_unsigned(a, _1, _2), zcmp(a, b)), == 0);
+ assert((zsub_unsigned(a, b, _2), zcmp(a, b)), == 0);
+ assert((zsub_unsigned(a, _1, c), zcmp(a, b)), == 0);
+ assert((zsub_unsigned(a, b, c), zcmp(a, b)), == 0);
+
+ assert_zu(zbits(_0), 1);
+ assert_zu(zbits(_1), 1);
+ assert_zu(zbits(_2), 2);
+ assert_zu(zbits(_3), 2);
+
+ assert_zu(zlsb(_0), SIZE_MAX);
+ assert_zu(zlsb(_1), 0);
+ assert_zu(zlsb(_2), 1);
+ assert_zu(zlsb(_3), 0);
+
+ assert((zand(a, _0, _0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zand(a, _0, _1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zand(a, _0, _2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zand(a, _0, _3), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zand(a, _1, _1), zcmp(a, _1)), == 0);
+ assert((zand(a, _1, _2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zand(a, _1, _3), zcmp(a, _1)), == 0);
+ assert((zand(a, _2, _2), zcmp(a, _2)), == 0);
+ assert((zand(a, _2, _3), zcmp(a, _2)), == 0);
+ assert((zand(a, _3, _3), zcmp(a, _3)), == 0);
+
+ assert((zor(a, _0, _0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zor(a, _0, _1), zcmp(a, _1)), == 0);
+ assert((zor(a, _0, _2), zcmp(a, _2)), == 0);
+ assert((zor(a, _0, _3), zcmp(a, _3)), == 0);
+ assert((zor(a, _1, _1), zcmp(a, _1)), == 0);
+ assert((zor(a, _1, _2), zcmp(a, _3)), == 0);
+ assert((zor(a, _1, _3), zcmp(a, _3)), == 0);
+ assert((zor(a, _2, _2), zcmp(a, _2)), == 0);
+ assert((zor(a, _2, _3), zcmp(a, _3)), == 0);
+ assert((zor(a, _3, _3), zcmp(a, _3)), == 0);
+
+ assert((zxor(a, _0, _0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zxor(a, _0, _1), zcmp(a, _1)), == 0);
+ assert((zxor(a, _0, _2), zcmp(a, _2)), == 0);
+ assert((zxor(a, _0, _3), zcmp(a, _3)), == 0);
+ assert((zxor(a, _1, _1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zxor(a, _1, _2), zcmp(a, _3)), == 0);
+ assert((zxor(a, _1, _3), zcmp(a, _2)), == 0);
+ assert((zxor(a, _2, _2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zxor(a, _2, _3), zcmp(a, _1)), == 0);
+ assert((zxor(a, _3, _3), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+
+ zneg(b, _1);
+ zneg(c, _3);
+ zneg(_1, _1);
+ zand(a, b, c);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), == 0);
+ zneg(_1, _1);
+ assert((zand(a, b, _3), zcmp(a, _1)), == 0);
+ assert((zand(a, _1, c), zcmp(a, _1)), == 0);
+ assert((zand(a, _0, c), zcmp(a, _0)), == 0);
+ assert((zand(a, b, _0), zcmp(a, _0)), == 0);
+
+ zneg(b, _1);
+ zneg(c, _2);
+ zneg(_3, _3);
+ zor(a, b, c);
+ assert(zcmpmag(a, _3), == 0);
+ assert(zcmp(a, _3), == 0);
+ zor(a, b, _2);
+ assert(zcmpmag(a, _3), == 0);
+ assert(zcmp(a, _3), == 0);
+ zor(a, _1, c);
+ assert((zcmpmag(a, _3)), == 0);
+ assert((zcmp(a, _3)), == 0);
+ assert((zor(a, _0, c), zcmp(a, c)), == 0);
+ assert((zor(a, b, _0), zcmp(a, b)), == 0);
+ zneg(_3, _3);
+
+ zneg(b, _1);
+ zneg(c, _2);
+ zxor(a, b, c);
+ assert(zcmpmag(a, _3), == 0);
+ assert(zcmp(a, _3), == 0);
+ zneg(_3, _3);
+ zxor(a, b, _2);
+ assert(zcmpmag(a, _3), == 0);
+ assert(zcmp(a, _3), == 0);
+ zxor(a, _1, c);
+ assert(zcmpmag(a, _3), == 0);
+ assert(zcmp(a, _3), == 0);
+ zxor(a, b, _0);
+ assert(zcmpmag(a, b), == 0);
+ assert(zcmp(a, b), == 0);
+ zxor(a, _0, c);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+ zneg(_3, _3);
+
+ assert((zlsh(a, _0, 0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zlsh(a, _0, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zlsh(a, _1, 0), zcmp(a, _1)), == 0);
+ assert((zlsh(a, _1, 1), zcmp(a, _2)), == 0);
+ assert((zlsh(a, _1, 2), zcmp(a, _2)), > 0);
+ assert((zlsh(a, _2, 0), zcmp(a, _2)), == 0);
+ assert((zlsh(a, _2, 1), zcmp(a, _2)), > 0);
+
+ zset(a, _0);
+ assert((zlsh(a, a, 0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zlsh(a, a, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ zset(a, _1);
+ assert((zlsh(a, a, 0), zcmp(a, _1)), == 0);
+ assert((zlsh(a, a, 1), zcmp(a, _2)), == 0);
+ assert((zlsh(a, a, 2), zcmp(a, _2)), > 0);
+ zset(a, _2);
+ assert((zlsh(a, a, 0), zcmp(a, _2)), == 0);
+ assert((zlsh(a, a, 1), zcmp(a, _2)), > 0);
+
+ assert((zrsh(a, _0, 0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, _0, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, _1, 0), zcmp(a, _1)), == 0);
+ assert((zrsh(a, _1, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, _1, 2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, _2, 0), zcmp(a, _2)), == 0);
+ assert((zrsh(a, _2, 1), zcmp(a, _1)), == 0);
+ assert((zrsh(a, _2, 2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+
+ zset(a, _0);
+ assert((zrsh(a, a, 0), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, a, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ zset(a, _1);
+ assert((zrsh(a, a, 0), zcmp(a, _1)), == 0);
+ assert((zrsh(a, a, 1), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ assert((zrsh(a, a, 2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+ zset(a, _2);
+ assert((zrsh(a, a, 0), zcmp(a, _2)), == 0);
+ assert((zrsh(a, a, 1), zcmp(a, _1)), == 0);
+ assert((zrsh(a, a, 2), zcmp(a, _0)), == 0);
+ assert(zzero(a), == 1);
+
+ assert(zbtest(_0, 0), == 0);
+ assert(zbtest(_1, 0), == 1);
+ assert(zbtest(_2, 0), == 0);
+ assert(zbtest(_3, 0), == 1);
+ assert(zbtest(_0, 1), == 0);
+ assert(zbtest(_1, 1), == 0);
+ assert(zbtest(_2, 1), == 1);
+ assert(zbtest(_3, 1), == 1);
+ assert(zbtest(_0, 2), == 0);
+ assert(zbtest(_1, 2), == 0);
+ assert(zbtest(_2, 2), == 0);
+ assert(zbtest(_3, 2), == 0);
+
+ znot(a, _2);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), != 0);
+ znot(a, a);
+ assert(zcmp(a, _0), == 0);
+
+ zsetu(a, 0xEEFF);
+ zsetu(c, 0xEE);
+ zsetu(d, 0xFF);
+ zsplit(a, b, a, 8);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmpmag(b, d), == 0);
+ zsetu(a, 0xEEFF);
+ zsplit(b, a, a, 8);
+ assert(zcmpmag(b, c), == 0);
+ assert(zcmpmag(a, d), == 0);
+
+ zmul(a, _2, _3);
+ assert(zcmpi(a, 6), == 0);
+ zneg(_3, _3);
+ zmul(a, _2, _3);
+ assert(zcmpi(a, -6), == 0);
+ zneg(_3, _3);
+ zneg(_2, _2);
+ zmul(a, _2, _3);
+ assert(zcmpi(a, -6), == 0);
+ zneg(_3, _3);
+ zmul(a, _2, _3);
+ assert(zcmpi(a, 6), == 0);
+ zneg(_3, _3);
+ zneg(_2, _2);
+
+ zmul(a, _3, _3);
+ assert(zcmpi(a, 9), == 0);
+ zsqr(a, _3);
+ assert(zcmpi(a, 9), == 0);
+ zneg(_3, _3);
+ zmul(a, _3, _3);
+ assert(zcmpi(a, 9), == 0);
+ zsqr(a, _3);
+ assert(zcmpi(a, 9), == 0);
+ zneg(_3, _3);
+
+ zseti(a, 8);
+ zseti(b, 2);
+ zdiv(c, a, b);
+ assert(zcmpi(c, 4), == 0);
+ zseti(b, -2);
+ zdiv(c, a, b);
+ assert(zcmpi(c, -4), == 0);
+ zseti(a, -8);
+ zseti(b, 2);
+ zdiv(c, a, b);
+ assert(zcmpi(c, -4), == 0);
+ zseti(b, -2);
+ zdiv(c, a, b);
+ assert(zcmpi(c, 4), == 0);
+
+ zseti(a, 1000);
+ zseti(b, 10);
+ zdiv(c, a, b);
+ assert(zcmpi(c, 100), == 0);
+ zseti(b, -10);
+ zdiv(c, a, b);
+ assert(zcmpi(c, -100), == 0);
+ zseti(a, -1000);
+ zseti(b, 10);
+ zdiv(c, a, b);
+ assert(zcmpi(c, -100), == 0);
+ zseti(b, -10);
+ zdiv(c, a, b);
+ assert(zcmpi(c, 100), == 0);
+
+ zseti(a, 7);
+ zseti(b, 3);
+ zmod(c, a, b);
+ assert(zcmpi(c, 1), == 0);
+ zseti(b, -3);
+ zmod(c, a, b);
+ assert(zcmpi(c, 1), == 0);
+ zseti(a, -7);
+ zseti(b, 3);
+ zmod(c, a, b);
+ assert(zcmpi(c, 1), == 0);
+ zseti(b, -3);
+ zmod(c, a, b);
+ assert(zcmpi(c, 1), == 0);
+
+ zseti(a, 7);
+ zseti(b, 3);
+ zdivmod(d, c, a, b);
+ assert(zcmpi(d, 2), == 0);
+ assert(zcmpi(c, 1), == 0);
+ zseti(b, -3);
+ zdivmod(d, c, a, b);
+ assert(zcmpi(d, -2), == 0);
+ assert(zcmpi(c, 1), == 0);
+ zseti(a, -7);
+ zseti(b, 3);
+ zdivmod(d, c, a, b);
+ assert(zcmpi(d, -2), == 0);
+ assert(zcmpi(c, 1), == 0);
+ zseti(b, -3);
+ zdivmod(d, c, a, b);
+ assert(zcmpi(d, 2), == 0);
+ assert(zcmpi(c, 1), == 0);
+
+ zseti(a, 10);
+ zseti(b, -1);
+ zpow(a, a, b);
+ assert(zcmp(a, _0), == 0);
+
+ zseti(a, 10);
+ zseti(b, -1);
+ zseti(a, 20);
+ zmodpow(a, a, b, c);
+ assert(zcmp(a, _0), == 0);
+
+ zseti(a, 10);
+ zseti(c, 100000L);
+ zpowu(a, a, 5);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, -10);
+ zseti(c, -100000L);
+ zpowu(a, a, 5);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, -10);
+ zseti(c, 10000L);
+ zpowu(a, a, 4);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, 10);
+ zseti(c, 3);
+ zmodpowu(a, a, 5, c);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), == 0);
+
+ zseti(a, 10);
+ zseti(b, 5);
+ zseti(c, 100000L);
+ zpow(a, a, b);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, -10);
+ zseti(b, 5);
+ zseti(c, -100000L);
+ zpow(a, a, b);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, -10);
+ zseti(b, 4);
+ zseti(c, 10000L);
+ zpow(a, a, b);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), == 0);
+
+ zseti(a, 10);
+ zseti(b, 5);
+ zseti(c, 3);
+ zmodpow(a, a, b, c);
+ assert(zcmpmag(a, _1), == 0);
+ assert(zcmp(a, _1), == 0);
+
+ zseti(a, 102);
+ zseti(b, 501);
+ zseti(c, 5);
+ zmodmul(a, a, b, c);
+ assert(zcmp(a, _2), == 0);
+
+ zseti(b, 2 * 3 * 3 * 7);
+ zseti(c, 3 * 7 * 11);
+ zseti(d, 3 * 7);
+ assert((zgcd(a, _0, _0), zcmp(a, _0)), == 0);
+ assert((zgcd(a, b, _0), zcmp(a, b)), == 0);
+ assert((zgcd(a, _0, c), zcmp(a, c)), == 0);
+ assert((zgcd(a, b, b), zcmp(a, b)), == 0);
+ assert((zgcd(a, b, _2), zcmp(a, _2)), == 0);
+ assert((zgcd(a, _2, b), zcmp(a, _2)), == 0);
+ assert((zgcd(a, _2, _2), zcmp(a, _2)), == 0);
+ assert((zgcd(a, c, _2), zcmp(a, _1)), == 0);
+ assert((zgcd(a, _2, c), zcmp(a, _1)), == 0);
+ assert((zgcd(a, b, _1), zcmp(a, _1)), == 0);
+ assert((zgcd(a, _1, c), zcmp(a, _1)), == 0);
+ assert((zgcd(a, _1, _1), zcmp(a, _1)), == 0);
+ assert((zgcd(a, b, c), zcmp(a, d)), == 0);
+ assert((zgcd(a, c, b), zcmp(a, d)), == 0);
+
+ zsets(a, "1234");
+ assert(zcmpi(a, 1234), == 0);
+ zsets(b, "+1234");
+ assert(zcmp(a, b), == 0);
+ assert_zu(zstr_length(_0, 10), 1);
+ assert_zu(zstr_length(_1, 10), 1);
+ assert_zu(zstr_length(_2, 10), 1);
+ assert_zu(zstr_length(_3, 10), 1);
+ zneg(_2, _2);
+ assert_zu(zstr_length(_2, 10), 2);
+ zneg(_2, _2);
+ assert_zu(zstr_length(a, 10), 4);
+ zstr(a, buf);
+ assert_s(buf, "1234");
+ zsets(a, "-1234");
+ zseti(b, -1234);
+ zseti(c, 1234);
+ assert(zcmp(a, _0), < 0);
+ assert(zcmp(a, b), == 0);
+ assert(zcmpmag(a, c), == 0);
+ assert(zcmp(a, c), < 0);
+ zstr(a, buf);
+ assert_s(buf, "-1234");
+ assert_s(zstr(a, buf), "-1234");
+
+ zsetu(d, 100000UL);
+ zrand(a, FAST_RANDOM, UNIFORM, d);
+ assert(zcmp(a, _0), >= 0);
+ assert(zcmp(a, d), <= 0);
+ zrand(b, SECURE_RANDOM, UNIFORM, d);
+ assert(zcmp(b, _0), >= 0);
+ assert(zcmp(b, d), <= 0);
+ zrand(c, FAST_RANDOM, UNIFORM, d);
+ assert(zcmp(c, _0), >= 0);
+ assert(zcmp(c, d), <= 0);
+ assert(zcmp(a, b), != 0);
+ assert(zcmp(a, c), != 0);
+ assert(zcmp(b, c), != 0);
+
+ assert((zseti(a, -5), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, -4), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, -3), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, -2), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, -1), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 0), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 1), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 2), zptest(0, a, 100)), == PRIME);
+ assert((zseti(a, 3), zptest(0, a, 100)), == PRIME);
+ assert((zseti(a, 4), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 5), zptest(0, a, 100)), != NONPRIME);
+ assert((zseti(a, 6), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 7), zptest(0, a, 100)), != NONPRIME);
+ assert((zseti(a, 8), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 9), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 10), zptest(0, a, 100)), == NONPRIME);
+ assert((zseti(a, 11), zptest(0, a, 100)), != NONPRIME);
+ assert((zseti(a, 101), zptest(0, a, 100)), != NONPRIME);
+
+done:
+ zfree(a), zfree(b), zfree(c), zfree(d), zfree(_0), zfree(_1), zfree(_2), zfree(_3);
+ zunsetup();
+ return ret;
+}