vector_victor/
ops.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::Matrix;
6use num_traits::Num;
7
8// borrowed from the auto_ops crate
9#[doc(hidden)]
10macro_rules! impl_matrix_op {
11    (neg) => {
12        _impl_op_unary_ex!(Neg::neg);
13    };
14    (!) => {
15        _impl_op_unary_ex!(Not::not);
16    };
17    (+) => {
18        _impl_op_binary_ex!(Add::add, AddAssign::add_assign);
19    };
20    (-) => {
21        _impl_op_binary_ex!(Sub::sub, SubAssign::sub_assign);
22    };
23    (*) => {
24        _impl_op_binary_ex!(Mul::mul, MulAssign::mul_assign);
25    };
26    (/) => {
27        _impl_op_binary_ex!(Div::div, DivAssign::div_assign);
28    };
29    (%) => {
30        _impl_op_binary_ex!(Rem::rem, RemAssign::rem_assign);
31    };
32    (&) => {
33        _impl_op_binary_ex!(BitAnd::bitand, BitAndAssign::bitand_assign);
34    };
35    (|) => {
36        _impl_op_binary_ex!(BitOr::bitor, BitOrAssign::bitor_assign);
37    };
38    (^) => {
39        _impl_op_binary_ex!(BitXor::bitxor, BitXorAssign::bitxor_assign);
40    };
41    (<<) => {
42        _impl_op_binary_ex!(Shl::shl, ShlAssign::shl_assign);
43    };
44    (>>) => {
45        _impl_op_binary_ex!(Shr::shr, ShrAssign::shr_assign);
46    };
47}
48
49#[doc(hidden)]
50macro_rules! _impl_op_unary_ex {
51    ($op_trait:ident::$op_fn:ident) => {
52        _impl_op_m_internal!($op_trait, $op_fn, Matrix<L,M,N>, Matrix<L,M,N>);
53        _impl_op_m_internal!($op_trait, $op_fn, &Matrix<L,M,N>, Matrix<L,M,N>);
54    }
55}
56
57#[doc(hidden)]
58macro_rules! _impl_op_binary_ex {
59    ($op_trait:ident::$op_fn:ident, $op_assign_trait:ident::$op_assign_fn:ident) => {
60        _impl_op_mm_internal!($op_trait, $op_fn, Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>);
61        _impl_op_mm_internal!($op_trait, $op_fn, &Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>);
62        _impl_op_mm_internal!($op_trait, $op_fn, Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>);
63        _impl_op_mm_internal!($op_trait, $op_fn, &Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>);
64
65        _impl_op_ms_internal!($op_trait, $op_fn, Matrix<L,M,N>, R, Matrix<L,M,N>);
66        _impl_op_ms_internal!($op_trait, $op_fn, &Matrix<L,M,N>, R, Matrix<L,M,N>);
67
68        _impl_opassign_mm_internal!($op_assign_trait, $op_assign_fn, Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>);
69        _impl_opassign_mm_internal!($op_assign_trait, $op_assign_fn, Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>);
70
71        _impl_opassign_ms_internal!($op_assign_trait, $op_assign_fn, Matrix<L,M,N>, R, Matrix<L,M,N>);
72
73    }
74}
75
76#[doc(hidden)]
77macro_rules! _impl_op_m_internal {
78    ($op_trait:ident, $op_fn:ident, $lhs:ty, $out:ty) => {
79        impl<L, const M: usize, const N: usize> ::std::ops::$op_trait for $lhs
80        where
81            L: ::std::ops::$op_trait<Output = L> + Copy,
82        {
83            type Output = $out;
84
85            #[inline(always)]
86            fn $op_fn(self) -> Self::Output {
87                let mut result = self.clone();
88                // we arnt using iterators because they dont seem to always vectorize correctly
89                for m in 0..M {
90                    for n in 0..N {
91                        result.data[m][n] = self.data[m][n].$op_fn();
92                    }
93                }
94                result
95            }
96        }
97    };
98}
99
100#[doc(hidden)]
101macro_rules! _impl_op_mm_internal {
102    ($op_trait:ident, $op_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => {
103        impl<L, R, const M: usize, const N: usize> ::std::ops::$op_trait<$rhs> for $lhs
104        where
105            L: ::std::ops::$op_trait<R, Output = L> + Copy,
106            R: Copy,
107        {
108            type Output = $out;
109
110            #[inline(always)]
111            fn $op_fn(self, other: $rhs) -> Self::Output {
112                let mut result = self.clone();
113                for m in 0..M {
114                    for n in 0..N {
115                        result.data[m][n] = self.data[m][n].$op_fn(other.data[m][n]);
116                    }
117                }
118                result
119            }
120        }
121    };
122}
123
124#[doc(hidden)]
125macro_rules! _impl_opassign_mm_internal {
126    ($op_trait:ident, $op_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => {
127        impl<L, R, const M: usize, const N: usize> ::std::ops::$op_trait<$rhs> for $lhs
128        where
129            L: ::std::ops::$op_trait<R> + Copy,
130            R: Copy,
131        {
132            #[inline(always)]
133            fn $op_fn(&mut self, other: $rhs) {
134                for m in 0..M {
135                    for n in 0..N {
136                        self.data[m][n].$op_fn(other.data[m][n]);
137                    }
138                }
139            }
140        }
141    };
142}
143
144#[doc(hidden)]
145macro_rules! _impl_op_ms_internal {
146    ($op_trait:ident, $op_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => {
147        impl<L, R, const M: usize, const N: usize> ::std::ops::$op_trait<$rhs> for $lhs
148        where
149            L: ::std::ops::$op_trait<R, Output = L> + Copy,
150            R: Copy + Num,
151        {
152            type Output = $out;
153
154            #[inline(always)]
155            fn $op_fn(self, other: $rhs) -> Self::Output {
156                let mut result = self.clone();
157                for m in 0..M {
158                    for n in 0..N {
159                        result.data[m][n] = self.data[m][n].$op_fn(other);
160                    }
161                }
162                result
163            }
164        }
165    };
166}
167
168#[doc(hidden)]
169macro_rules! _impl_opassign_ms_internal {
170    ($op_trait:ident, $op_fn:ident, $lhs:ty, $rhs:ty, $out:ty) => {
171        impl<L, R, const M: usize, const N: usize> ::std::ops::$op_trait<$rhs> for $lhs
172        where
173            L: ::std::ops::$op_trait<R> + Copy,
174            R: Copy + Num,
175        {
176            #[inline(always)]
177            fn $op_fn(&mut self, r: $rhs) {
178                for m in 0..M {
179                    for n in 0..N {
180                        self.data[m][n].$op_fn(r);
181                    }
182                }
183            }
184        }
185    };
186}
187
188impl_matrix_op!(neg);
189impl_matrix_op!(!);
190impl_matrix_op!(+);
191impl_matrix_op!(-);
192impl_matrix_op!(*);
193impl_matrix_op!(/);
194impl_matrix_op!(%);
195impl_matrix_op!(&);
196impl_matrix_op!(|);
197impl_matrix_op!(^);
198impl_matrix_op!(<<);
199impl_matrix_op!(>>);