X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-codec-support%2Fsrc%2Fvq%2Fgeneric_elbg.rs;h=d6c30d2a6de791d9d39268ea7c8d17a05810a53d;hp=91a56586d81bc1c619ddecde52d7edf6e8d6b3e0;hb=379524159c95f1c3639976ccf35f9d47cd9732ac;hpb=c5a6ae875be31f47bc318a6dc5b1a0209b9b66f7 diff --git a/nihav-codec-support/src/vq/generic_elbg.rs b/nihav-codec-support/src/vq/generic_elbg.rs index 91a5658..d6c30d2 100644 --- a/nihav-codec-support/src/vq/generic_elbg.rs +++ b/nihav-codec-support/src/vq/generic_elbg.rs @@ -9,7 +9,7 @@ impl RNG { fn new() -> Self { Self { seed: 0x1234 } } fn next(&mut self) -> u8 { if (self.seed & 0x8000) != 0 { - self.seed = (self.seed & 0x7FFF) * 2 ^ 0x1B2B; + self.seed = ((self.seed & 0x7FFF) * 2) ^ 0x1B2B; } else { self.seed <<= 1; } @@ -148,9 +148,10 @@ impl> ELBG { clu1.calc_dist(); clu0.dist + clu1.dist } - pub fn quantise(&mut self, src: &[T], dst: &mut [T]) { - if src.len() < 1 || dst.len() != self.clusters.len() { - return; + #[allow(clippy::cognitive_complexity)] + pub fn quantise(&mut self, src: &[T], dst: &mut [T]) -> usize { + if src.is_empty() || dst.len() != self.clusters.len() { + return 0; } let mut old_cb = vec![T::default(); self.clusters.len()]; let mut prev_dist = std::u64::MAX; @@ -176,6 +177,7 @@ impl> ELBG { entries.push(Entry { val: lastval, count: run }); drop(elements); + let mut cw_count = 0; let mut low_u: Vec = Vec::with_capacity(self.clusters.len()); let mut high_u: Vec = Vec::with_capacity(self.clusters.len()); let mut rng = RNG::new(); @@ -183,12 +185,21 @@ impl> ELBG { let mut do_elbg_step = true; while (iterations < 20) && (dist < prev_dist - prev_dist / 100) { prev_dist = dist; - for i in 0..dst.len() { - old_cb[i] = self.clusters[i].centroid; - self.clusters[i].reset(); + + cw_count = 0; + for cluster in self.clusters.iter() { + if cluster.count == 0 { + continue; + } + old_cb[cw_count] = cluster.centroid; + cw_count += 1; + } + for cluster in self.clusters.iter_mut() { + cluster.reset(); } + // put points into the nearest clusters - indices.truncate(0); + indices.clear(); for entry in entries.iter() { let mut bestidx = 0; let mut bestdist = std::u32::MAX; @@ -219,8 +230,8 @@ impl> ELBG { } let dmean = dist / (dst.len() as u64); - low_u.truncate(0); - high_u.truncate(0); + low_u.clear(); + high_u.clear(); let mut used = vec![false; dst.len()]; for (i, cluster) in self.clusters.iter().enumerate() { if cluster.dist < dmean { @@ -234,7 +245,7 @@ impl> ELBG { if do_elbg_step { do_elbg_step = false; for low_idx in low_u.iter() { - if high_u.len() == 0 { + if high_u.is_empty() { break; } let high_idx_idx = (rng.next() as usize) % high_u.len(); @@ -279,10 +290,16 @@ impl> ELBG { iterations += 1; } if dist < prev_dist { - for i in 0..dst.len() { - old_cb[i] = self.clusters[i].centroid; + cw_count = 0; + for cluster in self.clusters.iter() { + if cluster.count == 0 { + continue; + } + old_cb[cw_count] = cluster.centroid; + cw_count += 1; } } dst.copy_from_slice(&old_cb); + cw_count } }