apl: Phase 3 reshape ⍴ / transpose ⍉ — 27/27 structural tests green
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

Add apl-reshape (dyadic ⍴, cycling), apl-transpose (monadic ⍉, reverse
axes), apl-transpose-dyadic (dyadic ⍉, permutation), plus helpers
apl-strides / apl-flat->multi / apl-multi->flat.

lib/apl/tests/structural.sx: 27 new tests covering ravel, reshape,
monadic/dyadic transpose across scalar/vector/matrix/3-D cases.

test.sh now runs structural.sx via its own inline framework (skips
stale tests/runtime.sx which targeted a pre-Phase-2 list-based API).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 18:36:43 +00:00
parent 2314735431
commit be26f77410
3 changed files with 289 additions and 4 deletions

View File

@@ -347,3 +347,92 @@
build
(fn (i acc) (if (< i 1) acc (build (- i 1) (cons i acc)))))
(apl-vector (build n (list)))))))
(define
apl-strides
(fn
(shape)
(map
(fn (i) (reduce * 1 (drop shape (+ i 1))))
(range 0 (len shape)))))
(define
apl-flat->multi
(fn
(flat shape strides)
(map
(fn (i) (mod (floor (/ flat (nth strides i))) (nth shape i)))
(range 0 (len shape)))))
(define
apl-multi->flat
(fn (coords strides) (reduce + 0 (map * coords strides))))
(define
apl-reshape
(fn
(shape-arr data-arr)
(let
((new-shape (if (scalar? shape-arr) (list (disclose shape-arr)) (get shape-arr :ravel)))
(src-ravel
(if
(scalar? data-arr)
(list (disclose data-arr))
(get data-arr :ravel))))
(let
((new-size (reduce * 1 new-shape)) (src-len (len src-ravel)))
(let
((new-ravel (if (= new-size 0) (list) (if (= src-len 0) (map (fn (i) 0) (range 0 new-size)) (map (fn (i) (nth src-ravel (mod i src-len))) (range 0 new-size))))))
(make-array new-shape new-ravel))))))
(define
apl-transpose
(fn
(arr)
(let
((shape (get arr :shape)) (ravel (get arr :ravel)))
(if
(< (len shape) 2)
arr
(let
((new-shape (reverse shape)) (strides (apl-strides shape)))
(let
((new-strides (apl-strides new-shape)) (new-size (len ravel)))
(make-array
new-shape
(map
(fn
(new-flat)
(let
((new-coords (apl-flat->multi new-flat new-shape new-strides)))
(nth
ravel
(apl-multi->flat (reverse new-coords) strides))))
(range 0 new-size)))))))))
(define
apl-transpose-dyadic
(fn
(perm-arr data-arr)
(let
((perm (map (fn (p) (- p apl-io)) (get perm-arr :ravel)))
(shape (get data-arr :shape))
(ravel (get data-arr :ravel)))
(let
((new-shape (map (fn (k) (nth shape k)) perm))
(strides (apl-strides shape)))
(let
((inv-perm (map (fn (j) (index-of perm j)) (range 0 (len perm))))
(new-strides (apl-strides new-shape))
(new-size (len ravel)))
(make-array
new-shape
(map
(fn
(new-flat)
(let
((new-coords (apl-flat->multi new-flat new-shape new-strides)))
(let
((old-coords (map (fn (i) (nth new-coords (nth inv-perm i))) (range 0 (len shape)))))
(nth ravel (apl-multi->flat old-coords strides)))))
(range 0 new-size))))))))