sac-base 0.0.7

Base crate of the sac-signal and sac-control crates
Documentation
use crate::network::node::Node;
use core::ops;
use alloc::boxed::Box;
use core::any::Any;

pub struct Integrate<T> {
    last: T
}

impl<T> Integrate<T>
    where T: Copy + ops::Add<Output=T> + Default + 'static
{

    /// Generate a new integration operation
    ///
    /// ## Example
    /// ```rust
    /// use sac_base::operations::math::integrate::Integrate;
    /// let mut int = Integrate::new();
    /// let mut vec = Vec::new();
    /// vec.push(&[1.0][..]);
    /// int.process((vec, 1));
    /// let mut vec = Vec::new();
    /// vec.push(&[1.0][..]);
    /// int.process((vec, 1));
    /// assert_eq!(int.poll(), &[2.0][..]);
    /// ```
    pub fn new() -> Node<T> {
        let storage = Box::new(Integrate{
            last: T::default()
        }) as Box<dyn Any>;
        Node::new(storage, |data_input, data_container, output| {
            let integrate: &mut Integrate<T> = data_container.downcast_mut::<Integrate<T>>().unwrap();
            let (inputs, max_len) = data_input;
            output.clear();
            inputs.into_iter().take(1).into_iter().for_each(|data| {
                data.into_iter().take(max_len).into_iter().for_each(|v| {
                    let last = integrate.last;
                    let new_sample = last + *v;
                    output.push(new_sample);
                    integrate.last = new_sample;
                })
            })
        })
    }
}

#[cfg(test)]
mod tests {
    use crate::operations::math::integrate::Integrate;
    use alloc::vec::Vec;

    #[test]
    fn test_integrate_constant() {
        let mut int = Integrate::new();

        let mut input = Vec::new();
        input.push(&[1.0][..]);
        int.process((input, 1));

        let mut input = Vec::new();
        input.push(&[1.0][..]);
        int.process((input, 1));

        let mut input = Vec::new();
        input.push(&[1.0][..]);
        int.process((input, 1));
        assert_eq!(int.poll(), &[3.0][..]);
    }

    #[test]
    fn test_integrate_slope() {
        let mut int = Integrate::new();

        let mut input = Vec::new();
        input.push(&[-3.0][..]);
        int.process((input, 1));

        let mut input = Vec::new();
        input.push(&[2.0][..]);
        int.process((input, 1));

        let mut input = Vec::new();
        input.push(&[1.0][..]);
        int.process((input, 1));
        assert_eq!(int.poll(), &[0.0][..]);
    }

    #[test]
    fn test_longer_slice() {
        let mut int = Integrate::new();

        let mut input = Vec::new();
        input.push(&[-3.0, 3.0, 4.0][..]);
        int.process((input, 3));
        assert_eq!(int.poll(), &[-3.0, 0.0, 4.0][..]);

        let mut input = Vec::new();
        input.push(&[2.0][..]);
        int.process((input, 1));

        assert_eq!(int.poll(), &[6.0][..]);
    }

    #[test]
    fn test_longer_slice_limited() {
        let mut int = Integrate::new();

        let mut input = Vec::new();
        input.push(&[3.0, 3.0, 4.0][..]);
        int.process((input, 2));

        assert_eq!(int.poll(), &[3.0, 6.0][..]);
    }
}