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;

/// Differentiation of one input
pub struct Differentiate {}

impl Differentiate {

    /// Generate a new differentiation operation
    ///
    /// ## Example
    /// ```rust
    /// use sac_base::operations::math::differentiate::Differentiate;
    /// let mut diff = Differentiate::new();
    /// let mut vec = Vec::new();
    /// vec.push(&[1.0][..]);
    /// diff.process((vec, 1));
    /// let mut vec = Vec::new();
    /// vec.push(&[1.0][..]);
    /// diff.process((vec, 1));
    /// assert_eq!(diff.data, &[0.0][..]);
    /// ```
    pub fn new<T>() -> Node<T>
        where T: Copy + ops::Sub<Output=T> + 'static + Default
    {
        let storage = Box::new(T::default()) as Box<dyn Any>;
        Node::new(storage, |data_input, data_buffer,
                            output| {
            let (inputs, max_len) = data_input;
            let last_val: &mut T = data_buffer.downcast_mut::<T>().unwrap();
            output.clear();
            inputs.into_iter().take(1).into_iter().for_each(|data| {
                data.into_iter().take(max_len).into_iter().for_each(|v| {
                    let diff_result = *v - *last_val;
                    output.push(diff_result);
                    *last_val = *v;
                })
            })
        })
    }
}

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

    #[test]
    fn test_differentiate_constant() {
        let mut div = Differentiate::new();

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

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

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

    #[test]
    fn test_differentiate_slope() {
        let mut div = Differentiate::new();

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

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

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

    #[test]
    fn test_long_slice() {
        let mut div = Differentiate::new();

        let mut input = Vec::new();
        input.push(&[3.0, 2.0, 1.0][..]);
        div.process((input, 3));
        assert_eq!(div.poll(), &[3.0, -1.0, -1.0][..]);
    }
}