feat(v4.0.0): full-range UM* under plain F18 +* (D-3)
UM* as first written in DECOMPOSITION.md section 4 was exact only while u1 <= 2^(n-2): plain +* loses the carry out of T and its shift keeps T's sign bit, so the loop is exact only while S and T stay in [-2^(n-2), 2^(n-2)). The rewrite multiplies by s = u1 2/, which always lies in that range, starting T at t0 = u2 2/ when u1 is odd, so the loop yields hi:lo = t0 + s*u2 exactly. Then u1*u2 = 2*(hi:lo) + c_lo + c_hi*2^n c_lo = u1 & u2 & 1 c_hi = (u1<0 ? u2 : 0) + (u1 odd and u2<0 ? 1 : 0) restores the halved-away bits and the unsigned reading of both top bits. test_foundation.c runs the new definition against v4_umul over every pair of the edge vectors plus 20000 pseudo-random pairs, at 32- and 64-bit cells, optimised and under ASan+UBSan. The two pinned failing cases are now ordinary exactness checks. Two hand mutations of the correction step each fail more than 10000 checks at both widths. DECOMPOSITION.md: section 4 UM* replaced, D-3 ruling text updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
067f317c47
commit
9a391eb0ad
@@ -164,7 +164,7 @@ definition below depends on one, it says so.
|
||||
| --- | --- | --- |
|
||||
| **D-1** | Word addressing (pure Moore) or byte addressing. | **Word addressing.** `C@`/`C!` are CAP; `CELLS` is a no-op. |
|
||||
| **D-2** | Stack depth, and whether the stacks are visible. | **F18 circular stacks, hidden.** Data stack 10 deep (`T`, `S` + 8 circular), return stack 9 deep (`R` + 8 circular), exactly as the F18. No stack pointer is visible to code, so `DEPTH`, `PICK`, `ROLL`, `.S`, `SP@` and `SP!` are **retired everywhere**, host node included. |
|
||||
| **D-3** | Exact `+*` semantics at 32 bits: whether the add carries out of `T` into the shift. | **Plain F18 semantics.** The carry out of `T` is not kept. `UM*` in §4 must be revised accordingly (see the note there). |
|
||||
| **D-3** | Exact `+*` semantics at 32 bits: whether the add carries out of `T` into the shift. | **Plain F18 semantics.** The carry out of `T` is not kept. `UM*` in §4 is written for this and is exact over the full range (revised and proven on the golden model, 2026-10-02). |
|
||||
| **D-4** | Node memory map, including port and register addresses. | **Deferred** to step 2. Symbolic names only for now (§6, §7). |
|
||||
| **D-5** | Host node cell width. | **Match the host CPU:** 32 on a Zynq-7000 (Cortex-A9), 64 on an aarch64 host. The compiler capsule is written width-independent. |
|
||||
| **D-6** | Which heat structures exist in hardware: per-opcode counters only, or also per-call-target and word-to-word transition counters. | **Deferred** to step 2. The golden model implements per-opcode and per-call-target heat in the meantime. |
|
||||
@@ -201,11 +201,24 @@ dependency order.
|
||||
: U< ( u1 u2 -- flag ) 2DUP xor 0< IF NIP 0< ELSE - 0< THEN ;
|
||||
|
||||
\ ---- multiply (D-3) -----------------------------------------------------
|
||||
\ NEEDS REVISION: written for the carry-keeping +* that D-3 rejected. With
|
||||
\ plain F18 +* the carry out of T is lost, so this is only correct when the
|
||||
\ partial sums never overflow T (operands below 2^31). A full-range UM*
|
||||
\ needs a correction step; to be rewritten and proven on the golden model.
|
||||
: UM* ( u1 u2 -- ulo uhi ) a! 0 31 FOR +* UNEXT push drop a pop ;
|
||||
\ Plain F18 +* loses the carry out of T, and its shift keeps T's sign bit, so
|
||||
\ the loop is exact only while the multiplicand in S and the running T both
|
||||
\ lie in [-2^(n-2), 2^(n-2)). UM* therefore multiplies by s = u1 2/, which
|
||||
\ always does, starting T at t0 = u2 2/ when u1 is odd, and gets
|
||||
\ hi:lo = t0 + s*u2. Then u1*u2 = 2*(hi:lo) + c_lo + c_hi*2^n, where
|
||||
\ c_lo = u1 & u2 & 1
|
||||
\ c_hi = (u1<0 ? u2 : 0) + (u1 odd and u2<0 ? 1 : 0)
|
||||
\ restore the bits the two halvings dropped and the unsigned reading of
|
||||
\ both top bits. Exact over the full range; proven on the golden model.
|
||||
: UM* ( u1 u2 -- ulo uhi )
|
||||
over 0< over and push \ R: u1<0 ? u2 : 0
|
||||
over over 0< and 1 and pop + push \ R: c_hi
|
||||
over over and 1 and push \ R: c_hi c_lo
|
||||
over 1 and NEGATE over 2/ and push \ R: c_hi c_lo t0
|
||||
a! 2/ pop \ s t0 A: u2
|
||||
31 FOR +* UNEXT \ s hi A: lo
|
||||
NIP a 2* pop + SWAP \ lo' hi
|
||||
2* a 0< NEGATE + pop + ; \ lo' hi'
|
||||
|
||||
\ ---- divide: 32-step restoring division, divisor held in A --------------
|
||||
: UM/MOD ( ulo uhi ud -- urem uquot )
|
||||
|
||||
Reference in New Issue
Block a user