nx_jaro_winkler_test.nx source
↩ module page · 108 lines · 3300 B
1// nx_jaro_winkler_test.nx -- smoke for Jaro-Winkler similarity.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_jaro_winkler.nx"
6
7func _set_bytes(buf: *u8, lit: nx_int, n: nx_int) -> nx_int {
8 var i: nx_int = 0
9 while i < n {
10 buf[i] = lit
11 i = i + 1
12 }
13 return 0
14}
15
16func main() -> nx_int {
17 // === Test 1: identical strings -> Q10 ===
18 // "hello" vs "hello"
19 let a1: *u8 = sys_mmap(8)
20 a1[0] = 104 // h
21 a1[1] = 101 // e
22 a1[2] = 108 // l
23 a1[3] = 108 // l
24 a1[4] = 111 // o
25 let b1: *u8 = sys_mmap(8)
26 b1[0] = 104
27 b1[1] = 101
28 b1[2] = 108
29 b1[3] = 108
30 b1[4] = 111
31 let s1: nx_int = nx_jaro_winkler(a1, 5, b1, 5)
32 if s1 != NX_JW_Q { return 1 }
33 if nx_jaro_winkler_classify(s1) != NX_STRSIM_IDENTICAL { return 2 }
34
35 // === Test 2: completely different -> 0 ===
36 // "abc" vs "xyz"
37 let a2: *u8 = sys_mmap(8)
38 a2[0] = 97 // a
39 a2[1] = 98 // b
40 a2[2] = 99 // c
41 let b2: *u8 = sys_mmap(8)
42 b2[0] = 120 // x
43 b2[1] = 121 // y
44 b2[2] = 122 // z
45 let s2: nx_int = nx_jaro_winkler(a2, 3, b2, 3)
46 if s2 != 0 { return 10 }
47 if nx_jaro_winkler_classify(s2) != NX_STRSIM_DISTINCT { return 11 }
48
49 // === Test 3: empty inputs ===
50 if nx_jaro_winkler(a1, 0, b1, 0) != NX_JW_Q { return 20 }
51 if nx_jaro_winkler(a1, 0, b1, 5) != 0 { return 21 }
52 if nx_jaro_winkler(a1, 5, b1, 0) != 0 { return 22 }
53
54 // === Test 4: classic "MARTHA" vs "MARHTA" -> Jaro-Winkler ~ 0.961 ===
55 // Q10: 0.961 * 1024 ~ 984. Range [950, 1024].
56 let a4: *u8 = sys_mmap(8)
57 a4[0] = 77 // M
58 a4[1] = 65 // A
59 a4[2] = 82 // R
60 a4[3] = 84 // T
61 a4[4] = 72 // H
62 a4[5] = 65 // A
63 let b4: *u8 = sys_mmap(8)
64 b4[0] = 77 // M
65 b4[1] = 65 // A
66 b4[2] = 82 // R
67 b4[3] = 72 // H
68 b4[4] = 84 // T
69 b4[5] = 65 // A
70 let s4: nx_int = nx_jaro_winkler(a4, 6, b4, 6)
71 // Within reasonable band of the canonical 0.961.
72 if s4 < 900 { return 30 }
73 if s4 > 1024 { return 31 }
74 if nx_jaro_winkler_classify(s4) != NX_STRSIM_IDENTICAL { return 32 }
75
76 // === Test 5: shared common prefix bonus ===
77 // "blonde girl" vs "blonde girla" -- identical-then-extra; should
78 // be in NEAR_DUPLICATE or IDENTICAL band.
79 let a5: *u8 = sys_mmap(16)
80 a5[0] = 98 // b
81 a5[1] = 108 // l
82 a5[2] = 111 // o
83 a5[3] = 110 // n
84 a5[4] = 100 // d
85 a5[5] = 101 // e
86 a5[6] = 32 // space
87 a5[7] = 103 // g
88 a5[8] = 105 // i
89 a5[9] = 114 // r
90 a5[10] = 108 // l
91 let b5: *u8 = sys_mmap(16)
92 var k: nx_int = 0
93 while k < 11 {
94 b5[k] = a5[k]
95 k = k + 1
96 }
97 b5[11] = 97 // a
98 let s5: nx_int = nx_jaro_winkler(a5, 11, b5, 12)
99 if s5 < 921 { return 40 } // should hit IDENTICAL band
100
101 // === Test 6: sealed-enum validity ===
102 if nx_strsim_band_is_valid(NX_STRSIM_DISTINCT) != 1 { return 50 }
103 if nx_strsim_band_is_valid(NX_STRSIM_IDENTICAL) != 1 { return 51 }
104 if nx_strsim_band_is_valid(99) != 0 { return 52 }
105 if nx_strsim_band_is_valid(0 - 1) != 0 { return 53 }
106
107 return 0
108}