From 3d2bdc52b5b238ab106f727c5b50cc908abfb93a Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 6 May 2026 23:03:14 +0000 Subject: [PATCH] =?UTF-8?q?apl:=20compose=20f=E2=88=98g=20(+9=20tests,=201?= =?UTF-8?q?82/182)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/apl/runtime.sx | 4 +++ lib/apl/tests/operators.sx | 64 +++++++++++++++++++++++++++++++++++++- plans/apl-on-sx.md | 3 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/lib/apl/runtime.sx b/lib/apl/runtime.sx index 2dc96916..4ee5f295 100644 --- a/lib/apl/runtime.sx +++ b/lib/apl/runtime.sx @@ -1062,3 +1062,7 @@ (define apl-commute (fn (f x) (f x x))) (define apl-commute-dyadic (fn (f x y) (f y x))) + +(define apl-compose (fn (f g x) (f (g x)))) + +(define apl-compose-dyadic (fn (f g x y) (f x (g y)))) diff --git a/lib/apl/tests/operators.sx b/lib/apl/tests/operators.sx index 063269ac..43d67fa2 100644 --- a/lib/apl/tests/operators.sx +++ b/lib/apl/tests/operators.sx @@ -517,4 +517,66 @@ apl-mul (make-array (list 3) (list 2 3 4)) (make-array (list 3) (list 5 6 7)))) - (list 10 18 28)) \ No newline at end of file + (list 10 18 28)) + +(apl-test + "compose -∘| scalar (negative abs)" + (rv (apl-compose apl-neg-m apl-abs (apl-scalar -7))) + (list -7)) + +(apl-test + "compose -∘| vector" + (rv + (apl-compose apl-neg-m apl-abs (make-array (list 4) (list -1 2 -3 4)))) + (list -1 -2 -3 -4)) + +(apl-test + "compose ⌊∘- (floor of negate)" + (rv (apl-compose apl-floor apl-neg-m (make-array (list 3) (list 1 2 3)))) + (list -1 -2 -3)) + +(apl-test + "compose -∘| matrix shape preserved" + (sh + (apl-compose apl-neg-m apl-abs (make-array (list 2 2) (list -1 2 -3 4)))) + (list 2 2)) + +(apl-test + "compose-dyadic +∘- equals subtract scalar" + (rv (apl-compose-dyadic apl-add apl-neg-m (apl-scalar 10) (apl-scalar 3))) + (list 7)) + +(apl-test + "compose-dyadic +∘- equals subtract vector" + (rv + (apl-compose-dyadic + apl-add + apl-neg-m + (make-array (list 3) (list 10 20 30)) + (make-array (list 3) (list 1 2 3)))) + (list 9 18 27)) + +(apl-test + "compose-dyadic -∘| (subtract abs)" + (rv (apl-compose-dyadic apl-sub apl-abs (apl-scalar 10) (apl-scalar -3))) + (list 7)) + +(apl-test + "compose-dyadic ×∘- (multiply by negative)" + (rv + (apl-compose-dyadic + apl-mul + apl-neg-m + (make-array (list 3) (list 2 3 4)) + (make-array (list 3) (list 1 2 3)))) + (list -2 -6 -12)) + +(apl-test + "compose-dyadic shape preserved" + (sh + (apl-compose-dyadic + apl-add + apl-neg-m + (make-array (list 2 3) (list 1 2 3 4 5 6)) + (make-array (list 2 3) (list 1 1 1 1 1 1)))) + (list 2 3)) \ No newline at end of file diff --git a/plans/apl-on-sx.md b/plans/apl-on-sx.md index 6348f3c1..95f10e62 100644 --- a/plans/apl-on-sx.md +++ b/plans/apl-on-sx.md @@ -79,7 +79,7 @@ Core mapping: - [x] Outer product `∘.f` — `1 2 3 ∘.× 1 2 3` ↦ multiplication table - [x] Inner product `f.g` — `+.×` is matrix multiply - [x] Commute `f⍨` — `f⍨ x` ↔ `x f x`, `x f⍨ y` ↔ `y f x` -- [ ] Compose `f∘g` — applies `g` first then `f` +- [x] Compose `f∘g` — applies `g` first then `f` - [ ] Power `f⍣n` — apply f n times; `f⍣≡` until fixed point - [ ] Rank `f⍤k` — apply f at sub-rank k - [ ] At `@` — selective replace @@ -118,6 +118,7 @@ data; format for string templating. _Newest first._ +- 2026-05-06: Phase 4 step 7 — compose f∘g (apl-compose monadic f∘g x, apl-compose-dyadic dyadic f x (g y)); 182/182 tests - 2026-05-06: Phase 4 step 6 — commute f⍨ (apl-commute monadic dup, apl-commute-dyadic swap); 173/173 tests - 2026-05-06: Phase 4 step 5 — inner product f.g (apl-inner); +.× matrix multiply, ∧.= equal-vectors; 163/163 tests - 2026-05-06: Phase 4 step 4 — outer product ∘.f (apl-outer); rank-doubling result shape = a-shape++b-shape; 151/151 tests