nx_vtransform_dct2.nx source
↩ module page · 98 lines · 4688 B
1// nx_vtransform_dct2.nx -- ROYALTY-FREE integer DCT-II (4x4) for the sovereign video codec.
2// PATENT-CLEAN BY PROVENANCE: the literal Ahmed-Natarajan-Rao 1974 DCT-II basis cos((2n+1)*k*pi/8), evaluated
3// at scale 64 and rounded to integers -> matrix M, with UNIFORM scalar quantization. This is NOT H.264/AVC's
4// specific integer core ([1,1,1,1; 2,1,-1,-2; 1,-1,-1,1; 1,-2,2,-1]) and NOT its position-dependent Mf/Vi quant
5// tables (those are the AVC patent-pool technique), and NOT HEVC's 32x32-derived matrices. The DCT *itself* is
6// 1974 prior art -- CITED to the sovereign-fetched source knowledge/fetched/dct_provenance.raw ("Nasir Ahmed
7// ... in 1972 ... Natarajan ... Rao ... 1974"). Better energy compaction than Walsh-Hadamard on natural images
8// -> recovers the DCT RD win cleanly. Shape-compatible with nx_vtransform: vt2_fwd / vt2_inv / vt2_quant /
9// vt2_dequant operate on a 4x4 i64 block (row-major, 16 elements).
10// license_tier: ORIGINAL
11import "nx_syscalls.nx"
12
13// M = round( orthonormal DCT-II(N=4) * 64 ):
14// row0 [ 32, 32, 32, 32] (DC)
15// row1 [ 42, 17,-17,-42] (cos(pi/8)*sqrt(1/2)*64=41.8->42 ; cos(3pi/8)*sqrt(1/2)*64=17.3->17)
16// row2 [ 32,-32,-32, 32]
17// row3 [ 17,-42, 42,-17]
18// M*M^T ~= 4096*I (DC 4096, AC 4106 -> 0.24% gain imbalance, negligible for lossy). 2D round-trip ~= 4096^2 = 2^24.
19
20const DCT2_QSHIFT: i64 = 10 // q<<10: aligns the quant step with the WHT path's raw scale (DCT 2D fwd
21 // scale 16384 vs WHT 16 -> ratio 1024 = 2^10) so a given QP means ~the same
22 // bitrate on both transforms -> the RD comparison is fair.
23const DCT2_ISHIFT: i64 = 24 // inverse final descale (2D round-trip ~= 4096^2 = 2^24)
24const DCT2_IROUND: i64 = 8388608 // 1<<23, symmetric rounding for the inverse descale
25
26// 1D forward along (base, stride): Y[k] = sum_n M[k][n]*x[n]
27func vt2_1d_fwd(b: *i64, base: i64, st: i64) -> i64 {
28 let x0: i64 = b[base]
29 let x1: i64 = b[base+st]
30 let x2: i64 = b[base+2*st]
31 let x3: i64 = b[base+3*st]
32 b[base] = 32*(x0+x1+x2+x3)
33 b[base+st] = 42*x0 + 17*x1 - 17*x2 - 42*x3
34 b[base+2*st] = 32*(x0 - x1 - x2 + x3)
35 b[base+3*st] = 17*x0 - 42*x1 + 42*x2 - 17*x3
36 return 0
37}
38// 1D inverse along (base, stride): x[n] = sum_k M[k][n]*Y[k] (apply M^T)
39func vt2_1d_inv(b: *i64, base: i64, st: i64) -> i64 {
40 let y0: i64 = b[base]
41 let y1: i64 = b[base+st]
42 let y2: i64 = b[base+2*st]
43 let y3: i64 = b[base+3*st]
44 b[base] = 32*y0 + 42*y1 + 32*y2 + 17*y3
45 b[base+st] = 32*y0 + 17*y1 - 32*y2 - 42*y3
46 b[base+2*st] = 32*y0 - 17*y1 - 32*y2 + 42*y3
47 b[base+3*st] = 32*y0 - 42*y1 + 32*y2 - 17*y3
48 return 0
49}
50func vt2_fwd(blk: *i64) -> i64 {
51 var i: i64 = 0
52 while i < 4 { vt2_1d_fwd(blk, i*4, 1); i = i + 1 } // transform rows
53 i = 0
54 while i < 4 { vt2_1d_fwd(blk, i, 4); i = i + 1 } // transform columns
55 return 0
56}
57func vt2_inv(blk: *i64) -> i64 {
58 var i: i64 = 0
59 while i < 4 { vt2_1d_inv(blk, i, 4); i = i + 1 } // inverse columns
60 i = 0
61 while i < 4 { vt2_1d_inv(blk, i*4, 1); i = i + 1 } // inverse rows
62 i = 0
63 while i < 16 { // final descale (>>24) with symmetric rounding
64 let v: i64 = blk[i]
65 if v >= 0 { blk[i] = (v + DCT2_IROUND) >> DCT2_ISHIFT }
66 else { blk[i] = 0 - ((0 - v + DCT2_IROUND) >> DCT2_ISHIFT) }
67 i = i + 1
68 }
69 return 0
70}
71// QUANT ROUNDING OFFSET in 24ths of the step (rule-11; F1116 sweep 2026-07-28). 0 = the historical
72// floor-quant = WIDEST deadzone with dequant at the bin's LOWER EDGE (every nonzero systematically
73// under-reconstructed by ~d/2 mean). H.264 practice: f=d/6 (inter) .. d/3 (intra) narrows the deadzone
74// so reconstruction error centers. ENCODER-ONLY: dequant (and thus every decoder) is untouched; the
75// encoder reconstructs from the same levels, so enc==dec parity holds by construction at ANY value.
76const VC_QOFF_24: i64 = 10
77// deadzone scalar quant: blk[i] /= (q<<10), truncation toward zero (sign-explicit). returns nonzero count.
78func vt2_quant(blk: *i64, q: i64) -> i64 {
79 let d: i64 = q << DCT2_QSHIFT
80 let f0: i64 = (d * VC_QOFF_24) / 24
81 var nz: i64 = 0
82 var i: i64 = 0
83 while i < 16 {
84 let v: i64 = blk[i]
85 var r: i64 = 0
86 if v >= 0 { r = (v + f0) / d } else { r = 0 - ((0 - v + f0) / d) }
87 blk[i] = r
88 if r != 0 { nz = nz + 1 }
89 i = i + 1
90 }
91 return nz
92}
93func vt2_dequant(blk: *i64, q: i64) -> i64 {
94 let d: i64 = q << DCT2_QSHIFT
95 var i: i64 = 0
96 while i < 16 { blk[i] = blk[i] * d; i = i + 1 }
97 return 0
98}