test(v4.0.0): execute M+, D-, D0= and D= on the golden model
All four run exactly as written in DECOMPOSITION.md 5.6/5.7 and need no change now that D+ and DNEGATE are call-free. Checked against C at 32- and 64-bit cells, optimised and ASan+UBSan: every edge-vector combination (M+ over all triples, D- and D= over all 50625 quadruples, D0= over all pairs) plus 20000 pseudo-random cases weighted to equal low or high cells and low sums that wrap to 0. Mutations of D0= and M+ are caught. Headroom (data cells under args / return entries under return address): M+ 6/4, D- 5/4, D0= 7/7, D= 5/3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
092036c97a
commit
6a371b850e
@@ -14,7 +14,8 @@
|
||||
* call-free versions in sections 4 and 5.7; SM/REM is checked on dividends
|
||||
* built as q*n + r. D+ is the call-free version in 5.7, checked against C
|
||||
* over every quadruple of the edge vectors and pseudo-random pairs. /MOD,
|
||||
* U>, ABS, S>D and DABS are as written in section 5 and checked against C. Every one is also probed for how much of
|
||||
* U>, ABS, S>D, DABS, M+, D-, D0= and D= are as written in section 5 and
|
||||
* checked against C. Every one is also probed for how much of
|
||||
* the 10- and 9-deep circular stacks (D-2) it leaves to its caller.
|
||||
*
|
||||
* Every call is made with a canary under the arguments, and the canary must
|
||||
@@ -41,7 +42,7 @@ static v4_asm as;
|
||||
static v4_cell w_nip, w_swap, w_or, w_negate, w_rot, w_zless, w_zequal,
|
||||
w_2dup, w_minus, w_uless, w_umstar, w_ummod,
|
||||
w_ugreater, w_abs, w_s2d, w_dplus, w_dnegate, w_dabs, w_smrem,
|
||||
w_slashmod;
|
||||
w_slashmod, w_mplus, w_dminus, w_d0equal, w_dequal;
|
||||
|
||||
#define O(name) v4_asm_op(&as, V4_OP_##name)
|
||||
#define LIT(v) v4_asm_lit(&as, (v4_cell)(v))
|
||||
@@ -325,6 +326,22 @@ static void build(void)
|
||||
w_slashmod = v4_asm_label(&as);
|
||||
O(PUSH); CALL(w_s2d); O(RPOP); CALL(w_smrem); O(SEMI);
|
||||
|
||||
/* : M+ S>D D+ ; 5.6 */
|
||||
w_mplus = v4_asm_label(&as);
|
||||
CALL(w_s2d); CALL(w_dplus); O(SEMI);
|
||||
|
||||
/* : D- DNEGATE D+ ; 5.7 */
|
||||
w_dminus = v4_asm_label(&as);
|
||||
CALL(w_dnegate); CALL(w_dplus); O(SEMI);
|
||||
|
||||
/* : D0= OR 0= ; 5.7 */
|
||||
w_d0equal = v4_asm_label(&as);
|
||||
CALL(w_or); CALL(w_zequal); O(SEMI);
|
||||
|
||||
/* : D= D- D0= ; 5.7 */
|
||||
w_dequal = v4_asm_label(&as);
|
||||
CALL(w_dminus); CALL(w_d0equal); O(SEMI);
|
||||
|
||||
CHECK(v4_asm_ok(&as), "foundation words assemble");
|
||||
}
|
||||
|
||||
@@ -664,6 +681,50 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* M+, D-, D0= and D= against C: every edge-vector combination, then
|
||||
* pseudo-random doubles. */
|
||||
for (unsigned i = 0; i < NVEC; i++)
|
||||
for (unsigned j = 0; j < NVEC; j++) {
|
||||
v4_ucell ua = (v4_ucell)vec[i], ub = (v4_ucell)vec[j], rl, rh;
|
||||
CHECK(call(w_d0equal, 2, vec[i], vec[j], 0) && left1(FLAG(ua == 0 && ub == 0)),
|
||||
"D0= [%u,%u]", i, j);
|
||||
for (unsigned k = 0; k < NVEC; k++) {
|
||||
v4_cell c = vec[k];
|
||||
dadd(ua, ub, (v4_ucell)c, c < 0 ? MAXU : 0u, &rl, &rh);
|
||||
CHECK(call(w_mplus, 3, vec[i], vec[j], c) && left2((v4_cell)rl, (v4_cell)rh),
|
||||
"M+ [%u,%u,%u]", i, j, k);
|
||||
for (unsigned l = 0; l < NVEC; l++) {
|
||||
v4_ucell nl, nh;
|
||||
dneg((v4_ucell)vec[k], (v4_ucell)vec[l], &nl, &nh);
|
||||
dadd(ua, ub, nl, nh, &rl, &rh);
|
||||
CHECK(call4(w_dminus, vec[i], vec[j], vec[k], vec[l])
|
||||
&& left2((v4_cell)rl, (v4_cell)rh), "D- [%u,%u,%u,%u]", i, j, k, l);
|
||||
CHECK(call4(w_dequal, vec[i], vec[j], vec[k], vec[l])
|
||||
&& left1(FLAG(i == k && j == l)), "D= [%u,%u,%u,%u]", i, j, k, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
v4_ucell x = (v4_ucell)0x5851F42Du, v[4], rl, rh, nl, nh;
|
||||
for (unsigned i = 0; i < 20000; i++) {
|
||||
for (unsigned k = 0; k < 4; k++) { x ^= x << 13; x ^= x >> 7; x ^= x << 17; v[k] = x; }
|
||||
if (i & 1u) v[2] = v[0]; /* equal low cells */
|
||||
if (i & 2u) v[3] = v[1]; /* equal high cells */
|
||||
if (i & 4u) v[2] = 0u - v[0]; /* low sum wraps */
|
||||
dadd(v[0], v[1], v[2], (v4_cell)v[2] < 0 ? MAXU : 0u, &rl, &rh);
|
||||
CHECK(call(w_mplus, 3, (v4_cell)v[0], (v4_cell)v[1], (v4_cell)v[2])
|
||||
&& left2((v4_cell)rl, (v4_cell)rh), "M+ random [%u]", i);
|
||||
dneg(v[2], v[3], &nl, &nh);
|
||||
dadd(v[0], v[1], nl, nh, &rl, &rh);
|
||||
CHECK(call4(w_dminus, (v4_cell)v[0], (v4_cell)v[1], (v4_cell)v[2], (v4_cell)v[3])
|
||||
&& left2((v4_cell)rl, (v4_cell)rh), "D- random [%u]", i);
|
||||
CHECK(call4(w_dequal, (v4_cell)v[0], (v4_cell)v[1], (v4_cell)v[2], (v4_cell)v[3])
|
||||
&& left1(FLAG(v[0] == v[2] && v[1] == v[3])), "D= random [%u]", i);
|
||||
CHECK(call(w_d0equal, 2, (v4_cell)(v[0] & v[2]), (v4_cell)(v[1] & v[3]), 0)
|
||||
&& left1(FLAG((v[0] & v[2]) == 0 && (v[1] & v[3]) == 0)), "D0= random [%u]", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stack headroom of the two longest definitions. */
|
||||
{
|
||||
static const v4_cell umstar_args[][4] = {
|
||||
@@ -701,6 +762,18 @@ int main(void)
|
||||
CHECK(rh >= 5, "D+ leaves 5 return entries");
|
||||
headroom("DNEGATE", w_dnegate, 2, two_args, 5, 2, &dh, &rh);
|
||||
headroom("DABS", w_dabs, 2, two_args, 5, 2, &dh, &rh);
|
||||
static const v4_cell mplus_args[][4] = {
|
||||
{ -1, 0, 1, 0 }, { 5, 7, -9, 0 }, { 0, 0, -1, 0 }, { (v4_cell)V4_MSB, 0, (v4_cell)V4_MSB, 0 }
|
||||
};
|
||||
static const v4_cell dsub_args[][4] = {
|
||||
{ 0, 0, 1, 0 }, { 5, 7, 9, 11 }, { -1, -1, -1, -1 }, { 0, 1, 0, 1 },
|
||||
{ (v4_cell)V4_MSB, 0, (v4_cell)V4_MSB, 0 }, { 1, 0, 2, 0 }
|
||||
};
|
||||
headroom("M+", w_mplus, 3, mplus_args, 4, 2, &dh, &rh);
|
||||
headroom("D-", w_dminus, 4, dsub_args, 6, 2, &dh, &rh);
|
||||
headroom("D0=", w_d0equal, 2, two_args, 5, 1, &dh, &rh);
|
||||
headroom("D=", w_dequal, 4, dsub_args, 6, 1, &dh, &rh);
|
||||
CHECK(dh >= 0 && rh >= 0, "D= runs at all");
|
||||
headroom("SM/REM", w_smrem, 3, smrem_args, 5, 2, &dh, &rh);
|
||||
CHECK(rh >= 1, "SM/REM leaves room for /MOD's return address");
|
||||
headroom("/MOD", w_slashmod, 2, slashmod_args, 4, 2, &dh, &rh);
|
||||
|
||||
Reference in New Issue
Block a user