зеркало из https://github.com/github/putty.git
Add direct tests of division/modulus to testbn.
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.
This commit is contained in:
Родитель
90c7b1562c
Коммит
984792e9f4
59
sshbn.c
59
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);
|
||||
|
|
|
@ -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))
|
||||
|
|
Загрузка…
Ссылка в новой задаче