arr_rs/numeric/operations/
ops.rs

1use std::ops::{
2    Add, AddAssign,
3    Div, DivAssign,
4    Mul, MulAssign,
5    Neg,
6    Rem, RemAssign,
7    Sub, SubAssign,
8};
9
10use crate::{
11    core::prelude::*,
12    errors::prelude::*,
13    numeric::prelude::*,
14};
15
16macro_rules! impl_op {
17    ($op_trait: ident, $op_func: ident, $op_assign_trait: ident, $op_assign_func: ident) => {
18        impl<N: NumericOps> $op_trait<Array<N>> for Array<N> {
19            type Output = Array<N>;
20
21            fn $op_func(self, other: Self) -> Self::Output {
22                assert_eq!(self.get_shape(), other.get_shape());
23
24                let elements = self.elements.into_iter()
25                    .zip(other.elements.into_iter())
26                    .map(|(a, b)| a.$op_func(b))
27                    .collect();
28
29                Array::new(elements, self.shape).unwrap()
30            }
31        }
32
33        impl<N: NumericOps> $op_trait<N> for Array<N> {
34            type Output = Result<Array<N>, ArrayError>;
35
36            fn $op_func(self, other: N) -> Self::Output {
37                self.map(|i| i.$op_func(other))
38                    .reshape(&self.shape)
39            }
40        }
41
42        impl<N: NumericOps> $op_assign_trait<Array<N>> for Array<N> {
43            fn $op_assign_func(&mut self, other: Self) -> () {
44                assert_eq!(self.get_shape(), other.get_shape());
45
46                self.elements.iter_mut()
47                    .zip(other.elements.into_iter())
48                    .for_each(|(a, b)| a.$op_assign_func(b));
49            }
50        }
51
52        impl<N: NumericOps> $op_assign_trait<N> for Array<N> {
53            fn $op_assign_func(&mut self, other: N) -> () {
54                self.elements.iter_mut()
55                    .for_each(|a| a.$op_assign_func(other));
56            }
57        }
58    };
59}
60
61impl_op!(Add, add, AddAssign, add_assign);
62impl_op!(Sub, sub, SubAssign, sub_assign);
63impl_op!(Mul, mul, MulAssign, mul_assign);
64impl_op!(Div, div, DivAssign, div_assign);
65impl_op!(Rem, rem, RemAssign, rem_assign);
66
67// ==== Signed Ops
68
69impl <N: SignedNumericOps> Neg for Array<N> {
70    type Output = Self;
71
72    fn neg(self) -> Self::Output {
73        let elements = self.elements.into_iter()
74            .map(|a| -a)
75            .collect();
76
77        Self::new(elements, self.shape).unwrap()
78    }
79}