1use crate::abac::{BitModel, Decoder, Encoder, UintModel};
20use crate::wavelet::{Band, Pyramid};
21
22pub const KB: usize = 14;
24pub const CAP: u16 = 65535;
26pub const NCLASS: usize = 10;
28
29pub trait Bits {
31 fn bit(&mut self, bit: bool, m: &mut BitModel) -> bool;
33 fn bitp(&mut self, bit: bool, p1: u32) -> bool;
35 fn uint(&mut self, v: u64, m: &mut UintModel) -> u64;
37 #[inline]
39 fn tag(&mut self, _t: usize) {}
40}
41
42#[derive(Default, Debug)]
45pub struct Meter {
46 pub bits: [f64; 8],
48 cur: usize,
49}
50
51impl Bits for Meter {
52 fn bit(&mut self, bit: bool, m: &mut BitModel) -> bool {
53 self.bits[self.cur] += crate::abac::cost_bits(bit, m.p1());
54 m.update(bit);
55 bit
56 }
57 fn bitp(&mut self, bit: bool, p1: u32) -> bool {
58 self.bits[self.cur] += crate::abac::cost_bits(bit, p1);
59 bit
60 }
61 fn uint(&mut self, v: u64, m: &mut UintModel) -> u64 {
62 let mut e = Encoder::new();
63 m.encode(&mut e, v);
64 self.bits[self.cur] += 8.0 * e.finish().len() as f64 - 32.0;
65 v
66 }
67 fn tag(&mut self, t: usize) {
68 self.cur = t;
69 }
70}
71
72impl Bits for Encoder {
73 #[inline]
74 fn bit(&mut self, bit: bool, m: &mut BitModel) -> bool {
75 self.encode(bit, m);
76 bit
77 }
78 #[inline]
79 fn bitp(&mut self, bit: bool, p1: u32) -> bool {
80 self.encode_p(bit, p1);
81 bit
82 }
83 fn uint(&mut self, v: u64, m: &mut UintModel) -> u64 {
84 m.encode(self, v);
85 v
86 }
87}
88
89impl Bits for Decoder<'_> {
90 #[inline]
91 fn bit(&mut self, _: bool, m: &mut BitModel) -> bool {
92 self.decode(m)
93 }
94 #[inline]
95 fn bitp(&mut self, _: bool, p1: u32) -> bool {
96 self.decode_p(p1)
97 }
98 fn uint(&mut self, _: u64, m: &mut UintModel) -> u64 {
99 m.decode(self)
100 }
101}
102
103#[derive(Clone, Copy, Debug, Default)]
105pub struct Feat {
106 pub nb: [u16; 8],
109 pub sg: [i8; 3],
111 pub par: u16,
113 pub pnb: u16,
115 pub class: u8,
117 pub mask: u8,
119 pub has_par: bool,
121 pub pm: u16,
123 pub sv: [i32; NSV],
126 pub pv: i32,
128}
129
130pub const NSV: usize = 18;
132
133pub fn band_class(b: &Band) -> u8 {
135 if b.mask == 0 {
136 return (NCLASS - 1) as u8;
137 }
138 let nh = b.mask.count_ones() as usize;
139 (b.level.min(2) * 3 + nh - 1) as u8
140}
141
142pub trait CoefModel {
144 fn code<B: Bits>(&mut self, b: &mut B, f: &Feat, v: i32) -> i32;
146}
147
148fn bucket(a: u32, th: &[u32]) -> usize {
149 th.iter().position(|&t| a <= t).unwrap_or(th.len())
150}
151
152const A_TH: [u32; 11] = [0, 1, 2, 3, 5, 7, 10, 14, 20, 30, 48];
153const NA: usize = A_TH.len() + 1;
154const P_TH: [u32; 4] = [0, 2, 6, 16];
155const NP: usize = P_TH.len() + 1;
156pub const NE: usize = 18;
158
159#[inline]
163pub fn mag_scale(f: &Feat) -> usize {
164 let n = f.nb.map(|v| v as u64);
165 let mut s = 2 * (n[0] + n[1] + n[2]) + n[3] + n[4] + n[5] + n[6];
166 let mut w = 10;
167 s += 2 * f.pm as u64;
168 if f.has_par {
169 s += 2 * f.par as u64;
170 w += 2;
171 }
172 let v = 1 + 2 * s / w;
173 (v.ilog2() as usize).min(NE - 1)
174}
175
176#[derive(Clone, Debug)]
178pub struct HandModel {
179 sig: Vec<BitModel>,
180 mag: Vec<BitModel>,
181 low: Vec<BitModel>,
182 esc: Vec<UintModel>,
183 sign: Vec<BitModel>,
184}
185
186impl Default for HandModel {
187 fn default() -> Self {
188 Self {
189 sig: vec![BitModel::default(); NCLASS * NA * NP],
190 mag: vec![BitModel::default(); NCLASS * NE * KB],
191 low: vec![BitModel::default(); NE * 4],
192 esc: vec![UintModel::default(); NCLASS],
193 sign: vec![BitModel::default(); NCLASS * 27],
194 }
195 }
196}
197
198#[inline]
200pub fn activity(f: &Feat) -> u32 {
201 let n = f.nb.map(|v| v.min(15) as u32);
202 2 * (n[0] + n[1] + n[2]) + n[3] + n[4] + n[5] + n[6] + n[7]
203}
204
205impl CoefModel for HandModel {
206 fn code<B: Bits>(&mut self, b: &mut B, f: &Feat, v: i32) -> i32 {
207 let c = f.class as usize;
208 let a = activity(f) + f.pm.min(15) as u32;
209 let pa = 4 * f.par.min(15) as u32 + f.pnb.min(60) as u32;
210 let ab = bucket(a, &A_TH);
211 let pb = if f.has_par {
212 1 + bucket(pa, &P_TH[..NP - 2])
213 } else {
214 0
215 };
216 let mag = v.unsigned_abs();
217 b.tag(0);
218 if !b.bit(mag > 0, &mut self.sig[(c * NA + ab) * NP + pb]) {
219 return 0;
220 }
221 b.tag(1);
222 let e = mag_scale(f);
223 let k = e.saturating_sub(2) as u32;
224 let r = mag.wrapping_sub(1);
227 let hi = r >> k;
228 let mut h = 0u32;
229 while (h as usize) < KB {
230 if !b.bit(hi > h, &mut self.mag[(c * NE + e) * KB + h as usize]) {
231 break;
232 }
233 h += 1;
234 }
235 if h as usize == KB {
236 h += b.uint(hi.wrapping_sub(h) as u64, &mut self.esc[c]) as u32;
237 }
238 let mut lo = 0u32;
239 b.tag(2);
240 for j in (0..k).rev() {
241 let bit = (r >> j) & 1 == 1;
242 let pos = (k - 1 - j) as usize;
243 let got = if pos < 2 {
244 b.bit(
245 bit,
246 &mut self.low[(e * 2 + pos) * 2 + (pos == 1 && lo & 1 == 1) as usize],
247 )
248 } else {
249 b.bitp(bit, crate::abac::ONE / 2)
250 };
251 lo = (lo << 1) | got as u32;
252 }
253 let m = 1 + ((h << k) | lo);
254 b.tag(3);
255 let sctx = c * 27 + ((f.sg[0] + 1) * 9 + (f.sg[1] + 1) * 3 + (f.sg[2] + 1)) as usize;
256 let neg = b.bit(v < 0, &mut self.sign[sctx]);
257 if neg {
258 -(m as i32)
259 } else {
260 m as i32
261 }
262 }
263}
264
265#[inline]
267pub fn features(
268 p: &Pyramid,
269 bi: usize,
270 pbi: Option<usize>,
271 q: &[i32],
272 z: usize,
273 y: usize,
274 x: usize,
275) -> Feat {
276 let b = &p.bands[bi];
277 let [_, ny, nx] = p.dims;
278 let at = |z: usize, y: usize, x: usize| q[(z * ny + y) * nx + x];
279 let mag = |v: i32| (v.unsigned_abs().min(CAP as u32)) as u16;
280 let sgn = |v: i32| v.signum() as i8;
281 let (z0, y0, x0) = (b.start[0], b.start[1], b.start[2]);
282 let x1 = b.end[2];
283 let mut f = Feat {
284 class: band_class(b),
285 mask: b.mask,
286 ..Default::default()
287 };
288 if x > x0 {
289 let w = at(z, y, x - 1);
290 {
291 let t = w;
292 f.nb[0] = mag(t);
293 f.sv[0] = t;
294 }
295 f.sg[0] = sgn(w);
296 if x > x0 + 1 {
297 {
298 let t = at(z, y, x - 2);
299 f.nb[7] = mag(t);
300 f.sv[7] = t;
301 }
302 }
303 }
304 if y > y0 + 1 {
305 f.sv[9] = at(z, y - 2, x);
306 }
307 if z > z0 + 1 {
308 f.sv[10] = at(z - 2, y, x);
309 }
310 if z > z0 && x + 1 < x1 {
311 f.sv[11] = at(z - 1, y, x + 1);
312 }
313 if y > y0 {
314 let n = at(z, y - 1, x);
315 {
316 let t = n;
317 f.nb[1] = mag(t);
318 f.sv[1] = t;
319 }
320 f.sg[1] = sgn(n);
321 if x > x0 {
322 {
323 let t = at(z, y - 1, x - 1);
324 f.nb[3] = mag(t);
325 f.sv[3] = t;
326 }
327 }
328 if x + 1 < x1 {
329 {
330 let t = at(z, y - 1, x + 1);
331 f.nb[4] = mag(t);
332 f.sv[4] = t;
333 }
334 }
335 }
336 if z > z0 {
337 let u = at(z - 1, y, x);
338 {
339 let t = u;
340 f.nb[2] = mag(t);
341 f.sv[2] = t;
342 }
343 f.sg[2] = sgn(u);
344 if x > x0 {
345 {
346 let t = at(z - 1, y, x - 1);
347 f.nb[5] = mag(t);
348 f.sv[5] = t;
349 }
350 }
351 if y > y0 {
352 {
353 let t = at(z - 1, y - 1, x);
354 f.nb[6] = mag(t);
355 f.sv[6] = t;
356 }
357 }
358 }
359 if let Some(pi) = pbi {
360 let pb = &p.bands[pi];
361 let pp = p.parent_pos(b, pb, [z, y, x]);
362 f.has_par = true;
363 {
364 let t = at(pp[0], pp[1], pp[2]);
365 f.par = mag(t);
366 f.sv[8] = t;
367 }
368 let mut s = 0u32;
369 for a in 0..3 {
370 let mut lo = pp;
371 if lo[a] > pb.start[a] {
372 lo[a] -= 1;
373 let t = at(lo[0], lo[1], lo[2]);
374 f.sv[12 + 2 * a] = t;
375 s += t.unsigned_abs().min(CAP as u32);
376 }
377 let mut hi = pp;
378 if hi[a] + 1 < pb.end[a] {
379 hi[a] += 1;
380 let t = at(hi[0], hi[1], hi[2]);
381 f.sv[13 + 2 * a] = t;
382 s += t.unsigned_abs().min(CAP as u32);
383 }
384 }
385 f.pnb = s.min(CAP as u32) as u16;
386 }
387 f
388}
389
390pub const NTAP: usize = 7;
392pub const PSHIFT: u32 = 12;
394
395#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
402pub struct Pred {
403 pub on: bool,
405 pub w: [i16; NTAP],
407}
408
409#[inline]
410fn taps(
411 p: &Pyramid,
412 bi: usize,
413 pbi: Option<usize>,
414 q: &[i32],
415 z: usize,
416 y: usize,
417 x: usize,
418) -> [i32; NTAP] {
419 let b = &p.bands[bi];
420 let [_, ny, nx] = p.dims;
421 let at = |z: usize, y: usize, x: usize| q[(z * ny + y) * nx + x];
422 let (zi, yi, xi) = (z > b.start[0], y > b.start[1], x > b.start[2]);
423 let mut t = [0i32; NTAP];
424 if xi {
425 t[0] = at(z, y, x - 1);
426 }
427 if yi {
428 t[1] = at(z, y - 1, x);
429 if xi {
430 t[3] = at(z, y - 1, x - 1);
431 }
432 }
433 if zi {
434 t[2] = at(z - 1, y, x);
435 if xi {
436 t[4] = at(z - 1, y, x - 1);
437 }
438 if yi {
439 t[5] = at(z - 1, y - 1, x);
440 }
441 }
442 if let Some(pi) = pbi {
443 let pb = &p.bands[pi];
444 let pp = p.parent_pos(b, pb, [z, y, x]);
445 t[6] = at(pp[0], pp[1], pp[2]);
446 }
447 t
448}
449
450#[inline]
451fn predict(w: &[i16; NTAP], t: &[i32; NTAP]) -> i32 {
452 let s: i64 = w.iter().zip(t).map(|(&a, &b)| a as i64 * b as i64).sum();
453 ((s + (1 << (PSHIFT - 1))) >> PSHIFT).clamp(-(1 << 30), 1 << 30) as i32
454}
455
456pub fn fit_predictors(p: &Pyramid, q: &[i32]) -> Vec<Pred> {
460 let [_, ny, nx] = p.dims;
461 (0..p.bands.len())
462 .map(|bi| {
463 let band = &p.bands[bi];
464 let pbi = p.parent_band(bi);
465 let mut g = [[0.0f64; NTAP]; NTAP];
466 let mut h = [0.0f64; NTAP];
467 let mut n = 0usize;
468 for z in band.start[0]..band.end[0] {
469 for y in band.start[1]..band.end[1] {
470 for x in band.start[2]..band.end[2] {
471 let t = taps(p, bi, pbi, q, z, y, x);
472 let v = q[(z * ny + y) * nx + x] as f64;
473 if v == 0.0 && t.iter().all(|&a| a == 0) {
474 continue;
475 }
476 n += 1;
477 for i in 0..NTAP {
478 h[i] += t[i] as f64 * v;
479 for j in 0..NTAP {
480 g[i][j] += t[i] as f64 * t[j] as f64;
481 }
482 }
483 }
484 }
485 }
486 if n < 32 {
487 return Pred::default();
488 }
489 let mut a = g;
491 let mut r = h;
492 for i in 0..NTAP {
493 a[i][i] += 1e-3 * (g[i][i] + 1.0);
494 }
495 for c in 0..NTAP {
496 let piv = a[c][c];
497 if piv.abs() < 1e-12 {
498 continue;
499 }
500 for rr in 0..NTAP {
501 if rr != c {
502 let f = a[rr][c] / piv;
503 for k in 0..NTAP {
504 a[rr][k] -= f * a[c][k];
505 }
506 r[rr] -= f * r[c];
507 }
508 }
509 }
510 let mut w = [0i16; NTAP];
511 for i in 0..NTAP {
512 let wi = if a[i][i].abs() > 1e-12 {
513 r[i] / a[i][i]
514 } else {
515 0.0
516 };
517 w[i] = (wi * (1 << PSHIFT) as f64).round().clamp(-32767.0, 32767.0) as i16;
518 }
519 let (mut c0, mut c1) = (0.0f64, 0.0f64);
520 for z in band.start[0]..band.end[0] {
521 for y in band.start[1]..band.end[1] {
522 for x in band.start[2]..band.end[2] {
523 let v = q[(z * ny + y) * nx + x];
524 let pr = predict(&w, &taps(p, bi, pbi, q, z, y, x));
525 c0 += (1.0 + v.unsigned_abs() as f64).log2();
526 c1 += (1.0 + (v - pr).unsigned_abs() as f64).log2();
527 }
528 }
529 }
530 if c1 < 0.98 * c0 {
531 Pred { on: true, w }
532 } else {
533 Pred::default()
534 }
535 })
536 .collect()
537}
538
539pub fn write_preds(w: &mut crate::bitio::ByteWriter, preds: &[Pred]) {
541 for pr in preds {
542 w.u8(pr.on as u8);
543 if pr.on {
544 for &v in &pr.w {
545 w.svarint(v as i64);
546 }
547 }
548 }
549}
550
551pub fn read_preds(
553 r: &mut crate::bitio::ByteReader,
554 nbands: usize,
555) -> Result<Vec<Pred>, crate::bitio::DecodeError> {
556 (0..nbands)
557 .map(|_| {
558 let mut pr = Pred {
559 on: r.u8()? != 0,
560 ..Default::default()
561 };
562 if pr.on {
563 for v in pr.w.iter_mut() {
564 *v = r.svarint()?.clamp(-32767, 32767) as i16;
565 }
566 }
567 Ok(pr)
568 })
569 .collect()
570}
571
572fn traverse(
577 p: &Pyramid,
578 q: &mut [i32],
579 res: &mut [i32],
580 preds: &[Pred],
581 mut f: impl FnMut(&Feat, i32, i32) -> i32,
582) {
583 let [_, ny, nx] = p.dims;
584 for bi in 0..p.bands.len() {
585 let pbi = p.parent_band(bi);
586 let band = p.bands[bi].clone();
587 let pr = preds.get(bi).copied().unwrap_or_default();
588 for z in band.start[0]..band.end[0] {
589 for y in band.start[1]..band.end[1] {
590 for x in band.start[2]..band.end[2] {
591 let i = (z * ny + y) * nx + x;
592 let mut ft = features(p, bi, pbi, res, z, y, x);
593 let pv = if pr.on {
594 predict(&pr.w, &taps(p, bi, pbi, q, z, y, x))
595 } else {
596 0
597 };
598 ft.pm = pv.unsigned_abs().min(CAP as u32) as u16;
599 ft.pv = pv;
600 let r = f(&ft, pv, q[i].wrapping_sub(pv));
601 res[i] = r;
602 q[i] = r + pv;
603 }
604 }
605 }
606 }
607}
608
609fn tile_edge(nd: usize) -> usize {
612 match nd {
613 0 | 1 => 256,
614 2 => 16,
615 _ => 8,
616 }
617}
618
619fn band_tiles(b: &crate::wavelet::Band, nd: usize) -> ([usize; 3], [usize; 3]) {
621 let t = tile_edge(nd);
622 let mut e = [1usize; 3];
623 let mut n = [1usize; 3];
624 for k in 0..3 {
625 let len = b.end[k] - b.start[k];
626 if len > 1 {
627 e[k] = t;
628 n[k] = len.div_ceil(t);
629 }
630 }
631 (e, n)
632}
633
634pub fn tile_live(p: &Pyramid, q: &[i32], preds: &[Pred]) -> Vec<Vec<bool>> {
637 let [_, ny, nx] = p.dims;
638 let nd = p.dims.iter().filter(|&&d| d > 1).count();
639 let mut qq = q.to_vec();
640 let mut res = vec![0i32; q.len()];
641 traverse(p, &mut qq, &mut res, preds, |_, _, r| r);
642 p.bands
643 .iter()
644 .map(|b| {
645 let (e, n) = band_tiles(b, nd);
646 let mut live = vec![false; n[0] * n[1] * n[2]];
647 for z in b.start[0]..b.end[0] {
648 for y in b.start[1]..b.end[1] {
649 for x in b.start[2]..b.end[2] {
650 if res[(z * ny + y) * nx + x] != 0 {
651 let t = (((z - b.start[0]) / e[0]) * n[1] + (y - b.start[1]) / e[1])
652 * n[2]
653 + (x - b.start[2]) / e[2];
654 live[t] = true;
655 }
656 }
657 }
658 }
659 live
660 })
661 .collect()
662}
663
664pub fn code_bands_tiled<B: Bits, M: CoefModel>(
671 p: &Pyramid,
672 q: &mut [i32],
673 preds: &[Pred],
674 b: &mut B,
675 model: &mut M,
676 live: Option<&[Vec<bool>]>,
677) {
678 let [_, ny, nx] = p.dims;
679 let nd = p.dims.iter().filter(|&&d| d > 1).count();
680 let mut res = vec![0i32; q.len()];
681 let mut flag = [BitModel::new(1 << 15); NCLASS * 2];
682 for bi in 0..p.bands.len() {
683 let pbi = p.parent_band(bi);
684 let band = p.bands[bi].clone();
685 let (e, n) = band_tiles(&band, nd);
686 let c = band_class(&band) as usize;
687 let mut prev = 1usize;
688 let alive: Vec<bool> = (0..n[0] * n[1] * n[2])
689 .map(|t| {
690 let v = live.is_some_and(|l| l[bi][t]);
691 let v = b.bit(v, &mut flag[c * 2 + prev]);
692 prev = v as usize;
693 v
694 })
695 .collect();
696 let pr = preds.get(bi).copied().unwrap_or_default();
697 for z in band.start[0]..band.end[0] {
698 for y in band.start[1]..band.end[1] {
699 for x in band.start[2]..band.end[2] {
700 let i = (z * ny + y) * nx + x;
701 let t = (((z - band.start[0]) / e[0]) * n[1] + (y - band.start[1]) / e[1])
702 * n[2]
703 + (x - band.start[2]) / e[2];
704 let pv = if pr.on {
705 predict(&pr.w, &taps(p, bi, pbi, q, z, y, x))
706 } else {
707 0
708 };
709 let r = if alive[t] {
710 let mut ft = features(p, bi, pbi, &res, z, y, x);
711 ft.pm = pv.unsigned_abs().min(CAP as u32) as u16;
712 ft.pv = pv;
713 model.code(b, &ft, q[i].wrapping_sub(pv))
714 } else {
715 0
716 };
717 res[i] = r;
718 q[i] = r.wrapping_add(pv);
719 }
720 }
721 }
722 }
723}
724
725pub fn code_bands<B: Bits, M: CoefModel>(
729 p: &Pyramid,
730 q: &mut [i32],
731 preds: &[Pred],
732 b: &mut B,
733 model: &mut M,
734) {
735 let mut res = vec![0i32; q.len()];
736 traverse(p, q, &mut res, preds, |f, _, r| model.code(b, f, r));
737}
738
739pub fn visit<F: FnMut(&Feat, i32)>(p: &Pyramid, q: &[i32], preds: &[Pred], mut f: F) {
742 let mut qq = q.to_vec();
743 let mut res = vec![0i32; q.len()];
744 traverse(p, &mut qq, &mut res, preds, |ft, _, r| {
745 f(ft, r);
746 r
747 });
748}
749
750pub fn encode_hand(p: &Pyramid, q: &[i32], preds: &[Pred]) -> Vec<u8> {
752 let mut e = Encoder::new();
753 let mut qq = q.to_vec();
754 code_bands(p, &mut qq, preds, &mut e, &mut HandModel::default());
755 e.finish()
756}
757
758pub fn decode_hand(p: &Pyramid, bytes: &[u8], preds: &[Pred]) -> Vec<i32> {
760 let mut d = Decoder::new(bytes);
761 let mut q = vec![0i32; p.len()];
762 code_bands(p, &mut q, preds, &mut d, &mut HandModel::default());
763 q
764}
765
766#[cfg(test)]
767mod tests {
768 use super::*;
769 use crate::wavelet::{forward_97, MAX_LEVELS};
770
771 #[test]
772 fn round_trip_hand_model() {
773 let d = [12, 20, 33];
774 let p = Pyramid::new(d, MAX_LEVELS);
775 let mut x: Vec<f64> = (0..p.len())
776 .map(|i| ((i as f64) * 0.013).sin() * 100.0 + (i % 17) as f64)
777 .collect();
778 forward_97(&p, &mut x);
779 let mut q: Vec<i32> = x.iter().map(|v| (v / 0.7).round() as i32).collect();
780 q[5] = 1_000_000; q[77] = -123_456;
782 for preds in [vec![], fit_predictors(&p, &q)] {
783 let bytes = encode_hand(&p, &q, &preds);
784 assert_eq!(decode_hand(&p, &bytes, &preds), q);
785 assert_eq!(encode_hand(&p, &q, &preds), bytes, "deterministic");
786 }
787 }
788}