+static int chkscan(const mpw *v, const mpw *vl,
+ const void *pp, size_t sz, int step)
+{
+ mpscan mps;
+ const octet *p = pp;
+ unsigned bit = 0;
+ int ok = 1;
+
+ mpscan_initx(&mps, v, vl);
+ while (sz) {
+ unsigned x = *p;
+ int i;
+ p += step;
+ for (i = 0; i < 8 && MPSCAN_STEP(&mps); i++) {
+ if (MPSCAN_BIT(&mps) != (x & 1)) {
+ fprintf(stderr,
+ "\n*** error, step %i, bit %u, expected %u, found %u\n",
+ step, bit, x & 1, MPSCAN_BIT(&mps));
+ ok = 0;
+ }
+ x >>= 1;
+ bit++;
+ }
+ sz--;
+ }
+
+ return (ok);
+}
+
+static int loadstore(dstr *v)
+{
+ dstr d = DSTR_INIT;
+ size_t sz = MPW_RQ(v->len) * 2, diff;
+ mpw *m, *ml;
+ int ok = 1;
+
+ dstr_ensure(&d, v->len);
+ m = xmalloc(MPWS(sz));
+
+ for (diff = 0; diff < sz; diff += 5) {
+ size_t oct;
+
+ ml = m + sz - diff;
+
+ mpx_loadl(m, ml, v->buf, v->len);
+ if (!chkscan(m, ml, v->buf, v->len, +1))
+ ok = 0;
+ MPX_OCTETS(oct, m, ml);
+ mpx_storel(m, ml, d.buf, d.sz);
+ if (memcmp(d.buf, v->buf, oct) != 0) {
+ dumpbits("\n*** storel failed", d.buf, d.sz);
+ ok = 0;
+ }
+
+ mpx_loadb(m, ml, v->buf, v->len);
+ if (!chkscan(m, ml, v->buf + v->len - 1, v->len, -1))
+ ok = 0;
+ MPX_OCTETS(oct, m, ml);
+ mpx_storeb(m, ml, d.buf, d.sz);
+ if (memcmp(d.buf + d.sz - oct, v->buf + v->len - oct, oct) != 0) {
+ dumpbits("\n*** storeb failed", d.buf, d.sz);
+ ok = 0;
+ }
+ }
+
+ if (!ok)
+ dumpbits("input data", v->buf, v->len);
+
+ free(m);
+ dstr_destroy(&d);
+ return (ok);
+}
+
+static int twocl(dstr *v)
+{
+ dstr d = DSTR_INIT;
+ mpw *m, *ml;
+ size_t sz;
+ int ok = 1;
+
+ sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
+ dstr_ensure(&d, sz);
+
+ sz = MPW_RQ(sz);
+ m = xmalloc(MPWS(sz));
+ ml = m + sz;
+
+ mpx_loadl(m, ml, v[0].buf, v[0].len);
+ mpx_storel2cn(m, ml, d.buf, v[1].len);
+ if (memcmp(d.buf, v[1].buf, v[1].len)) {
+ dumpbits("\n*** storel2cn failed", d.buf, v[1].len);
+ ok = 0;
+ }
+
+ mpx_loadl2cn(m, ml, v[1].buf, v[1].len);
+ mpx_storel(m, ml, d.buf, v[0].len);
+ if (memcmp(d.buf, v[0].buf, v[0].len)) {
+ dumpbits("\n*** loadl2cn failed", d.buf, v[0].len);
+ ok = 0;
+ }
+
+ if (!ok) {
+ dumpbits("pos", v[0].buf, v[0].len);
+ dumpbits("neg", v[1].buf, v[1].len);
+ }
+
+ free(m);
+ dstr_destroy(&d);
+
+ return (ok);
+}
+
+static int twocb(dstr *v)
+{
+ dstr d = DSTR_INIT;
+ mpw *m, *ml;
+ size_t sz;
+ int ok = 1;
+
+ sz = v[0].len; if (v[1].len > sz) sz = v[1].len;
+ dstr_ensure(&d, sz);
+
+ sz = MPW_RQ(sz);
+ m = xmalloc(MPWS(sz));
+ ml = m + sz;
+
+ mpx_loadb(m, ml, v[0].buf, v[0].len);
+ mpx_storeb2cn(m, ml, d.buf, v[1].len);
+ if (memcmp(d.buf, v[1].buf, v[1].len)) {
+ dumpbits("\n*** storeb2cn failed", d.buf, v[1].len);
+ ok = 0;
+ }
+
+ mpx_loadb2cn(m, ml, v[1].buf, v[1].len);
+ mpx_storeb(m, ml, d.buf, v[0].len);
+ if (memcmp(d.buf, v[0].buf, v[0].len)) {
+ dumpbits("\n*** loadb2cn failed", d.buf, v[0].len);
+ ok = 0;
+ }
+
+ if (!ok) {
+ dumpbits("pos", v[0].buf, v[0].len);
+ dumpbits("neg", v[1].buf, v[1].len);
+ }
+
+ free(m);
+ dstr_destroy(&d);
+
+ return (ok);
+}
+
+static int lsl(dstr *v)
+{
+ mpw *a, *al;
+ int n = *(int *)v[1].buf;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
+
+ mpx_lsl(d, dl, a, al, n);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** lsl(%i) failed\n", n);
+ dumpmp(" a", a, al);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(c); free(d);
+ return (ok);
+}
+
+static int lslc(dstr *v)
+{
+ mpw *a, *al;
+ int n = *(int *)v[1].buf;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS);
+
+ mpx_lslc(d, dl, a, al, n);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** lslc(%i) failed\n", n);
+ dumpmp(" a", a, al);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(c); free(d);
+ return (ok);
+}
+
+static int lsr(dstr *v)
+{
+ mpw *a, *al;
+ int n = *(int *)v[1].buf;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, al - a + (n + MPW_BITS - 1) / MPW_BITS + 1);
+
+ mpx_lsr(d, dl, a, al, n);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** lsr(%i) failed\n", n);
+ dumpmp(" a", a, al);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(c); free(d);
+ return (ok);
+}
+
+static int uadd(dstr *v)
+{
+ mpw *a, *al;
+ mpw *b, *bl;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(b, bl, &v[1]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, MAX(al - a, bl - b) + 1);
+
+ mpx_uadd(d, dl, a, al, b, bl);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** uadd failed\n");
+ dumpmp(" a", a, al);
+ dumpmp(" b", b, bl);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(b); free(c); free(d);
+ return (ok);
+}
+
+static int usub(dstr *v)
+{
+ mpw *a, *al;
+ mpw *b, *bl;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(b, bl, &v[1]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, al - a);
+
+ mpx_usub(d, dl, a, al, b, bl);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** usub failed\n");
+ dumpmp(" a", a, al);
+ dumpmp(" b", b, bl);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(b); free(c); free(d);
+ return (ok);
+}
+
+static int umul(dstr *v)
+{
+ mpw *a, *al;
+ mpw *b, *bl;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(b, bl, &v[1]);
+ LOAD(c, cl, &v[2]);
+ ALLOC(d, dl, (al - a) + (bl - b));
+
+ mpx_umul(d, dl, a, al, b, bl);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** umul failed\n");
+ dumpmp(" a", a, al);
+ dumpmp(" b", b, bl);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(b); free(c); free(d);
+ return (ok);
+}
+
+static int usqr(dstr *v)
+{
+ mpw *a, *al;
+ mpw *c, *cl;
+ mpw *d, *dl;
+ int ok = 1;
+
+ LOAD(a, al, &v[0]);
+ LOAD(c, cl, &v[1]);
+ ALLOC(d, dl, 2 * (al - a));
+
+ mpx_usqr(d, dl, a, al);
+ if (!mpx_ueq(d, dl, c, cl)) {
+ fprintf(stderr, "\n*** usqr failed\n");
+ dumpmp(" a", a, al);
+ dumpmp("expected", c, cl);
+ dumpmp(" result", d, dl);
+ ok = 0;
+ }
+
+ free(a); free(c); free(d);
+ return (ok);
+}
+
+static int udiv(dstr *v)
+{
+ mpw *a, *al;
+ mpw *b, *bl;
+ mpw *q, *ql;
+ mpw *r, *rl;
+ mpw *qq, *qql;
+ mpw *s, *sl;
+ int ok = 1;
+
+ ALLOC(a, al, MPW_RQ(v[0].len) + 2); mpx_loadb(a, al, v[0].buf, v[0].len);
+ LOAD(b, bl, &v[1]);
+ LOAD(q, ql, &v[2]);
+ LOAD(r, rl, &v[3]);
+ ALLOC(qq, qql, al - a);
+ ALLOC(s, sl, (bl - b) + 1);
+
+ mpx_udiv(qq, qql, a, al, b, bl, s, sl);
+ if (!mpx_ueq(qq, qql, q, ql) ||
+ !mpx_ueq(a, al, r, rl)) {
+ fprintf(stderr, "\n*** udiv failed\n");
+ dumpmp(" divisor", b, bl);
+ dumpmp("expect r", r, rl);
+ dumpmp("result r", a, al);
+ dumpmp("expect q", q, ql);
+ dumpmp("result q", qq, qql);
+ ok = 0;
+ }
+
+ free(a); free(b); free(r); free(q); free(s); free(qq);
+ return (ok);
+}
+
+static test_chunk defs[] = {
+ { "load-store", loadstore, { &type_hex, 0 } },
+ { "2cl", twocl, { &type_hex, &type_hex, } },
+ { "2cb", twocb, { &type_hex, &type_hex, } },
+ { "lsl", lsl, { &type_hex, &type_int, &type_hex, 0 } },
+ { "lslc", lslc, { &type_hex, &type_int, &type_hex, 0 } },
+ { "lsr", lsr, { &type_hex, &type_int, &type_hex, 0 } },
+ { "uadd", uadd, { &type_hex, &type_hex, &type_hex, 0 } },
+ { "usub", usub, { &type_hex, &type_hex, &type_hex, 0 } },
+ { "umul", umul, { &type_hex, &type_hex, &type_hex, 0 } },
+ { "usqr", usqr, { &type_hex, &type_hex, 0 } },
+ { "udiv", udiv, { &type_hex, &type_hex, &type_hex, &type_hex, 0 } },
+ { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+ test_run(argc, argv, defs, SRCDIR"/tests/mpx");
+ return (0);
+}
+
+#endif
+