starkernel: item 4.3.3b -- geometry drawing wordset, fixed Q.TO-INT sign bug
Adds LINE (Bresenham in raster space, endpoints projected once each -- valid because the cavalier projection is linear), CIRCLE/ELLIPSE (36-segment polygon approximation), and ARC (18 segments over a caller radian range) to capsules/fabric.4th (blocks 4903-4912). TO-RASTER factored out of CART-PLOT (same behavior) so LINE can reuse the projection+flip for both endpoints. Found mid-implementation: colon definitions cannot span block boundaries in this capsule loader -- verified with a throwaway test capsule, the continuation lands in a [CAPSULE][DEFER] path that never resolves. LINE's body is split across LINE-SETUP/LINE-DONE?/LINE-STUCK?/LINE-STEP, each self-contained within its block, rather than one long definition. A fourth real bug, serious this time: CIRCLE's first live test rendered only one quadrant, then hung the VM for several minutes on a follow-up call. Root cause: q48_to_u64() (include/q48_16.h and include/starkernel/q48_16.h, backing Q.TO-INT) did an unsigned logical shift, corrupting any negative Q48.16 value into a huge garbage integer instead of sign-extending -- inevitable once Q.SIN/Q.COS leave the first quadrant. That garbage became a bogus LINE target with no bound on LINE-STEP's Bresenham loop. Fixed q48_to_u64 to shift through a signed int64_t intermediate (bit-identical for the non-negative case). Also added LINE-STUCK? (LSTEPS vs FB-WIDTH+FB-HEIGHT, the true worst case for an on-screen line) as a defense-in-depth cap against any future bad target. Verified live on amd64 after both fixes: -65536 Q.TO-INT . now prints -1; LINE/CIRCLE/ARC/ELLIPSE all complete without hanging or erroring, and a combined screendump shows all four rendering correctly and distinctly. All three architectures boot clean to ok> with the DoE completing; dict_hash identical across all three and unchanged from 4.3.3a (expected -- fabric.4th isn't loaded at boot, and the Q.TO-INT fix doesn't change dictionary structure). FABRIC.md item 4.3.3b marked done with full acceptance evidence.
This commit is contained in:
@@ -3757,11 +3757,46 @@ document and committing that amendment as its own item.*
|
||||
> to the same `-27` as `sin(π)`, confirming range reduction across multiple turns. Both
|
||||
> hosted and kernel (amd64) builds clean.
|
||||
|
||||
- [ ] **4.3.3b — Geometry drawing primitive wordset.** `LINE`, `CIRCLE`, `ARC`, `ELLIPSE` in
|
||||
- [x] **4.3.3b — Geometry drawing primitive wordset.** `LINE`, `CIRCLE`, `ARC`, `ELLIPSE` in
|
||||
`capsules/fabric.4th`, built on 4.3.3's `PLOT`/`CART-PLOT` and 4.3.3a's `Q.SIN`/`Q.COS`.
|
||||
Raised 2026-08-07. Q48.16 throughout; resolution-agnostic (48 integer bits comfortably
|
||||
covers 1080p and well beyond — no hardcoded viewport assumptions). *Refs:* §27.3.
|
||||
|
||||
> **Done, 2026-08-07.** Blocks 4903–4912. `TO-RASTER` factored out of `CART-PLOT` (same
|
||||
> behavior, not a change) so `LINE` can project both endpoints once and Bresenham the
|
||||
> straight line between them in raster space — valid because the cavalier projection is
|
||||
> linear, so projecting endpoints and interpolating is equivalent to projecting every point
|
||||
> along the line. `LINE` itself split across three helper words (`LINE-SETUP`,
|
||||
> `LINE-DONE?`/`LINE-STUCK?`, `LINE-STEP`) — discovered mid-implementation that colon
|
||||
> definitions **cannot span block boundaries** in this capsule loader (verified with a
|
||||
> throwaway test capsule: the continuation lands in a `[CAPSULE][DEFER]` path that never
|
||||
> resolves and errors out), so anything too long for one 16-line/64-char block has to be
|
||||
> factored into separate, block-local word definitions instead. `CIRCLE`/`ELLIPSE` are
|
||||
> 36-segment polygon approximations (`LINE` calls between consecutive `Q.SIN`/`Q.COS`
|
||||
> points); `ARC` is the same at 18 segments over a caller-supplied `[a0, a1]` radian range.
|
||||
>
|
||||
> **A fourth real bug, this one serious — found, fixed, verified with the recommended fix
|
||||
> applied both times.** `CIRCLE`'s first live test rendered only its first quadrant, then
|
||||
> a follow-up test call hung the VM for several minutes before being killed. Root cause:
|
||||
> `q48_to_u64()` (`include/q48_16.h` and `include/starkernel/q48_16.h`, backing
|
||||
> `Q.TO-INT`) did `q >> 16` as an **unsigned logical shift**. For any negative `q48_16_t` —
|
||||
> inevitable once `Q.SIN`/`Q.COS` leave the first quadrant — this produces a huge garbage
|
||||
> integer instead of sign-extending. That garbage became a bogus `LINE` target, and
|
||||
> `LINE-STEP`'s Bresenham loop had no bound, so it churned for a very long time trying to
|
||||
> converge on a point that was effectively unreachable. Fixed by shifting through a signed
|
||||
> `int64_t` intermediate (bit-identical output for the non-negative case, which is all the
|
||||
> inference engine's own caller ever produces). Independently, added `LINE-STUCK?`
|
||||
> (`LSTEPS` counter vs. `FB-WIDTH + FB-HEIGHT`, the true worst case for any on-screen line)
|
||||
> as a defense-in-depth cap, so a future bad target degrades to "stops drawing" rather than
|
||||
> hanging the VM again.
|
||||
>
|
||||
> **Verified live on amd64**, fresh boot after both fixes: `-65536 Q.TO-INT .` now prints
|
||||
> `-1`. `LINE`, `CIRCLE`, `ARC` (semicircle, 0 to π), and `ELLIPSE` all completed without
|
||||
> hanging or erroring, and a combined screendump shows all four rendering correctly and
|
||||
> distinctly — full circle, correct upper-half arc, properly proportioned ellipse (wider
|
||||
> than tall, matching unequal radii), and the earlier diagonal `LINE` test.
|
||||
> `fb/amd64/geom-test-circle-fixed.png`, `fb/amd64/geom-test-full-wordset.png`.
|
||||
|
||||
- [ ] **4.3.4 — Checkpoint: draw a cube.** First real exercise of the 4.3.3/4.3.3a/4.3.3b
|
||||
coordinate/projection/geometry machinery — cube edges use `LINE`. Stop and review here
|
||||
before scoping the next 4.3.x item — not expected to be fast. *Refs:* §27.4.
|
||||
|
||||
Reference in New Issue
Block a user