chiark / gitweb /
math/scaf.c, etc.: Only need 3*NPIECE words of scratch space.
[catacomb] / math / group-test.c
1 /* -*-c-*-
2  *
3  * Testing group operations
4  *
5  * (c) 2004 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <stdarg.h>
31
32 #include <mLib/testrig.h>
33
34 #include "group.h"
35 #include "fibrand.h"
36 #include "ec.h"
37 #include "ec-test.h"
38
39 /*----- Main code ---------------------------------------------------------*/
40
41 static group *getgroup(const char *p) {
42   group *g; qd_parse qd;
43   qd.p = p; qd.e = 0; g = group_parse(&qd);
44   if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; }
45   if (!g) {
46     fprintf(stderr, "bad group string `%.*s|%s': %s\n",
47             (int)(qd.p - p), p, qd.p, qd.e);
48     exit(1);
49   }
50   return (g);
51 }
52
53 static ge *getge(group *g, const char *p) {
54   ge *x = G_CREATE(g);
55   if (group_readstring(g, x, p, 0)) {
56     fprintf(stderr, "bad group element `%s'\n", p);
57     exit(1);
58   }
59   return (x);
60 }
61
62 static void show(group *g, const char *p, ge *x) {
63   fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
64   putc('\n', stderr);
65 }
66
67 static void showec(const char *p, ec *q) {
68   fprintf(stderr, "*** %s = ", p);
69   if (EC_ATINF(q)) fprintf(stderr, "inf\n");
70   else {
71     mp_writefile(q->x, stderr, 16); fputs(", ", stderr);
72     mp_writefile(q->x, stderr, 16); putchar('\n');
73   }
74 }
75
76 static void showmp(const char *p, mp *x, int r) {
77   fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r);
78   putc('\n', stderr);
79 }
80
81 static int EXECL_LIKE(0)
82   check(const char *op, const char *gd, group *g, ge *r, ge *c, ...)
83 {
84   va_list ap;
85
86   if (G_EQ(g, r, c)) return (1);
87   fprintf(stderr, "\n*** %s failed\n", op);
88   fprintf(stderr, "*** group: %s\n", gd);
89   va_start(ap, c);
90   for (;;) {
91     const char *p; ge *x;
92     p = va_arg(ap, const char *); if (!p) break;
93     x = va_arg(ap, ge *); show(g, p, x);
94   }
95   show(g, "expected", r);
96   show(g, "computed", c);
97   return (0);
98 }
99
100 /*----- Actual tests ------------------------------------------------------*/
101
102 static int vcheck(dstr *v)
103 {
104   group *g = getgroup(v[0].buf);
105   grand *gr = fibrand_create(0);
106   const char *e = G_CHECK(g, gr);
107   int ok = 1;
108   gr->ops->destroy(gr);
109   if (!e) e = "ok";
110   G_DESTROYGROUP(g);
111   if (strcmp(e, v[1].buf)) {
112     ok = 0;
113     fprintf(stderr, "*** check failed\n");
114     fprintf(stderr, "*** group: %s\n", v[0].buf);
115     fprintf(stderr, "*** expected: %s\n", v[1].buf);
116     fprintf(stderr, "*** returned: %s\n", e);
117   }
118   assert(mparena_count(MPARENA_GLOBAL) == 0);
119   return (ok);
120 }
121
122 static int vcheckelt(dstr *v)
123 {
124   group *g = getgroup(v[0].buf);
125   ge *x = getge(g, v[1].buf);
126   int ir = *(int *)v[2].buf;
127   int ic = group_check(g, x);
128   int ok = 1;
129   if (ir != ic) {
130     ok = 0;
131     fprintf(stderr, "*** check failed\n");
132     fprintf(stderr, "*** group: %s\n", v[0].buf);
133     show(g, "x", x);
134     fprintf(stderr, "*** expected %s\n", ir ? "failure" : "success");
135   }
136   G_DESTROY(g, x);
137   G_DESTROYGROUP(g);
138   assert(mparena_count(MPARENA_GLOBAL) == 0);
139   return (ok);
140 }
141
142 static int vmul(dstr *v)
143 {
144   group *g = getgroup(v[0].buf);
145   ge *x = getge(g, v[1].buf);
146   ge *y = getge(g, v[2].buf);
147   ge *r = getge(g, v[3].buf);
148   ge *c = G_CREATE(g);
149   int ok = 1;
150   G_MUL(g, c, x, y);
151   ok &= check("mul", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
152   G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
153   G_DESTROYGROUP(g);
154   assert(mparena_count(MPARENA_GLOBAL) == 0);
155   return (ok);
156 }
157
158 static int vsqr(dstr *v)
159 {
160   group *g = getgroup(v[0].buf);
161   ge *x = getge(g, v[1].buf);
162   ge *r = getge(g, v[2].buf);
163   ge *c = G_CREATE(g);
164   int ok = 1;
165   G_SQR(g, c, x);
166   ok &= check("sqr", v[0].buf, g, r, c, "x", x, (char *)0);
167   G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
168   G_DESTROYGROUP(g);
169   assert(mparena_count(MPARENA_GLOBAL) == 0);
170   return (ok);
171 }
172
173 static int vinv(dstr *v)
174 {
175   group *g = getgroup(v[0].buf);
176   ge *x = getge(g, v[1].buf);
177   ge *r = getge(g, v[2].buf);
178   ge *c = G_CREATE(g);
179   int ok = 1;
180   G_INV(g, c, x);
181   ok &= check("inv", v[0].buf, g, r, c, "x", x, (char *)0);
182   G_DESTROY(g, x); G_DESTROY(g, r); G_DESTROY(g, c);
183   G_DESTROYGROUP(g);
184   assert(mparena_count(MPARENA_GLOBAL) == 0);
185   return (ok);
186 }
187
188 static int vdiv(dstr *v)
189 {
190   group *g = getgroup(v[0].buf);
191   ge *x = getge(g, v[1].buf);
192   ge *y = getge(g, v[2].buf);
193   ge *r = getge(g, v[3].buf);
194   ge *c = G_CREATE(g);
195   int ok = 1;
196   G_DIV(g, c, x, y);
197   ok &= check("div", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
198   group_stddiv(g, c, x, y);
199   ok &= check("stddiv", v[0].buf, g, r, c, "x", x, "y", y, (char *)0);
200   G_DESTROY(g, x); G_DESTROY(g, y); G_DESTROY(g, r); G_DESTROY(g, c);
201   G_DESTROYGROUP(g);
202   assert(mparena_count(MPARENA_GLOBAL) == 0);
203   return (ok);
204 }
205
206 static int vexp(dstr *v)
207 {
208   group *g = getgroup(v[0].buf);
209   ge *x = getge(g, v[1].buf);
210   mp *n = *(mp **)v[2].buf;
211   ge *r = getge(g, v[3].buf);
212   ge *c = G_CREATE(g);
213   int ok = 1;
214   G_EXP(g, c, x, n);
215   if (!G_EQ(g, r, c)) {
216     ok = 0;
217     fprintf(stderr, "\n*** exp failed\n");
218     fprintf(stderr, "*** group: %s\n", v[0].buf);
219     show(g, "x", x); showmp("n", n, 10);
220     show(g, "expected", r); show(g, "computed", c);
221   }
222   group_stdexp(g, c, x, n);
223   if (!G_EQ(g, r, c)) {
224     ok = 0;
225     fprintf(stderr, "\n*** stdexp failed\n");
226     fprintf(stderr, "*** group: %s\n", v[0].buf);
227     show(g, "x", x); showmp("n", n, 10);
228     show(g, "expected", r); show(g, "computed", c);
229   }
230   G_DESTROY(g, x); MP_DROP(n); G_DESTROY(g, r); G_DESTROY(g, c);
231   G_DESTROYGROUP(g);
232   assert(mparena_count(MPARENA_GLOBAL) == 0);
233   return (ok);
234 }
235
236 static int vmexp(size_t n, dstr *v)
237 {
238   group *g = getgroup(v[0].buf);
239   ge *c, *r;
240   group_expfactor *f = xmalloc(n * sizeof(group_expfactor));
241   int ok = 1;
242   size_t i;
243   for (i = 0; i < n; i++) {
244     f[i].base = getge(g, v[1 + 2 * i].buf);
245     f[i].exp = *(mp **)v[2 + 2 * i].buf;
246   }
247   r = getge(g, v[1 + 2 * n].buf);
248   c = G_CREATE(g);
249   G_MEXP(g, c, f, n);
250   if (!G_EQ(g, r, c)) {
251     ok = 0;
252     fprintf(stderr, "\n*** mexp failed\n");
253     fprintf(stderr, "*** group: %s\n", v[0].buf);
254     for (i = 0; i < n; i++) {
255       show(g, "base", f[i].base);
256       showmp("exp", f[i].exp, 10);
257     }
258     show(g, "expected", r); show(g, "computed", c);
259   }
260   group_stdmexp(g, c, f, n);
261   if (!G_EQ(g, r, c)) {
262     ok = 0;
263     fprintf(stderr, "\n*** stdmexp failed\n");
264     fprintf(stderr, "*** group: %s\n", v[0].buf);
265     for (i = 0; i < n; i++) {
266       show(g, "base", f[i].base);
267       showmp("exp", f[i].exp, 10);
268     }
269     show(g, "expected", r); show(g, "computed", c);
270   }
271   for (i = 0; i < n; i++) { G_DESTROY(g, f[i].base); MP_DROP(f[i].exp); }
272   G_DESTROY(g, r); G_DESTROY(g, c);
273   G_DESTROYGROUP(g);
274   assert(mparena_count(MPARENA_GLOBAL) == 0);
275   return (ok);
276 }
277
278 static int vmexp1(dstr *v) { return vmexp(1, v); }
279 static int vmexp2(dstr *v) { return vmexp(2, v); }
280 static int vmexp3(dstr *v) { return vmexp(3, v); }
281 static int vmexp4(dstr *v) { return vmexp(4, v); }
282
283 static int vtoint(dstr *v)
284 {
285   group *g = getgroup(v[0].buf);
286   ge *x = getge(g, v[1].buf);
287   int ir = *(int *)v[2].buf;
288   mp *r = *(mp **)v[3].buf;
289   mp *c;
290   int ic;
291   int ok = 1;
292   c = G_TOINT(g, MP_NEW, x);
293   ic = c ? 0 : -1;
294   if (ir != ic || (!ic && !MP_EQ(r, c))) {
295     ok = 0;
296     fprintf(stderr, "\n*** toint failed\n");
297     fprintf(stderr, "*** group: %s\n", v[0].buf);
298     if (ir) fprintf(stderr, "*** expected failure\n");
299     else { show(g, "x", x); showmp("expected", r, 16);
300     showmp("computed", c, 16); }
301   }
302   G_DESTROY(g, x); mp_drop(r); mp_drop(c);
303   G_DESTROYGROUP(g);
304   assert(mparena_count(MPARENA_GLOBAL) == 0);
305   return (ok);
306 }
307
308 static int vfromint(dstr *v)
309 {
310   group *g = getgroup(v[0].buf);
311   mp *x = *(mp **)v[1].buf;
312   int ir = *(int *)v[2].buf;
313   ge *r = getge(g, v[3].buf);
314   int ic;
315   ge *c = G_CREATE(g);
316   int ok = 1;
317   ic = G_FROMINT(g, c, x);
318   if (ir != ic || (!ic && !G_EQ(g, r, c))) {
319     ok = 0;
320     fprintf(stderr, "\n*** fromint failed\n");
321     fprintf(stderr, "*** group: %s\n", v[0].buf);
322     showmp("x", x, 16); if (ir) fprintf(stderr, "*** should have failed\n");
323     else { show(g, "expected", r); show(g, "computed", c); }
324   }
325   MP_DROP(x); G_DESTROY(g, r); G_DESTROY(g, c);
326   G_DESTROYGROUP(g);
327   assert(mparena_count(MPARENA_GLOBAL) == 0);
328   return (ok);
329 }
330
331 static int vtoec(dstr *v)
332 {
333   group *g = getgroup(v[0].buf);
334   ge *x = getge(g, v[1].buf);
335   int ir = *(int *)v[2].buf;
336   ec *r = (ec *)v[3].buf;
337   int ic;
338   ec c = EC_INIT;
339   int ok = 1;
340   ic = G_TOEC(g, &c, x);
341   if (ir != ic || (!ic && !EC_EQ(r, &c))) {
342     ok = 0;
343     fprintf(stderr, "\n*** toec failed\n");
344     fprintf(stderr, "*** group: %s\n", v[0].buf);
345     show(g, "x", x);
346     if (ir) fprintf(stderr, "*** should have failed\n");
347     else { showec("expected", r); showec("computed", &c); }
348   }
349   G_DESTROY(g, x); EC_DESTROY(&c); EC_DESTROY(r);
350   G_DESTROYGROUP(g);
351   assert(mparena_count(MPARENA_GLOBAL) == 0);
352   return (ok);
353 }
354
355 static int vfromec(dstr *v)
356 {
357   group *g = getgroup(v[0].buf);
358   ec *p = (ec *)v[1].buf;
359   int ir = *(int *)v[2].buf;
360   ge *r = getge(g, v[3].buf);
361   int ic;
362   ge *c = G_CREATE(g);
363   int ok = 1;
364   ic = G_FROMEC(g, c, p);
365   if (ir != ic || (!ic && !G_EQ(g, r, c))) {
366     ok = 0;
367     fprintf(stderr, "\n*** fromec failed\n");
368     fprintf(stderr, "*** group: %s\n", v[0].buf);
369     showec("p", p); if (ir) fprintf(stderr, "*** should have failed\n");
370     else { show(g, "expected", r); show(g, "computed", c); }
371   }
372   EC_DESTROY(p); G_DESTROY(g, r); G_DESTROY(g, c);
373   G_DESTROYGROUP(g);
374   assert(mparena_count(MPARENA_GLOBAL) == 0);
375   return (ok);
376 }
377
378 static int vtobuf(dstr *v)
379 {
380   group *g = getgroup(v[0].buf);
381   ge *x = getge(g, v[1].buf);
382   int ir = *(int *)v[2].buf;
383   dstr c = DSTR_INIT;
384   int ic;
385   buf b;
386   int ok = 1;
387
388   dstr_ensure(&c, v[3].len);
389   buf_init(&b, c.buf, v[3].len);
390   ic = G_TOBUF(g, &b, x);
391   c.len = BLEN(&b);
392   if (ic != ir || (!ic && (c.len != v[3].len ||
393                            memcmp(c.buf, v[3].buf, c.len)))) {
394     ok = 0;
395     fprintf(stderr, "*** tobuf failed\n");
396     fprintf(stderr, "*** group: %s\n", v[0].buf);
397     show(g, "x", x);
398     if (ir) fprintf(stderr, "*** expected failure\n");
399     else {
400       fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
401       fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
402       fputc('\n', stderr);
403     }
404   }
405   G_DESTROY(g, x); dstr_destroy(&c);
406   G_DESTROYGROUP(g);
407   assert(mparena_count(MPARENA_GLOBAL) == 0);
408   return (ok);
409 }
410
411 static int vfrombuf(dstr *v)
412 {
413   group *g = getgroup(v[0].buf);
414   int ir = *(int *)v[2].buf;
415   ge *r = getge(g, v[3].buf);
416   int ic;
417   ge *c = G_CREATE(g);
418   buf b;
419   int ok = 1;
420
421   buf_init(&b, v[1].buf, v[1].len);
422   ic = G_FROMBUF(g, &b, c);
423   if ((ic < 0) != (ir < 0) || (ir >= 0 &&
424                                (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
425     ok = 0;
426     fprintf(stderr, "*** frombuf failed\n");
427     fprintf(stderr, "*** group: %s\n", v[0].buf);
428     fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
429     fputc('\n', stderr);
430     if (ir < 0) fprintf(stderr, "*** expected failure\n");
431     else {
432       show(g, "expected", r); show(g, "computed", c);
433       fprintf(stderr, "*** expected used = %d\n", ir);
434       fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
435     }
436   }
437   G_DESTROY(g, r); G_DESTROY(g, c);
438   G_DESTROYGROUP(g);
439   assert(mparena_count(MPARENA_GLOBAL) == 0);
440   return (ok);
441 }
442
443 static int vtoraw(dstr *v)
444 {
445   group *g = getgroup(v[0].buf);
446   ge *x = getge(g, v[1].buf);
447   int ir = *(int *)v[2].buf;
448   dstr c = DSTR_INIT;
449   int ic;
450   buf b;
451   int ok = 1;
452
453   dstr_ensure(&c, v[3].len);
454   buf_init(&b, c.buf, v[3].len);
455   ic = G_TORAW(g, &b, x);
456   c.len = BLEN(&b);
457   if (ic != ir || (!ic && (c.len != v[3].len ||
458                            memcmp(c.buf, v[3].buf, c.len)))) {
459     ok = 0;
460     fprintf(stderr, "*** toraw failed\n");
461     fprintf(stderr, "*** group: %s\n", v[0].buf);
462     show(g, "x", x);
463     if (ir) fprintf(stderr, "*** expected failure\n");
464     else {
465       fprintf(stderr, "*** expected: "); type_hex.dump(&v[3], stderr);
466       fprintf(stderr, "\n*** computed: "); type_hex.dump(&c, stderr);
467       fputc('\n', stderr);
468     }
469   }
470   G_DESTROY(g, x); dstr_destroy(&c);
471   G_DESTROYGROUP(g);
472   assert(mparena_count(MPARENA_GLOBAL) == 0);
473   return (ok);
474 }
475
476 static int vfromraw(dstr *v)
477 {
478   group *g = getgroup(v[0].buf);
479   int ir = *(int *)v[2].buf;
480   ge *r = getge(g, v[3].buf);
481   int ic;
482   ge *c = G_CREATE(g);
483   buf b;
484   int ok = 1;
485
486   buf_init(&b, v[1].buf, v[1].len);
487   ic = G_FROMRAW(g, &b, c);
488   if ((ic < 0) != (ir < 0) || (ir >= 0 &&
489                                (ir != BLEN(&b) || !G_EQ(g, r, c)))) {
490     ok = 0;
491     fprintf(stderr, "*** fromraw failed\n");
492     fprintf(stderr, "*** group: %s\n", v[0].buf);
493     fprintf(stderr, "*** input string: "); type_hex.dump(&v[1], stderr);
494     fputc('\n', stderr);
495     if (ir < 0) fprintf(stderr, "*** expected failure\n");
496     else {
497       show(g, "expected", r); show(g, "computed", c);
498       fprintf(stderr, "*** expected used = %d\n", ir);
499       fprintf(stderr, "*** computed used = %lu\n", (unsigned long)BLEN(&b));
500     }
501   }
502   G_DESTROY(g, r); G_DESTROY(g, c);
503   G_DESTROYGROUP(g);
504   assert(mparena_count(MPARENA_GLOBAL) == 0);
505   return (ok);
506 }
507
508 static const test_chunk tests[] = {
509   { "check",    vcheck,         { &type_string, &type_string } },
510   { "checkelt", vcheckelt,      { &type_string, &type_string, &type_int } },
511   { "mul",      vmul,           { &type_string, &type_string,
512                                   &type_string, &type_string } },
513   { "sqr",      vsqr,           { &type_string, &type_string,
514                                   &type_string } },
515   { "inv",      vinv,           { &type_string, &type_string,
516                                   &type_string } },
517   { "div",      vdiv,           { &type_string, &type_string,
518                                   &type_string, &type_string } },
519   { "exp",      vexp,           { &type_string, &type_string,
520                                   &type_mp, &type_string } },
521   { "mexp-1",   vmexp1,         { &type_string,
522                                   &type_string, &type_mp,
523                                   &type_string } },
524   { "mexp-2",   vmexp2,         { &type_string,
525                                   &type_string, &type_mp,
526                                   &type_string, &type_mp,
527                                   &type_string } },
528   { "mexp-3",   vmexp3,         { &type_string,
529                                   &type_string, &type_mp,
530                                   &type_string, &type_mp,
531                                   &type_string, &type_mp,
532                                   &type_string } },
533   { "mexp-4",   vmexp4,         { &type_string,
534                                   &type_string, &type_mp,
535                                   &type_string, &type_mp,
536                                   &type_string, &type_mp,
537                                   &type_string, &type_mp,
538                                   &type_string } },
539   { "toint",    vtoint,         { &type_string, &type_string,
540                                   &type_int, &type_mp } },
541   { "fromint",  vfromint,       { &type_string, &type_mp,
542                                   &type_int, &type_string } },
543   { "toec",     vtoec,          { &type_string, &type_string,
544                                   &type_int, &type_ec } },
545   { "fromec",   vfromec,        { &type_string, &type_ec,
546                                   &type_int, &type_string } },
547   { "tobuf",    vtobuf,         { &type_string, &type_string,
548                                   &type_int, &type_hex } },
549   { "frombuf",  vfrombuf,       { &type_string, &type_hex,
550                                   &type_int, &type_string } },
551   { "toraw",    vtoraw,         { &type_string, &type_string,
552                                   &type_int, &type_hex } },
553   { "fromraw",  vfromraw,       { &type_string, &type_hex,
554                                   &type_int, &type_string } },
555   { 0 }
556 };
557
558 int main(int argc, char *argv[])
559 {
560   sub_init();
561   test_run(argc, argv, tests, SRCDIR "/t/group");
562   return (0);
563 }
564
565 /*----- That's all, folks -------------------------------------------------*/