feat(v4.0.0): SM/REM and DNEGATE call-free; execute /MOD and its section 5 words
SM/REM as written in section 4 never returned correctly for a negative dividend. It holds three entries on the return stack and then calls DABS -> DNEGATE -> D+ -> U> -> SWAP/U<, which overflows the 9-deep circular return stack (D-2). DABS itself could not run: DNEGATE as written (inv SWAP inv SWAP 1 0 D+) left its caller no return entries. - DNEGATE: inv over if L1 drop push inv 1 + pop ; L1: drop 1 + ; i.e. ~d + 1, carrying into the high cell exactly when lo = 0. - SM/REM: sign tests are native -if (as in 0<) and NEGATE is in line; the only calls are DNEGATE and UM/MOD, both call-free inside. Executed on the golden model at 32- and 64-bit cells, optimised and under ASan+UBSan: - SM/REM on dividends built as q*n + r with |r| < |n| and r signed as d: every edge-vector q, n with r = 0 and r = +-(|n|-1), plus 20000 pseudo-random cases. - /MOD, U>, ABS, S>D, D+ and DABS as written in section 5, against C (D+ over all 50625 edge-vector quadruples). Mutations of DNEGATE's carry and of each SM/REM sign branch are caught. Headroom (data cells under args / return entries under return address): SM/REM 5/3, /MOD 5/2, DNEGATE 7/7, DABS 7/6, ABS 8/7, U> 6/5. D+ as written is exact but leaves only 1 return entry; recorded in DECOMPOSITION.md 5.7 as not yet revised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3b9d1e4337
commit
93d09840da