replace vec.truncate(0) with vec.clear()
[nihav.git] / nihav-codec-support / src / vq / generic_elbg.rs
index 01feaa852084c7cbc30c95de74337de62883d87a..d6c30d2a6de791d9d39268ea7c8d17a05810a53d 100644 (file)
@@ -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<T: VQElement+Default, TS: VQElementSum<T>> ELBG<T, TS> {
         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,19 +177,29 @@ impl<T: VQElement+Default, TS: VQElementSum<T>> ELBG<T, TS> {
         entries.push(Entry { val: lastval, count: run });
         drop(elements);
 
+        let mut cw_count = 0;
         let mut low_u:  Vec<usize> = Vec::with_capacity(self.clusters.len());
         let mut high_u: Vec<usize> = Vec::with_capacity(self.clusters.len());
         let mut rng = RNG::new();
         let mut iterations = 0usize;
         let mut do_elbg_step = true;
-        while (iterations < 20) && (dist < prev_dist - prev_dist / 1000) {
+        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<T: VQElement+Default, TS: VQElementSum<T>> ELBG<T, TS> {
             }
 
             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<T: VQElement+Default, TS: VQElementSum<T>> ELBG<T, TS> {
             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<T: VQElement+Default, TS: VQElementSum<T>> ELBG<T, TS> {
             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
     }
 }