Optimize single step Smoother::next()
By not having to take multiple steps into account.
This commit is contained in:
parent
dd320c4c1f
commit
17a928647e
|
@ -237,7 +237,30 @@ impl<T: Smoothable> Smoother<T> {
|
||||||
#[allow(clippy::should_implement_trait)]
|
#[allow(clippy::should_implement_trait)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next(&self) -> T {
|
pub fn next(&self) -> T {
|
||||||
self.next_step(1)
|
// NOTE: This used to be implemented in terms of `next_step()`, but this is more efficient
|
||||||
|
// for the common use case of single steps
|
||||||
|
if self.steps_left.load(Ordering::Relaxed) > 0 {
|
||||||
|
let current = self.current.load(Ordering::Relaxed);
|
||||||
|
let target = self.target.to_f32();
|
||||||
|
|
||||||
|
// The number of steps usually won't fit exactly, so make sure we don't end up with
|
||||||
|
// quantization errors on overshoots or undershoots. We also need to account for the
|
||||||
|
// possibility that we only have `n < steps` steps left. This is especially important
|
||||||
|
// for the `Exponential` smoothing style, since that won't reach the target value
|
||||||
|
// exactly.
|
||||||
|
let old_steps_left = self.steps_left.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
let new = if old_steps_left == 1 {
|
||||||
|
self.steps_left.store(0, Ordering::Relaxed);
|
||||||
|
target
|
||||||
|
} else {
|
||||||
|
self.style.next(current, target, self.step_size)
|
||||||
|
};
|
||||||
|
self.current.store(new, Ordering::Relaxed);
|
||||||
|
|
||||||
|
T::from_f32(new)
|
||||||
|
} else {
|
||||||
|
self.target
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`next()`][Self::next()], but with the ability to skip forward in the smoother.
|
/// [`next()`][Self::next()], but with the ability to skip forward in the smoother.
|
||||||
|
|
Loading…
Reference in a new issue