apl: mandelbrot real-axis batched z=z²+c (+9 tests, 296/296)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m5s

This commit is contained in:
2026-05-07 05:07:25 +00:00
parent 20a61de693
commit 49eb22243a
6 changed files with 110 additions and 6 deletions

View File

@@ -836,6 +836,35 @@
(apl-eq sum-board (apl-scalar 3))
(apl-and board (apl-eq sum-board (apl-scalar 4))))))))
(define
apl-mandelbrot-step
(fn
(cs z counts alive iters-left)
(if
(= iters-left 0)
counts
(let
((still-alive (apl-and alive (apl-le (apl-mul z z) (apl-scalar 4)))))
(let
((new-z (apl-mul still-alive (apl-add (apl-mul z z) cs))))
(let
((new-counts (apl-add counts still-alive)))
(apl-mandelbrot-step
cs
new-z
new-counts
still-alive
(- iters-left 1))))))))
(define
apl-mandelbrot-1d
(fn
(cs max-iter)
(let
((zero (apl-mul cs (apl-scalar 0)))
(ones (apl-add (apl-mul cs (apl-scalar 0)) (apl-scalar 1))))
(apl-mandelbrot-step cs zero zero ones max-iter))))
(define
apl-reduce
(fn

View File

@@ -5,9 +5,9 @@
"dfn": {"pass": 24, "fail": 0},
"tradfn": {"pass": 20, "fail": 0},
"valence": {"pass": 14, "fail": 0},
"programs": {"pass": 18, "fail": 0}
"programs": {"pass": 27, "fail": 0}
},
"total_pass": 287,
"total_pass": 296,
"total_fail": 0,
"total": 287
"total": 296
}

View File

@@ -9,8 +9,8 @@ _Generated by `lib/apl/conformance.sh`_
| dfn | 24 | 0 | 24 |
| tradfn | 20 | 0 | 20 |
| valence | 14 | 0 | 14 |
| programs | 18 | 0 | 18 |
| **Total** | **287** | **0** | **287** |
| programs | 27 | 0 | 27 |
| **Total** | **296** | **0** | **296** |
## Notes

View File

@@ -192,3 +192,48 @@
0
0
0))
(apl-test
"mandelbrot c=0 stays bounded"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0)) 100))
(list 100))
(apl-test
"mandelbrot c=-1 cycle bounded"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list -1)) 100))
(list 100))
(apl-test
"mandelbrot c=-2 boundary stays bounded"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list -2)) 100))
(list 100))
(apl-test
"mandelbrot c=0.25 boundary stays bounded"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0.25)) 100))
(list 100))
(apl-test
"mandelbrot c=1 escapes at iter 3"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list 1)) 100))
(list 3))
(apl-test
"mandelbrot c=0.5 escapes at iter 5"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list 0.5)) 100))
(list 5))
(apl-test
"mandelbrot batched grid (rank-polymorphic)"
(mkrv (apl-mandelbrot-1d (make-array (list 5) (list -2 -1 0 1 2)) 10))
(list 10 10 10 3 2))
(apl-test
"mandelbrot batched preserves shape"
(mksh (apl-mandelbrot-1d (make-array (list 5) (list -2 -1 0 1 2)) 10))
(list 5))
(apl-test
"mandelbrot c=-1.5 stays bounded"
(mkrv (apl-mandelbrot-1d (make-array (list 1) (list -1.5)) 100))
(list 100))

View File

@@ -0,0 +1,29 @@
⍝ Mandelbrot — real-axis subset
⍝ For complex c, the Mandelbrot set is { c : |z_n| stays bounded } where
⍝ z_0 = 0, z_{n+1} = z_n² + c.
⍝ Restricting c (and z) to gives the segment c ∈ [-2, 1/4]
⍝ where the iteration stays bounded.
⍝ Rank-polymorphic batched-iteration form:
⍝ mandelbrot ← {⍵ ⍵⍵ +,( × ) }
⍝ Pseudocode (as we don't have ⎕ system fns yet):
⍝ z ← 0×c ⍝ start at zero
⍝ alive ← 1+0×c ⍝ all "still in"
⍝ for k iterations:
⍝ alive ← alive ∧ 4 ≥ z×z ⍝ still bounded?
⍝ z ← alive × c + z×z ⍝ freeze escaped via mask
⍝ count ← count + alive ⍝ tally surviving iters
⍝ Examples (count after 100 iterations):
⍝ c=0 : 100 (z stays at 0)
⍝ c=-1 : 100 (cycles 0,-1,0,-1,...)
⍝ c=-2 : 100 (settles at 2 — boundary)
⍝ c=0.25 : 100 (boundary — converges to 0.5)
⍝ c=0.5 : 5 (escapes by iteration 6)
⍝ c=1 : 3 (escapes quickly)
⍝ Real-axis Mandelbrot set: bounded for c ∈ [-2, 0.25].
mandelbrot {zalivecount0× {alivealive4z×z zalive×+z×z count+alive}}

View File

@@ -96,7 +96,7 @@ Core mapping:
### Phase 6 — classic programs + drive corpus
- [ ] Classic programs in `lib/apl/tests/programs/`:
- [x] `life.apl` — Conway's Game of Life as a one-liner using `⊂` `⊖` `⌽` `+/`
- [ ] `mandelbrot.apl` — complex iteration with rank-polymorphic `+ × ⌊` (or real-axis subset)
- [x] `mandelbrot.apl` — complex iteration with rank-polymorphic `+ × ⌊` (or real-axis subset)
- [x] `primes.apl``(2=+⌿0=A∘.|A)/A←N` sieve
- [ ] `n-queens.apl` — backtracking via reduce
- [ ] `quicksort.apl` — the classic Roger Hui one-liner
@@ -118,6 +118,7 @@ data; format for string templating.
_Newest first._
- 2026-05-07: Phase 6 mandelbrot real-axis — apl-mandelbrot-1d batched z=z²+c with permanent alive-mask; c∈{-2,-1,0,0.25} bounded, c=1→3, c=0.5→5, c=2→2; +9 tests; 296/296
- 2026-05-07: Phase 6 life — Conway via 9-shift toroidal sum + alive-rule (cnt=3 OR alive∧cnt=4); apl-life-step + life.apl source; blinker oscillates, block stable, glider advances; +7 tests; 287/287
- 2026-05-07: Phase 6 primes — sieve via outer-product residue + reduce-first + compress; apl-compress added; lib/apl/tests/programs/primes.apl source; +11 tests; 280/280
- 2026-05-07: Phase 5 conformance.sh + scoreboard.{json,md} — per-suite runner; current snapshot 269/269; **Phase 5 complete**