nx_jpeg_entropy_test.nx source
↩ module page · 154 lines · 5976 B
1// nx_jpeg_entropy_test.nx -- KAT for baseline JPEG entropy decoder.
2//
3// Designs hand-built Huffman tables + a known bitstream that should
4// decode to a specific 64-entry zig-zag-ordered block, then verifies.
5//
6// Tables:
7// DC: BITS={1,1,1,0,...}, HUFFVAL={0,1,2}
8// symbol 0 = code "0" (1 bit)
9// symbol 1 = code "10" (2 bits)
10// symbol 2 = code "110" (3 bits)
11// AC: BITS={2,0,...}, HUFFVAL={0x00, 0x01}
12// symbol 0x00 = code "0" (EOB)
13// symbol 0x01 = code "1" (run=0 size=1)
14//
15// Block 1: DC=+1, AC[1]=+1, EOB.
16// DC stream: symbol 1 "10" + 1 mag bit "1" = "101"
17// AC stream: symbol 0x01 "1" + 1 mag bit "1" = "11"
18// EOB: symbol 0x00 "0" = "0"
19// total: "101110" = 6 bits
20//
21// Block 2: DC delta=+3 (prev_dc was 1, want 4), then EOB.
22// DC stream: symbol 2 "110" + 2 mag bits "11" = "11011"
23// EOB: symbol 0x00 "0" = "0"
24// total: "110110" = 6 bits
25//
26// Combined 12 bits, packed MSB-first:
27// byte 0 = 0b10111011 = 0xBB
28// byte 1 = 0b01100000 = 0x60
29//
30// expect_exit: 0
31// license_tier: ORIGINAL
32
33import "nx_syscalls.nx"
34import "nx_jpeg_dht.nx"
35import "nx_jpeg_entropy.nx"
36
37func _fail(n: i64) -> i64 {
38 let b: *u8 = sys_mmap(16)
39 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D
40 sys_write(2, b, 5)
41 var x: i64 = n
42 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x }
43 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) }
44 else {
45 let buf: *u8 = sys_mmap(16)
46 var pos: i64 = 0
47 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 }
48 let out: *u8 = sys_mmap(16)
49 var i: i64 = 0
50 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 }
51 sys_write(2, out, pos)
52 }
53 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1)
54 return 0
55}
56
57func main() -> i64 {
58 // ============================================================
59 // Section A: EXTEND() spot checks per T.81 Fig F.12
60 // ============================================================
61 // EXTEND(0b00, t=1): raw 0 < 2^0=1 ? yes -> 0 - (2-1) = -1
62 if nx_jpeg_ent_extend(0, 1) != (0 - 1) { _fail(1); return 1 }
63 // EXTEND(1, t=1): 1 < 1 ? no -> 1
64 if nx_jpeg_ent_extend(1, 1) != 1 { _fail(2); return 2 }
65 // EXTEND(0, t=2): 0 < 2 ? yes -> 0 - 3 = -3
66 if nx_jpeg_ent_extend(0, 2) != (0 - 3) { _fail(3); return 3 }
67 // EXTEND(2, t=2): 2 < 2 ? no -> 2
68 if nx_jpeg_ent_extend(2, 2) != 2 { _fail(4); return 4 }
69 // EXTEND(3, t=2): 3 < 2 ? no -> 3
70 if nx_jpeg_ent_extend(3, 2) != 3 { _fail(5); return 5 }
71 // EXTEND(0, t=0) = 0
72 if nx_jpeg_ent_extend(0, 0) != 0 { _fail(6); return 6 }
73
74 // ============================================================
75 // Section B: build DC + AC Huffman tables via nx_jpeg_dht_parse
76 // ============================================================
77 let tables: *NxJpegHTable = sys_mmap(NX_JPEG_HTABLE_BYTES * 4) as *NxJpegHTable
78 let bits_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
79 let hv_pool: *i64 = sys_mmap(4 * 256 * 8) as *i64
80 let mc_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
81 let xc_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
82 let vp_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
83 let count_p: *i64 = sys_mmap(8) as *i64
84
85 // DHT payload: DC table + AC table stacked.
86 let pld: *u8 = sys_mmap(128)
87 // DC: tc=0, th=0, BITS={1,1,1,0,...}, HUFFVAL={0,1,2}
88 pld[0] = 0x00
89 pld[1] = 1; pld[2] = 1; pld[3] = 1
90 var i: i64 = 4
91 while i <= 16 { pld[i] = 0; i = i + 1 }
92 pld[17] = 0; pld[18] = 1; pld[19] = 2
93 // AC: tc=1, th=0, BITS={2,0,...}, HUFFVAL={0x00, 0x01}
94 pld[20] = 0x10
95 pld[21] = 2
96 i = 22
97 while i <= 36 { pld[i] = 0; i = i + 1 }
98 pld[37] = 0x00
99 pld[38] = 0x01
100
101 let rc_p: i64 = nx_jpeg_dht_parse(pld, 39, tables, bits_pool, hv_pool, mc_pool, xc_pool, vp_pool, count_p)
102 if rc_p != NX_JPEG_DHT_OK { _fail(10); return 10 }
103 if count_p[0] != 2 { _fail(11); return 11 }
104
105 let dc_table: *NxJpegHTable = tables
106 let ac_table: *NxJpegHTable = (tables as i64 + NX_JPEG_HTABLE_BYTES) as *NxJpegHTable
107
108 // ============================================================
109 // Section C: decode 2 blocks from a hand-packed bitstream.
110 // ============================================================
111 let stream: *u8 = sys_mmap(8)
112 stream[0] = 0xBB
113 stream[1] = 0x60
114
115 let bit_off_p: *i64 = sys_mmap(8) as *i64
116 let byte_idx_p: *i64 = sys_mmap(8) as *i64
117 bit_off_p[0] = 0
118 byte_idx_p[0] = 0
119
120 let prev_dc_p: *i64 = sys_mmap(8) as *i64
121 prev_dc_p[0] = 0
122
123 let block: *i64 = sys_mmap(64 * 8) as *i64
124
125 // Block 1: expect DC=+1, AC[1]=+1, rest=0.
126 let rc1: i64 = nx_jpeg_ent_decode_block(dc_table, ac_table, prev_dc_p,
127 block, stream, bit_off_p, byte_idx_p, 2)
128 if rc1 != NX_JPEG_ENT_OK { _fail(20); return 20 }
129 if block[0] != 1 { _fail(21); return 21 }
130 if block[1] != 1 { _fail(22); return 22 }
131 var k: i64 = 2
132 while k < 64 {
133 if block[k] != 0 { _fail(23 + k); return 23 }
134 k = k + 1
135 }
136 if prev_dc_p[0] != 1 { _fail(100); return 100 }
137
138 // Block 2: expect DC=+4 (delta=+3 from prev=1), rest=0.
139 let rc2: i64 = nx_jpeg_ent_decode_block(dc_table, ac_table, prev_dc_p,
140 block, stream, bit_off_p, byte_idx_p, 2)
141 if rc2 != NX_JPEG_ENT_OK { _fail(110); return 110 }
142 if block[0] != 4 { _fail(111); return 111 }
143 k = 1
144 while k < 64 {
145 if block[k] != 0 { _fail(112 + k); return 112 }
146 k = k + 1
147 }
148 if prev_dc_p[0] != 4 { _fail(200); return 200 }
149
150 let pass: *u8 = sys_mmap(16)
151 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A
152 sys_write(1, pass, 5)
153 return 0
154}