+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);
+ }
+
+ xfree(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;
+ }
+
+ xfree(a); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(b); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(b); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(b); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(c); xfree(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;
+ }
+
+ xfree(a); xfree(b); xfree(r); xfree(q); xfree(s); xfree(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
+