New multiprecision integer arithmetic suite.
[u/mdw/catacomb] / mpx-test.c
1 /* -*-c-*-
2 *
3 * $Id: mpx-test.c,v 1.1 1999/11/13 01:50:04 mdw Exp $
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <mLib/alloc.h>
11 #include <mLib/dstr.h>
12 #include <mLib/quis.h>
13 #include <mLib/testrig.h>
14
15 #include "mpx.h"
16 #include "mpscan.h"
17
18 #define ALLOC(v, vl, sz) do { \
19 size_t _sz = (sz); \
20 mpw *_vv = xmalloc(MPWS(_sz)); \
21 mpw *_vvl = _vv + _sz; \
22 (v) = _vv; \
23 (vl) = _vvl; \
24 } while (0)
25
26 #define LOAD(v, vl, d) do { \
27 const dstr *_d = (d); \
28 mpw *_v, *_vl; \
29 ALLOC(_v, _vl, MPW_RQ(_d->len)); \
30 mpx_loadb(_v, _vl, _d->buf, _d->len); \
31 (v) = _v; \
32 (vl) = _vl; \
33 } while (0)
34
35 #define MAX(x, y) ((x) > (y) ? (x) : (y))
36
37 static void dumpbits(const char *msg, const void *pp, size_t sz)
38 {
39 const octet *p = pp;
40 fputs(msg, stderr);
41 for (; sz; sz--)
42 fprintf(stderr, " %02x", *p++);
43 fputc('\n', stderr);
44 }
45
46 static void dumpmp(const char *msg, const mpw *v, const mpw *vl)
47 {
48 fputs(msg, stderr);
49 MPX_SHRINK(v, vl);
50 while (v < vl)
51 fprintf(stderr, " %08lx", (unsigned long)*--vl);
52 fputc('\n', stderr);
53 }
54
55 static int chkscan(const mpw *v, const mpw *vl,
56 const void *pp, size_t sz, int step)
57 {
58 mpscan mps;
59 const octet *p = pp;
60 unsigned bit = 0;
61 int ok = 1;
62
63 mpscan_initx(&mps, v, vl);
64 while (sz) {
65 unsigned x = *p;
66 int i;
67 p += step;
68 for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) {
69 if (MPSCAN_BIT(&mps) != (x & 1)) {
70 fprintf(stderr,
71 "\n*** error, step %i, bit %u, expected %u, found %u\n",
72 step, bit, x & 1, MPSCAN_BIT(&mps));
73 ok = 0;
74 }
75 x >>= 1;
76 bit++;
77 }
78 sz--;
79 }
80
81 return (ok);
82 }
83
84 static int loadstore(dstr *v)
85 {
86 dstr d = DSTR_INIT;
87 size_t sz = MPW_RQ(v->len) * 2, diff;
88 mpw *m, *ml;
89 int ok = 1;
90
91 dstr_ensure(&d, v->len);
92 m = xmalloc(MPWS(sz));
93
94 for (diff = 0; diff < sz; diff += 5) {
95 size_t oct;
96
97 ml = m + sz - diff;
98
99 mpx_loadl(m, ml, v->buf, v->len);
100 if (!chkscan(m, ml, v->buf, v->len, +1))
101 ok = 0;
102 MPX_OCTETS(oct, m, ml);
103 mpx_storel(m, ml, d.buf, d.sz);
104 if (memcmp(d.buf, v->buf, oct) != 0) {
105 dumpbits("\n*** storel failed", d.buf, d.sz);
106 ok = 0;
107 }
108
109 mpx_loadb(m, ml, v->buf, v->len);
110 if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1))
111 ok = 0;
112 MPX_OCTETS(oct, m, ml);
113 mpx_storeb(m, ml, d.buf, d.sz);
114 if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) {
115 dumpbits("\n*** storeb failed", d.buf, d.sz);
116 ok = 0;
117 }
118 }
119
120 if (!ok)
121 dumpbits("input data", v->buf, v->len);
122
123 free(m);
124 dstr_destroy(&d);
125 return (ok);
126 }
127
128 static int lsl(dstr *v)
129 {
130 mpw *a, *al;
131 int n = *(int *)v[1].buf;
132 mpw *c, *cl;
133 mpw *d, *dl;
134 int ok = 1;
135
136 LOAD(a, al, &v[0]);
137 LOAD(c, cl, &v[2]);
138 ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
139
140 mpx_lsl(d, dl, a, al, n);
141 if (MPX_UCMP(d, dl, !=, c, cl)) {
142 fprintf(stderr, "\n*** lsl(%i) failed\n", n);
143 dumpmp(" a", a, al);
144 dumpmp("expected", c, cl);
145 dumpmp(" result", d, dl);
146 ok = 0;
147 }
148
149 free(a); free(c); free(d);
150 return (ok);
151 }
152
153 static int lsr(dstr *v)
154 {
155 mpw *a, *al;
156 int n = *(int *)v[1].buf;
157 mpw *c, *cl;
158 mpw *d, *dl;
159 int ok = 1;
160
161 LOAD(a, al, &v[0]);
162 LOAD(c, cl, &v[2]);
163 ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1);
164
165 mpx_lsr(d, dl, a, al, n);
166 if (MPX_UCMP(d, dl, !=, c, cl)) {
167 fprintf(stderr, "\n*** lsr(%i) failed\n", n);
168 dumpmp(" a", a, al);
169 dumpmp("expected", c, cl);
170 dumpmp(" result", d, dl);
171 ok = 0;
172 }
173
174 free(a); free(c); free(d);
175 return (ok);
176 }
177
178 static int uadd(dstr *v)
179 {
180 mpw *a, *al;
181 mpw *b, *bl;
182 mpw *c, *cl;
183 mpw *d, *dl;
184 int ok = 1;
185
186 LOAD(a, al, &v[0]);
187 LOAD(b, bl, &v[1]);
188 LOAD(c, cl, &v[2]);
189 ALLOC(d, dl, MAX(al - a, bl - b) + 1);
190
191 mpx_uadd(d, dl, a, al, b, bl);
192 if (MPX_UCMP(d, dl, !=, c, cl)) {
193 fprintf(stderr, "\n*** uadd failed\n");
194 dumpmp(" a", a, al);
195 dumpmp(" b", b, bl);
196 dumpmp("expected", c, cl);
197 dumpmp(" result", d, dl);
198 ok = 0;
199 }
200
201 free(a); free(b); free(c); free(d);
202 return (ok);
203 }
204
205 static int usub(dstr *v)
206 {
207 mpw *a, *al;
208 mpw *b, *bl;
209 mpw *c, *cl;
210 mpw *d, *dl;
211 int ok = 1;
212
213 LOAD(a, al, &v[0]);
214 LOAD(b, bl, &v[1]);
215 LOAD(c, cl, &v[2]);
216 ALLOC(d, dl, al - a);
217
218 mpx_usub(d, dl, a, al, b, bl);
219 if (MPX_UCMP(d, dl, !=, c, cl)) {
220 fprintf(stderr, "\n*** usub failed\n");
221 dumpmp(" a", a, al);
222 dumpmp(" b", b, bl);
223 dumpmp("expected", c, cl);
224 dumpmp(" result", d, dl);
225 ok = 0;
226 }
227
228 free(a); free(b); free(c); free(d);
229 return (ok);
230 }
231
232 static int umul(dstr *v)
233 {
234 mpw *a, *al;
235 mpw *b, *bl;
236 mpw *c, *cl;
237 mpw *d, *dl;
238 int ok = 1;
239
240 LOAD(a, al, &v[0]);
241 LOAD(b, bl, &v[1]);
242 LOAD(c, cl, &v[2]);
243 ALLOC(d, dl, (al - a) + (bl - b));
244
245 mpx_umul(d, dl, a, al, b, bl);
246 if (MPX_UCMP(d, dl, !=, c, cl)) {
247 fprintf(stderr, "\n*** umul failed\n");
248 dumpmp(" a", a, al);
249 dumpmp(" b", b, bl);
250 dumpmp("expected", c, cl);
251 dumpmp(" result", d, dl);
252 ok = 0;
253 }
254
255 free(a); free(b); free(c); free(d);
256 return (ok);
257 }
258
259 static int usqr(dstr *v)
260 {
261 mpw *a, *al;
262 mpw *c, *cl;
263 mpw *d, *dl;
264 int ok = 1;
265
266 LOAD(a, al, &v[0]);
267 LOAD(c, cl, &v[1]);
268 ALLOC(d, dl, 2 * (al - a));
269
270 mpx_usqr(d, dl, a, al);
271 if (MPX_UCMP(d, dl, !=, c, cl)) {
272 fprintf(stderr, "\n*** usqr failed\n");
273 dumpmp(" a", a, al);
274 dumpmp("expected", c, cl);
275 dumpmp(" result", d, dl);
276 ok = 0;
277 }
278
279 free(a); free(c); free(d);
280 return (ok);
281 }
282
283 static int udiv(dstr *v)
284 {
285 mpw *a, *al;
286 mpw *b, *bl;
287 mpw *q, *ql;
288 mpw *r, *rl;
289 mpw *qq, *qql;
290 mpw *s, *sl;
291 int ok = 1;
292
293 ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
294 LOAD(b, bl, &v[1]);
295 LOAD(q, ql, &v[2]);
296 LOAD(r, rl, &v[3]);
297 ALLOC(qq, qql, al - a);
298 ALLOC(s, sl, 2 * (bl - b) + 2);
299
300 mpx_udiv(qq, qql, a, al, b, bl, s, sl);
301 if (MPX_UCMP(qq, qql, !=, q, ql) ||
302 MPX_UCMP(a, al, !=, r, rl)) {
303 fprintf(stderr, "\n*** udiv failed\n");
304 dumpmp(" divisor", b, bl);
305 dumpmp("expect r", r, rl);
306 dumpmp("result r", a, al);
307 dumpmp("expect q", q, ql);
308 dumpmp("result q", qq, qql);
309 ok = 0;
310 }
311
312 free(a); free(b); free(r); free(q); free(s); free(qq);
313 return (ok);
314 }
315
316 static test_chunk defs[] = {
317 { "load-store", loadstore, { &type_hex, 0 } },
318 { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } },
319 { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } },
320 { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } },
321 { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } },
322 { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
323 { "usqr", usqr, { &type_hex, &type_hex, 0 } },
324 { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
325 { 0, 0, { 0 } }
326 };
327
328 int main(int argc, char *argv[])
329 {
330 test_run(argc, argv, defs, SRCDIR"/tests/mpx");
331 return (0);
332 }