1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//! Quantize-trailing-shift (qts) as a composable layer over `i16` samples.
//!
//! ADC samples are often multiples of a power of two (the low bits carry no
//! information). qts finds the largest right-shift `q` that loses none of
//! that information — every sample's low `q` bits are zero — and applies it
//! before further compression. The shift is lossless: [`unshift_inplace`]
//! restores the original values exactly.
//!
//! This is a fixed `i16`-only transform (unlike [`crate::delta`] /
//! [`crate::zigzag`], which are generic over several integer types) — it
//! exists specifically to feed the ex-zd pipeline, and there is only one
//! type it is ever applied to.
use Vec;
use Vec;
/// Find the largest `q` in `0..=max` such that every sample's low `q` bits are zero.
///
/// Returns `0` if no such shift exists (e.g. `samples` is empty, or any
/// sample has its lowest bit set).
///
/// # Examples
///
/// ```
/// # use svb::quantize::find_qts;
/// assert_eq!(find_qts(&[8i16, 16, -24], 5), 3);
/// assert_eq!(find_qts(&[8i16, 17, -24], 5), 0);
/// ```
/// Right-shift every sample by `q` (arithmetic shift), returning a new `Vec`.
///
/// # Examples
///
/// ```
/// # use svb::quantize::apply_shift;
/// assert_eq!(apply_shift(&[8i16, -24], 3), [1, -3]);
/// ```
/// Left-shift every sample by `q` in place, undoing [`apply_shift`].
///
/// `q` is masked to `0..=15` so the shift can never panic, even on a `q`
/// value read from untrusted/corrupted input.
///
/// # Examples
///
/// ```
/// # use svb::quantize::unshift_inplace;
/// let mut samples = [1i16, -3];
/// unshift_inplace(&mut samples, 3);
/// assert_eq!(samples, [8, -24]);
/// ```