arr_rs/numeric/operations/
ops.rs1use 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
67impl <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}