(wrong string) ée

From: <git_AT_suckless.org>
Date: Sat, 5 Mar 2016 20:17:22 +0100 (CET)

commit 5860237d2f05f6ae45a98569b0d567c2227904c6
Author: Mattias Andrée <maandree_AT_kth.se>
AuthorDate: Sat Mar 5 20:16:14 2016 +0100
Commit: Mattias Andrée <maandree_AT_kth.se>
CommitDate: Sat Mar 5 20:16:14 2016 +0100

    Fix bugs and add a randomised testing
    
    Signed-off-by: Mattias Andrée <maandree_AT_kth.se>

diff --git a/.gitignore b/.gitignore
index 9260786..68ad537 100644
--- a/.gitignore
+++ b/.gitignore
_AT_@ -4,3 +4,4 @@
 *.a
 *.so
 /test
+/test-random.c
diff --git a/Makefile b/Makefile
index 1d86a86..9f664a4 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -58,7 +58,7 @@ FUN =\
 OBJ = $(FUN:=.o)
 MAN = $(foreach F,$(FUN),man/$(F).3) man/libzahl.7
 
-all: libzahl.a test
+all: libzahl.a
 
 %.o: src/%.c $(HDR) config.mk
         $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $_AT_ $<
_AT_@ -67,13 +67,16 @@ libzahl.a: $(OBJ)
         $(AR) rc $_AT_ $?
         $(RANLIB) $_AT_
 
-test: test.c libzahl.a
- $(CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) -o $_AT_ $^
+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
 
 check: test
         ./test
 
 clean:
- -rm -- *.o *.su *.a *.so test 2>/dev/null
+ -rm -- *.o *.su *.a *.so test test-random.c 2>/dev/null
 
 .PHONY: all check clean
diff --git a/man/zsplit.3 b/man/zsplit.3
index 5f83b8c..6298e5b 100644
--- a/man/zsplit.3
+++ b/man/zsplit.3
_AT_@ -22,7 +22,12 @@ The result stored in
 .I high
 is shifted
 .I n
-bits to the right.
+bits to the right. Both
+.I high
+and
+.I low
+will have the same sign as
+.IR a .
 .P
 It is safe to call
 .B zsplit
diff --git a/src/zadd.c b/src/zadd.c
index 73e5b42..e7d5265 100644
--- a/src/zadd.c
+++ b/src/zadd.c
_AT_@ -9,16 +9,20 @@ zadd_unsigned(z_t a, z_t b, z_t c)
         uint32_t carry[] = {0, 0};
         zahl_char_t *addend;
 
- if (a == c) {
- zadd_unsigned(a, c, b);
+ if (zzero(b)) {
+ zabs(a, c);
+ return;
+ } else if (zzero(c)) {
+ zabs(a, b);
                 return;
         }
 
         size = MAX(b->used, c->used);
+ n = b->used + c->used - size;
+
         ENSURE_SIZE(a, size + 1);
         a->chars[size] = 0;
 
- n = b->used + c->used - size;
         if (a == b) {
                 if (a->used < c->used) {
                         n = c->used;
_AT_@ -56,7 +60,7 @@ zadd_unsigned(z_t a, z_t b, z_t c)
 
         if (a->used < i)
                 a->used = i;
- SET_SIGNUM(a, !zzero(b) | !zzero(c));
+ SET_SIGNUM(a, 1);
 }
 
 
diff --git a/src/zdivmod.c b/src/zdivmod.c
index e145c27..def98b5 100644
--- a/src/zdivmod.c
+++ b/src/zdivmod.c
_AT_@ -32,8 +32,6 @@ zdivmod(z_t a, z_t b, z_t c, z_t d)
                         zseti(a, sign);
                         SET_SIGNUM(b, 0);
                         return;
- } else if (sign < 0) {
- zsub_unsigned(b, d, c);
                 } else {
                         SET(b, c);
                 }
diff --git a/src/zload.c b/src/zload.c
index a77ae57..3ab939d 100644
--- a/src/zload.c
+++ b/src/zload.c
_AT_@ -8,12 +8,9 @@ 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 = 0;
- if (a->sign)
+ if (a->sign) {
                 ENSURE_SIZE(a, a->used);
- else
- a->chars = 0;
- if (!zzero(a))
                 zmemcpy(a->chars, buf, a->used);
+ }
         return sizeof(int) + sizeof(size_t) + (zzero(a) ? 0 : a->used * sizeof(zahl_char_t));
 }
