use super::Signal;
use core::marker::PhantomData;
#[cfg(any(feature = "num-libm", feature = "num-std"))]
use num_traits::{Float, FloatConst, FromPrimitive, One, Zero};
#[derive(Clone)]
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Ease<S>
where
S: Signal,
{
pub(super) signal: S,
pub(super) prev: S::Type,
pub(super) inv_amount: S::Type,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Signal for Ease<S>
where
S: Signal,
S::Type: Float,
{
type Type = S::Type;
fn next(&mut self) -> Self::Type {
let next = self.prev + self.inv_amount * (self.signal.next() - self.prev);
core::mem::replace(&mut self.prev, next)
}
}
#[derive(Clone)]
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Lerp<A, B>
where
A: Signal,
{
pub(super) a: A,
pub(super) b: B,
pub(super) t: A::Type,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<A, B> Signal for Lerp<A, B>
where
A: Signal,
B: Signal<Type = A::Type>,
A::Type: Float,
{
type Type = A::Type;
fn next(&mut self) -> Self::Type {
let a = self.a.next();
let b = self.b.next();
a + self.t * (b - a)
}
}
macro_rules! signal_for_bin_op {
($name:tt, $f:tt) => {
#[derive(Clone)]
pub struct $name<T, L, R> {
pub(super) left: L,
pub(super) right: R,
pub(super) _marker: PhantomData<T>,
}
impl<L, R, RefL, RefR, T> Signal for $name<T, L, R>
where
T: num_traits::$name,
RefL: AsRef<T>,
RefR: AsRef<T>,
L: Signal<Type = RefL>,
R: Signal<Type = RefR>,
{
type Type = T;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::$name::$f(self.left.next().as_ref(), self.right.next().as_ref())
}
}
};
}
signal_for_bin_op!(WrappingAdd, wrapping_add);
signal_for_bin_op!(WrappingSub, wrapping_sub);
signal_for_bin_op!(WrappingMul, wrapping_mul);
signal_for_bin_op!(SaturatingAdd, saturating_add);
signal_for_bin_op!(SaturatingSub, saturating_sub);
signal_for_bin_op!(SaturatingMul, saturating_mul);
macro_rules! signal_for_bin_op_sh {
($name:tt, $f:tt) => {
#[derive(Clone)]
pub struct $name<T, L, R> {
pub(super) left: L,
pub(super) right: R,
pub(super) _marker: PhantomData<T>,
}
impl<L, R, RefL, T> Signal for $name<T, L, R>
where
T: num_traits::$name,
RefL: AsRef<T>,
L: Signal<Type = RefL>,
R: Signal<Type = u32>,
{
type Type = T;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::$name::$f(self.left.next().as_ref(), self.right.next())
}
}
};
}
signal_for_bin_op_sh!(WrappingShr, wrapping_shr);
signal_for_bin_op_sh!(WrappingShl, wrapping_shl);
macro_rules! signal_for_bin_op_checked {
($name:tt, $f:tt) => {
#[derive(Clone)]
pub struct $name<T, L, R> {
pub(super) left: L,
pub(super) right: R,
pub(super) _marker: PhantomData<T>,
}
impl<L, R, RefL, RefR, T> Signal for $name<T, L, R>
where
T: num_traits::$name,
RefL: AsRef<T>,
RefR: AsRef<T>,
L: Signal<Type = RefL>,
R: Signal<Type = RefR>,
{
type Type = Option<T>;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::$name::$f(self.left.next().as_ref(), self.right.next().as_ref())
}
}
};
}
signal_for_bin_op_checked!(CheckedAdd, checked_add);
signal_for_bin_op_checked!(CheckedSub, checked_sub);
signal_for_bin_op_checked!(CheckedMul, checked_mul);
macro_rules! signal_for_bin_op_sh_checked {
($name:tt, $f:tt) => {
#[derive(Clone)]
pub struct $name<T, L, R> {
pub(super) left: L,
pub(super) right: R,
pub(super) _marker: PhantomData<T>,
}
impl<L, R, RefL, T> Signal for $name<T, L, R>
where
T: num_traits::$name,
RefL: AsRef<T>,
L: Signal<Type = RefL>,
R: Signal<Type = u32>,
{
type Type = Option<T>;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::$name::$f(self.left.next().as_ref(), self.right.next())
}
}
};
}
signal_for_bin_op_sh_checked!(CheckedShr, checked_shr);
signal_for_bin_op_sh_checked!(CheckedShl, checked_shl);
#[derive(Clone)]
pub struct Inv<S> {
pub(super) signal: S,
}
impl<S> Signal for Inv<S>
where
S: Signal,
S::Type: num_traits::Inv,
{
type Type = <S::Type as num_traits::Inv>::Output;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::Inv::inv(self.signal.next())
}
}
#[derive(Clone)]
pub struct MulAdd<S, M, A> {
pub(super) signal: S,
pub(super) mul: M,
pub(super) add: A,
}
impl<S, M, A> Signal for MulAdd<S, M, A>
where
S: Signal,
M: Signal,
A: Signal,
S::Type: num_traits::MulAdd<M::Type, A::Type>,
{
type Type = <S::Type as num_traits::MulAdd<M::Type, A::Type>>::Output;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::MulAdd::mul_add(self.signal.next(), self.mul.next(), self.add.next())
}
}
#[derive(Clone)]
pub struct Pow<S, E> {
pub(super) signal: S,
pub(super) exp: E,
}
impl<S, E> Signal for Pow<S, E>
where
S: Signal,
E: Signal,
S::Type: num_traits::Pow<E::Type>,
{
type Type = <S::Type as num_traits::Pow<E::Type>>::Output;
#[inline]
fn next(&mut self) -> Self::Type {
num_traits::Pow::pow(self.signal.next(), self.exp.next())
}
}
#[derive(Clone)]
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Interpolate<S, I>
where
S: Signal,
{
pub(super) signal: S,
pub(super) length: usize,
pub(super) count: usize,
pub(super) a: S::Type,
pub(super) b: S::Type,
pub(super) interpolate: I,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S, I> Signal for Interpolate<S, I>
where
S: Signal,
I: FnMut(S::Type, S::Type, S::Type) -> S::Type,
S::Type: Float + FromPrimitive,
{
type Type = S::Type;
fn next(&mut self) -> Self::Type {
let val = (self.interpolate)(
self.a.clone(),
self.b.clone(),
S::Type::from_usize(self.count).unwrap() / S::Type::from_usize(self.length).unwrap(),
);
self.count += 1;
if self.count >= self.length {
self.count = 0;
self.a = self.b;
self.b = self.signal.next();
}
val
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
#[derive(Clone)]
pub struct Phase<S: Signal> {
steps: S,
phase: S::Type,
period: S::Type,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Phase<S>
where
S: Signal,
S::Type: Float,
{
#[inline]
pub fn new(steps: S, period: S::Type) -> Self {
Self::new_with_phase(steps, period, Zero::zero())
}
#[inline]
pub fn new_with_phase(steps: S, period: S::Type, initial_phase: S::Type) -> Self {
Self {
steps,
phase: initial_phase,
period,
}
}
#[inline]
pub fn next_phase(&mut self) -> S::Type {
let next_phase = (self.phase + self.steps.next()) % self.period;
core::mem::replace(&mut self.phase, next_phase)
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Oscillator<S: Signal, F> {
pub(super) phase: Phase<S>,
pub(super) waveform: F,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S, F, T> Signal for Oscillator<S, F>
where
S: Signal,
S::Type: Float,
F: FnMut(S::Type) -> T,
{
type Type = T;
#[inline]
fn next(&mut self) -> Self::Type {
(self.waveform)(self.phase.next_phase())
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Sine<S: Signal> {
pub(super) phase: Phase<S>,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Signal for Sine<S>
where
S: Signal,
S::Type: Float + FloatConst,
{
type Type = S::Type;
#[inline]
fn next(&mut self) -> Self::Type {
(self.phase.next_phase() * S::Type::TAU()).sin()
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Sawtooth<S: Signal> {
pub(super) phase: Phase<S>,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Signal for Sawtooth<S>
where
S: Signal,
S::Type: Float,
{
type Type = S::Type;
#[inline]
fn next(&mut self) -> Self::Type {
let phase = self.phase.next_phase();
(phase + phase) - One::one()
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Square<S: Signal> {
pub(super) phase: Phase<S>,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Signal for Square<S>
where
S: Signal,
S::Type: Float,
{
type Type = S::Type;
#[inline]
fn next(&mut self) -> Self::Type {
let phase = self.phase.next_phase();
if phase + phase < One::one() {
S::Type::one()
} else {
-S::Type::one()
}
}
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
pub struct Triangle<S: Signal> {
pub(super) phase: Phase<S>,
}
#[cfg(any(feature = "num-libm", feature = "num-std"))]
impl<S> Signal for Triangle<S>
where
S: Signal,
S::Type: Float,
{
type Type = S::Type;
#[inline]
fn next(&mut self) -> Self::Type {
let phase = self.phase.next_phase();
((phase + phase) - One::one()).abs()
}
}