apl: primes sieve (2=+⌿0=A∘.|A)/A←⍳N + apl-compress (+11 tests, 280/280)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m6s

This commit is contained in:
2026-05-07 04:07:09 +00:00
parent ec26b61cbe
commit ed0853f4a0
8 changed files with 112 additions and 6 deletions

View File

@@ -13,7 +13,7 @@ if [ ! -x "$SX_SERVER" ]; then
exit 1
fi
SUITES=(structural operators dfn tradfn valence)
SUITES=(structural operators dfn tradfn valence programs)
OUT_JSON="lib/apl/scoreboard.json"
OUT_MD="lib/apl/scoreboard.md"

View File

@@ -796,6 +796,34 @@
((result (filter (fn (x) (not (index-of b-ravel x))) a-ravel)))
(make-array (list (len result)) result)))))
(define
apl-compress
(fn
(mask arr)
(let
((mask-ravel (get mask :ravel)) (arr-ravel (get arr :ravel)))
(let
((kept (filter (fn (i) (not (= 0 (nth mask-ravel i)))) (range 0 (len arr-ravel)))))
(let
((picked (map (fn (i) (nth arr-ravel i)) kept)))
(make-array (list (len picked)) picked))))))
(define
apl-primes
(fn
(n)
(let
((a (apl-iota (apl-scalar n))))
(let
((mod-table (apl-outer apl-mod a a)))
(let
((zero-mask (apl-eq (apl-scalar 0) mod-table)))
(let
((divisor-counts (apl-reduce-first apl-add zero-mask)))
(let
((prime-mask (apl-eq (apl-scalar 2) divisor-counts)))
(apl-compress prime-mask a))))))))
(define
apl-reduce
(fn

View File

@@ -4,9 +4,10 @@
"operators": {"pass": 117, "fail": 0},
"dfn": {"pass": 24, "fail": 0},
"tradfn": {"pass": 20, "fail": 0},
"valence": {"pass": 14, "fail": 0}
"valence": {"pass": 14, "fail": 0},
"programs": {"pass": 11, "fail": 0}
},
"total_pass": 269,
"total_pass": 280,
"total_fail": 0,
"total": 269
"total": 280
}

View File

@@ -9,7 +9,8 @@ _Generated by `lib/apl/conformance.sh`_
| dfn | 24 | 0 | 24 |
| tradfn | 20 | 0 | 20 |
| valence | 14 | 0 | 14 |
| **Total** | **269** | **0** | **269** |
| programs | 11 | 0 | 11 |
| **Total** | **280** | **0** | **280** |
## Notes

View File

@@ -31,6 +31,7 @@ cat > "$TMPFILE" << 'EPOCHS'
(load "lib/apl/tests/dfn.sx")
(load "lib/apl/tests/tradfn.sx")
(load "lib/apl/tests/valence.sx")
(load "lib/apl/tests/programs.sx")
(epoch 4)
(eval "(list apl-test-pass apl-test-fail)")
EPOCHS

58
lib/apl/tests/programs.sx Normal file
View File

@@ -0,0 +1,58 @@
; Tests for classic APL programs (lib/apl/tests/programs/*.apl).
; Programs are showcase APL source; runtime impl is in lib/apl/runtime.sx.
(define mkrv (fn (arr) (get arr :ravel)))
(define mksh (fn (arr) (get arr :shape)))
; ===== primes (Sieve of Eratosthenes) =====
(apl-test "primes 1 → empty" (mkrv (apl-primes 1)) (list))
(apl-test "primes 2 → just 2" (mkrv (apl-primes 2)) (list 2))
(apl-test "primes 10 → 2 3 5 7" (mkrv (apl-primes 10)) (list 2 3 5 7))
(apl-test
"primes 20 → 2 3 5 7 11 13 17 19"
(mkrv (apl-primes 20))
(list 2 3 5 7 11 13 17 19))
(apl-test
"primes 30"
(mkrv (apl-primes 30))
(list 2 3 5 7 11 13 17 19 23 29))
(apl-test
"primes 50"
(mkrv (apl-primes 50))
(list 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47))
(apl-test "primes 7 length" (first (mksh (apl-primes 7))) 4)
(apl-test "primes 100 has 25 primes" (first (mksh (apl-primes 100))) 25)
; ===== compress helper sanity =====
(apl-test
"compress 1 0 1 0 1 / 10 20 30 40 50"
(mkrv
(apl-compress
(make-array (list 5) (list 1 0 1 0 1))
(make-array (list 5) (list 10 20 30 40 50))))
(list 10 30 50))
(apl-test
"compress all-zero mask → empty"
(mkrv
(apl-compress
(make-array (list 3) (list 0 0 0))
(make-array (list 3) (list 1 2 3))))
(list))
(apl-test
"compress all-one mask → full vector"
(mkrv
(apl-compress
(make-array (list 3) (list 1 1 1))
(make-array (list 3) (list 1 2 3))))
(list 1 2 3))

View File

@@ -0,0 +1,16 @@
⍝ Sieve of Eratosthenes — the classic APL one-liner
⍝ primes ← (2=+⌿0=A∘.|A)/A←N
⍝ Read right-to-left:
⍝ A ← N : A is 1..N
⍝ A∘.|A : outer-product residue table — M[i,j] = A[j] mod A[i]
⍝ 0=... : boolean — true where A[i] divides A[j]
⍝ +⌿... : column sums — count of divisors per A[j]
⍝ 2=... : true for numbers with exactly 2 divisors (1 and self) → primes
⍝ .../A : compress — select A[j] where mask[j] is true
⍝ Examples:
⍝ primes 10 → 2 3 5 7
⍝ primes 30 → 2 3 5 7 11 13 17 19 23 29
primes {(2=+0=.|)/}