apl: scan f\ + f⍀ (+15 tests, 125/125)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s

This commit is contained in:
2026-05-06 20:46:16 +00:00
parent c63c0d26e8
commit c56f400403
3 changed files with 166 additions and 2 deletions

View File

@@ -873,3 +873,91 @@
(first col)
(rest col))))
(range 0 inner-size)))))))))
(define
apl-scan
(fn
(f arr)
(let
((shape (get arr :shape)) (ravel (get arr :ravel)))
(if
(= (len shape) 0)
arr
(if
(= (len shape) 1)
(let
((n (first shape)))
(make-array
shape
(map
(fn
(i)
(let
((slice (take ravel (+ i 1))))
(reduce
(fn
(a b)
(disclose (f (apl-scalar a) (apl-scalar b))))
(first slice)
(rest slice))))
(range 0 n))))
(let
((last-dim (last shape))
(pre-size (reduce * 1 (take shape (- (len shape) 1)))))
(make-array
shape
(flatten
(map
(fn
(i)
(let
((start (* i last-dim))
(row
(map
(fn (j) (nth ravel (+ start j)))
(range 0 last-dim))))
(map
(fn
(k)
(let
((slice (take row (+ k 1))))
(reduce
(fn
(a b)
(disclose (f (apl-scalar a) (apl-scalar b))))
(first slice)
(rest slice))))
(range 0 last-dim))))
(range 0 pre-size))))))))))
(define
apl-scan-first
(fn
(f arr)
(let
((shape (get arr :shape)) (ravel (get arr :ravel)))
(if
(< (len shape) 2)
(apl-scan f arr)
(let
((first-dim (first shape))
(inner-size (reduce * 1 (rest shape))))
(make-array
shape
(flatten
(map
(fn
(i)
(map
(fn
(j)
(let
((col (map (fn (k) (nth ravel (+ j (* k inner-size)))) (range 0 (+ i 1)))))
(reduce
(fn
(a b)
(disclose (f (apl-scalar a) (apl-scalar b))))
(first col)
(rest col))))
(range 0 inner-size)))
(range 0 first-dim)))))))))

View File

@@ -82,4 +82,79 @@
"reduce-first max/ matrix col maxima"
(rv
(apl-reduce-first apl-max (make-array (list 3 2) (list 1 9 2 8 3 7))))
(list 3 9))
(list 3 9))
(apl-test
"scan +\\ vector"
(rv (apl-scan apl-add (make-array (list 5) (list 1 2 3 4 5))))
(list 1 3 6 10 15))
(apl-test
"scan x\\ vector cumulative product"
(rv (apl-scan apl-mul (make-array (list 5) (list 1 2 3 4 5))))
(list 1 2 6 24 120))
(apl-test
"scan max\\ vector running max"
(rv (apl-scan apl-max (make-array (list 5) (list 3 1 4 1 5))))
(list 3 3 4 4 5))
(apl-test
"scan min\\ vector running min"
(rv (apl-scan apl-min (make-array (list 5) (list 3 1 4 1 5))))
(list 3 1 1 1 1))
(apl-test
"scan +\\ single element"
(rv (apl-scan apl-add (make-array (list 1) (list 42))))
(list 42))
(apl-test
"scan +\\ scalar no-op"
(rv (apl-scan apl-add (apl-scalar 7)))
(list 7))
(apl-test
"scan +\\ vector preserves shape"
(sh (apl-scan apl-add (make-array (list 5) (list 1 2 3 4 5))))
(list 5))
(apl-test
"scan +\\ matrix preserves shape"
(sh (apl-scan apl-add (make-array (list 2 3) (list 1 2 3 4 5 6))))
(list 2 3))
(apl-test
"scan +\\ matrix row-wise"
(rv (apl-scan apl-add (make-array (list 2 3) (list 1 2 3 4 5 6))))
(list 1 3 6 4 9 15))
(apl-test
"scan max\\ matrix row-wise running max"
(rv (apl-scan apl-max (make-array (list 2 3) (list 3 1 4 1 5 9))))
(list 3 3 4 1 5 9))
(apl-test
"scan-first +\\ vector same as scan"
(rv (apl-scan-first apl-add (make-array (list 5) (list 1 2 3 4 5))))
(list 1 3 6 10 15))
(apl-test
"scan-first +\\ scalar no-op"
(rv (apl-scan-first apl-add (apl-scalar 9)))
(list 9))
(apl-test
"scan-first +\\ matrix preserves shape"
(sh (apl-scan-first apl-add (make-array (list 2 3) (list 1 2 3 4 5 6))))
(list 2 3))
(apl-test
"scan-first +\\ matrix col-wise"
(rv (apl-scan-first apl-add (make-array (list 2 3) (list 1 2 3 4 5 6))))
(list 1 2 3 5 7 9))
(apl-test
"scan-first max\\ matrix col-wise running max"
(rv (apl-scan-first apl-max (make-array (list 3 2) (list 3 1 4 1 5 9))))
(list 3 1 4 1 5 9))

View File

@@ -74,7 +74,7 @@ Core mapping:
### Phase 4 — operators (THE SHOWCASE)
- [x] Reduce `f/` (last axis), `f⌿` (first axis) — including `∧/`, `/`, `+/`, `×/`, `⌈/`, `⌊/`
- [ ] Scan `f\`, `f⍀`
- [x] Scan `f\`, `f⍀`
- [ ] Each `f¨` — applies `f` to each scalar/element
- [ ] Outer product `∘.f``1 2 3 ∘.× 1 2 3` ↦ multiplication table
- [ ] Inner product `f.g``+.×` is matrix multiply
@@ -118,6 +118,7 @@ data; format for string templating.
_Newest first._
- 2026-05-06: Phase 4 step 2 — scan f\ (last axis) + f⍀ (first axis); apl-scan/apl-scan-first; 125/125 tests
- 2026-05-06: Phase 4 step 1 — reduce f/ (last axis) + f⌿ (first axis); apl-reduce/apl-reduce-first; 110/110 tests
- 2026-05-06: Phase 3 complete — membership ∊, dyadic (index-of), without ~ (index-of returns nil for not-found); 94/94 tests
- 2026-05-06: Phase 3 step 6 — enclose ⊂ / disclose ⊃ (box/unbox, rank-0 detect via type-of); 82/82 tests