nx_align_test.nx source
↩ module page · 156 lines · 6186 B
1// nx_align_test.nx -- KAT for Smith-Waterman local alignment.
2//
3// All vectors hand-verifiable from the SW recurrence stated in
4// nx_align.nx. Convention: scoring (match, mismatch, gap) declared
5// per-test; tie-break = first max found wins (row-major scan).
6//
7// expect_exit: 0
8//
9// license_tier: ORIGINAL
10
11import "nx_syscalls.nx"
12import "nx_align.nx"
13
14func write_str8(buf: *u8, s0: i64, s1: i64, s2: i64, s3: i64,
15 s4: i64, s5: i64, s6: i64, s7: i64) -> i64 {
16 buf[0] = s0 & 0xff
17 buf[1] = s1 & 0xff
18 buf[2] = s2 & 0xff
19 buf[3] = s3 & 0xff
20 buf[4] = s4 & 0xff
21 buf[5] = s5 & 0xff
22 buf[6] = s6 & 0xff
23 buf[7] = s7 & 0xff
24 return 0
25}
26
27func main() -> i64 {
28
29 let a: *u8 = sys_mmap(32)
30 let b: *u8 = sys_mmap(32)
31 let mi: *i64 = sys_mmap(16) as *i64
32 let mj: *i64 = sys_mmap(16) as *i64
33
34 // ============================================================
35 // Section A -- identical "ACGT" vs "ACGT", m=+2 mis=-1 gap=-2
36 // Expected: score = 8, end (4, 4)
37 // ============================================================
38
39 write_str8(a, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
40 write_str8(b, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
41 let s1: i64 = smith_waterman_linear(a, 4, b, 4, 2, -1, -2, mi, mj)
42 if s1 != 8 { return 1 }
43 if mi[0] != 4 { return 2 }
44 if mj[0] != 4 { return 3 }
45
46 // ============================================================
47 // Section B -- embedded match: "ACGT" vs "TTACGTGG"
48 // Expected: score = 8, end (4, 6) (alignment at b[2..5])
49 // ============================================================
50
51 write_str8(a, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
52 b[0]=0x54; b[1]=0x54; b[2]=0x41; b[3]=0x43; b[4]=0x47; b[5]=0x54; b[6]=0x47; b[7]=0x47
53 let s2: i64 = smith_waterman_linear(a, 4, b, 8, 2, -1, -2, mi, mj)
54 if s2 != 8 { return 10 }
55 if mi[0] != 4 { return 11 }
56 if mj[0] != 6 { return 12 }
57
58 // ============================================================
59 // Section C -- all-mismatch "AAAA" vs "TTTT", m=+2 mis=-1 gap=-2
60 // Expected: score = 0, end (0, 0)
61 // ============================================================
62
63 write_str8(a, 0x41, 0x41, 0x41, 0x41, 0, 0, 0, 0)
64 write_str8(b, 0x54, 0x54, 0x54, 0x54, 0, 0, 0, 0)
65 let s3: i64 = smith_waterman_linear(a, 4, b, 4, 2, -1, -2, mi, mj)
66 if s3 != 0 { return 20 }
67 if mi[0] != 0 { return 21 }
68 if mj[0] != 0 { return 22 }
69
70 // ============================================================
71 // Section D -- degenerate empty inputs return 0, (0, 0).
72 // ============================================================
73
74 write_str8(a, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
75 let s4: i64 = smith_waterman_linear(a, 0, b, 4, 2, -1, -2, mi, mj)
76 if s4 != 0 { return 30 }
77 if mi[0] != 0 { return 31 }
78
79 let s5: i64 = smith_waterman_linear(a, 4, b, 0, 2, -1, -2, mi, mj)
80 if s5 != 0 { return 32 }
81 if mj[0] != 0 { return 33 }
82
83 // ============================================================
84 // Section E -- single-char match. "A" vs "TAT", m=+2 mis=-1 gap=-2
85 // Expected: score = 2, end (1, 2) (A matches at b[1])
86 // ============================================================
87
88 a[0] = 0x41
89 b[0]=0x54; b[1]=0x41; b[2]=0x54
90 let s6: i64 = smith_waterman_linear(a, 1, b, 3, 2, -1, -2, mi, mj)
91 if s6 != 2 { return 40 }
92 if mi[0] != 1 { return 41 }
93 if mj[0] != 2 { return 42 }
94
95 // ============================================================
96 // Section F -- substitution path: "ACAT" vs "ACGT", m=+2 mis=-1 gap=-2
97 // Expected: score = 5, end (4, 4) (3 matches + 1 mismatch = 6-1=5)
98 // ============================================================
99
100 write_str8(a, 0x41, 0x43, 0x41, 0x54, 0, 0, 0, 0)
101 write_str8(b, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
102 let s7: i64 = smith_waterman_linear(a, 4, b, 4, 2, -1, -2, mi, mj)
103 if s7 != 5 { return 50 }
104 if mi[0] != 4 { return 51 }
105 if mj[0] != 4 { return 52 }
106
107 // ============================================================
108 // Section G -- gap-in-A path: "ACT" vs "AGCT", m=+2 mis=-1 gap=-2
109 // Expected: score = 4, end (3, 4) (3 matches + 1 gap = 6-2=4)
110 // ============================================================
111
112 write_str8(a, 0x41, 0x43, 0x54, 0, 0, 0, 0, 0)
113 write_str8(b, 0x41, 0x47, 0x43, 0x54, 0, 0, 0, 0)
114 let s8: i64 = smith_waterman_linear(a, 3, b, 4, 2, -1, -2, mi, mj)
115 if s8 != 4 { return 60 }
116 if mi[0] != 3 { return 61 }
117 if mj[0] != 4 { return 62 }
118
119 // ============================================================
120 // Section H -- gap-in-B path: "AGCT" vs "ACT" -- symmetric of G.
121 // Expected: score = 4, end (4, 3)
122 // ============================================================
123
124 write_str8(a, 0x41, 0x47, 0x43, 0x54, 0, 0, 0, 0)
125 write_str8(b, 0x41, 0x43, 0x54, 0, 0, 0, 0, 0)
126 let s9: i64 = smith_waterman_linear(a, 4, b, 3, 2, -1, -2, mi, mj)
127 if s9 != 4 { return 70 }
128 if mi[0] != 4 { return 71 }
129 if mj[0] != 3 { return 72 }
130
131 // ============================================================
132 // Section I -- BWA-MEM-style scoring (m=+5 mis=-3 gap=-4)
133 // "ACGT" vs "ACGT" -> 4 * 5 = 20.
134 // ============================================================
135
136 write_str8(a, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
137 write_str8(b, 0x41, 0x43, 0x47, 0x54, 0, 0, 0, 0)
138 let s10: i64 = smith_waterman_linear(a, 4, b, 4, 5, -3, -4, mi, mj)
139 if s10 != 20 { return 80 }
140
141 // ============================================================
142 // Section J -- tie-break determinism.
143 // "AA" vs "AAA" with m=+2. Two valid alignments score 4:
144 // AA matching b[0..1] or b[1..2]. Strict-> tie-break picks FIRST
145 // max in row-major scan = (2, 2).
146 // ============================================================
147
148 write_str8(a, 0x41, 0x41, 0, 0, 0, 0, 0, 0)
149 write_str8(b, 0x41, 0x41, 0x41, 0, 0, 0, 0, 0)
150 let s11: i64 = smith_waterman_linear(a, 2, b, 3, 2, -1, -2, mi, mj)
151 if s11 != 4 { return 90 }
152 if mi[0] != 2 { return 91 }
153 if mj[0] != 2 { return 92 }
154
155 return 0
156}