diff --git a/lib/apl/runtime.sx b/lib/apl/runtime.sx index 19db9f8d..2dc96916 100644 --- a/lib/apl/runtime.sx +++ b/lib/apl/runtime.sx @@ -1058,3 +1058,7 @@ (rest pairs)))) (range 0 b-post-size))) (range 0 a-pre-size))))))))))) + +(define apl-commute (fn (f x) (f x x))) + +(define apl-commute-dyadic (fn (f x y) (f y x))) diff --git a/lib/apl/tests/operators.sx b/lib/apl/tests/operators.sx index 2e507811..063269ac 100644 --- a/lib/apl/tests/operators.sx +++ b/lib/apl/tests/operators.sx @@ -455,4 +455,66 @@ apl-mul (make-array (list 1) (list 6)) (make-array (list 1) (list 7)))) - (list 42)) \ No newline at end of file + (list 42)) + +(apl-test + "commute +⍨ scalar doubles" + (rv (apl-commute apl-add (apl-scalar 5))) + (list 10)) + +(apl-test + "commute ×⍨ vector squares" + (rv (apl-commute apl-mul (make-array (list 4) (list 1 2 3 4)))) + (list 1 4 9 16)) + +(apl-test + "commute +⍨ vector doubles" + (rv (apl-commute apl-add (make-array (list 3) (list 1 2 3)))) + (list 2 4 6)) + +(apl-test + "commute +⍨ shape preserved" + (sh (apl-commute apl-add (make-array (list 3) (list 1 2 3)))) + (list 3)) + +(apl-test + "commute ×⍨ matrix shape preserved" + (sh (apl-commute apl-mul (make-array (list 2 2) (list 1 2 3 4)))) + (list 2 2)) + +(apl-test + "commute-dyadic -⍨ swaps subtraction" + (rv (apl-commute-dyadic apl-sub (apl-scalar 5) (apl-scalar 3))) + (list -2)) + +(apl-test + "commute-dyadic ÷⍨ swaps division" + (rv (apl-commute-dyadic apl-div (apl-scalar 4) (apl-scalar 12))) + (list 3)) + +(apl-test + "commute-dyadic -⍨ on vectors" + (rv + (apl-commute-dyadic + apl-sub + (make-array (list 3) (list 10 20 30)) + (make-array (list 3) (list 1 2 3)))) + (list -9 -18 -27)) + +(apl-test + "commute-dyadic +⍨ commutative same result" + (rv + (apl-commute-dyadic + apl-add + (make-array (list 3) (list 1 2 3)) + (make-array (list 3) (list 10 20 30)))) + (list 11 22 33)) + +(apl-test + "commute-dyadic ×⍨ commutative same result" + (rv + (apl-commute-dyadic + 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 diff --git a/plans/apl-on-sx.md b/plans/apl-on-sx.md index 08e68318..6348f3c1 100644 --- a/plans/apl-on-sx.md +++ b/plans/apl-on-sx.md @@ -78,7 +78,7 @@ Core mapping: - [x] Each `f¨` — applies `f` to each scalar/element - [x] Outer product `∘.f` — `1 2 3 ∘.× 1 2 3` ↦ multiplication table - [x] Inner product `f.g` — `+.×` is matrix multiply -- [ ] Commute `f⍨` — `f⍨ x` ↔ `x f x`, `x f⍨ y` ↔ `y f x` +- [x] Commute `f⍨` — `f⍨ x` ↔ `x f x`, `x f⍨ y` ↔ `y 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 @@ -118,6 +118,7 @@ data; format for string templating. _Newest first._ +- 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 - 2026-05-06: Phase 4 step 3 — each f¨ (monadic apl-each + dyadic apl-each-dyadic); scalar broadcast both sides; 139/139 tests