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;
use crate::helper::iter::iter_n_inputs;

/// Divide two or more inputs.
pub struct Divide {}
pub struct IntegerDivide {}

impl Divide {
    /// Generate a new division operation
    ///
    /// ## Example
    /// ```rust
    /// use sac_base::operations::math::divide::{Divide, IntegerDivide};
    /// let mut div = Divide::new();
    /// let mut vec = Vec::new();
    /// vec.push(&[2.0][..]);
    /// vec.push(&[4.0][..]);
    /// vec.push(&[0.5][..]);
    /// div.process((vec, 1));
    /// assert_eq!(div.poll(), &[1.0][..]);
    /// ```
    /// TODO: Zero divisions currently return INF and is not defined for integer values. These have to be specifically implemented
    pub fn new<T>() -> Node<T>
        where T: Copy + ops::Div<Output=T> + Default {
        let storage = Box::new(0) as Box<dyn Any>;
        Node::new(storage, |data_input, _input, output| {
            iter_n_inputs(data_input, output, |left: T, right: T| {
                return left / right
            })
        })
    }
}

impl IntegerDivide {
    /// Generate a new division operation
    ///
    /// ## Example
    /// ```rust
    /// use sac_base::operations::math::divide::Divide;
    /// let mut div = Divide::new();
    /// let mut vec = Vec::new();
    /// vec.push(&[2.0][..]);
    /// vec.push(&[4.0][..]);
    /// vec.push(&[0.5][..]);
    /// div.process((vec, 1));
    /// assert_eq!(div.poll(), &[1.0][..]);
    /// ```
    pub fn new() -> Node<u32> {
        let storage = Box::new(0) as Box<dyn Any>;
        Node::new(storage, |data_input, _input, output| {
            iter_n_inputs(data_input, output, |left: u32, right: u32| {
                if right == 0 {
                    return 0;
                }
                return left / right
            })
        })
    }
}



#[cfg(test)]
mod tests {
    use alloc::vec::Vec;
    use crate::operations::math::divide::{Divide, IntegerDivide};

    #[test]
    fn test_div() {

        let mut inputs = Vec::new();
        inputs.push(&[1.0][..]);
        inputs.push(&[2.0][..]);

        let mut div = Divide::new();
        div.process((inputs, 1));

        assert_eq!(div.poll(), &[0.5][..]);
    }

    #[test]
    fn test_multiple() {

        let mut inputs = Vec::new();
        inputs.push(&[1.0][..]);
        inputs.push(&[2.0][..]);
        inputs.push(&[2.0][..]);

        let mut div = Divide::new();
        div.process((inputs, 1));

        assert_eq!(div.poll(), &[0.25][..]);
    }

    #[test]
    fn test_multiple_runs() {

        let mut inputs = Vec::new();
        inputs.push(&[1.0][..]);
        inputs.push(&[1.0][..]);

        let mut div = Divide::new();
        div.process((inputs, 1));


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

        assert_eq!(div.poll(), &[0.5][..]);
    }

    #[test]
    fn test_multiple_single() {

        let mut inputs = Vec::new();
        inputs.push(&[1.0][..]);

        let mut div = Divide::new();
        div.process((inputs, 1));

        assert_eq!(div.poll(), &[1.0][..]);
    }

    #[test]
    fn test_float_div_zero() {

        let mut inputs = Vec::new();
        inputs.push(&[1.0][..]);
        inputs.push(&[0.0][..]);

        let mut div = Divide::new();
        div.process((inputs, 1));

        assert_eq!(div.poll(), &[f32::INFINITY][..]);
    }

    #[test]
    fn test_int_div_zero() {

        let mut inputs = Vec::new();
        inputs.push(&[1][..]);
        inputs.push(&[0][..]);

        let mut div = IntegerDivide::new();
        div.process((inputs, 1));

        assert_eq!(div.poll(), &[0][..]);
    }
}