Skip to main content

sac_base/operations/math/
divide.rs

1use crate::network::node::Node;
2use core::ops;
3use alloc::boxed::Box;
4use core::any::Any;
5use crate::helper::iter::iter_n_inputs;
6
7/// Divide two or more inputs.
8pub struct Divide {}
9pub struct IntegerDivide {}
10
11impl Divide {
12    /// Generate a new division operation
13    ///
14    /// ## Example
15    /// ```rust
16    /// use sac_base::operations::math::divide::{Divide, IntegerDivide};
17    /// let mut div = Divide::new();
18    /// let mut vec = Vec::new();
19    /// vec.push(&[2.0][..]);
20    /// vec.push(&[4.0][..]);
21    /// vec.push(&[0.5][..]);
22    /// div.process((vec, 1));
23    /// assert_eq!(div.poll(), &[1.0][..]);
24    /// ```
25    /// TODO: Zero divisions currently return INF and is not defined for integer values. These have to be specifically implemented
26    pub fn new<T>() -> Node<T>
27        where T: Copy + ops::Div<Output=T> + Default {
28        let storage = Box::new(0) as Box<dyn Any>;
29        Node::new(storage, |data_input, _input, output| {
30            iter_n_inputs(data_input, output, |left: T, right: T| {
31                return left / right
32            })
33        })
34    }
35}
36
37impl IntegerDivide {
38    /// Generate a new division operation
39    ///
40    /// ## Example
41    /// ```rust
42    /// use sac_base::operations::math::divide::Divide;
43    /// let mut div = Divide::new();
44    /// let mut vec = Vec::new();
45    /// vec.push(&[2.0][..]);
46    /// vec.push(&[4.0][..]);
47    /// vec.push(&[0.5][..]);
48    /// div.process((vec, 1));
49    /// assert_eq!(div.poll(), &[1.0][..]);
50    /// ```
51    pub fn new() -> Node<u32> {
52        let storage = Box::new(0) as Box<dyn Any>;
53        Node::new(storage, |data_input, _input, output| {
54            iter_n_inputs(data_input, output, |left: u32, right: u32| {
55                if right == 0 {
56                    return 0;
57                }
58                return left / right
59            })
60        })
61    }
62}
63
64
65
66#[cfg(test)]
67mod tests {
68    use alloc::vec::Vec;
69    use crate::operations::math::divide::{Divide, IntegerDivide};
70
71    #[test]
72    fn test_div() {
73
74        let mut inputs = Vec::new();
75        inputs.push(&[1.0][..]);
76        inputs.push(&[2.0][..]);
77
78        let mut div = Divide::new();
79        div.process((inputs, 1));
80
81        assert_eq!(div.poll(), &[0.5][..]);
82    }
83
84    #[test]
85    fn test_multiple() {
86
87        let mut inputs = Vec::new();
88        inputs.push(&[1.0][..]);
89        inputs.push(&[2.0][..]);
90        inputs.push(&[2.0][..]);
91
92        let mut div = Divide::new();
93        div.process((inputs, 1));
94
95        assert_eq!(div.poll(), &[0.25][..]);
96    }
97
98    #[test]
99    fn test_multiple_runs() {
100
101        let mut inputs = Vec::new();
102        inputs.push(&[1.0][..]);
103        inputs.push(&[1.0][..]);
104
105        let mut div = Divide::new();
106        div.process((inputs, 1));
107
108
109        let mut inputs = Vec::new();
110        inputs.push(&[2.0][..]);
111        inputs.push(&[4.0][..]);
112        div.process((inputs, 1));
113
114        assert_eq!(div.poll(), &[0.5][..]);
115    }
116
117    #[test]
118    fn test_multiple_single() {
119
120        let mut inputs = Vec::new();
121        inputs.push(&[1.0][..]);
122
123        let mut div = Divide::new();
124        div.process((inputs, 1));
125
126        assert_eq!(div.poll(), &[1.0][..]);
127    }
128
129    #[test]
130    fn test_float_div_zero() {
131
132        let mut inputs = Vec::new();
133        inputs.push(&[1.0][..]);
134        inputs.push(&[0.0][..]);
135
136        let mut div = Divide::new();
137        div.process((inputs, 1));
138
139        assert_eq!(div.poll(), &[f32::INFINITY][..]);
140    }
141
142    #[test]
143    fn test_int_div_zero() {
144
145        let mut inputs = Vec::new();
146        inputs.push(&[1][..]);
147        inputs.push(&[0][..]);
148
149        let mut div = IntegerDivide::new();
150        div.process((inputs, 1));
151
152        assert_eq!(div.poll(), &[0][..]);
153    }
154}
155