]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Add direct tests of division/modulus to testbn.
authorSimon Tatham <anakin@pobox.com>
Sun, 13 Dec 2015 14:46:43 +0000 (14:46 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 13 Dec 2015 14:46:43 +0000 (14:46 +0000)
I'm about to rewrite the division code, so it'll be useful to have a
way to test it directly, particularly one which exercises difficult
cases such as extreme values of the leading word and remainders just
above and below zero.

sshbn.c
testdata/bignum.py

diff --git a/sshbn.c b/sshbn.c
index afc38a0bb2b5dfd056a50fae8483fa7dd020e6ba..c98590938b5d98917348232b7bdc468877f686c6 100644 (file)
--- a/sshbn.c
+++ b/sshbn.c
@@ -2059,6 +2059,65 @@ int main(int argc, char **argv)
             freebn(modulus);
             freebn(expected);
             freebn(answer);
+        } else if (!strcmp(buf, "divmod")) {
+            Bignum n, d, expect_q, expect_r, answer_q, answer_r;
+            int fail;
+
+            if (ptrnum != 4) {
+                printf("%d: divmod with %d parameters, expected 4\n", line, ptrnum);
+                exit(1);
+            }
+
+            n = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
+            d = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
+            expect_q = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
+            expect_r = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]);
+            answer_q = bigdiv(n, d);
+            answer_r = bigmod(n, d);
+
+            fail = FALSE;
+            if (bignum_cmp(expect_q, answer_q) != 0) {
+                char *as = bignum_decimal(n);
+                char *bs = bignum_decimal(d);
+                char *cs = bignum_decimal(answer_q);
+                char *ds = bignum_decimal(expect_q);
+
+                printf("%d: fail: %s / %s gave %s expected %s\n",
+                       line, as, bs, cs, ds);
+                fail = TRUE;
+
+                sfree(as);
+                sfree(bs);
+                sfree(cs);
+                sfree(ds);
+            }
+            if (bignum_cmp(expect_r, answer_r) != 0) {
+                char *as = bignum_decimal(n);
+                char *bs = bignum_decimal(d);
+                char *cs = bignum_decimal(answer_r);
+                char *ds = bignum_decimal(expect_r);
+
+                printf("%d: fail: %s mod %s gave %s expected %s\n",
+                       line, as, bs, cs, ds);
+                fail = TRUE;
+
+                sfree(as);
+                sfree(bs);
+                sfree(cs);
+                sfree(ds);
+            }
+
+            freebn(n);
+            freebn(d);
+            freebn(expect_q);
+            freebn(expect_r);
+            freebn(answer_q);
+            freebn(answer_r);
+
+            if (fail)
+                fails++;
+            else
+                passes++;
         } else {
             printf("%d: unrecognised test keyword: '%s'\n", line, buf);
             exit(1);
index b2a6614b03ad2ee6763d0081d86b336f2d523c15..15ffe319b42d1637bf140d39b5ab5bde32f5487d 100644 (file)
@@ -103,6 +103,21 @@ for i in range(1,4200):
     a, b, p = findprod((1<<i)+1, +1, (i, i+1))
     print "mul", hexstr(a), hexstr(b), hexstr(p)
 
+# Bare tests of division/modulo.
+prefixes = [2**63, int(2**63.5), 2**64-1]
+for nsize in range(20, 200):
+    for dsize in range(20, 200):
+        for dprefix in prefixes:
+            d = sqrt(3<<(2*dsize)) + (dprefix<<dsize)
+            for nprefix in prefixes:
+                nbase = sqrt(3<<(2*nsize)) + (nprefix<<nsize)
+                for modulus in sorted({-1, 0, +1, d/2, nbase % d}):
+                    n = nbase - (nbase % d) + modulus
+                    if n < 0:
+                        n += d
+                        assert n >= 0
+                    print "divmod", hexstr(n), hexstr(d), hexstr(n/d), hexstr(n%d)
+
 # Simple tests of modmul.
 for ai in range(20, 200, 60):
     a = sqrt(3<<(2*ai-1))