diff --git a/src/znot.c b/src/znot.c
index bcb17e2..d0e52c0 100644
--- a/src/znot.c
+++ b/src/znot.c
_AT_@ -18,12 +18,12 @@ znot(z_t a, z_t b)
 
         for (n = a->used; n--;)
                 a->chars[n] = ~(a->chars[n]);
- bits &= BITS_PER_CHAR - 1;
- a->chars[a->used - 1] &= ((zahl_char_t)1 << bits) - 1;
+ bits = BITS_IN_LAST_CHAR(bits);
+ if (bits)
+ a->chars[a->used - 1] &= ((zahl_char_t)1 << bits) - 1;
 
- for (; a->used; a->used--)
- if (a->chars[a->used - 1])
- break;
+ while (a->used && !a->chars[a->used - 1])
+ a->used--;
         if (!a->used)
                 SET_SIGNUM(a, 0);
 }
diff --git a/src/zor.c b/src/zor.c
index 240024e..c50f5f8 100644
--- a/src/zor.c
+++ b/src/zor.c
_AT_@ -20,16 +20,17 @@ zor(z_t a, z_t b, z_t c)
 
         m = MAX(b->used, c->used);
         n = b->used + c->used - m;
- a->used = m;
 
         ENSURE_SIZE(a, m);
 
         if (a == b) {
- zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
+ if (b->used < c->used)
+ zmemcpy(a->chars + n, c->chars + n, m - n);
                 while (n--)
                         a->chars[n] |= c->chars[n];
         } else if (a == c) {
- zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
+ if (c->used < b->used)
+ zmemcpy(a->chars + n, b->chars + n, m - n);
                 while (n--)
                         a->chars[n] |= b->chars[n];
         } else if (m == b->used) {
_AT_@ -42,5 +43,6 @@ zor(z_t a, z_t b, z_t c)
                         a->chars[n] |= b->chars[n];
         }
 
+ a->used = m;
         SET_SIGNUM(a, (zsignum(b) > 0 && zsignum(c) > 0) * 2 - 1);
 }
diff --git a/src/zsplit.c b/src/zsplit.c
index 384c5d7..8f51721 100644
--- a/src/zsplit.c
+++ b/src/zsplit.c
_AT_@ -5,27 +5,17 @@
 void
 zsplit(z_t high, z_t low, z_t a, size_t delim)
 {
- size_t chars;
-
         if (zzero(a)) {
                 SET_SIGNUM(high, 0);
                 SET_SIGNUM(low, 0);
                 return;
         }
 
- chars = FLOOR_BITS_TO_CHARS(delim);
-
         if (high == a) {
- if (a->used < chars)
- SET_SIGNUM(low, 0);
- else
- ztrunc(low, a, delim);
+ ztrunc(low, a, delim);
                 zrsh(high, a, delim);
         } else {
                 zrsh(high, a, delim);
- if (a->used < chars)
- SET_SIGNUM(low, 0);
- else
- ztrunc(low, a, delim);
+ ztrunc(low, a, delim);
         }
 }
