commit aff09967d194d062ae8d83c0fbe1edf158804ef9
Author:     Mattias Andrée <[email protected]>
AuthorDate: Fri Mar 4 10:45:10 2016 +0100
Commit:     Mattias Andrée <[email protected]>
CommitDate: Fri Mar 4 10:47:53 2016 +0100

    Clean up, fix a few bugs, and add a test
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/.gitignore b/.gitignore
index aef436d..9260786 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 *.su
 *.a
 *.so
+/test
diff --git a/Makefile b/Makefile
index 0670292..f3a6ad7 100644
--- 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
index 77ea29b..5b1f9c3 100644
--- 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
index 2aa7e38..6ab3ae8 100644
--- 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
index 6b8dc4a..e07705a 100644
--- 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
index d7b7784..c379e2a 100644
--- 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
index c708453..ff54afb 100644
--- 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
index e301d44..b631c1a 100644
--- 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
index fe18060..884e9ff 100644
--- 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
index 578d8a5..f237bc9 100644
--- 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
index 1d3952d..f594828 100644
--- 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
index 16988f7..c064f60 100644
--- 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
index c5c8e8a..cb0b375 100644
--- 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
index c3bd63e..c5a1a05 100644
--- 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
index 989bb1c..b67fe4a 100644
--- 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
index f37be7e..37fbf7c 100644
--- 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
index be89c37..a9cebd0 100644
--- 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
index ffbbbe0..f86fb8e 100644
--- 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
index f570fdf..fcbb3ae 100644
--- 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
new file mode 100644
index 0000000..d82c7bc
--- /dev/null
+++ 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;
+}

Reply via email to