code wiki / _hdl_build / nx_huffman_kat.nx
nx_huffman_kat.nx source
↩ module page · 66 lines · 4358 B
1// nx_huffman_kat.nx -- KAT for nx_huffman (canonical Huffman build + decode; the DEFLATE symbol layer).
2// HONESTY [W] weak point (reach=122; the in-file main self-tests via return-codes but no external node).
3// Formalizes the canonical-build KAT (RFC-1951 canonical code assignment for lengths [2,1,3,3]) and adds a
4// DECODE ROUNDTRIP the demo lacked: pack canonical codes MSB-first, decode them back to the symbols.
5// license_tier: ORIGINAL expect_exit:0
6import "nx_syscalls.nx"
7import "nx_bitio.nx"
8import "nx_bitstream.nx"
9import "nx_huffman.nx"
10
11func hw(s: *u8) -> i64 { var n:i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
12func hn(v: i64) -> i64 { let b:*u8=sys_mmap(24); var m:i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
13
14func main() -> i64 {
15 var pass: i64 = 0
16
17 // canonical table for lengths [2,1,3,3] -> codes sym1=0, sym0=10, sym2=110, sym3=111
18 let lens: *nx_int = sys_mmap(64) as *nx_int
19 lens[0] = 2; lens[1] = 1; lens[2] = 3; lens[3] = 3
20 let t: *NxHuffmanTable = nx_huffman_build(lens, 4)
21 if (t as i64) == 0 { hw("build failed\nNX-HUFFMAN-KAT 0/6 RED\n" as *u8); return 1 }
22
23 // T1: shape
24 if t.n_symbols == 4 { if t.max_length == 3 { pass = pass + 1; hw("T1 shape PASS\n" as *u8) } else { hw("T1 FAIL max_len\n" as *u8) } } else { hw("T1 FAIL n_sym\n" as *u8) }
25
26 // T2: per-length counts
27 if t.count[1] == 1 { if t.count[2] == 1 { if t.count[3] == 2 { pass = pass + 1; hw("T2 counts PASS\n" as *u8) } else { hw("T2 FAIL c3\n" as *u8) } } else { hw("T2 FAIL c2\n" as *u8) } } else { hw("T2 FAIL c1\n" as *u8) }
28
29 // T3: canonical first_code (0, (0+1)*2=2, (2+1)*2=6)
30 if t.first_code[1] == 0 { if t.first_code[2] == 2 { if t.first_code[3] == 6 { pass = pass + 1; hw("T3 first_code canonical PASS\n" as *u8) } else { hw("T3 FAIL fc3\n" as *u8) } } else { hw("T3 FAIL fc2\n" as *u8) } } else { hw("T3 FAIL fc1\n" as *u8) }
31
32 // T4: symbol_table sorted by (length,symbol): [1,0,2,3]
33 if t.symbol_table[0] == 1 { if t.symbol_table[1] == 0 { if t.symbol_table[2] == 2 { if t.symbol_table[3] == 3 { pass = pass + 1; hw("T4 symtab sorted PASS\n" as *u8) } else { hw("T4 FAIL s3\n" as *u8) } } else { hw("T4 FAIL s2\n" as *u8) } } else { hw("T4 FAIL s1\n" as *u8) } } else { hw("T4 FAIL s0\n" as *u8) }
34
35 // T5: DECODE ROUNDTRIP -- pack codes MSB-first (sym1=0, sym0=10, sym2=110, sym3=111) then decode
36 let buf: *u8 = sys_mmap(16)
37 var i: i64 = 0; while i < 16 { buf[i] = 0 as u8; i = i + 1 }
38 var bp: i64 = 0
39 bp = nx_bw_put(buf, bp, 0, 1) // sym1 code 0
40 bp = nx_bw_put(buf, bp, 2, 2) // sym0 code 10
41 bp = nx_bw_put(buf, bp, 6, 3) // sym2 code 110
42 bp = nx_bw_put(buf, bp, 7, 3) // sym3 code 111
43 let bs: *NxBitStream = nx_bitstream_alloc(buf, 4)
44 let d0: i64 = nx_huffman_decode_msb(t, bs)
45 let d1: i64 = nx_huffman_decode_msb(t, bs)
46 let d2: i64 = nx_huffman_decode_msb(t, bs)
47 let d3: i64 = nx_huffman_decode_msb(t, bs)
48 if d0 == 1 { if d1 == 0 { if d2 == 2 { if d3 == 3 { pass = pass + 1; hw("T5 decode roundtrip [1,0,2,3] PASS\n" as *u8) } else { hw("T5 FAIL d3=" as *u8); hn(d3); hw("\n" as *u8) } } else { hw("T5 FAIL d2=" as *u8); hn(d2); hw("\n" as *u8) } } else { hw("T5 FAIL d1=" as *u8); hn(d1); hw("\n" as *u8) } } else { hw("T5 FAIL d0=" as *u8); hn(d0); hw("\n" as *u8) }
49
50 // T6: 2-symbol table [1,1] -> codes 0,1 ; decode '0'->0, '1'->1
51 let l2: *nx_int = sys_mmap(32) as *nx_int
52 l2[0] = 1; l2[1] = 1
53 let t2: *NxHuffmanTable = nx_huffman_build(l2, 2)
54 let b2: *u8 = sys_mmap(8); b2[0] = 0 as u8
55 nx_bw_put(b2, 0, 0, 1) // code 0 -> sym0
56 nx_bw_put(b2, 1, 1, 1) // code 1 -> sym1
57 let bs2: *NxBitStream = nx_bitstream_alloc(b2, 1)
58 let e0: i64 = nx_huffman_decode_msb(t2, bs2)
59 let e1: i64 = nx_huffman_decode_msb(t2, bs2)
60 if e0 == 0 { if e1 == 1 { pass = pass + 1; hw("T6 2-sym decode PASS\n" as *u8) } else { hw("T6 FAIL e1=" as *u8); hn(e1); hw("\n" as *u8) } } else { hw("T6 FAIL e0=" as *u8); hn(e0); hw("\n" as *u8) }
61
62 hw("NX-HUFFMAN-KAT " as *u8); hn(pass); hw("/6" as *u8)
63 if pass == 6 { hw(" GREEN\n" as *u8); return 0 }
64 hw(" RED\n" as *u8)
65 return 1
66}