diff --git a/src/zsub.c b/src/zsub.c
index 8616542..5096eb0 100644
--- a/src/zsub.c
+++ b/src/zsub.c
_AT_@ -5,28 +5,49 @@
 void
 zsub_unsigned(z_t a, z_t b, z_t c)
 {
- int magcmp = zcmpmag(b, c);
- z_t s;
- size_t i, n;
         zahl_char_t carry[] = {0, 0};
+ zahl_char_t *s;
+ size_t i, n;
+ int magcmp;
+
+ if (zzero(b)) {
+ zabs(a, c);
+ zneg(a, a);
+ return;
+ } else if (zzero(c)) {
+ zabs(a, b);
+ return;
+ } else if (a == b || a == c) {
+ /* TODO This should not be necessary. */
+ z_t tb, tc;
+ zinit(tb);
+ zinit(tc);
+ zset(tb, b);
+ zset(tc, c);
+ zsub_unsigned(a, tb, tc);
+ zfree(tb);
+ zfree(tc);
+ return;
+ }
 
+ magcmp = zcmpmag(b, c);
         if (magcmp <= 0) {
                 if (magcmp == 0) {
                         SET_SIGNUM(a, 0);
                         return;
                 }
                 SET(a, c);
- *s = *b;
+ n = MIN(a->used, b->used);
+ s = b->chars;
         } else {
                 SET(a, b);
- *s = *c;
+ n = MIN(a->used, c->used);
+ s = c->chars;
         }
 
- n = MIN(a->used, s->used);
-
         for (i = 0; i < n; i++) {
- carry[~i & 1] = carry[i & 1] ? (a->chars[i] <= s->chars[i]) : (a->chars[i] < s->chars[i]);
- a->chars[i] -= s->chars[i];
+ carry[~i & 1] = carry[i & 1] ? (a->chars[i] <= s[i]) : (a->chars[i] < s[i]);
+ a->chars[i] -= s[i];
                 a->chars[i] -= carry[i & 1];
         }
 
diff --git a/src/zxor.c b/src/zxor.c
index fcbb3ae..d152ed7 100644
--- a/src/zxor.c
+++ b/src/zxor.c
_AT_@ -21,19 +21,16 @@ zxor(z_t a, z_t b, z_t c)
         m = MAX(b->used, c->used);
         n = b->used + c->used - m;
 
- if (n == m && !zmemcmp(b->chars, c->chars, m)) {
- SET_SIGNUM(a, 0);
- return;
- }
-
         ENSURE_SIZE(a, m);
 
         if (a == b) {
- zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
+ if (b->used < c->used)
+ zmemcpy(a->chars + n, c->chars + n, m - n);
                 while (n--)
                         a->chars[n] ^= c->chars[n];
         } else if (a == c) {
- zmemcpy(a->chars + n, m == b->used ? b->chars : c->chars, m - n);
+ if (c->used < b->used)
+ zmemcpy(a->chars + n, b->chars + n, m - n);
                 while (n--)
                         a->chars[n] ^= b->chars[n];
         } else if (m == b->used) {
_AT_@ -46,5 +43,11 @@ zxor(z_t a, z_t b, z_t c)
                         a->chars[n] ^= b->chars[n];
         }
 
- SET_SIGNUM(a, 1 - 2 * ((zsignum(b) ^ zsignum(c)) < 0));
+ a->used = m;
+ while (a->used && !a->chars[a->used - 1])
+ a->used--;
+ if (a->used)
+ SET_SIGNUM(a, 1 - 2 * ((zsignum(b) ^ zsignum(c)) < 0));
+ else
+ SET_SIGNUM(a, 0);
 }
