From 7f33f172cb66676deb50123e32ebd68f766470b4 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 5 Sep 2022 14:00:56 +0200 Subject: [PATCH] Clean up optimized block smoothing This is easier to follow and avoids computing and subsequently overwriting the last smoothed value. --- src/param/smoothing.rs | 60 ++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/param/smoothing.rs b/src/param/smoothing.rs index 284f8ea6..4897b4f8 100644 --- a/src/param/smoothing.rs +++ b/src/param/smoothing.rs @@ -337,26 +337,30 @@ impl Smoother { let steps_left = self.steps_left.load(Ordering::Relaxed) as usize; let num_smoothed_values = block_values.len().min(steps_left); if num_smoothed_values > 0 { - // This is the same as calling `next()` `num_smoothed_values` times, but with some - // conditionals optimized out let mut current = self.current.load(Ordering::Relaxed); let target = self.target.to_f32(); - block_values[..num_smoothed_values].fill_with(|| { - current = self.style.next(current, target, self.step_size); - T::from_f32(current) - }); - - // In `next()` the last step snaps the value to the target value. Since we're computing - // many values in a row, we'll just overwrite the last value with the target value - // instead to avoid the conditional. if num_smoothed_values == steps_left { + // This is the same as calling `next()` `num_smoothed_values` times, but with some + // conditionals optimized out + block_values[..num_smoothed_values - 1].fill_with(|| { + current = self.style.next(current, target, self.step_size); + T::from_f32(current) + }); + + // In `next()` the last step snaps the value to the target value, so we'll do the + // same thing here current = target.to_f32(); - block_values[num_smoothed_values - 1..].fill(self.target); + block_values[num_smoothed_values - 1] = self.target; } else { - block_values[num_smoothed_values..].fill(self.target); + block_values[..num_smoothed_values].fill_with(|| { + current = self.style.next(current, target, self.step_size); + T::from_f32(current) + }); } + block_values[num_smoothed_values..].fill(self.target); + self.current.store(current, Ordering::Relaxed); self.steps_left .fetch_sub(num_smoothed_values as i32, Ordering::Relaxed); @@ -395,34 +399,38 @@ impl Smoother { if num_smoothed_values > 0 { let mut current = self.current.load(Ordering::Relaxed); - for (idx, value) in block_values - .iter_mut() - .enumerate() - .take(num_smoothed_values) - { - current = self.style.next(current, target, self.step_size); - *value = f(idx, current); - } - + // See `next_block_exact()` for more details if num_smoothed_values == steps_left { - current = target.to_f32(); for (idx, value) in block_values .iter_mut() .enumerate() - .skip(num_smoothed_values - 1) + .take(num_smoothed_values - 1) { - *value = f(idx, target); + current = self.style.next(current, target, self.step_size); + *value = f(idx, current); } + + current = target.to_f32(); + block_values[num_smoothed_values - 1] = f(num_smoothed_values - 1, target); } else { for (idx, value) in block_values .iter_mut() .enumerate() - .skip(num_smoothed_values) + .take(num_smoothed_values) { - *value = f(idx, target); + current = self.style.next(current, target, self.step_size); + *value = f(idx, current); } } + for (idx, value) in block_values + .iter_mut() + .enumerate() + .skip(num_smoothed_values) + { + *value = f(idx, target); + } + self.current.store(current, Ordering::Relaxed); self.steps_left .fetch_sub(num_smoothed_values as i32, Ordering::Relaxed);