test(v4.0.0): D-10 two-cell Q48.16; execute Q.ABS and Q.NEG against v3
D-10 (ruled 2026-10-02): a Q48.16 value is two cells at every cell width, so every Q word is the same double word on 32- and 64-bit nodes. Recorded in DECOMPOSITION.md section 3 and 5.26; the open note on the Q.+/Q.- row is resolved by it. Q.ABS and Q.NEG are the DABS and DNEGATE words. Checked against v3's q48_abs and 0 - q on the 15 edge Q values and 20000 pseudo-random values, at 32- and 64-bit cells, optimised and ASan+UBSan: - 32-bit cells: bit-for-bit v3, including v3's wrap of Q min to itself. - 64-bit cells: the low cell is v3's; the high cell is the true sign (so ABS and NEG of Q min give +2^63 rather than wrapping), per D-10. Breaking DNEGATE's carry fails Q.NEG, Q.ABS and Q.- checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4f493fa317
commit
d948e0c1a3
@@ -171,6 +171,7 @@ definition below depends on one, it says so.
|
||||
| **D-7** | `ROLL` semantics. | **Moot.** `ROLL` is retired under D-2. |
|
||||
| **D-8** | Q48.16 signedness. | **Signed.** v3's unsigned comparisons and `Q.FROM-INT` clamping are retired. |
|
||||
| **D-9** | Instruction word width on a 64-bit-cell host (ruled 2026-10-02). | **32 bits at every cell width.** Six 5-bit slots plus 2 spare bits, as in §1.2. On a 64-bit host the instruction word is the low 32 bits of the cell and the high half is ignored, so compiled code is identical at both widths. Only data and `@p` literals are a full cell wide. |
|
||||
| **D-10** | Q48.16 width on a 64-bit-cell node (ruled 2026-10-02). | **Two cells at every cell width.** A Q value is a signed double on 32- and 64-bit nodes alike, so every Q word is the same double word at both widths. At 32-bit cells this is bit-for-bit v3's 64-bit Q. At 64-bit cells the low cell is v3's value, and where v3 wraps on Q48.16 overflow (a sum past Q max, `ABS` or `NEG` of Q min) the high cell carries the true result instead. |
|
||||
|
||||
**Consequences of D-2 that every definition must respect.** The data stack holds 10 items and the
|
||||
return stack 9, and every `call`, `FOR`, `DO` loop frame and `push` uses return-stack slots. Nesting
|
||||
@@ -640,14 +641,14 @@ index should use them; they cost one instruction per iteration.
|
||||
### 5.26 Q48.16 fixed-point math
|
||||
|
||||
A Q48.16 value is 64 bits, so on a 32-bit node it occupies **two cells** and every Q word is a double
|
||||
word. Per D-8, v4 Q values are signed.
|
||||
word. Per D-10 it occupies two cells on a 64-bit node too. Per D-8, v4 Q values are signed.
|
||||
|
||||
| Word | Fate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `Q.+` `Q.-` | CAP | `D+`, `D-` — executed on the golden model (2026-10-02) against v3's `q48_add`/`q48_sub` (`uint64_t` wrapping). At 32-bit cells the result is bit-for-bit v3's, overflow included. **Open:** at 64-bit cells a Q value as a sign-extended double has the same low cell as v3, but on Q48.16 overflow the high cell holds the true carry where v3 wraps. Whether a Q value is one cell or two on a 64-bit node is not yet ruled. |
|
||||
| `Q.+` `Q.-` | CAP | `D+`, `D-` — executed on the golden model (2026-10-02) against v3's `q48_add`/`q48_sub` (`uint64_t` wrapping): bit-for-bit at 32-bit cells; at 64-bit cells the low cell is v3's, per D-10. |
|
||||
| `Q.*` | CAP | 64×64 product from four `UM*` partial products, shifted right 16. |
|
||||
| `Q./` | CAP | Shifted long division. **Division by zero sets an error** (v3 returned 0 silently). |
|
||||
| `Q.ABS` `Q.NEG` | CAP | `DABS`, `DNEGATE` |
|
||||
| `Q.ABS` `Q.NEG` | CAP | `DABS`, `DNEGATE` — executed on the golden model (2026-10-02) against v3's `q48_abs` and `0 - q`: bit-for-bit at 32-bit cells, including v3's wrap of Q min to itself; at 64-bit cells the low cell is v3's and the high cell is the true sign, per D-10. |
|
||||
| `Q.LOG` `Q.EXP` `Q.SQRT` `Q.SIN` `Q.COS` | CAP | Algorithms ported from `q48_words.c`; the hosted C versions are the golden model. |
|
||||
| `Q.FROM-INT` | CAP | `S>D` shifted left 16. Negative values are no longer clamped to 0. |
|
||||
| `Q.TO-INT` | CAP | Shift right 16, take the low cell. |
|
||||
|
||||
Reference in New Issue
Block a user