diff --git a/test-generate.py b/test-generate.py
new file mode 100755
index 0000000..24c5b8a
--- /dev/null
+++ b/test-generate.py
_AT_@ -0,0 +1,797 @@
+#!/usr/bin/env python3
+# See LICENSE file for copyright and license details.
+
+import random
+
+
+def mod(a, b):
+ return abs(a) % abs(b)
+
+def div(a, b): # Python's division is floored, not truncated.
+ r = abs(a) // abs(b)
+ if a < 0:
+ r = -r
+ if b < 0:
+ r = -r
+ return r
+
+def gcd(u, v):
+ if u == 0:
+ return v
+ if v == 0:
+ return u
+ uneg = u < 0
+ vneg = v < 0
+ u = abs(u)
+ v = abs(v)
+
+ shift = 0
+ while ((u | v) & 1) == 0:
+ u >>= 1
+ v >>= 1
+ shift += 1
+
+ while (u & 1) == 0:
+ u >>= 1
+
+ while True:
+ while (v & 1) == 0:
+ v >>= 1
+ if u > v:
+ (u, v) = (v, u)
+ v -= u
+ if v == 0:
+ break
+
+ u <<= shift
+ if uneg and vneg:
+ u = -u
+ return u
+
+
+def zabs():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('zabs(b, a);')
+ print('zabs(a, a);')
+ print('assert(zcmp(a, b), == 0);')
+ print('assert_s(zstr(a, buf), "%i");' % abs(a))
+
+def zadd():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = a + b
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zadd(c, a, b);')
+ print('zset(d, b);')
+ print('zadd(d, a, d);')
+ print('zadd(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+
+def zadd_unsigned():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = abs(a) + abs(b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zadd_unsigned(c, a, b);')
+ print('zset(d, b);')
+ print('zadd_unsigned(d, a, d);')
+ print('zadd_unsigned(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ c = abs(b) * 2
+ print('zadd_unsigned(c, b, b);')
+ print('zadd_unsigned(b, b, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert(zcmp(b, c), == 0);')
+
+def zand():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = abs(a) & abs(b)
+ if a < 0 and b < 0:
+ c = -c
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zand(c, a, b);')
+ print('zset(d, b);')
+ print('zand(d, a, d);')
+ print('zand(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('zsets(a, "%i");' % a)
+ print('zand(d, a, a);')
+ print('zand(a, a, a);')
+ print('assert_s(zstr(d, buf), "%i");' % a)
+ print('assert_s(zstr(a, buf), "%i");' % a)
+
+def zbits():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ a = abs(a)
+ if a == 0:
+ b = 1
+ else:
+ b = 0
+ while a > 0:
+ b += 1
+ a >>= 1
+ print('assert_zu(zbits(a), %i);' % b)
+
+def zbset():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(0, 2 * LIMIT)
+ cs = (abs(a) | (1 << b)) * (-1 if a < 0 else 1)
+ cc = (abs(a) & ~(1 << b)) * (-1 if a < 0 else 1)
+ cf = (abs(a) ^ (1 << b)) * (-1 if a < 0 else 1)
+ print('zsets(a, "%i");' % a)
+ print('zset(d, a);')
+ print('zbset(b, a, %i, 1);' % b)
+ print('assert_s(zstr(b, buf), "%i");' % cs)
+ print('zbset(b, a, %i, 0);' % b)
+ print('assert_s(zstr(b, buf), "%i");' % cc)
+ print('zbset(b, a, %i, -1);' % b)
+ print('assert_s(zstr(b, buf), "%i");' % cf)
+ print('zset(a, d);')
+ print('zbset(a, a, %i, 1);' % b)
+ print('assert_s(zstr(a, buf), "%i");' % cs)
+ print('zset(a, d);')
+ print('zbset(a, a, %i, 0);' % b)
+ print('assert_s(zstr(a, buf), "%i");' % cc)
+ print('zset(a, d);')
+ print('zbset(a, a, %i, -1);' % b)
+ print('assert_s(zstr(a, buf), "%i");' % cf)
+
+def zbtest():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(0, 2 * LIMIT)
+ c = (abs(a) >> b) & 1
+ print('zsets(a, "%i");' % a)
+ print('assert(zbtest(a, %i), == %i);' % (b, c))
+
+def zcmp():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = -1 if a < b else (1 if a > b else 0)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('assert(zcmp(a, b), == %i);' % c)
+
+def zcmpmag():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ a = abs(a)
+ b = abs(b)
+ c = -1 if a < b else (1 if a > b else 0)
+ print('assert(zcmpmag(a, b), == %i);' % c)
+
+def zlsb():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ a = abs(a)
+ if a == 0:
+ b = "SIZE_MAX"
+ else:
+ b = 0
+ while (a & 1) == 0:
+ b += 1
+ a >>= 1
+ b = str(b)
+ print('assert_zu(zlsb(a), %s);' % b)
+
+def zlsh():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, 2 * LIMIT)
+ c = a << bits
+ print('zsets(a, "%i");' % a)
+ print('zlsh(b, a, %i);' % bits)
+ print('zlsh(a, a, %i);' % bits)
+ print('assert(zcmp(a, b), == 0);')
+ print('assert_s(zstr(a, buf), "%i");' % c)
+
+def zneg():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('zneg(b, a);')
+ print('zneg(a, a);')
+ print('assert(zcmp(a, b), == 0);')
+ print('assert_s(zstr(a, buf), "%i");' % -a)
+
+def zor():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = abs(a) | abs(b)
+ if a < 0 or b < 0:
+ c = -c
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zor(c, a, b);')
+ print('zset(d, b);')
+ print('zor(d, a, d);')
+ print('zor(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('zsets(a, "%i");' % a)
+ print('zor(d, a, a);')
+ print('zor(a, a, a);')
+ print('assert_s(zstr(d, buf), "%i");' % a)
+ print('assert_s(zstr(a, buf), "%i");' % a)
+
+def zrsh():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ c = (abs(a) >> bits) * (-1 if a < 0 else 1)
+ print('zsets(a, "%i");' % a)
+ print('zrsh(b, a, %i);' % bits)
+ print('zrsh(a, a, %i);' % bits)
+ print('assert(zcmp(a, b), == 0);')
+ print('assert_s(zstr(a, buf), "%i");' % c)
+
+def zsplit():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, 2 * LIMIT)
+ sign = -1 if a < 0 else 1
+ c = (abs(a) >> bits) * sign
+ d = (abs(a) - (abs(c) << bits)) * sign
+ print('zsets(a, "%i");' % a)
+ print('zset(b, a);')
+ print('zsplit(b, d, b, %i);' % bits)
+ print('assert_s(zstr(b, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zsplit(c, d, a, %i);' % bits)
+ print('assert(zcmp(b, c), == 0);')
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zsplit(c, a, a, %i);' % bits)
+ print('assert(zcmp(a, d), == 0);')
+ print('assert(zcmp(b, c), == 0);')
+
+def zstr():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('assert_s(zstr(a, buf), "%i");' % a)
+
+def zstr_length():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('assert_zu(zstr_length(a, 10), %i);' % len(str(a)))
+
+def zsub():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = a - b
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsub(c, a, b);')
+ print('zset(d, b);')
+ print('zsub(d, a, d);')
+ print('zsub(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+
+def zsub_unsigned():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = abs(a) - abs(b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsub_unsigned(c, a, b);')
+ print('zset(d, b);')
+ print('zsub_unsigned(d, a, d);')
+ print('zsub_unsigned(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('zsub_unsigned(a, b, b);')
+ print('assert(zzero(a), == 1);')
+ print('zsub_unsigned(b, b, b);')
+ print('assert(zzero(b), == 1);')
+
+def ztrunc():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, 2 * LIMIT)
+ c = (abs(a) & ((1 << bits) - 1)) * (-1 if a < 0 else 1)
+ print('zsets(a, "%i");' % a)
+ print('ztrunc(b, a, %i);' % bits)
+ print('ztrunc(a, a, %i);' % bits)
+ print('assert(zcmp(a, b), == 0);')
+ print('assert_s(zstr(a, buf), "%i");' % c)
+
+def zxor():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = abs(a) ^ abs(b)
+ if (a < 0) != (b < 0):
+ c = -c
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zxor(c, a, b);')
+ print('zset(d, b);')
+ print('zxor(d, a, d);')
+ print('zxor(a, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % c)
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('zsets(a, "%i");' % a)
+ print('zxor(d, a, a);')
+ print('zxor(a, a, a);')
+ print('assert(zzero(d), == 1);')
+ print('assert(zzero(a), == 1);')
+
+def zeven():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = 1 if (abs(a) & 1) == 0 else 0
+ print('zsets(a, "%i");' % a)
+ print('assert(zeven(a), == %i);' % b)
+
+def zodd():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = 1 if (abs(a) & 1) != 0 else 0
+ print('zsets(a, "%i");' % a)
+ print('assert(zodd(a), == %i);' % b)
+
+def zeven_nonzero():
+ bits = random.randint(0, LIMIT)
+ a = 0
+ while a == 0:
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = 1 if (abs(a) & 1) == 0 else 0
+ print('zsets(a, "%i");' % a)
+ print('assert(zeven_nonzero(a), == %i);' % b)
+
+def zodd_nonzero():
+ bits = random.randint(0, LIMIT)
+ a = 0
+ while a == 0:
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = 1 if (abs(a) & 1) != 0 else 0
+ print('zsets(a, "%i");' % a)
+ print('assert(zodd_nonzero(a), == %i);' % b)
+
+def zzero():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = 1 if a == 0 else 0
+ print('zsets(a, "%i");' % a)
+ print('assert(zzero(a), == %i);' % b)
+
+def zsignum():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = -1 if a < 0 else (1 if a > 0 else 0)
+ print('zsets(a, "%i");' % a)
+ print('assert(zsignum(a), == %i);' % b)
+
+def zdiv():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = 0
+ while b == 0:
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = div(a, b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(d, "%i");' % c)
+ print('zdiv(c, a, b);')
+ print('zdiv(a, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zdiv(b, a, b);')
+ print('assert(zcmp(b, d), == 0);')
+
+def zmod():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = 0
+ while b == 0:
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = mod(a, b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(d, "%i");' % c)
+ print('zmod(c, a, b);')
+ print('zmod(a, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zmod(b, a, b);')
+ print('assert(zcmp(b, d), == 0);')
+
+def zdivmod():
+ bits = random.randint(0, LIMIT)
+ ap = random.randint(0, 1 << bits)
+ bits = random.randint(0, LIMIT)
+ bp = 0
+ while bp == 0:
+ bp = random.randint(0, 1 << bits)
+ for (a_sign, b_sign) in ((1, 1), (1, -1), (-1, 1), (-1, -1)):
+ a = ap * a_sign
+ b = bp * b_sign
+ (c, d) = (div(a, b), mod(a, b))
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(c, d, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zdivmod(a, b, a, b);')
+ print('assert(zcmp(a, c), == 0);')
+ print('assert(zcmp(b, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(b, a, a, b);')
+ print('assert(zcmp(b, c), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(b, a, b, b);')
+ print('assert(zcmpu(b, 1), == 0);')
+ print('assert(zcmpu(a, 0), == 0);')
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(a, b, b, b);')
+ print('assert(zcmpu(a, 1), == 0);')
+ print('assert(zcmpu(b, 0), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(a, d, a, b);')
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zdivmod(c, b, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(b, buf), "%i");' % d)
+ a = bp * a_sign
+ b = bp * b_sign
+ (c, d) = (div(a, b), mod(a, b))
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(c, d, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zdivmod(a, b, a, b);')
+ print('assert(zcmp(a, c), == 0);')
+ print('assert(zcmp(b, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(b, a, a, b);')
+ print('assert(zcmp(b, c), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(b, a, b, b);')
+ print('assert(zcmpu(b, 1), == 0);')
+ print('assert(zcmpu(a, 0), == 0);')
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(a, b, b, b);')
+ print('assert(zcmpu(a, 1), == 0);')
+ print('assert(zcmpu(b, 0), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zdivmod(a, d, a, b);')
+ print('assert_s(zstr(a, buf), "%i");' % c)
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zdivmod(c, b, a, b);')
+ print('assert_s(zstr(c, buf), "%i");' % c)
+ print('assert_s(zstr(b, buf), "%i");' % d)
+
+def zmul():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = a * b
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(d, "%i");' % c)
+ print('zmul(c, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+ print('zmul(c, b, a);')
+ print('assert(zcmp(c, d), == 0);')
+ print('zmul(a, a, b);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zmul(b, a, b);')
+ print('assert(zcmp(b, d), == 0);')
+ c = a * a
+ print('zsets(d, "%i");' % c)
+ print('zmul(c, a, a);')
+ print('assert(zcmp(c, d), == 0);')
+ print('zmul(a, a, a);')
+ print('assert(zcmp(a, d), == 0);')
+
+def zsqr():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ c = a * a
+ print('zsets(a, "%i");' % a)
+ print('zsets(d, "%i");' % c)
+ print('zsqr(c, a);')
+ print('assert(zcmp(c, d), == 0);')
+ print('zsqr(a, a);')
+ print('assert(zcmp(a, d), == 0);')
+
+def zmodmul():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ c = 0
+ while c == 0:
+ c = random.randint(-(1 << bits), 1 << bits)
+ d = mod(a * b, c)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(c, "%i");' % c)
+ print('zmodmul(d, a, b, c);')
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zmodmul(a, a, b, c);')
+ print('assert_s(zstr(a, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zmodmul(b, a, b, c);')
+ print('assert_s(zstr(b, buf), "%i");' % d)
+ print('zsets(b, "%i");' % b)
+ print('zmodmul(c, a, b, c);')
+ print('assert_s(zstr(c, buf), "%i");' % d)
+ print('zsets(c, "%i");' % c)
+ print('zmodmul(d, b, a, c);')
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zmodmul(a, b, a, c);')
+ print('assert_s(zstr(a, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zmodmul(b, b, a, c);')
+ print('assert_s(zstr(b, buf), "%i");' % d)
+ print('zsets(b, "%i");' % b)
+ print('zmodmul(c, b, a, c);')
+ print('assert_s(zstr(c, buf), "%i");' % d)
+ print('zsets(c, "%i");' % c)
+ d = mod(a * a, c)
+ print('zmodmul(d, a, a, c);')
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('zmodmul(a, a, a, c);')
+ print('assert_s(zstr(a, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zmodmul(c, a, a, c);')
+ print('assert_s(zstr(c, buf), "%i");' % d)
+ if a != 0:
+ d = mod(a * b, a)
+ print('zsets(d, "%i");' % d)
+ print('zmodmul(c, a, b, a);')
+ print('assert_s(zstr(c, buf), "%i");' % d)
+ print('zmodmul(a, a, b, a);')
+ print('assert_s(zstr(a, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zmodmul(b, a, b, a);')
+ print('assert_s(zstr(b, buf), "%i");' % d)
+ print('zsets(b, "%i");' % b)
+ print('zmodmul(c, b, a, a);')
+ print('assert_s(zstr(c, buf), "%i");' % d)
+ print('zmodmul(a, b, a, a);')
+ print('assert_s(zstr(a, buf), "%i");' % d)
+ print('zsets(a, "%i");' % a)
+ print('zmodmul(b, b, a, a);')
+ print('assert_s(zstr(b, buf), "%i");' % d)
+ print('zmodmul(b, a, a, a);')
+ print('assert(zzero(b), == 1);')
+ print('zmodmul(a, a, a, a);')
+ print('assert(zzero(a), == 1);')
+
+def zmodsqr():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = 0
+ while b == 0:
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = mod(a ** 2, b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(d, "%i");' % c)
+ print('zmodsqr(c, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+ print('zset(c, a);')
+ print('zmodsqr(a, a, b);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zset(a, c);')
+ print('zset(c, b);')
+ print('zmodsqr(b, a, b);')
+ print('assert(zcmp(b, d), == 0);')
+ if a != 0:
+ c = mod(a ** 2, a)
+ print('zmodsqr(b, a, a);')
+ print('assert(zzero(b), == 1);')
+ print('zmodsqr(a, a, a);')
+ print('assert(zzero(a), == 1);')
+
+def zcmpi():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(-(1 << 63), (1 << 63) - 1)
+ c = -1 if a < b else (1 if a > b else 0)
+ print('zsets(a, "%i");' % a)
+ if b >= 0:
+ print('assert(zcmpi(a, %iLL), == %i);' % (b, c))
+ else:
+ print('assert(zcmpi(a, %iLL - 1LL), == %i);' % (b + 1, c))
+
+def zcmpu():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(0, (1 << 64) - 1)
+ c = -1 if a < b else (1 if a > b else 0)
+ print('zsets(a, "%i");' % a)
+ print('assert(zcmpu(a, %iULL), == %i);' % (b, c))
+
+def zgcd():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ bits = random.randint(0, LIMIT)
+ b = random.randint(-(1 << bits), 1 << bits)
+ c = gcd(a, b)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(d, "%i");' % c)
+ print('zgcd(c, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+
+def zpow():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(1, 16)
+ c = a ** b
+ print('zsets(a, "%i");' % a)
+ print('zsetu(b, %i);' % b)
+ print('zsets(d, "%i");' % c)
+ print('zpow(c, a, b);')
+ print('zpow(a, a, b);')
+ print('assert(zcmp(c, d), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zpow(b, a, b);')
+ print('assert(zcmp(b, d), == 0);')
+
+def zpowu():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(1, 16)
+ c = a ** b
+ print('zsets(a, "%i");' % a)
+ print('zsets(d, "%i");' % c)
+ print('zpowu(c, a, %i);' % b)
+ print('zpowu(a, a, %i);' % b)
+ print('assert(zcmp(c, d), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+
+def zmodpowu():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(1, 16)
+ bits = random.randint(0, LIMIT)
+ c = 0
+ while c == 0:
+ c = random.randint(-(1 << bits), 1 << bits)
+ d = mod(a ** b, c)
+ print('zsets(a, "%i");' % a)
+ print('zsets(c, "%i");' % c)
+ print('zsets(d, "%i");' % d)
+ print('zmodpowu(b, a, %i, c);' % b)
+ print('zmodpowu(a, a, %i, c);' % b)
+ print('assert(zcmp(b, d), == 0);')
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zmodpowu(c, a, %i, c);' % b)
+ print('assert(zcmp(c, d), == 0);')
+
+def zmodpow():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ b = random.randint(1, 16)
+ bits = random.randint(0, LIMIT)
+ c = 0
+ while c == 0:
+ c = random.randint(-(1 << bits), 1 << bits)
+ d = mod(a ** b, c)
+ print('zsets(a, "%i");' % a)
+ print('zsets(b, "%i");' % b)
+ print('zsets(c, "%i");' % c)
+ print('zsets(d, "%i");' % d)
+ print('zmodpow(d, a, b, c);')
+ print('zmodpow(a, a, b, c);')
+ print('assert_s(zstr(d, buf), "%i");' % d)
+ print('assert(zcmp(a, d), == 0);')
+ print('zsets(a, "%i");' % a)
+ print('zmodpow(b, a, b, c);')
+ print('assert(zcmp(b, d), == 0);')
+ print('zsets(b, "%i");' % b)
+ print('zmodpow(c, a, b, c);')
+ print('assert(zcmp(c, d), == 0);')
+
+def znot():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ sign = -(-1 if a < 0 else 1)
+ b = abs(a)
+ bits = 0
+ x = b
+ while x > 0:
+ bits += 1
+ x >>= 1
+ b = ~b
+ b &= (1 << bits) - 1
+ b *= sign
+ print('zsets(a, "%i");' % a)
+ print('zsets(c, "%i");' % b)
+ print('znot(b, a);')
+ print('znot(a, a);')
+ print('assert(zcmp(b, c), == 0);')
+ print('assert(zcmp(a, c), == 0);')
+
+def zsave_zload():
+ bits = random.randint(0, LIMIT)
+ a = random.randint(-(1 << bits), 1 << bits)
+ print('zsets(a, "%i");' % a)
+ print('n = zsave(a, 0);')
+ print('assert_zu(zsave(a, buf), n);')
+ print('assert_zu(zload(b, buf), n);')
+ print('assert(zcmp(a, b), == 0);')
+
+
+
+functions = [zzero, zsignum, zeven_nonzero, zodd_nonzero, zeven, zcmp, zcmpi, zcmpu, zcmpmag,
+ zodd, zabs, zneg, zlsh, zrsh, ztrunc, zsplit, zand, zor, zxor, zbits, zlsb, znot,
+ zbtest, zbset, zadd_unsigned, zsub_unsigned, zadd, zsub, zmul, zsqr, zdivmod,
+ zdiv, zmod, zmodmul, zmodsqr, zsave_zload, zgcd, zpow, zpowu, zmodpow, zmodpowu,
+ zstr_length, zstr] # untested: zptest, zrand
+
+limits = [200]
+
+for LIMIT in limits:
+ for function in functions:
+ print('/* %s */' % function.__qualname__)
+ for i in range(100):
+ function()
+ print()
+ print()
+
diff --git a/test.c b/test.c
index 69d5170..624abb0 100644
--- a/test.c
+++ b/test.c
_AT_@ -62,7 +62,7 @@ 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;
- static char buf[1000];
+ static char buf[2000];
         static int ret = 0;
         static jmp_buf env, env2;
         static size_t n;
_AT_@ -309,6 +309,19 @@ main(void)
         assert((zadd_unsigned(a, b, _2), zcmp(a, _3)), == 0);
         assert((zadd_unsigned(a, _1, c), zcmp(a, _3)), == 0);
 
+ assert((zadd_unsigned(a, _0, _0), zcmp(a, _0)), == 0);
+ assert((zadd_unsigned(a, _0, _1), zcmp(a, _1)), == 0);
+ assert((zadd_unsigned(a, _1, _1), zcmp(a, _2)), == 0);
+ assert((zadd_unsigned(a, _1, _0), zcmp(a, _1)), == 0);
+ zneg(_1, _1);
+ assert((zadd_unsigned(a, _0, _0), zcmp(a, _0)), == 0);
+ assert((zadd_unsigned(a, _0, _1), zcmp(a, _1)), != 0);
+ assert((zadd_unsigned(a, _0, _1), zcmpmag(a, _1)), == 0);
+ assert((zadd_unsigned(a, _1, _1), zcmp(a, _2)), == 0);
+ assert((zadd_unsigned(a, _1, _0), zcmp(a, _1)), != 0);
+ assert((zadd_unsigned(a, _1, _0), zcmpmag(a, _1)), == 0);
+ zneg(_1, _1);
+
         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);
_AT_@ -992,8 +1005,11 @@ main(void)
         zsqr(a, a);
         assert_s(zstr(a, buf), "1000000000000000000000000000000");
 
+#include "test-random.c"
+
 done:
         zfree(a), zfree(b), zfree(c), zfree(d), zfree(_0), zfree(_1), zfree(_2), zfree(_3);
         zunsetup();
         return ret;
 }
+
diff --git a/zahl.h b/zahl.h
index 993d7b1..a5946fc 100644
--- a/zahl.h
+++ b/zahl.h
_AT_@ -86,7 +86,7 @@ void zpowu(z_t, z_t, unsigned long long int);
 void zmodpowu(z_t, z_t, unsigned long long int, z_t);
 
 /* These are used internally and may be removed in a future version. */
-void zadd_unsigned(z_t, z_t, z_t); /* a := |b| + |c|, b and c must not be the same reference. */
+void zadd_unsigned(z_t, z_t, z_t); /* a := |b| + |c| */
 void zsub_unsigned(z_t, z_t, z_t); /* a := |b| - |c| */
 
 
Received on Sat Mar 05 2016 - 20:17:22 CET

This archive was generated by hypermail 2.3.0 : Sat Mar 05 2016 - 20:24:19 CET