nx_render_target_match_test.nx source
↩ module page · 107 lines · 4252 B
1// nx_render_target_match_test.nx -- smoke for target-vs-rendered verdict.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_image_feature_extract.nx"
6import "nx_render_target_match.nx"
7
8func _fill_vec(v: *nx_int, base: nx_int) -> nx_int {
9 var i: nx_int = 0
10 while i < NX_IMAGE_FEATURE_LEN {
11 v[i] = base + i * 10
12 i = i + 1
13 }
14 return 0
15}
16
17func main() -> nx_int {
18 let rep: *RenderTargetMatchReport =
19 (sys_mmap(12 * NX_SIZEOF_NX_INT)) as *RenderTargetMatchReport
20
21 // === Test 1: identical vectors -> MATCH_EXCELLENT, SHIP ===
22 let target: *nx_int = (sys_mmap(NX_IMAGE_FEATURE_LEN * NX_SIZEOF_NX_INT)) as *nx_int
23 let rendered: *nx_int = (sys_mmap(NX_IMAGE_FEATURE_LEN * NX_SIZEOF_NX_INT)) as *nx_int
24 _fill_vec(target, 500)
25 _fill_vec(rendered, 500)
26 nx_render_target_match(target, rendered, rep)
27 if rep.verdict != NX_RTM_MATCH_EXCELLENT { return 1 }
28 if rep.recommended_action != NX_RTM_ACTION_SHIP { return 2 }
29 if rep.n_diverged_axes != 0 { return 3 }
30 if rep.worst_axis_delta_q10 != 0 { return 4 }
31
32 // === Test 2: one-axis divergence (color) -> GOOD + REFINE_COLOR ===
33 // Target has color_harmony = 800, rendered has 400. Delta = 400 (above
34 // tolerance 200). All other axes match. Cosine high.
35 _fill_vec(target, 500)
36 _fill_vec(rendered, 500)
37 target[NX_IMG_FEAT_COLOR_HARMONY] = 800
38 rendered[NX_IMG_FEAT_COLOR_HARMONY] = 400
39 nx_render_target_match(target, rendered, rep)
40 // High cosine (15/16 axes match) but worst-axis delta = 400 > 100
41 // -> demoted from EXCELLENT to GOOD.
42 if rep.verdict != NX_RTM_MATCH_GOOD { return 10 }
43 if rep.worst_axis_index != NX_IMG_FEAT_COLOR_HARMONY { return 11 }
44 if rep.recommended_action != NX_RTM_ACTION_REFINE_COLOR { return 12 }
45 if rep.n_diverged_axes != 1 { return 13 }
46
47 // === Test 3: symmetry axis divergence -> action REFINE_SYMMETRY ===
48 _fill_vec(target, 500)
49 _fill_vec(rendered, 500)
50 target[NX_IMG_FEAT_SYM_H] = 900
51 rendered[NX_IMG_FEAT_SYM_H] = 100
52 nx_render_target_match(target, rendered, rep)
53 if rep.worst_axis_index != NX_IMG_FEAT_SYM_H { return 20 }
54 if rep.recommended_action != NX_RTM_ACTION_REFINE_SYMMETRY { return 21 }
55
56 // === Test 4: anti-parallel vectors -> MATCH_FAILED ===
57 var i: nx_int = 0
58 while i < NX_IMAGE_FEATURE_LEN {
59 target[i] = 500
60 rendered[i] = -500
61 i = i + 1
62 }
63 nx_render_target_match(target, rendered, rep)
64 if rep.verdict != NX_RTM_MATCH_FAILED { return 30 }
65
66 // === Test 5: moderate alignment (cosine 0.6) -> PARTIAL ===
67 // Target = [1, 1, 1, ...], rendered = [1, 0.6, 0.6, ...] would
68 // give cos ~ 0.84. Use larger spread instead: keep some axes
69 // identical, perturb others heavily.
70 _fill_vec(target, 600)
71 var k: nx_int = 0
72 while k < NX_IMAGE_FEATURE_LEN {
73 rendered[k] = 600
74 k = k + 1
75 }
76 // Perturb half the axes by setting them to 0.
77 rendered[0] = 0
78 rendered[1] = 0
79 rendered[2] = 0
80 rendered[3] = 0
81 rendered[4] = 0
82 rendered[5] = 0
83 rendered[6] = 0
84 rendered[7] = 0
85 nx_render_target_match(target, rendered, rep)
86 // 8 axes match, 8 zeroed -> cos around 0.7
87 // n_diverged_axes should be 8 (the zeroed ones).
88 if rep.n_diverged_axes != 8 { return 40 }
89
90 // === Test 6: sealed-enum validity ===
91 if nx_render_target_match_verdict_is_valid(NX_RTM_MATCH_EXCELLENT) != 1 { return 60 }
92 if nx_render_target_match_verdict_is_valid(NX_RTM_MATCH_FAILED) != 1 { return 61 }
93 if nx_render_target_match_verdict_is_valid(99) != 0 { return 62 }
94 if nx_render_target_match_action_is_valid(NX_RTM_ACTION_SHIP) != 1 { return 63 }
95 if nx_render_target_match_action_is_valid(NX_RTM_ACTION_REFINE_COLOR) != 1 { return 64 }
96 if nx_render_target_match_action_is_valid(99) != 0 { return 65 }
97
98 // === Test 7: lighting-axis worst -> REFINE_LIGHTING action ===
99 _fill_vec(target, 500)
100 _fill_vec(rendered, 500)
101 target[NX_IMG_FEAT_LIGHTING] = 950
102 rendered[NX_IMG_FEAT_LIGHTING] = 50
103 nx_render_target_match(target, rendered, rep)
104 if rep.recommended_action != NX_RTM_ACTION_REFINE_LIGHTING { return 70 }
105
106 return 0
107}