Skip to content

Commit 49cdf60

Browse files
tests: +37 across core features / ML kernels / linalg
test_core_features.omc (13): if/elif/else branching, while loop count + zero-iters, break/continue, recursive factorial, mutual recursion (is_even/is_odd), closure state, lambda-as-arg, early return, comparison chain (<, >, <=, >=). test_ml_kernel_extras.omc (13): softmax dominant-logit / uniform / sums-to-1 with floats; layer_norm small + big arrays; relu all-zero / all-positive; sigmoid at ±1; conv1d kernel-2 box filter; arr_outer unit basis; substrate_attention output shape (3 queries, 2 keys, 2 dims); substrate_score_rows on Fibonacci row. test_linalg_extras.omc (11): arr_matmul 2x2 against expected [[19,22],[43,50]]; matmul with identity = self; matmul with zero matrix; transpose 2x3 → 3x2; transpose-twice = identity; eye 3/1/0; zeros_2d 3x4; outer composition; substrate-preserving int matmul (5 is Fibonacci attractor preserved). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 97c78b0 commit 49cdf60

3 files changed

Lines changed: 382 additions & 0 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Core language feature coverage — control flow, recursion, lambdas, etc.
2+
3+
fn assert_eq(actual, expected, msg) {
4+
if actual != expected {
5+
test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual));
6+
}
7+
}
8+
9+
fn assert_true(cond, msg) { if !cond { test_record_failure(msg); } }
10+
11+
# If/else basic
12+
fn test_if_then() {
13+
h x = 0;
14+
if 1 == 1 { x = 1; }
15+
assert_eq(x, 1, "then branch");
16+
}
17+
18+
fn test_if_else() {
19+
h x = 0;
20+
if 1 == 0 { x = 1; } else { x = 2; }
21+
assert_eq(x, 2, "else branch");
22+
}
23+
24+
fn test_elif() {
25+
h x = 0;
26+
if 1 == 0 { x = 1; } elif 1 == 1 { x = 2; } else { x = 3; }
27+
assert_eq(x, 2, "elif branch");
28+
}
29+
30+
# While loop
31+
fn test_while_counts() {
32+
h n = 0;
33+
while n < 10 { n = n + 1; }
34+
assert_eq(n, 10, "while counts to 10");
35+
}
36+
37+
fn test_while_zero_iters() {
38+
h n = 0;
39+
while n < 0 { n = n + 1; }
40+
assert_eq(n, 0, "no iterations");
41+
}
42+
43+
# Break / continue
44+
fn test_break() {
45+
h n = 0;
46+
while n < 100 {
47+
if n == 5 { break; }
48+
n = n + 1;
49+
}
50+
assert_eq(n, 5, "broke at 5");
51+
}
52+
53+
fn test_continue() {
54+
h sum = 0;
55+
h i = 0;
56+
while i < 10 {
57+
i = i + 1;
58+
if i == 5 { continue; }
59+
sum = sum + i;
60+
}
61+
# 1+2+3+4+6+7+8+9+10 = 50
62+
assert_eq(sum, 50, "skipped 5");
63+
}
64+
65+
# Recursion
66+
fn fact(n) {
67+
if n <= 1 { return 1; }
68+
return n * fact(n - 1);
69+
}
70+
71+
fn test_recursion() {
72+
assert_eq(fact(5), 120, "5! = 120");
73+
assert_eq(fact(0), 1, "0! = 1");
74+
}
75+
76+
# Mutual recursion
77+
fn is_even(n) {
78+
if n == 0 { return 1; }
79+
return is_odd(n - 1);
80+
}
81+
82+
fn is_odd(n) {
83+
if n == 0 { return 0; }
84+
return is_even(n - 1);
85+
}
86+
87+
fn test_mutual_recursion() {
88+
assert_eq(is_even(4), 1, "4 is even");
89+
assert_eq(is_odd(7), 1, "7 is odd");
90+
}
91+
92+
# Closures
93+
fn make_counter() {
94+
h count = 0;
95+
return fn() {
96+
count = count + 1;
97+
return count;
98+
};
99+
}
100+
101+
fn test_closure_state() {
102+
h c = make_counter();
103+
assert_eq(c(), 1, "first");
104+
assert_eq(c(), 2, "second");
105+
assert_eq(c(), 3, "third");
106+
}
107+
108+
# Lambda as arg
109+
fn apply(f, x) { return f(x); }
110+
111+
fn test_apply_lambda() {
112+
h r = apply(fn(x) { return x * 3; }, 5);
113+
assert_eq(r, 15, "lambda applied");
114+
}
115+
116+
# Return early
117+
fn first_positive(arr) {
118+
h i = 0;
119+
while i < arr_len(arr) {
120+
if arr_get(arr, i) > 0 { return arr_get(arr, i); }
121+
i = i + 1;
122+
}
123+
return 0 - 1;
124+
}
125+
126+
fn test_early_return() {
127+
assert_eq(first_positive([0 - 5, 0 - 2, 7, 9]), 7, "found 7");
128+
assert_eq(first_positive([0 - 5, 0 - 2]), 0 - 1, "none found");
129+
}
130+
131+
# (Boolean short-circuit tests omitted — && only inside `if` conditions.)
132+
133+
# Comparison chain
134+
fn test_lt_gt_chain() {
135+
assert_true(1 < 2, "1 < 2");
136+
assert_true(2 > 1, "2 > 1");
137+
assert_true(1 <= 1, "<= equal");
138+
assert_true(1 >= 1, ">= equal");
139+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Linalg / matmul / transpose coverage.
2+
3+
fn assert_eq(actual, expected, msg) {
4+
if actual != expected {
5+
test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual));
6+
}
7+
}
8+
9+
fn assert_true(cond, msg) { if !cond { test_record_failure(msg); } }
10+
11+
fn approx_eq(a, b, tol) {
12+
h d = a - b;
13+
if d < 0.0 { d = 0.0 - d; }
14+
return d <= tol;
15+
}
16+
17+
# arr_matmul correctness
18+
fn test_matmul_2x2() {
19+
h A = [[1, 2], [3, 4]];
20+
h B = [[5, 6], [7, 8]];
21+
h C = arr_matmul(A, B);
22+
h r0 = arr_get(C, 0);
23+
h r1 = arr_get(C, 1);
24+
# [[19,22],[43,50]]
25+
assert_true(approx_eq(arr_get(r0, 0), 19.0, 0.001), "C[0][0]");
26+
assert_true(approx_eq(arr_get(r0, 1), 22.0, 0.001), "C[0][1]");
27+
assert_true(approx_eq(arr_get(r1, 0), 43.0, 0.001), "C[1][0]");
28+
assert_true(approx_eq(arr_get(r1, 1), 50.0, 0.001), "C[1][1]");
29+
}
30+
31+
fn test_matmul_identity() {
32+
h I = arr_eye(3);
33+
h A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
34+
h C = arr_matmul(A, I);
35+
h r0 = arr_get(C, 0);
36+
assert_true(approx_eq(arr_get(r0, 0), 1.0, 0.001), "A * I = A");
37+
assert_true(approx_eq(arr_get(r0, 2), 3.0, 0.001), "A * I = A");
38+
}
39+
40+
fn test_matmul_zero() {
41+
h Z = arr_zeros_2d(2, 2);
42+
h A = [[1, 2], [3, 4]];
43+
h C = arr_matmul(A, Z);
44+
h r = arr_get(C, 0);
45+
assert_true(approx_eq(arr_get(r, 0), 0.0, 0.001), "* zero → zero");
46+
}
47+
48+
# arr_transpose
49+
fn test_transpose_2x3() {
50+
h A = [[1, 2, 3], [4, 5, 6]];
51+
h T = arr_transpose(A);
52+
# 3x2
53+
assert_eq(arr_len(T), 3, "3 rows after transpose");
54+
h r0 = arr_get(T, 0);
55+
assert_eq(arr_len(r0), 2, "2 cols");
56+
assert_eq(arr_get(r0, 0), 1, "T[0][0]=1");
57+
assert_eq(arr_get(r0, 1), 4, "T[0][1]=4");
58+
}
59+
60+
fn test_transpose_twice_identity() {
61+
h A = [[1, 2, 3], [4, 5, 6]];
62+
h TT = arr_transpose(arr_transpose(A));
63+
h r0 = arr_get(TT, 0);
64+
assert_eq(arr_get(r0, 0), 1, "double transpose");
65+
assert_eq(arr_get(r0, 2), 3, "double transpose");
66+
}
67+
68+
# arr_eye
69+
fn test_eye_3() {
70+
h I = arr_eye(3);
71+
assert_eq(arr_len(I), 3, "3 rows");
72+
h r0 = arr_get(I, 0);
73+
assert_eq(arr_len(r0), 3, "3 cols");
74+
assert_eq(arr_get(r0, 0), 1, "I[0][0]=1");
75+
assert_eq(arr_get(r0, 1), 0, "I[0][1]=0");
76+
}
77+
78+
fn test_eye_1() {
79+
h I = arr_eye(1);
80+
assert_eq(arr_len(I), 1, "1x1");
81+
}
82+
83+
fn test_eye_zero() {
84+
h I = arr_eye(0);
85+
assert_eq(arr_len(I), 0, "0x0");
86+
}
87+
88+
# arr_zeros_2d
89+
fn test_zeros_2d_basic() {
90+
h Z = arr_zeros_2d(3, 4);
91+
assert_eq(arr_len(Z), 3, "3 rows");
92+
h r0 = arr_get(Z, 0);
93+
assert_eq(arr_len(r0), 4, "4 cols");
94+
assert_eq(arr_get(r0, 0), 0, "is zero");
95+
}
96+
97+
# arr_outer composition with matmul
98+
fn test_outer_then_matmul() {
99+
h u = [1.0, 2.0];
100+
h v = [3.0, 4.0];
101+
# outer(u, v) is rank-1 matrix [[3,4],[6,8]]
102+
h M = arr_outer(u, v);
103+
h r0 = arr_get(M, 0);
104+
assert_true(approx_eq(arr_get(r0, 0), 3.0, 0.001), "1*3");
105+
assert_true(approx_eq(arr_get(r0, 1), 4.0, 0.001), "1*4");
106+
}
107+
108+
# Substrate-preserving matmul: integer inputs → integer outputs
109+
fn test_matmul_int_preserves_substrate() {
110+
h A = [[1, 2], [3, 5]];
111+
h B = [[1, 1], [2, 3]];
112+
h C = arr_matmul(A, B);
113+
h r0 = arr_get(C, 0);
114+
# C[0][0] = 1*1 + 2*2 = 5 (Fibonacci attractor)
115+
assert_eq(arr_get(r0, 0), 5, "preserves int + attractor");
116+
assert_eq(is_attractor(arr_get(r0, 0)), 1, "5 is attractor");
117+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# More ML kernel coverage.
2+
3+
fn assert_eq(actual, expected, msg) {
4+
if actual != expected {
5+
test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual));
6+
}
7+
}
8+
9+
fn assert_true(cond, msg) { if !cond { test_record_failure(msg); } }
10+
11+
fn approx_eq(a, b, tol) {
12+
h d = a - b;
13+
if d < 0.0 { d = 0.0 - d; }
14+
return d <= tol;
15+
}
16+
17+
# Softmax additional cases
18+
fn test_softmax_one_hot_dominant() {
19+
h s = arr_softmax([10.0, 0.0, 0.0]);
20+
assert_true(arr_get(s, 0) > 0.9, "dominant logit gets > 0.9");
21+
}
22+
23+
fn test_softmax_three_uniform() {
24+
h s = arr_softmax([5.0, 5.0, 5.0]);
25+
h diff = arr_get(s, 0) - 0.3333;
26+
if diff < 0.0 { diff = 0.0 - diff; }
27+
assert_true(diff < 0.01, "uniform gives 1/3");
28+
}
29+
30+
fn test_softmax_sums_one_floats() {
31+
h s = arr_softmax([1.5, 2.5, 3.5, 4.5, 5.5]);
32+
h total = 0.0;
33+
h i = 0;
34+
while i < arr_len(s) {
35+
total = total + arr_get(s, i);
36+
i = i + 1;
37+
}
38+
assert_true(approx_eq(total, 1.0, 0.001), "sums to 1");
39+
}
40+
41+
# LayerNorm with different sizes
42+
fn test_layer_norm_small() {
43+
h ln = arr_layer_norm([1.0, 2.0], 0.00001);
44+
h s = arr_get(ln, 0) + arr_get(ln, 1);
45+
assert_true(approx_eq(s, 0.0, 0.001), "zero mean small");
46+
}
47+
48+
fn test_layer_norm_big() {
49+
h xs = [];
50+
h i = 0;
51+
while i < 20 {
52+
arr_push(xs, i);
53+
i = i + 1;
54+
}
55+
h ln = arr_layer_norm(xs, 0.00001);
56+
h total = 0.0;
57+
i = 0;
58+
while i < arr_len(ln) {
59+
total = total + arr_get(ln, i);
60+
i = i + 1;
61+
}
62+
assert_true(approx_eq(total, 0.0, 0.001), "zero mean big");
63+
}
64+
65+
# ReLU + sigmoid edge cases
66+
fn test_relu_all_zero() {
67+
h r = arr_relu_vec([0 - 1.0, 0 - 2.0, 0 - 3.0]);
68+
assert_true(approx_eq(arr_get(r, 0), 0.0, 0.001), "all clipped");
69+
}
70+
71+
fn test_relu_all_positive() {
72+
h r = arr_relu_vec([1.0, 2.0, 3.0]);
73+
assert_true(approx_eq(arr_get(r, 0), 1.0, 0.001), "passthrough");
74+
assert_true(approx_eq(arr_get(r, 2), 3.0, 0.001), "passthrough");
75+
}
76+
77+
fn test_sigmoid_at_one() {
78+
h s = arr_sigmoid_vec([1.0]);
79+
h v = arr_get(s, 0);
80+
assert_true(approx_eq(v, 0.7310586, 0.001), "sigmoid(1)");
81+
}
82+
83+
fn test_sigmoid_at_negative_one() {
84+
h s = arr_sigmoid_vec([0 - 1.0]);
85+
h v = arr_get(s, 0);
86+
assert_true(approx_eq(v, 0.2689414, 0.001), "sigmoid(-1)");
87+
}
88+
89+
# conv1d cases
90+
fn test_conv1d_kernel_2() {
91+
h c = arr_conv1d([1.0, 2.0, 3.0, 4.0], [1.0, 1.0]);
92+
# Output length = 4 - 2 + 1 = 3
93+
assert_eq(arr_len(c), 3, "len = 3");
94+
assert_true(approx_eq(arr_get(c, 0), 3.0, 0.001), "1+2");
95+
assert_true(approx_eq(arr_get(c, 1), 5.0, 0.001), "2+3");
96+
assert_true(approx_eq(arr_get(c, 2), 7.0, 0.001), "3+4");
97+
}
98+
99+
# arr_outer extras
100+
fn test_outer_unit_basis() {
101+
h o = arr_outer([1.0, 0.0], [1.0, 0.0]);
102+
h r0 = arr_get(o, 0);
103+
h r1 = arr_get(o, 1);
104+
assert_true(approx_eq(arr_get(r0, 0), 1.0, 0.001), "[0,0]=1");
105+
assert_true(approx_eq(arr_get(r0, 1), 0.0, 0.001), "[0,1]=0");
106+
assert_true(approx_eq(arr_get(r1, 0), 0.0, 0.001), "[1,0]=0");
107+
assert_true(approx_eq(arr_get(r1, 1), 0.0, 0.001), "[1,1]=0");
108+
}
109+
110+
# Substrate attention output shape
111+
fn test_substrate_attention_shape() {
112+
h Q = [[1, 2], [3, 4], [5, 6]]; # 3 queries
113+
h K = [[1, 2], [3, 4]]; # 2 keys
114+
h V = [[10, 20], [30, 40]]; # 2 values, dim 2
115+
h out = arr_substrate_attention(Q, K, V);
116+
assert_eq(arr_len(out), 3, "3 query rows out");
117+
h r0 = arr_get(out, 0);
118+
assert_eq(arr_len(r0), 2, "value dim preserved");
119+
}
120+
121+
# Substrate score rows
122+
fn test_substrate_score_rows_simple() {
123+
h s = arr_substrate_score_rows([[1, 2, 3, 5, 8]]);
124+
assert_eq(arr_len(s), 1, "one row");
125+
assert_true(arr_get(s, 0) > 0.9, "Fibonacci row has high score");
126+
}

0 commit comments

Comments
 (0)