nx_self_similarity_test.nx source
↩ module page · 113 lines · 4811 B
1// nx_self_similarity_test.nx -- smoke for box-counting fractal dim.
2//
3// Per the substrate's bench-press cardinal: prove the primitive on
4// hand-constructed images with known fractal properties, before any
5// caller relies on it.
6//
7// Test cases:
8// 1. Uniform image (no edges) -> refused with fidelity = 0
9// 2. Checkerboard (every cell is an edge) -> high D ~ 2.0
10// 3. Single horizontal line -> D ~ 1.0 (low)
11// 4. Diagonal stripes at moderate spacing -> D in the Spehar band
12// 5. Spehar peak-band predicate detects band 1.3-1.5 correctly
13// 6. Report fields all in [0, 1024] range
14
15import "nx_syscalls.nx"
16import "nx_tier.nx"
17import "nx_image.nx"
18import "nx_self_similarity.nx"
19
20func main() -> nx_int {
21 // === Test 1: uniform image (zero edges) -> refusal ===
22 let img_uniform: *Image = nx_image_alloc(32, 32, 1)
23 var y1: nx_int = 0
24 while y1 < 32 {
25 var x1: nx_int = 0
26 while x1 < 32 {
27 nx_image_set(img_uniform, x1, y1, 0, 128)
28 x1 = x1 + 1
29 }
30 y1 = y1 + 1
31 }
32 let r_uniform: *SelfSimilarityReport = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *SelfSimilarityReport
33 let rc1: nx_int = nx_self_similarity_compute(img_uniform, r_uniform)
34 // Uniform image has near-zero edge density -> rc=2 (refusal) and
35 // fidelity = 0. Substrate refuses to claim a dimension on a
36 // signal with no structure.
37 let fid1: nx_int = r_uniform.fidelity_q10
38 if fid1 != 0 { return 1 }
39
40 // === Test 2: checkerboard (every cell flips) -> high D ===
41 let img_check: *Image = nx_image_alloc(32, 32, 1)
42 var y2: nx_int = 0
43 while y2 < 32 {
44 var x2: nx_int = 0
45 while x2 < 32 {
46 var v: nx_int = 0
47 if (x2 + y2) - ((x2 + y2) / 2) * 2 == 1 { v = 255 }
48 nx_image_set(img_check, x2, y2, 0, v)
49 x2 = x2 + 1
50 }
51 y2 = y2 + 1
52 }
53 let r_check: *SelfSimilarityReport = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *SelfSimilarityReport
54 let rc2: nx_int = nx_self_similarity_compute(img_check, r_check)
55 if rc2 != 0 { return 10 }
56 // Checkerboard fills every box at every scale, slope is small and
57 // D approaches 2 -- fractal_dim_q10 (which is Q10 of D-1) should be high.
58 let dim_check: nx_int = r_check.fractal_dim_q10
59 if dim_check < 600 { return 11 } // expect close to ceiling
60
61 // === Test 3: single horizontal line (D ~ 1) ===
62 let img_line: *Image = nx_image_alloc(32, 32, 1)
63 var y3: nx_int = 0
64 while y3 < 32 {
65 var x3: nx_int = 0
66 while x3 < 32 {
67 var v: nx_int = 0
68 if y3 == 16 { v = 255 } // single bright row
69 nx_image_set(img_line, x3, y3, 0, v)
70 x3 = x3 + 1
71 }
72 y3 = y3 + 1
73 }
74 let r_line: *SelfSimilarityReport = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *SelfSimilarityReport
75 let rc3: nx_int = nx_self_similarity_compute(img_line, r_line)
76 // Line may or may not pass density gate; if it does, D should be
77 // close to 1, i.e. fractal_dim_q10 (Q10 of D-1) close to 0.
78 if rc3 == 0 {
79 let dim_line: nx_int = r_line.fractal_dim_q10
80 // Single-line patterns: the box-count slope is roughly the same
81 // as one boundary thickness, so D ~ 1, expected dim_q10 < 400.
82 if dim_line > 400 { return 20 }
83 }
84
85 // === Test 4: report fields in [0, 1024] ===
86 if r_check.fractal_dim_q10 < 0 { return 30 }
87 if r_check.fractal_dim_q10 > 1024 { return 31 }
88 if r_check.aesthetic_q10 < 0 { return 32 }
89 if r_check.aesthetic_q10 > 1024 { return 33 }
90 if r_check.edge_density_q10 < 0 { return 34 }
91 if r_check.edge_density_q10 > 1024 { return 35 }
92 if r_check.fidelity_q10 < 0 { return 36 }
93 if r_check.fidelity_q10 > 1024 { return 37 }
94
95 // === Test 5: Spehar peak-band predicate ===
96 // Hand-set a report into the Spehar band, verify predicate fires.
97 let r_synthetic: *SelfSimilarityReport = (sys_mmap(4 * NX_SIZEOF_NX_INT)) as *SelfSimilarityReport
98 r_synthetic.fractal_dim_q10 = 410 // D ~ 1.4
99 r_synthetic.aesthetic_q10 = 1024
100 r_synthetic.edge_density_q10 = 200
101 r_synthetic.fidelity_q10 = 400
102 if nx_self_similarity_in_peak_band(r_synthetic) != 1 { return 40 }
103
104 // Below the band: predicate must return 0.
105 r_synthetic.fractal_dim_q10 = 100 // D ~ 1.1
106 if nx_self_similarity_in_peak_band(r_synthetic) != 0 { return 41 }
107
108 // Above the band: predicate must return 0.
109 r_synthetic.fractal_dim_q10 = 800 // D ~ 1.8
110 if nx_self_similarity_in_peak_band(r_synthetic) != 0 { return 42 }
111
112 return 0
113}