easy_ml/matrices/
operations.rs

1/*!
2 * Matrix operations.
3 *
4 * [Numeric](crate::numeric) type matrices implement elementwise addition and subtraction and
5 * matrix multiplication.
6 *
7 * When doing numeric operations with matrices you should be careful to not consume a matrix by
8 * accidentally using it by value. All the operations are also defined on references to matrices
9 * so you should favor &x * &y style notation for matrices you intend to continue using.
10 * There are also convenience operations defined for a matrix and a scalar.
11 *
12 * These implementations are written here but Rust docs will display them on their implemented
13 * types. All 16 combinations of owned and referenced [Matrix] and [MatrixView] operations are
14 * implemented. All 8 left hand side assigning addition (`+=`) and subtraction (`-=`) operations
15 * are also implemented.
16 *
17 * Matrix multiplication is such that a matrix of dimensionality (LxM) multiplied with
18 * a matrix of dimensionality (MxN) yields a new matrix of dimensionality (LxN) with each element
19 * corresponding to the sum of products of the ith row in the first matrix and the jth column in
20 * the second matrix.
21 *
22 * Operations on matrices of the wrong sizes will result in a panic. No broadcasting is performed,
23 * ie you cannot multiply a (NxM) matrix by a (Nx1) column vector, you must transpose one of the
24 * arguments so that the operation is valid.
25 */
26
27use crate::matrices::iterators::{
28    ColumnReferenceIterator, RowMajorReferenceIterator, RowMajorReferenceMutIterator,
29    RowReferenceIterator,
30};
31use crate::matrices::views::{MatrixMut, MatrixRef, MatrixView, NoInteriorMutability};
32use crate::matrices::{Column, Matrix, Row};
33use crate::numeric::{Numeric, NumericRef};
34
35use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
36
37// TODO: Unify partial eq implementations
38
39#[track_caller]
40#[inline]
41fn matrix_view_addition_iter<'l, 'r, T, S1, S2>(
42    left_iter: S1,
43    left_size: (Row, Column),
44    right_iter: S2,
45    right_size: (Row, Column),
46) -> Matrix<T>
47where
48    T: Numeric,
49    T: 'l,
50    T: 'r,
51    for<'a> &'a T: NumericRef<T>,
52    S1: Iterator<Item = &'l T>,
53    S2: Iterator<Item = &'r T>,
54{
55    // LxM + LxM -> LxM
56    assert!(
57        left_size == right_size,
58        "Mismatched matrices, left is {}x{}, right is {}x{}, + is only defined for MxN + MxN",
59        left_size.0,
60        left_size.1,
61        right_size.0,
62        right_size.1
63    );
64
65    let values = left_iter.zip(right_iter).map(|(x, y)| x + y).collect();
66    Matrix::from_flat_row_major(left_size, values)
67}
68
69#[track_caller]
70#[inline]
71fn matrix_view_subtraction_iter<'l, 'r, T, S1, S2>(
72    left_iter: S1,
73    left_size: (Row, Column),
74    right_iter: S2,
75    right_size: (Row, Column),
76) -> Matrix<T>
77where
78    T: Numeric,
79    T: 'l,
80    T: 'r,
81    for<'a> &'a T: NumericRef<T>,
82    S1: Iterator<Item = &'l T>,
83    S2: Iterator<Item = &'r T>,
84{
85    // LxM - LxM -> LxM
86    assert!(
87        left_size == right_size,
88        "Mismatched matrices, left is {}x{}, right is {}x{}, + is only defined for MxN + MxN",
89        left_size.0,
90        left_size.1,
91        right_size.0,
92        right_size.1
93    );
94
95    let values = left_iter.zip(right_iter).map(|(x, y)| x - y).collect();
96    Matrix::from_flat_row_major(left_size, values)
97}
98
99#[track_caller]
100#[inline]
101fn matrix_view_assign_addition_iter<'l, 'r, T, S1, S2>(
102    left_iter: S1,
103    left_size: (Row, Column),
104    right_iter: S2,
105    right_size: (Row, Column),
106) where
107    T: Numeric,
108    T: 'l,
109    T: 'r,
110    for<'a> &'a T: NumericRef<T>,
111    S1: Iterator<Item = &'l mut T>,
112    S2: Iterator<Item = &'r T>,
113{
114    // LxM + LxM -> LxM
115    assert!(
116        left_size == right_size,
117        "Mismatched matrices, left is {}x{}, right is {}x{}, += is only defined for MxN + MxN",
118        left_size.0,
119        left_size.1,
120        right_size.0,
121        right_size.1
122    );
123
124    for (x, y) in left_iter.zip(right_iter) {
125        // Numeric doesn't define &mut T + &T so we have to clone the left hand side
126        // in order to add them. For all normal number types this should be exceptionally
127        // cheap since the types are all Copy anyway.
128        *x = x.clone() + y;
129    }
130}
131
132#[track_caller]
133#[inline]
134fn matrix_view_assign_subtraction_iter<'l, 'r, T, S1, S2>(
135    left_iter: S1,
136    left_size: (Row, Column),
137    right_iter: S2,
138    right_size: (Row, Column),
139) where
140    T: Numeric,
141    T: 'l,
142    T: 'r,
143    for<'a> &'a T: NumericRef<T>,
144    S1: Iterator<Item = &'l mut T>,
145    S2: Iterator<Item = &'r T>,
146{
147    // LxM + LxM -> LxM
148    assert!(
149        left_size == right_size,
150        "Mismatched matrices, left is {}x{}, right is {}x{}, -= is only defined for MxN + MxN",
151        left_size.0,
152        left_size.1,
153        right_size.0,
154        right_size.1
155    );
156
157    for (x, y) in left_iter.zip(right_iter) {
158        // Numeric doesn't define &mut T + &T so we have to clone the left hand side
159        // in order to add them. For all normal number types this should be exceptionally
160        // cheap since the types are all Copy anyway.
161        *x = x.clone() - y;
162    }
163}
164
165#[track_caller]
166#[inline]
167fn matrix_view_multiplication<T, S1, S2>(left: &S1, right: &S2) -> Matrix<T>
168where
169    T: Numeric,
170    for<'a> &'a T: NumericRef<T>,
171    S1: MatrixRef<T> + NoInteriorMutability,
172    S2: MatrixRef<T> + NoInteriorMutability,
173{
174    use crate::tensors::operations::scalar_product;
175    // LxM * MxN -> LxN
176    assert!(
177        left.view_columns() == right.view_rows(),
178        "Mismatched Matrices, left is {}x{}, right is {}x{}, * is only defined for MxN * NxL",
179        left.view_rows(),
180        left.view_columns(),
181        right.view_rows(),
182        right.view_columns()
183    );
184
185    let mut result = Matrix::empty(T::zero(), (left.view_rows(), right.view_columns()));
186
187    for ((i, j), x) in result.row_major_reference_mut_iter().with_index() {
188        // Select the i'th row in the left tensor to give us a vector
189        let left = RowReferenceIterator::from(left, i);
190        // Select the j'th column in the right tensor to give us a vector
191        let right = ColumnReferenceIterator::from(right, j);
192        // Since we checked earlier that we have MxN * NxL these two vectors have the same length.
193        *x = scalar_product::<T, _, _>(left, right);
194    }
195    result
196}
197
198macro_rules! matrix_view_reference_matrix_view_reference_operation {
199    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
200        #[doc=$doc]
201        impl<T, S1, S2> $op<&MatrixView<T, S2>> for &MatrixView<T, S1>
202        where
203            T: Numeric,
204            for<'a> &'a T: NumericRef<T>,
205            S1: MatrixRef<T> + NoInteriorMutability,
206            S2: MatrixRef<T> + NoInteriorMutability,
207        {
208            type Output = Matrix<T>;
209
210            #[track_caller]
211            #[inline]
212            fn $method(self, rhs: &MatrixView<T, S2>) -> Self::Output {
213                $implementation::<T, S1, S2>(self.source_ref(), rhs.source_ref())
214            }
215        }
216    };
217}
218
219macro_rules! matrix_view_reference_matrix_view_reference_operation_iter {
220    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
221        #[doc=$doc]
222        impl<T, S1, S2> $op<&MatrixView<T, S2>> for &MatrixView<T, S1>
223        where
224            T: Numeric,
225            for<'a> &'a T: NumericRef<T>,
226            S1: MatrixRef<T> + NoInteriorMutability,
227            S2: MatrixRef<T> + NoInteriorMutability,
228        {
229            type Output = Matrix<T>;
230
231            #[track_caller]
232            #[inline]
233            fn $method(self, rhs: &MatrixView<T, S2>) -> Self::Output {
234                $implementation::<T, _, _>(
235                    RowMajorReferenceIterator::from(self.source_ref()),
236                    self.size(),
237                    RowMajorReferenceIterator::from(rhs.source_ref()),
238                    rhs.size(),
239                )
240            }
241        }
242    };
243}
244
245matrix_view_reference_matrix_view_reference_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for two referenced matrix views");
246matrix_view_reference_matrix_view_reference_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two referenced matrix views");
247matrix_view_reference_matrix_view_reference_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for two referenced matrix views");
248
249macro_rules! matrix_view_assign_matrix_view_reference_operation_iter {
250    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
251        #[doc=$doc]
252        impl<T, S1, S2> $op<&MatrixView<T, S2>> for MatrixView<T, S1>
253        where
254            T: Numeric,
255            for<'a> &'a T: NumericRef<T>,
256            S1: MatrixMut<T> + NoInteriorMutability,
257            S2: MatrixRef<T> + NoInteriorMutability,
258        {
259            #[track_caller]
260            #[inline]
261            fn $method(&mut self, rhs: &MatrixView<T, S2>) {
262                let left_size = self.size();
263                $implementation::<T, _, _>(
264                    RowMajorReferenceMutIterator::from(self.source_ref_mut()),
265                    left_size,
266                    RowMajorReferenceIterator::from(rhs.source_ref()),
267                    rhs.size(),
268                )
269            }
270        }
271    };
272}
273
274matrix_view_assign_matrix_view_reference_operation_iter!(impl AddAssign for MatrixView { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for two referenced matrix views");
275matrix_view_assign_matrix_view_reference_operation_iter!(impl SubAssign for MatrixView { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for two referenced matrix views");
276
277macro_rules! matrix_view_reference_matrix_view_value_operation {
278    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
279        #[doc=$doc]
280        impl<T, S1, S2> $op<MatrixView<T, S2>> for &MatrixView<T, S1>
281        where
282            T: Numeric,
283            for<'a> &'a T: NumericRef<T>,
284            S1: MatrixRef<T> + NoInteriorMutability,
285            S2: MatrixRef<T> + NoInteriorMutability,
286        {
287            type Output = Matrix<T>;
288
289            #[track_caller]
290            #[inline]
291            fn $method(self, rhs: MatrixView<T, S2>) -> Self::Output {
292                $implementation::<T, S1, S2>(self.source_ref(), rhs.source_ref())
293            }
294        }
295    };
296}
297
298macro_rules! matrix_view_reference_matrix_view_value_operation_iter {
299    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
300        #[doc=$doc]
301        impl<T, S1, S2> $op<MatrixView<T, S2>> for &MatrixView<T, S1>
302        where
303            T: Numeric,
304            for<'a> &'a T: NumericRef<T>,
305            S1: MatrixRef<T> + NoInteriorMutability,
306            S2: MatrixRef<T> + NoInteriorMutability,
307        {
308            type Output = Matrix<T>;
309
310            #[track_caller]
311            #[inline]
312            fn $method(self, rhs: MatrixView<T, S2>) -> Self::Output {
313                $implementation::<T, _, _>(
314                    RowMajorReferenceIterator::from(self.source_ref()),
315                    self.size(),
316                    RowMajorReferenceIterator::from(rhs.source_ref()),
317                    rhs.size(),
318                )
319            }
320        }
321    };
322}
323
324matrix_view_reference_matrix_view_value_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for two matrix views with one referenced");
325matrix_view_reference_matrix_view_value_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two matrix views with one referenced");
326matrix_view_reference_matrix_view_value_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for two matrix views with one referenced");
327
328macro_rules! matrix_view_assign_matrix_view_value_operation_iter {
329    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
330        #[doc=$doc]
331        impl<T, S1, S2> $op<MatrixView<T, S2>> for MatrixView<T, S1>
332        where
333            T: Numeric,
334            for<'a> &'a T: NumericRef<T>,
335            S1: MatrixMut<T> + NoInteriorMutability,
336            S2: MatrixRef<T> + NoInteriorMutability,
337        {
338            #[track_caller]
339            #[inline]
340            fn $method(&mut self, rhs: MatrixView<T, S2>) {
341                let left_size = self.size();
342                $implementation::<T, _, _>(
343                    RowMajorReferenceMutIterator::from(self.source_ref_mut()),
344                    left_size,
345                    RowMajorReferenceIterator::from(rhs.source_ref()),
346                    rhs.size(),
347                )
348            }
349        }
350    };
351}
352
353matrix_view_assign_matrix_view_value_operation_iter!(impl AddAssign for MatrixView { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for two matrix views with one referenced");
354matrix_view_assign_matrix_view_value_operation_iter!(impl SubAssign for MatrixView { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for two matrix views with one referenced");
355
356macro_rules! matrix_view_value_matrix_view_reference_operation {
357    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
358        #[doc=$doc]
359        impl<T, S1, S2> $op<&MatrixView<T, S2>> for MatrixView<T, S1>
360        where
361            T: Numeric,
362            for<'a> &'a T: NumericRef<T>,
363            S1: MatrixRef<T> + NoInteriorMutability,
364            S2: MatrixRef<T> + NoInteriorMutability,
365        {
366            type Output = Matrix<T>;
367
368            #[track_caller]
369            #[inline]
370            fn $method(self, rhs: &MatrixView<T, S2>) -> Self::Output {
371                $implementation::<T, S1, S2>(self.source_ref(), rhs.source_ref())
372            }
373        }
374    };
375}
376
377macro_rules! matrix_view_value_matrix_view_reference_operation_iter {
378    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
379        #[doc=$doc]
380        impl<T, S1, S2> $op<&MatrixView<T, S2>> for MatrixView<T, S1>
381        where
382            T: Numeric,
383            for<'a> &'a T: NumericRef<T>,
384            S1: MatrixRef<T> + NoInteriorMutability,
385            S2: MatrixRef<T> + NoInteriorMutability,
386        {
387            type Output = Matrix<T>;
388
389            #[track_caller]
390            #[inline]
391            fn $method(self, rhs: &MatrixView<T, S2>) -> Self::Output {
392                $implementation::<T, _, _>(
393                    RowMajorReferenceIterator::from(self.source_ref()),
394                    self.size(),
395                    RowMajorReferenceIterator::from(rhs.source_ref()),
396                    rhs.size(),
397                )
398            }
399        }
400    };
401}
402
403matrix_view_value_matrix_view_reference_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for two matrix views with one referenced");
404matrix_view_value_matrix_view_reference_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise addition for two matrix views with one referenced");
405matrix_view_value_matrix_view_reference_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for two matrix views with one referenced");
406
407macro_rules! matrix_view_value_matrix_view_value_operation {
408    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
409        #[doc=$doc]
410        impl<T, S1, S2> $op<MatrixView<T, S2>> for MatrixView<T, S1>
411        where
412            T: Numeric,
413            for<'a> &'a T: NumericRef<T>,
414            S1: MatrixRef<T> + NoInteriorMutability,
415            S2: MatrixRef<T> + NoInteriorMutability,
416        {
417            type Output = Matrix<T>;
418
419            #[track_caller]
420            #[inline]
421            fn $method(self, rhs: MatrixView<T, S2>) -> Self::Output {
422                $implementation::<T, S1, S2>(self.source_ref(), rhs.source_ref())
423            }
424        }
425    };
426}
427
428macro_rules! matrix_view_value_matrix_view_value_operation_iter {
429    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
430        #[doc=$doc]
431        impl<T, S1, S2> $op<MatrixView<T, S2>> for MatrixView<T, S1>
432        where
433            T: Numeric,
434            for<'a> &'a T: NumericRef<T>,
435            S1: MatrixRef<T> + NoInteriorMutability,
436            S2: MatrixRef<T> + NoInteriorMutability,
437        {
438            type Output = Matrix<T>;
439
440            #[track_caller]
441            #[inline]
442            fn $method(self, rhs: MatrixView<T, S2>) -> Self::Output {
443                $implementation::<T, _, _>(
444                    RowMajorReferenceIterator::from(self.source_ref()),
445                    self.size(),
446                    RowMajorReferenceIterator::from(rhs.source_ref()),
447                    rhs.size(),
448                )
449            }
450        }
451    };
452}
453
454matrix_view_value_matrix_view_value_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for two matrix views");
455matrix_view_value_matrix_view_value_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two matrix views");
456matrix_view_value_matrix_view_value_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for two matrix views");
457
458macro_rules! matrix_view_reference_matrix_reference_operation {
459    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
460        #[doc=$doc]
461        impl<T, S> $op<&Matrix<T>> for &MatrixView<T, S>
462        where
463            T: Numeric,
464            for<'a> &'a T: NumericRef<T>,
465            S: MatrixRef<T> + NoInteriorMutability,
466        {
467            type Output = Matrix<T>;
468
469            #[track_caller]
470            #[inline]
471            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
472                $implementation::<T, S, Matrix<T>>(self.source_ref(), rhs)
473            }
474        }
475    };
476}
477
478macro_rules! matrix_view_reference_matrix_reference_operation_iter {
479    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
480        #[doc=$doc]
481        impl<T, S> $op<&Matrix<T>> for &MatrixView<T, S>
482        where
483            T: Numeric,
484            for<'a> &'a T: NumericRef<T>,
485            S: MatrixRef<T> + NoInteriorMutability,
486        {
487            type Output = Matrix<T>;
488
489            #[track_caller]
490            #[inline]
491            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
492                $implementation::<T, _, _>(
493                    RowMajorReferenceIterator::from(self.source_ref()),
494                    self.size(),
495                    rhs.direct_row_major_reference_iter(),
496                    rhs.size(),
497                )
498            }
499        }
500    };
501}
502
503matrix_view_reference_matrix_reference_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for a referenced matrix view and a referenced matrix");
504matrix_view_reference_matrix_reference_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a referenced matrix view and a referenced matrix");
505matrix_view_reference_matrix_reference_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for a referenced matrix view and a referenced matrix");
506
507macro_rules! matrix_view_assign_matrix_reference_operation_iter {
508    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
509        #[doc=$doc]
510        impl<T, S> $op<&Matrix<T>> for MatrixView<T, S>
511        where
512            T: Numeric,
513            for<'a> &'a T: NumericRef<T>,
514            S: MatrixMut<T> + NoInteriorMutability,
515        {
516            #[track_caller]
517            #[inline]
518            fn $method(&mut self, rhs: &Matrix<T>) {
519                let left_size = self.size();
520                $implementation::<T, _, _>(
521                    RowMajorReferenceMutIterator::from(self.source_ref_mut()),
522                    left_size,
523                    rhs.direct_row_major_reference_iter(),
524                    rhs.size(),
525                )
526            }
527        }
528    };
529}
530
531matrix_view_assign_matrix_reference_operation_iter!(impl AddAssign for MatrixView { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for a referenced matrix view and a referenced matrix");
532matrix_view_assign_matrix_reference_operation_iter!(impl SubAssign for MatrixView { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for a referenced matrix view and a referenced matrix");
533
534macro_rules! matrix_view_reference_matrix_value_operation {
535    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
536        #[doc=$doc]
537        impl<T, S> $op<Matrix<T>> for &MatrixView<T, S>
538        where
539            T: Numeric,
540            for<'a> &'a T: NumericRef<T>,
541            S: MatrixRef<T> + NoInteriorMutability,
542        {
543            type Output = Matrix<T>;
544
545            #[track_caller]
546            #[inline]
547            fn $method(self, rhs: Matrix<T>) -> Self::Output {
548                $implementation::<T, S, Matrix<T>>(self.source_ref(), &rhs)
549            }
550        }
551    };
552}
553
554macro_rules! matrix_view_reference_matrix_value_operation_iter {
555    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
556        #[doc=$doc]
557        impl<T, S> $op<Matrix<T>> for &MatrixView<T, S>
558        where
559            T: Numeric,
560            for<'a> &'a T: NumericRef<T>,
561            S: MatrixRef<T> + NoInteriorMutability,
562        {
563            type Output = Matrix<T>;
564
565            #[track_caller]
566            #[inline]
567            fn $method(self, rhs: Matrix<T>) -> Self::Output {
568                $implementation::<T, _, _>(
569                    RowMajorReferenceIterator::from(self.source_ref()),
570                    self.size(),
571                    rhs.direct_row_major_reference_iter(),
572                    rhs.size(),
573                )
574            }
575        }
576    };
577}
578
579matrix_view_reference_matrix_value_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for a referenced matrix view and a matrix");
580matrix_view_reference_matrix_value_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a referenced matrix view and a matrix");
581matrix_view_reference_matrix_value_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for a referenced matrix view and a matrix");
582
583macro_rules! matrix_view_assign_matrix_value_operation_iter {
584    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
585        #[doc=$doc]
586        impl<T, S> $op<Matrix<T>> for MatrixView<T, S>
587        where
588            T: Numeric,
589            for<'a> &'a T: NumericRef<T>,
590            S: MatrixMut<T> + NoInteriorMutability,
591        {
592            #[track_caller]
593            #[inline]
594            fn $method(&mut self, rhs: Matrix<T>) {
595                let left_size = self.size();
596                $implementation::<T, _, _>(
597                    RowMajorReferenceMutIterator::from(self.source_ref_mut()),
598                    left_size,
599                    rhs.direct_row_major_reference_iter(),
600                    rhs.size(),
601                )
602            }
603        }
604    };
605}
606
607matrix_view_assign_matrix_value_operation_iter!(impl AddAssign for MatrixView { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for a referenced matrix view and a matrix");
608matrix_view_assign_matrix_value_operation_iter!(impl SubAssign for MatrixView { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for a referenced matrix view and a matrix");
609
610macro_rules! matrix_view_value_matrix_reference_operation {
611    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
612        #[doc=$doc]
613        impl<T, S> $op<&Matrix<T>> for MatrixView<T, S>
614        where
615            T: Numeric,
616            for<'a> &'a T: NumericRef<T>,
617            S: MatrixRef<T> + NoInteriorMutability,
618        {
619            type Output = Matrix<T>;
620
621            #[track_caller]
622            #[inline]
623            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
624                $implementation::<T, S, Matrix<T>>(self.source_ref(), rhs)
625            }
626        }
627    };
628}
629
630macro_rules! matrix_view_value_matrix_reference_operation_iter {
631    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
632        #[doc=$doc]
633        impl<T, S> $op<&Matrix<T>> for MatrixView<T, S>
634        where
635            T: Numeric,
636            for<'a> &'a T: NumericRef<T>,
637            S: MatrixRef<T> + NoInteriorMutability,
638        {
639            type Output = Matrix<T>;
640
641            #[track_caller]
642            #[inline]
643            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
644                $implementation::<T, _, _>(
645                    RowMajorReferenceIterator::from(self.source_ref()),
646                    self.size(),
647                    rhs.direct_row_major_reference_iter(),
648                    rhs.size(),
649                )
650            }
651        }
652    };
653}
654
655matrix_view_value_matrix_reference_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for a matrix view and a referenced matrix");
656matrix_view_value_matrix_reference_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a matrix view and a referenced matrix");
657matrix_view_value_matrix_reference_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for a matrix view and a referenced matrix");
658
659macro_rules! matrix_view_value_matrix_value_operation {
660    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
661        #[doc=$doc]
662        impl<T, S> $op<Matrix<T>> for MatrixView<T, S>
663        where
664            T: Numeric,
665            for<'a> &'a T: NumericRef<T>,
666            S: MatrixRef<T> + NoInteriorMutability,
667        {
668            type Output = Matrix<T>;
669
670            #[track_caller]
671            #[inline]
672            fn $method(self, rhs: Matrix<T>) -> Self::Output {
673                $implementation::<T, S, Matrix<T>>(self.source_ref(), &rhs)
674            }
675        }
676    };
677}
678
679macro_rules! matrix_view_value_matrix_value_operation_iter {
680    (impl $op:tt for MatrixView { fn $method:ident } $implementation:ident $doc:tt) => {
681        #[doc=$doc]
682        impl<T, S> $op<Matrix<T>> for MatrixView<T, S>
683        where
684            T: Numeric,
685            for<'a> &'a T: NumericRef<T>,
686            S: MatrixRef<T> + NoInteriorMutability,
687        {
688            type Output = Matrix<T>;
689
690            #[track_caller]
691            #[inline]
692            fn $method(self, rhs: Matrix<T>) -> Self::Output {
693                $implementation::<T, _, _>(
694                    RowMajorReferenceIterator::from(self.source_ref()),
695                    self.size(),
696                    rhs.direct_row_major_reference_iter(),
697                    rhs.size(),
698                )
699            }
700        }
701    };
702}
703
704matrix_view_value_matrix_value_operation_iter!(impl Add for MatrixView { fn add } matrix_view_addition_iter "Elementwise addition for a matrix view and a matrix");
705matrix_view_value_matrix_value_operation_iter!(impl Sub for MatrixView { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a matrix view and a matrix");
706matrix_view_value_matrix_value_operation!(impl Mul for MatrixView { fn mul } matrix_view_multiplication "Matrix multiplication for a matrix view and a matrix");
707
708macro_rules! matrix_reference_matrix_view_reference_operation {
709    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
710        #[doc=$doc]
711        impl<T, S> $op<&MatrixView<T, S>> for &Matrix<T>
712        where
713            T: Numeric,
714            for<'a> &'a T: NumericRef<T>,
715            S: MatrixRef<T> + NoInteriorMutability,
716        {
717            type Output = Matrix<T>;
718
719            #[track_caller]
720            #[inline]
721            fn $method(self, rhs: &MatrixView<T, S>) -> Self::Output {
722                $implementation::<T, Matrix<T>, S>(self, rhs.source_ref())
723            }
724        }
725    };
726}
727
728macro_rules! matrix_reference_matrix_view_reference_operation_iter {
729    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
730        #[doc=$doc]
731        impl<T, S> $op<&MatrixView<T, S>> for &Matrix<T>
732        where
733            T: Numeric,
734            for<'a> &'a T: NumericRef<T>,
735            S: MatrixRef<T> + NoInteriorMutability,
736        {
737            type Output = Matrix<T>;
738
739            #[track_caller]
740            #[inline]
741            fn $method(self, rhs: &MatrixView<T, S>) -> Self::Output {
742                $implementation::<T, _, _>(
743                    self.direct_row_major_reference_iter(),
744                    self.size(),
745                    RowMajorReferenceIterator::from(rhs.source_ref()),
746                    rhs.size(),
747                )
748            }
749        }
750    };
751}
752
753matrix_reference_matrix_view_reference_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for a referenced matrix and a referenced matrix view");
754matrix_reference_matrix_view_reference_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a referenced matrix and a referenced matrix view");
755matrix_reference_matrix_view_reference_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for a referenced matrix and a referenced matrix view");
756
757macro_rules! matrix_assign_matrix_view_reference_operation_iter {
758    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
759        #[doc=$doc]
760        impl<T, S> $op<&MatrixView<T, S>> for Matrix<T>
761        where
762            T: Numeric,
763            for<'a> &'a T: NumericRef<T>,
764            S: MatrixRef<T> + NoInteriorMutability,
765        {
766            #[track_caller]
767            #[inline]
768            fn $method(&mut self, rhs: &MatrixView<T, S>) {
769                let left_size = self.size();
770                $implementation::<T, _, _>(
771                    self.direct_row_major_reference_iter_mut(),
772                    left_size,
773                    RowMajorReferenceIterator::from(rhs.source_ref()),
774                    rhs.size(),
775                )
776            }
777        }
778    };
779}
780
781matrix_assign_matrix_view_reference_operation_iter!(impl AddAssign for Matrix { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for a referenced matrix and a referenced matrix view");
782matrix_assign_matrix_view_reference_operation_iter!(impl SubAssign for Matrix { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for a referenced matrix and a referenced matrix view");
783
784macro_rules! matrix_reference_matrix_view_value_operation {
785    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
786        #[doc=$doc]
787        impl<T, S> $op<MatrixView<T, S>> for &Matrix<T>
788        where
789            T: Numeric,
790            for<'a> &'a T: NumericRef<T>,
791            S: MatrixRef<T> + NoInteriorMutability,
792        {
793            type Output = Matrix<T>;
794
795            #[track_caller]
796            #[inline]
797            fn $method(self, rhs: MatrixView<T, S>) -> Self::Output {
798                $implementation::<T, Matrix<T>, S>(self, rhs.source_ref())
799            }
800        }
801    };
802}
803
804macro_rules! matrix_reference_matrix_view_value_operation_iter {
805    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
806        #[doc=$doc]
807        impl<T, S> $op<MatrixView<T, S>> for &Matrix<T>
808        where
809            T: Numeric,
810            for<'a> &'a T: NumericRef<T>,
811            S: MatrixRef<T> + NoInteriorMutability,
812        {
813            type Output = Matrix<T>;
814
815            #[track_caller]
816            #[inline]
817            fn $method(self, rhs: MatrixView<T, S>) -> Self::Output {
818                $implementation::<T, _, _>(
819                    self.direct_row_major_reference_iter(),
820                    self.size(),
821                    RowMajorReferenceIterator::from(rhs.source_ref()),
822                    rhs.size(),
823                )
824            }
825        }
826    };
827}
828
829matrix_reference_matrix_view_value_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for a referenced matrix and a matrix view");
830matrix_reference_matrix_view_value_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a referenced matrix and a matrix view");
831matrix_reference_matrix_view_value_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for a referenced matrix and a matrix view");
832
833macro_rules! matrix_assign_matrix_view_value_operation_iter {
834    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
835        #[doc=$doc]
836        impl<T, S> $op<MatrixView<T, S>> for Matrix<T>
837        where
838            T: Numeric,
839            for<'a> &'a T: NumericRef<T>,
840            S: MatrixRef<T> + NoInteriorMutability,
841        {
842            #[track_caller]
843            #[inline]
844            fn $method(&mut self, rhs: MatrixView<T, S>) {
845                let left_size = self.size();
846                $implementation::<T, _, _>(
847                    self.direct_row_major_reference_iter_mut(),
848                    left_size,
849                    RowMajorReferenceIterator::from(rhs.source_ref()),
850                    rhs.size(),
851                )
852            }
853        }
854    };
855}
856
857matrix_assign_matrix_view_value_operation_iter!(impl AddAssign for Matrix { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for a referenced matrix and a matrix view");
858matrix_assign_matrix_view_value_operation_iter!(impl SubAssign for Matrix { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for a referenced matrix and a matrix view");
859
860macro_rules! matrix_value_matrix_view_reference_operation {
861    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
862        #[doc=$doc]
863        impl<T, S> $op<&MatrixView<T, S>> for Matrix<T>
864        where
865            T: Numeric,
866            for<'a> &'a T: NumericRef<T>,
867            S: MatrixRef<T> + NoInteriorMutability,
868        {
869            type Output = Matrix<T>;
870
871            #[track_caller]
872            #[inline]
873            fn $method(self, rhs: &MatrixView<T, S>) -> Self::Output {
874                $implementation::<T, Matrix<T>, S>(&self, rhs.source_ref())
875            }
876        }
877    };
878}
879
880macro_rules! matrix_value_matrix_view_reference_operation_iter {
881    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
882        #[doc=$doc]
883        impl<T, S> $op<&MatrixView<T, S>> for Matrix<T>
884        where
885            T: Numeric,
886            for<'a> &'a T: NumericRef<T>,
887            S: MatrixRef<T> + NoInteriorMutability,
888        {
889            type Output = Matrix<T>;
890
891            #[track_caller]
892            #[inline]
893            fn $method(self, rhs: &MatrixView<T, S>) -> Self::Output {
894                $implementation::<T, _, _>(
895                    self.direct_row_major_reference_iter(),
896                    self.size(),
897                    RowMajorReferenceIterator::from(rhs.source_ref()),
898                    rhs.size(),
899                )
900            }
901        }
902    };
903}
904
905matrix_value_matrix_view_reference_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for a matrix and a referenced matrix view");
906matrix_value_matrix_view_reference_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a matrix and a referenced matrix view");
907matrix_value_matrix_view_reference_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for a matrix and a referenced matrix view");
908
909macro_rules! matrix_value_matrix_view_value_operation {
910    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
911        #[doc=$doc]
912        impl<T, S> $op<MatrixView<T, S>> for Matrix<T>
913        where
914            T: Numeric,
915            for<'a> &'a T: NumericRef<T>,
916            S: MatrixRef<T> + NoInteriorMutability,
917        {
918            type Output = Matrix<T>;
919
920            #[track_caller]
921            #[inline]
922            fn $method(self, rhs: MatrixView<T, S>) -> Self::Output {
923                $implementation::<T, Matrix<T>, S>(&self, rhs.source_ref())
924            }
925        }
926    };
927}
928
929macro_rules! matrix_value_matrix_view_value_operation_iter {
930    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
931        #[doc=$doc]
932        impl<T, S> $op<MatrixView<T, S>> for Matrix<T>
933        where
934            T: Numeric,
935            for<'a> &'a T: NumericRef<T>,
936            S: MatrixRef<T> + NoInteriorMutability,
937        {
938            type Output = Matrix<T>;
939
940            #[track_caller]
941            #[inline]
942            fn $method(self, rhs: MatrixView<T, S>) -> Self::Output {
943                $implementation::<T, _, _>(
944                    self.direct_row_major_reference_iter(),
945                    self.size(),
946                    RowMajorReferenceIterator::from(rhs.source_ref()),
947                    rhs.size(),
948                )
949            }
950        }
951    };
952}
953
954matrix_value_matrix_view_value_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for a matrix and a matrix view");
955matrix_value_matrix_view_value_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for a matrix and a matrix view");
956matrix_value_matrix_view_value_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for a matrix and a matrix view");
957
958macro_rules! matrix_reference_matrix_reference_operation {
959    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
960        #[doc=$doc]
961        impl<T> $op<&Matrix<T>> for &Matrix<T>
962        where
963            T: Numeric,
964            for<'a> &'a T: NumericRef<T>,
965        {
966            type Output = Matrix<T>;
967
968            #[track_caller]
969            #[inline]
970            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
971                $implementation::<T, Matrix<T>, Matrix<T>>(self, rhs)
972            }
973        }
974    };
975}
976
977macro_rules! matrix_reference_matrix_reference_operation_iter {
978    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
979        #[doc=$doc]
980        impl<T> $op<&Matrix<T>> for &Matrix<T>
981        where
982            T: Numeric,
983            for<'a> &'a T: NumericRef<T>,
984        {
985            type Output = Matrix<T>;
986
987            #[track_caller]
988            #[inline]
989            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
990                $implementation::<T, _, _>(
991                    self.direct_row_major_reference_iter(),
992                    self.size(),
993                    rhs.direct_row_major_reference_iter(),
994                    rhs.size(),
995                )
996            }
997        }
998    };
999}
1000
1001matrix_reference_matrix_reference_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for two referenced matrices");
1002matrix_reference_matrix_reference_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two referenced matrices");
1003matrix_reference_matrix_reference_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for two referenced matrices");
1004
1005macro_rules! matrix_assign_matrix_reference_operation_iter {
1006    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1007        #[doc=$doc]
1008        impl<T> $op<&Matrix<T>> for Matrix<T>
1009        where
1010            T: Numeric,
1011            for<'a> &'a T: NumericRef<T>,
1012        {
1013            #[track_caller]
1014            #[inline]
1015            fn $method(&mut self, rhs: &Matrix<T>) {
1016                let left_size = self.size();
1017                $implementation::<T, _, _>(
1018                    self.direct_row_major_reference_iter_mut(),
1019                    left_size,
1020                    rhs.direct_row_major_reference_iter(),
1021                    rhs.size(),
1022                )
1023            }
1024        }
1025    };
1026}
1027
1028matrix_assign_matrix_reference_operation_iter!(impl AddAssign for Matrix { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for two referenced matrices");
1029matrix_assign_matrix_reference_operation_iter!(impl SubAssign for Matrix { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for two referenced matrices");
1030
1031macro_rules! matrix_reference_matrix_value_operation {
1032    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1033        #[doc=$doc]
1034        impl<T> $op<Matrix<T>> for &Matrix<T>
1035        where
1036            T: Numeric,
1037            for<'a> &'a T: NumericRef<T>,
1038        {
1039            type Output = Matrix<T>;
1040
1041            #[track_caller]
1042            #[inline]
1043            fn $method(self, rhs: Matrix<T>) -> Self::Output {
1044                $implementation::<T, Matrix<T>, Matrix<T>>(self, &rhs)
1045            }
1046        }
1047    };
1048}
1049
1050macro_rules! matrix_reference_matrix_value_operation_iter {
1051    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1052        #[doc=$doc]
1053        impl<T> $op<Matrix<T>> for &Matrix<T>
1054        where
1055            T: Numeric,
1056            for<'a> &'a T: NumericRef<T>,
1057        {
1058            type Output = Matrix<T>;
1059
1060            #[track_caller]
1061            #[inline]
1062            fn $method(self, rhs: Matrix<T>) -> Self::Output {
1063                $implementation::<T, _, _>(
1064                    self.direct_row_major_reference_iter(),
1065                    self.size(),
1066                    rhs.direct_row_major_reference_iter(),
1067                    rhs.size(),
1068                )
1069            }
1070        }
1071    };
1072}
1073
1074matrix_reference_matrix_value_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for two matrices with one referenced");
1075matrix_reference_matrix_value_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two matrices with one referenced");
1076matrix_reference_matrix_value_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for two matrices with one referenced");
1077
1078macro_rules! matrix_assign_matrix_value_operation_iter {
1079    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1080        #[doc=$doc]
1081        impl<T> $op<Matrix<T>> for Matrix<T>
1082        where
1083            T: Numeric,
1084            for<'a> &'a T: NumericRef<T>,
1085        {
1086            #[track_caller]
1087            #[inline]
1088            fn $method(&mut self, rhs: Matrix<T>) {
1089                let left_size = self.size();
1090                $implementation::<T, _, _>(
1091                    self.direct_row_major_reference_iter_mut(),
1092                    left_size,
1093                    rhs.direct_row_major_reference_iter(),
1094                    rhs.size(),
1095                )
1096            }
1097        }
1098    };
1099}
1100
1101matrix_assign_matrix_value_operation_iter!(impl AddAssign for Matrix { fn add_assign } matrix_view_assign_addition_iter "Elementwise assigning addition for two matrices with one referenced");
1102matrix_assign_matrix_value_operation_iter!(impl SubAssign for Matrix { fn sub_assign } matrix_view_assign_subtraction_iter "Elementwise assigning subtraction for two matrices with one referenced");
1103
1104macro_rules! matrix_value_matrix_reference_operation {
1105    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1106        #[doc=$doc]
1107        impl<T> $op<&Matrix<T>> for Matrix<T>
1108        where
1109            T: Numeric,
1110            for<'a> &'a T: NumericRef<T>,
1111        {
1112            type Output = Matrix<T>;
1113
1114            #[track_caller]
1115            #[inline]
1116            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
1117                $implementation::<T, Matrix<T>, Matrix<T>>(&self, rhs)
1118            }
1119        }
1120    };
1121}
1122
1123macro_rules! matrix_value_matrix_reference_operation_iter {
1124    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1125        #[doc=$doc]
1126        impl<T> $op<&Matrix<T>> for Matrix<T>
1127        where
1128            T: Numeric,
1129            for<'a> &'a T: NumericRef<T>,
1130        {
1131            type Output = Matrix<T>;
1132
1133            #[track_caller]
1134            #[inline]
1135            fn $method(self, rhs: &Matrix<T>) -> Self::Output {
1136                $implementation::<T, _, _>(
1137                    self.direct_row_major_reference_iter(),
1138                    self.size(),
1139                    rhs.direct_row_major_reference_iter(),
1140                    rhs.size(),
1141                )
1142            }
1143        }
1144    };
1145}
1146
1147matrix_value_matrix_reference_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for two matrices with one referenced");
1148matrix_value_matrix_reference_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two matrices with one referenced");
1149matrix_value_matrix_reference_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for two matrices with one referenced");
1150
1151macro_rules! matrix_value_matrix_value_operation {
1152    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1153        #[doc=$doc]
1154        impl<T> $op<Matrix<T>> for Matrix<T>
1155        where
1156            T: Numeric,
1157            for<'a> &'a T: NumericRef<T>,
1158        {
1159            type Output = Matrix<T>;
1160
1161            #[track_caller]
1162            #[inline]
1163            fn $method(self, rhs: Matrix<T>) -> Self::Output {
1164                $implementation::<T, Matrix<T>, Matrix<T>>(&self, &rhs)
1165            }
1166        }
1167    };
1168}
1169
1170macro_rules! matrix_value_matrix_value_operation_iter {
1171    (impl $op:tt for Matrix { fn $method:ident } $implementation:ident $doc:tt) => {
1172        #[doc=$doc]
1173        impl<T> $op<Matrix<T>> for Matrix<T>
1174        where
1175            T: Numeric,
1176            for<'a> &'a T: NumericRef<T>,
1177        {
1178            type Output = Matrix<T>;
1179
1180            #[track_caller]
1181            #[inline]
1182            fn $method(self, rhs: Matrix<T>) -> Self::Output {
1183                $implementation::<T, _, _>(
1184                    self.direct_row_major_reference_iter(),
1185                    self.size(),
1186                    rhs.direct_row_major_reference_iter(),
1187                    rhs.size(),
1188                )
1189            }
1190        }
1191    };
1192}
1193
1194matrix_value_matrix_value_operation_iter!(impl Add for Matrix { fn add } matrix_view_addition_iter "Elementwise addition for two matrices");
1195matrix_value_matrix_value_operation_iter!(impl Sub for Matrix { fn sub } matrix_view_subtraction_iter "Elementwise subtraction for two matrices");
1196matrix_value_matrix_value_operation!(impl Mul for Matrix { fn mul } matrix_view_multiplication "Matrix multiplication for two matrices");
1197
1198#[test]
1199fn test_all_16_combinations() {
1200    fn matrix() -> Matrix<i8> {
1201        Matrix::from_scalar(1)
1202    }
1203    fn matrix_view() -> MatrixView<i8, Matrix<i8>> {
1204        MatrixView::from(Matrix::from_scalar(1))
1205    }
1206    let mut results = Vec::with_capacity(16);
1207    results.push(matrix() + matrix());
1208    results.push(matrix() + &matrix());
1209    results.push(&matrix() + matrix());
1210    results.push(&matrix() + &matrix());
1211    results.push(matrix_view() + matrix());
1212    results.push(matrix_view() + &matrix());
1213    results.push(&matrix_view() + matrix());
1214    results.push(&matrix_view() + &matrix());
1215    results.push(matrix() + matrix_view());
1216    results.push(matrix() + &matrix_view());
1217    results.push(&matrix() + matrix_view());
1218    results.push(&matrix() + &matrix_view());
1219    results.push(matrix_view() + matrix_view());
1220    results.push(matrix_view() + &matrix_view());
1221    results.push(&matrix_view() + matrix_view());
1222    results.push(&matrix_view() + &matrix_view());
1223    for total in results {
1224        assert_eq!(total.scalar(), 2);
1225    }
1226}
1227
1228#[test]
1229fn elementwise_addition_assign_test_all_8_combinations() {
1230    fn matrix() -> Matrix<i8> {
1231        Matrix::from_scalar(1)
1232    }
1233    fn matrix_view() -> MatrixView<i8, Matrix<i8>> {
1234        MatrixView::from(Matrix::from_scalar(1))
1235    }
1236    let mut results_matrix = Vec::with_capacity(16);
1237    let mut results_matrix_views = Vec::with_capacity(16);
1238    results_matrix.push({
1239        let mut x = matrix();
1240        x += matrix();
1241        x
1242    });
1243    results_matrix.push({
1244        let mut x = matrix();
1245        x += &matrix();
1246        x
1247    });
1248    results_matrix_views.push({
1249        let mut x = matrix_view();
1250        x += matrix();
1251        x
1252    });
1253    results_matrix_views.push({
1254        let mut x = matrix_view();
1255        x += &matrix();
1256        x
1257    });
1258    results_matrix.push({
1259        let mut x = matrix();
1260        x += matrix_view();
1261        x
1262    });
1263    results_matrix.push({
1264        let mut x = matrix();
1265        x += &matrix_view();
1266        x
1267    });
1268    results_matrix_views.push({
1269        let mut x = matrix_view();
1270        x += matrix_view();
1271        x
1272    });
1273    results_matrix_views.push({
1274        let mut x = matrix_view();
1275        x += &matrix_view();
1276        x
1277    });
1278    for total in results_matrix {
1279        assert_eq!(total.scalar(), 2);
1280    }
1281    for total in results_matrix_views {
1282        assert_eq!(total.get(0, 0), 2);
1283    }
1284}
1285
1286#[test]
1287fn elementwise_subtraction_assign_test_all_8_combinations() {
1288    fn matrix() -> Matrix<i8> {
1289        Matrix::from_scalar(1)
1290    }
1291    fn matrix_view() -> MatrixView<i8, Matrix<i8>> {
1292        MatrixView::from(Matrix::from_scalar(1))
1293    }
1294    let mut results_matrix = Vec::with_capacity(16);
1295    let mut results_matrix_views = Vec::with_capacity(16);
1296    results_matrix.push({
1297        let mut x = matrix();
1298        x -= matrix();
1299        x
1300    });
1301    results_matrix.push({
1302        let mut x = matrix();
1303        x -= &matrix();
1304        x
1305    });
1306    results_matrix_views.push({
1307        let mut x = matrix_view();
1308        x -= matrix();
1309        x
1310    });
1311    results_matrix_views.push({
1312        let mut x = matrix_view();
1313        x -= &matrix();
1314        x
1315    });
1316    results_matrix.push({
1317        let mut x = matrix();
1318        x -= matrix_view();
1319        x
1320    });
1321    results_matrix.push({
1322        let mut x = matrix();
1323        x -= &matrix_view();
1324        x
1325    });
1326    results_matrix_views.push({
1327        let mut x = matrix_view();
1328        x -= matrix_view();
1329        x
1330    });
1331    results_matrix_views.push({
1332        let mut x = matrix_view();
1333        x -= &matrix_view();
1334        x
1335    });
1336    for total in results_matrix {
1337        assert_eq!(total.scalar(), 0);
1338    }
1339    for total in results_matrix_views {
1340        assert_eq!(total.get(0, 0), 0);
1341    }
1342}
1343
1344/**
1345 * Elementwise negation for a referenced matrix.
1346 */
1347impl<T: Numeric> Neg for &Matrix<T>
1348where
1349    for<'a> &'a T: NumericRef<T>,
1350{
1351    type Output = Matrix<T>;
1352
1353    #[inline]
1354    fn neg(self) -> Self::Output {
1355        self.map(|v| -v)
1356    }
1357}
1358
1359/**
1360 * Elementwise negation for a matrix.
1361 */
1362impl<T: Numeric> Neg for Matrix<T>
1363where
1364    for<'a> &'a T: NumericRef<T>,
1365{
1366    type Output = Matrix<T>;
1367
1368    #[inline]
1369    fn neg(self) -> Self::Output {
1370        -&self
1371    }
1372}
1373
1374/**
1375 * Elementwise negation for a referenced matrix view.
1376 */
1377impl<T, S> Neg for &MatrixView<T, S>
1378where
1379    T: Numeric,
1380    for<'a> &'a T: NumericRef<T>,
1381    S: MatrixRef<T>,
1382{
1383    type Output = Matrix<T>;
1384
1385    #[inline]
1386    fn neg(self) -> Self::Output {
1387        self.map(|v| -v)
1388    }
1389}
1390
1391/**
1392 * Elementwise negation for a matrix view.
1393 */
1394impl<T, S> Neg for MatrixView<T, S>
1395where
1396    T: Numeric,
1397    for<'a> &'a T: NumericRef<T>,
1398    S: MatrixRef<T>,
1399{
1400    type Output = Matrix<T>;
1401
1402    #[inline]
1403    fn neg(self) -> Self::Output {
1404        -&self
1405    }
1406}
1407
1408macro_rules! matrix_scalar {
1409    (impl $op:tt for Matrix { fn $method:ident }) => {
1410        /**
1411         * Operation for a matrix and scalar by reference. The scalar is applied to
1412         * all elements, this is a shorthand for [map()](Matrix::map).
1413         */
1414        impl<T: Numeric> $op<&T> for &Matrix<T>
1415        where
1416            for<'a> &'a T: NumericRef<T>,
1417        {
1418            type Output = Matrix<T>;
1419            #[inline]
1420            fn $method(self, rhs: &T) -> Self::Output {
1421                self.map(|x| (x).$method(rhs.clone()))
1422            }
1423        }
1424
1425        /**
1426         * Operation for a matrix by value and scalar by reference. The scalar is applied to
1427         * all elements, this is a shorthand for [map()](Matrix::map).
1428         */
1429        impl<T: Numeric> $op<&T> for Matrix<T>
1430        where
1431            for<'a> &'a T: NumericRef<T>,
1432        {
1433            type Output = Matrix<T>;
1434            #[inline]
1435            fn $method(self, rhs: &T) -> Self::Output {
1436                self.map(|x| (x).$method(rhs.clone()))
1437            }
1438        }
1439
1440        /**
1441         * Operation for a matrix by reference and scalar by value. The scalar is applied to
1442         * all elements, this is a shorthand for [map()](Matrix::map).
1443         */
1444        impl<T: Numeric> $op<T> for &Matrix<T>
1445        where
1446            for<'a> &'a T: NumericRef<T>,
1447        {
1448            type Output = Matrix<T>;
1449            #[inline]
1450            fn $method(self, rhs: T) -> Self::Output {
1451                self.map(|x| (x).$method(rhs.clone()))
1452            }
1453        }
1454
1455        /**
1456         * Operation for a matrix and scalar by value. The scalar is applied to
1457         * all elements, this is a shorthand for [map()](Matrix::map).
1458         */
1459        impl<T: Numeric> $op<T> for Matrix<T>
1460        where
1461            for<'a> &'a T: NumericRef<T>,
1462        {
1463            type Output = Matrix<T>;
1464            #[inline]
1465            fn $method(self, rhs: T) -> Self::Output {
1466                self.map(|x| (x).$method(rhs.clone()))
1467            }
1468        }
1469    };
1470}
1471
1472macro_rules! matrix_view_scalar {
1473    (impl $op:tt for MatrixView { fn $method:ident }) => {
1474        /**
1475         * Operation for a matrix view and scalar by reference. The scalar is applied to
1476         * all elements, this is a shorthand for [map()](MatrixView::map).
1477         */
1478        impl<T, S> $op<&T> for &MatrixView<T, S>
1479        where
1480            T: Numeric,
1481            for<'a> &'a T: NumericRef<T>,
1482            S: MatrixRef<T>,
1483        {
1484            type Output = Matrix<T>;
1485            #[inline]
1486            fn $method(self, rhs: &T) -> Self::Output {
1487                self.map(|x| (x).$method(rhs.clone()))
1488            }
1489        }
1490
1491        /**
1492         * Operation for a matrix viiew by value and scalar by reference. The scalar is applied to
1493         * all elements, this is a shorthand for [map()](MatrixView::map).
1494         */
1495        impl<T, S> $op<&T> for MatrixView<T, S>
1496        where
1497            T: Numeric,
1498            for<'a> &'a T: NumericRef<T>,
1499            S: MatrixRef<T>,
1500        {
1501            type Output = Matrix<T>;
1502            #[inline]
1503            fn $method(self, rhs: &T) -> Self::Output {
1504                self.map(|x| (x).$method(rhs.clone()))
1505            }
1506        }
1507
1508        /**
1509         * Operation for a matrix view by reference and scalar by value. The scalar is applied to
1510         * all elements, this is a shorthand for [map()](MatrixView::map).
1511         */
1512        impl<T, S> $op<T> for &MatrixView<T, S>
1513        where
1514            T: Numeric,
1515            for<'a> &'a T: NumericRef<T>,
1516            S: MatrixRef<T>,
1517        {
1518            type Output = Matrix<T>;
1519            #[inline]
1520            fn $method(self, rhs: T) -> Self::Output {
1521                self.map(|x| (x).$method(rhs.clone()))
1522            }
1523        }
1524
1525        /**
1526         * Operation for a matrix view and scalar by value. The scalar is applied to
1527         * all elements, this is a shorthand for [map()](MatrixView::map).
1528         */
1529        impl<T, S> $op<T> for MatrixView<T, S>
1530        where
1531            T: Numeric,
1532            for<'a> &'a T: NumericRef<T>,
1533            S: MatrixRef<T>,
1534        {
1535            type Output = Matrix<T>;
1536            #[inline]
1537            fn $method(self, rhs: T) -> Self::Output {
1538                self.map(|x| (x).$method(rhs.clone()))
1539            }
1540        }
1541    };
1542}
1543
1544matrix_scalar!(impl Add for Matrix { fn add });
1545matrix_scalar!(impl Sub for Matrix { fn sub });
1546matrix_scalar!(impl Mul for Matrix { fn mul });
1547matrix_scalar!(impl Div for Matrix { fn div });
1548
1549matrix_view_scalar!(impl Add for MatrixView { fn add });
1550matrix_view_scalar!(impl Sub for MatrixView { fn sub });
1551matrix_view_scalar!(impl Mul for MatrixView { fn mul });
1552matrix_view_scalar!(impl Div for MatrixView { fn div });