1
0
Fork 0

Clean up optimized block smoothing

This is easier to follow and avoids computing and subsequently
overwriting the last smoothed value.
This commit is contained in:
Robbert van der Helm 2022-09-05 14:00:56 +02:00
parent a21daef96b
commit 7f33f172cb

View file

@ -337,26 +337,30 @@ impl<T: Smoothable> Smoother<T> {
let steps_left = self.steps_left.load(Ordering::Relaxed) as usize; let steps_left = self.steps_left.load(Ordering::Relaxed) as usize;
let num_smoothed_values = block_values.len().min(steps_left); let num_smoothed_values = block_values.len().min(steps_left);
if num_smoothed_values > 0 { 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 mut current = self.current.load(Ordering::Relaxed);
let target = self.target.to_f32(); 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 { 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(); current = target.to_f32();
block_values[num_smoothed_values - 1..].fill(self.target); block_values[num_smoothed_values - 1] = self.target;
} else { } 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.current.store(current, Ordering::Relaxed);
self.steps_left self.steps_left
.fetch_sub(num_smoothed_values as i32, Ordering::Relaxed); .fetch_sub(num_smoothed_values as i32, Ordering::Relaxed);
@ -395,34 +399,38 @@ impl<T: Smoothable> Smoother<T> {
if num_smoothed_values > 0 { if num_smoothed_values > 0 {
let mut current = self.current.load(Ordering::Relaxed); let mut current = self.current.load(Ordering::Relaxed);
for (idx, value) in block_values // See `next_block_exact()` for more details
.iter_mut()
.enumerate()
.take(num_smoothed_values)
{
current = self.style.next(current, target, self.step_size);
*value = f(idx, current);
}
if num_smoothed_values == steps_left { if num_smoothed_values == steps_left {
current = target.to_f32();
for (idx, value) in block_values for (idx, value) in block_values
.iter_mut() .iter_mut()
.enumerate() .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 { } else {
for (idx, value) in block_values for (idx, value) in block_values
.iter_mut() .iter_mut()
.enumerate() .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.current.store(current, Ordering::Relaxed);
self.steps_left self.steps_left
.fetch_sub(num_smoothed_values as i32, Ordering::Relaxed); .fetch_sub(num_smoothed_values as i32, Ordering::Relaxed);