feat(v4.0.0): Q./ under D-11, with (UQ/), D2*C and the (Q/) variable
D-11 (ruled 2026-10-02): Q./ rounds toward zero, saturates to Q max / Q min on overflow, and on division by zero returns Q max / Q min by the dividend's sign (0 for 0/0) and sets the new NODE-ERROR register (7), which VM-ERROR? reads. - (UQ/): unsigned floor(a * 2^16 / b) for b != 0 and no overflow. Restoring division, 2N+16 steps, on one shifting register (quotient above remainder). Quotient register and divisor live in a 5-cell variable (Q/), like BASE and the hold buffer, so the stacks carry only the remainder, the quotient bit and the loop count. A first version kept the divisor on the return stack and overflowed it when called from Q./ (it never returned). - D2*C: double shift left with carry in and out. - Q./: zero-divisor handling, signs (kept in (Q/)), an overflow test that needs no division (|a| * 2^16 >= |b| * 2^(2N-1), possible only for |b| < 2^17), then (UQ/) and the sign. Checked at 32- and 64-bit cells, optimised and ASan+UBSan, against an independent limb-by-limb long division (including NODE-ERROR): every pair of 18 edge Q values, 13 width-native edge values (true Q max/min at either width), the overflow boundary, divisors in [2^(2N-2), 2^(2N-1)), and pseudo-random cases; and against v3's q48_div for non-negative a < 2^48. Q.* now also runs on the width-native edge values. Mutations of the compare paths, the take path, the error flag and the overflow mask are all caught (the mask matters only for Q min / -1.0). Headroom (data under args / return): Q./ 3/2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8f37e15f8a
commit
9e03bdab19