/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.35.0/src/base/ops.rs
Line | Count | Source |
1 | | use num::{One, Zero}; |
2 | | use std::iter; |
3 | | use std::ops::{ |
4 | | Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, |
5 | | }; |
6 | | |
7 | | use simba::scalar::{ |
8 | | ClosedAddAssign, ClosedDivAssign, ClosedMulAssign, ClosedNeg, ClosedSubAssign, |
9 | | }; |
10 | | |
11 | | use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; |
12 | | use crate::base::blas_uninit::gemm_uninit; |
13 | | use crate::base::constraint::{ |
14 | | AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, |
15 | | }; |
16 | | use crate::base::dimension::{Dim, DimMul, DimName, DimProd, Dyn}; |
17 | | use crate::base::storage::{Storage, StorageMut}; |
18 | | use crate::base::uninit::Uninit; |
19 | | use crate::base::{DefaultAllocator, Matrix, MatrixSum, OMatrix, Scalar, VectorView}; |
20 | | use crate::storage::IsContiguous; |
21 | | use crate::uninit::{Init, InitStatus}; |
22 | | use crate::{RawStorage, RawStorageMut, SimdComplexField}; |
23 | | use std::mem::MaybeUninit; |
24 | | |
25 | | /* |
26 | | * |
27 | | * Indexing. |
28 | | * |
29 | | */ |
30 | | impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Index<usize> for Matrix<T, R, C, S> { |
31 | | type Output = T; |
32 | | |
33 | | #[inline] |
34 | 20.5k | fn index(&self, i: usize) -> &Self::Output { |
35 | 20.5k | let ij = self.vector_to_matrix_index(i); |
36 | 20.5k | &self[ij] |
37 | 20.5k | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<hyperdual::OHyperdual<f64, nalgebra::base::dimension::Const<7>>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<hyperdual::OHyperdual<f64, nalgebra::base::dimension::Const<7>>, 3, 1>> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::index::Index<usize>>::index <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<4>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 4, 1>> as core::ops::index::Index<usize>>::index Line | Count | Source | 34 | 20.5k | fn index(&self, i: usize) -> &Self::Output { | 35 | 20.5k | let ij = self.vector_to_matrix_index(i); | 36 | 20.5k | &self[ij] | 37 | 20.5k | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 5, 1>> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::index::Index<usize>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<7>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 7, 1>> as core::ops::index::Index<usize>>::index |
38 | | } |
39 | | |
40 | | impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Index<(usize, usize)> for Matrix<T, R, C, S> { |
41 | | type Output = T; |
42 | | |
43 | | #[inline] |
44 | 205k | fn index(&self, ij: (usize, usize)) -> &Self::Output { |
45 | 205k | let shape = self.shape(); |
46 | 205k | assert!( |
47 | 205k | ij.0 < shape.0 && ij.1 < shape.1, |
48 | 0 | "Matrix index out of bounds." |
49 | | ); |
50 | | |
51 | 205k | unsafe { self.get_unchecked((ij.0, ij.1)) } |
52 | 205k | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<hyperdual::OHyperdual<f64, nalgebra::base::dimension::Const<7>>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<hyperdual::OHyperdual<f64, nalgebra::base::dimension::Const<7>>, 3, 1>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 1, 1>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 2>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> as core::ops::index::Index<(usize, usize)>>::index <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::index::Index<(usize, usize)>>::index Line | Count | Source | 44 | 184k | fn index(&self, ij: (usize, usize)) -> &Self::Output { | 45 | 184k | let shape = self.shape(); | 46 | 184k | assert!( | 47 | 184k | ij.0 < shape.0 && ij.1 < shape.1, | 48 | 0 | "Matrix index out of bounds." | 49 | | ); | 50 | | | 51 | 184k | unsafe { self.get_unchecked((ij.0, ij.1)) } | 52 | 184k | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::index::Index<(usize, usize)>>::index <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<4>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 4, 1>> as core::ops::index::Index<(usize, usize)>>::index Line | Count | Source | 44 | 20.5k | fn index(&self, ij: (usize, usize)) -> &Self::Output { | 45 | 20.5k | let shape = self.shape(); | 46 | 20.5k | assert!( | 47 | 20.5k | ij.0 < shape.0 && ij.1 < shape.1, | 48 | 0 | "Matrix index out of bounds." | 49 | | ); | 50 | | | 51 | 20.5k | unsafe { self.get_unchecked((ij.0, ij.1)) } | 52 | 20.5k | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 5, 1>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::index::Index<(usize, usize)>>::index Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<7>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 7, 1>> as core::ops::index::Index<(usize, usize)>>::index |
53 | | } |
54 | | |
55 | | // Mutable versions. |
56 | | impl<T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IndexMut<usize> for Matrix<T, R, C, S> { |
57 | | #[inline] |
58 | 0 | fn index_mut(&mut self, i: usize) -> &mut T { |
59 | 0 | let ij = self.vector_to_matrix_index(i); |
60 | 0 | &mut self[ij] |
61 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<core::mem::maybe_uninit::MaybeUninit<f64>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<core::mem::maybe_uninit::MaybeUninit<f64>, 1, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<core::mem::maybe_uninit::MaybeUninit<f64>, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<core::mem::maybe_uninit::MaybeUninit<f64>, 5, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<(usize, usize), nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<(usize, usize), 3, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 5, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<7>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 7, 1>> as core::ops::index::IndexMut<usize>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<5>>> as core::ops::index::IndexMut<usize>>::index_mut |
62 | | } |
63 | | |
64 | | impl<T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IndexMut<(usize, usize)> for Matrix<T, R, C, S> { |
65 | | #[inline] |
66 | 0 | fn index_mut(&mut self, ij: (usize, usize)) -> &mut T { |
67 | 0 | let shape = self.shape(); |
68 | 0 | assert!( |
69 | 0 | ij.0 < shape.0 && ij.1 < shape.1, |
70 | 0 | "Matrix index out of bounds." |
71 | | ); |
72 | | |
73 | 0 | unsafe { self.get_unchecked_mut((ij.0, ij.1)) } |
74 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<core::mem::maybe_uninit::MaybeUninit<f64>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<core::mem::maybe_uninit::MaybeUninit<f64>, 1, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<core::mem::maybe_uninit::MaybeUninit<f64>, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<core::mem::maybe_uninit::MaybeUninit<f64>, 5, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<(usize, usize), nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<(usize, usize), 3, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 2>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<5>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 5, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<7>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 7, 1>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<5>>> as core::ops::index::IndexMut<(usize, usize)>>::index_mut |
75 | | } |
76 | | |
77 | | /* |
78 | | * |
79 | | * Neg |
80 | | * |
81 | | */ |
82 | | impl<T, R: Dim, C: Dim, S> Neg for Matrix<T, R, C, S> |
83 | | where |
84 | | T: Scalar + ClosedNeg, |
85 | | S: Storage<T, R, C>, |
86 | | DefaultAllocator: Allocator<R, C>, |
87 | | { |
88 | | type Output = OMatrix<T, R, C>; |
89 | | |
90 | | #[inline] |
91 | 0 | fn neg(self) -> Self::Output { |
92 | 0 | let mut res = self.into_owned(); |
93 | 0 | res.neg_mut(); |
94 | 0 | res |
95 | 0 | } |
96 | | } |
97 | | |
98 | | impl<T, R: Dim, C: Dim, S> Neg for &Matrix<T, R, C, S> |
99 | | where |
100 | | T: Scalar + ClosedNeg, |
101 | | S: Storage<T, R, C>, |
102 | | DefaultAllocator: Allocator<R, C>, |
103 | | { |
104 | | type Output = OMatrix<T, R, C>; |
105 | | |
106 | | #[inline] |
107 | | fn neg(self) -> Self::Output { |
108 | | -self.clone_owned() |
109 | | } |
110 | | } |
111 | | |
112 | | impl<T, R: Dim, C: Dim, S> Matrix<T, R, C, S> |
113 | | where |
114 | | T: Scalar + ClosedNeg, |
115 | | S: StorageMut<T, R, C>, |
116 | | { |
117 | | /// Negates `self` in-place. |
118 | | #[inline] |
119 | 0 | pub fn neg_mut(&mut self) { |
120 | 0 | for e in self.iter_mut() { |
121 | 0 | *e = -e.clone() |
122 | | } |
123 | 0 | } |
124 | | } |
125 | | |
126 | | /* |
127 | | * |
128 | | * Addition & Subtraction |
129 | | * |
130 | | */ |
131 | | |
132 | | macro_rules! componentwise_binop_impl( |
133 | | ($Trait: ident, $method: ident, $bound: ident; |
134 | | $TraitAssign: ident, $method_assign: ident, $method_assign_statically_unchecked: ident, |
135 | | $method_assign_statically_unchecked_rhs: ident; |
136 | | $method_to: ident, $method_to_statically_unchecked_uninit: ident) => { |
137 | | |
138 | | impl<T, R1: Dim, C1: Dim, SA: Storage<T, R1, C1>> Matrix<T, R1, C1, SA> |
139 | | where T: Scalar + $bound { |
140 | | |
141 | | /* |
142 | | * |
143 | | * Methods without dimension checking at compile-time. |
144 | | * This is useful for code reuse because the sum representative system does not plays |
145 | | * easily with static checks. |
146 | | * |
147 | | */ |
148 | | #[inline] |
149 | | fn $method_to_statically_unchecked_uninit<Status, R2: Dim, C2: Dim, SB, |
150 | | R3: Dim, C3: Dim, SC>(&self, |
151 | | _status: Status, |
152 | | rhs: &Matrix<T, R2, C2, SB>, |
153 | | out: &mut Matrix<Status::Value, R3, C3, SC>) |
154 | | where Status: InitStatus<T>, |
155 | | SB: RawStorage<T, R2, C2>, |
156 | | SC: RawStorageMut<Status::Value, R3, C3> { |
157 | | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); |
158 | | assert_eq!(self.shape(), out.shape(), "Matrix addition/subtraction output dimensions mismatch."); |
159 | | |
160 | | // This is the most common case and should be deduced at compile-time. |
161 | | // TODO: use specialization instead? |
162 | | unsafe { |
163 | | if self.data.is_contiguous() && rhs.data.is_contiguous() && out.data.is_contiguous() { |
164 | | let arr1 = self.data.as_slice_unchecked(); |
165 | | let arr2 = rhs.data.as_slice_unchecked(); |
166 | | let out = out.data.as_mut_slice_unchecked(); |
167 | | for i in 0 .. arr1.len() { |
168 | | Status::init(out.get_unchecked_mut(i), arr1.get_unchecked(i).clone().$method(arr2.get_unchecked(i).clone())); |
169 | | } |
170 | | } else { |
171 | | for j in 0 .. self.ncols() { |
172 | | for i in 0 .. self.nrows() { |
173 | | let val = self.get_unchecked((i, j)).clone().$method(rhs.get_unchecked((i, j)).clone()); |
174 | | Status::init(out.get_unchecked_mut((i, j)), val); |
175 | | } |
176 | | } |
177 | | } |
178 | | } |
179 | | } |
180 | | |
181 | | |
182 | | #[inline] |
183 | 398 | fn $method_assign_statically_unchecked<R2, C2, SB>(&mut self, rhs: &Matrix<T, R2, C2, SB>) |
184 | 398 | where R2: Dim, |
185 | 398 | C2: Dim, |
186 | 398 | SA: StorageMut<T, R1, C1>, |
187 | 398 | SB: Storage<T, R2, C2> { |
188 | 398 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); |
189 | | |
190 | | // This is the most common case and should be deduced at compile-time. |
191 | | // TODO: use specialization instead? |
192 | | unsafe { |
193 | 398 | if self.data.is_contiguous() && rhs.data.is_contiguous() { |
194 | 398 | let arr1 = self.data.as_mut_slice_unchecked(); |
195 | 398 | let arr2 = rhs.data.as_slice_unchecked(); |
196 | | |
197 | 2.23k | for i in 0 .. arr2.len() { |
198 | 2.23k | arr1.get_unchecked_mut(i).$method_assign(arr2.get_unchecked(i).clone()); |
199 | 2.23k | } |
200 | | } else { |
201 | 0 | for j in 0 .. rhs.ncols() { |
202 | 0 | for i in 0 .. rhs.nrows() { |
203 | 0 | self.get_unchecked_mut((i, j)).$method_assign(rhs.get_unchecked((i, j)).clone()) |
204 | | } |
205 | | } |
206 | | } |
207 | | } |
208 | 398 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>>>::add_assign_statically_unchecked::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>::add_assign_statically_unchecked::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> Line | Count | Source | 183 | 105 | fn $method_assign_statically_unchecked<R2, C2, SB>(&mut self, rhs: &Matrix<T, R2, C2, SB>) | 184 | 105 | where R2: Dim, | 185 | 105 | C2: Dim, | 186 | 105 | SA: StorageMut<T, R1, C1>, | 187 | 105 | SB: Storage<T, R2, C2> { | 188 | 105 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 189 | | | 190 | | // This is the most common case and should be deduced at compile-time. | 191 | | // TODO: use specialization instead? | 192 | | unsafe { | 193 | 105 | if self.data.is_contiguous() && rhs.data.is_contiguous() { | 194 | 105 | let arr1 = self.data.as_mut_slice_unchecked(); | 195 | 105 | let arr2 = rhs.data.as_slice_unchecked(); | 196 | | | 197 | 315 | for i in 0 .. arr2.len() { | 198 | 315 | arr1.get_unchecked_mut(i).$method_assign(arr2.get_unchecked(i).clone()); | 199 | 315 | } | 200 | | } else { | 201 | 0 | for j in 0 .. rhs.ncols() { | 202 | 0 | for i in 0 .. rhs.nrows() { | 203 | 0 | self.get_unchecked_mut((i, j)).$method_assign(rhs.get_unchecked((i, j)).clone()) | 204 | | } | 205 | | } | 206 | | } | 207 | | } | 208 | 105 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>>>::add_assign_statically_unchecked::<nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>>>::sub_assign_statically_unchecked::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> Line | Count | Source | 183 | 173 | fn $method_assign_statically_unchecked<R2, C2, SB>(&mut self, rhs: &Matrix<T, R2, C2, SB>) | 184 | 173 | where R2: Dim, | 185 | 173 | C2: Dim, | 186 | 173 | SA: StorageMut<T, R1, C1>, | 187 | 173 | SB: Storage<T, R2, C2> { | 188 | 173 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 189 | | | 190 | | // This is the most common case and should be deduced at compile-time. | 191 | | // TODO: use specialization instead? | 192 | | unsafe { | 193 | 173 | if self.data.is_contiguous() && rhs.data.is_contiguous() { | 194 | 173 | let arr1 = self.data.as_mut_slice_unchecked(); | 195 | 173 | let arr2 = rhs.data.as_slice_unchecked(); | 196 | | | 197 | 1.55k | for i in 0 .. arr2.len() { | 198 | 1.55k | arr1.get_unchecked_mut(i).$method_assign(arr2.get_unchecked(i).clone()); | 199 | 1.55k | } | 200 | | } else { | 201 | 0 | for j in 0 .. rhs.ncols() { | 202 | 0 | for i in 0 .. rhs.nrows() { | 203 | 0 | self.get_unchecked_mut((i, j)).$method_assign(rhs.get_unchecked((i, j)).clone()) | 204 | | } | 205 | | } | 206 | | } | 207 | | } | 208 | 173 | } |
<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>::sub_assign_statically_unchecked::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> Line | Count | Source | 183 | 120 | fn $method_assign_statically_unchecked<R2, C2, SB>(&mut self, rhs: &Matrix<T, R2, C2, SB>) | 184 | 120 | where R2: Dim, | 185 | 120 | C2: Dim, | 186 | 120 | SA: StorageMut<T, R1, C1>, | 187 | 120 | SB: Storage<T, R2, C2> { | 188 | 120 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 189 | | | 190 | | // This is the most common case and should be deduced at compile-time. | 191 | | // TODO: use specialization instead? | 192 | | unsafe { | 193 | 120 | if self.data.is_contiguous() && rhs.data.is_contiguous() { | 194 | 120 | let arr1 = self.data.as_mut_slice_unchecked(); | 195 | 120 | let arr2 = rhs.data.as_slice_unchecked(); | 196 | | | 197 | 360 | for i in 0 .. arr2.len() { | 198 | 360 | arr1.get_unchecked_mut(i).$method_assign(arr2.get_unchecked(i).clone()); | 199 | 360 | } | 200 | | } else { | 201 | 0 | for j in 0 .. rhs.ncols() { | 202 | 0 | for i in 0 .. rhs.nrows() { | 203 | 0 | self.get_unchecked_mut((i, j)).$method_assign(rhs.get_unchecked((i, j)).clone()) | 204 | | } | 205 | | } | 206 | | } | 207 | | } | 208 | 120 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>::sub_assign_statically_unchecked::<nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> |
209 | | |
210 | | |
211 | | #[inline] |
212 | | fn $method_assign_statically_unchecked_rhs<R2, C2, SB>(&self, rhs: &mut Matrix<T, R2, C2, SB>) |
213 | | where R2: Dim, |
214 | | C2: Dim, |
215 | | SB: StorageMut<T, R2, C2> { |
216 | | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); |
217 | | |
218 | | // This is the most common case and should be deduced at compile-time. |
219 | | // TODO: use specialization instead? |
220 | | unsafe { |
221 | | if self.data.is_contiguous() && rhs.data.is_contiguous() { |
222 | | let arr1 = self.data.as_slice_unchecked(); |
223 | | let arr2 = rhs.data.as_mut_slice_unchecked(); |
224 | | |
225 | | for i in 0 .. arr1.len() { |
226 | | let res = arr1.get_unchecked(i).clone().$method(arr2.get_unchecked(i).clone()); |
227 | | *arr2.get_unchecked_mut(i) = res; |
228 | | } |
229 | | } else { |
230 | | for j in 0 .. self.ncols() { |
231 | | for i in 0 .. self.nrows() { |
232 | | let r = rhs.get_unchecked_mut((i, j)); |
233 | | *r = self.get_unchecked((i, j)).clone().$method(r.clone()) |
234 | | } |
235 | | } |
236 | | } |
237 | | } |
238 | | } |
239 | | |
240 | | |
241 | | /* |
242 | | * |
243 | | * Methods without dimension checking at compile-time. |
244 | | * This is useful for code reuse because the sum representative system does not plays |
245 | | * easily with static checks. |
246 | | * |
247 | | */ |
248 | | /// Equivalent to `self + rhs` but stores the result into `out` to avoid allocations. |
249 | | #[inline] |
250 | | pub fn $method_to<R2: Dim, C2: Dim, SB, |
251 | | R3: Dim, C3: Dim, SC>(&self, |
252 | | rhs: &Matrix<T, R2, C2, SB>, |
253 | | out: &mut Matrix<T, R3, C3, SC>) |
254 | | where SB: Storage<T, R2, C2>, |
255 | | SC: StorageMut<T, R3, C3>, |
256 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> + |
257 | | SameNumberOfRows<R1, R3> + SameNumberOfColumns<C1, C3> { |
258 | | self.$method_to_statically_unchecked_uninit(Init, rhs, out) |
259 | | } |
260 | | } |
261 | | |
262 | | impl<'b, T, R1, C1, R2, C2, SA, SB> $Trait<&'b Matrix<T, R2, C2, SB>> for Matrix<T, R1, C1, SA> |
263 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
264 | | T: Scalar + $bound, |
265 | | SA: Storage<T, R1, C1>, |
266 | | SB: Storage<T, R2, C2>, |
267 | | DefaultAllocator: SameShapeAllocator<R1, C1, R2, C2>, |
268 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> { |
269 | | type Output = MatrixSum<T, R1, C1, R2, C2>; |
270 | | |
271 | | #[inline] |
272 | 398 | fn $method(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { |
273 | 398 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); |
274 | 398 | let mut res = self.into_owned_sum::<R2, C2>(); |
275 | 398 | res.$method_assign_statically_unchecked(rhs); |
276 | 398 | res |
277 | 398 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Add<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>>>>::add <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Add<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::add Line | Count | Source | 272 | 105 | fn $method(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { | 273 | 105 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 274 | 105 | let mut res = self.into_owned_sum::<R2, C2>(); | 275 | 105 | res.$method_assign_statically_unchecked(rhs); | 276 | 105 | res | 277 | 105 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Add<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>>>>::add <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Sub<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>>>>::sub Line | Count | Source | 272 | 173 | fn $method(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { | 273 | 173 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 274 | 173 | let mut res = self.into_owned_sum::<R2, C2>(); | 275 | 173 | res.$method_assign_statically_unchecked(rhs); | 276 | 173 | res | 277 | 173 | } |
<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Sub<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::sub Line | Count | Source | 272 | 120 | fn $method(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { | 273 | 120 | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); | 274 | 120 | let mut res = self.into_owned_sum::<R2, C2>(); | 275 | 120 | res.$method_assign_statically_unchecked(rhs); | 276 | 120 | res | 277 | 120 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::arith::Sub<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>>::sub |
278 | | } |
279 | | |
280 | | impl<'a, T, R1, C1, R2, C2, SA, SB> $Trait<Matrix<T, R2, C2, SB>> for &'a Matrix<T, R1, C1, SA> |
281 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
282 | | T: Scalar + $bound, |
283 | | SA: Storage<T, R1, C1>, |
284 | | SB: Storage<T, R2, C2>, |
285 | | DefaultAllocator: SameShapeAllocator<R2, C2, R1, C1>, |
286 | | ShapeConstraint: SameNumberOfRows<R2, R1> + SameNumberOfColumns<C2, C1> { |
287 | | type Output = MatrixSum<T, R2, C2, R1, C1>; |
288 | | |
289 | | #[inline] |
290 | | fn $method(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { |
291 | | let mut rhs = rhs.into_owned_sum::<R1, C1>(); |
292 | | assert_eq!(self.shape(), rhs.shape(), "Matrix addition/subtraction dimensions mismatch."); |
293 | | self.$method_assign_statically_unchecked_rhs(&mut rhs); |
294 | | rhs |
295 | | } |
296 | | } |
297 | | |
298 | | impl<T, R1, C1, R2, C2, SA, SB> $Trait<Matrix<T, R2, C2, SB>> for Matrix<T, R1, C1, SA> |
299 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
300 | | T: Scalar + $bound, |
301 | | SA: Storage<T, R1, C1>, |
302 | | SB: Storage<T, R2, C2>, |
303 | | DefaultAllocator: SameShapeAllocator<R1, C1, R2, C2>, |
304 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> { |
305 | | type Output = MatrixSum<T, R1, C1, R2, C2>; |
306 | | |
307 | | #[inline] |
308 | 398 | fn $method(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { |
309 | 398 | self.$method(&rhs) |
310 | 398 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Add>::add <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Add>::add Line | Count | Source | 308 | 105 | fn $method(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { | 309 | 105 | self.$method(&rhs) | 310 | 105 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Add>::add <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Sub>::sub Line | Count | Source | 308 | 173 | fn $method(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { | 309 | 173 | self.$method(&rhs) | 310 | 173 | } |
<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Sub>::sub Line | Count | Source | 308 | 120 | fn $method(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { | 309 | 120 | self.$method(&rhs) | 310 | 120 | } |
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>> as core::ops::arith::Sub>::sub |
311 | | } |
312 | | |
313 | | impl<'a, 'b, T, R1, C1, R2, C2, SA, SB> $Trait<&'b Matrix<T, R2, C2, SB>> for &'a Matrix<T, R1, C1, SA> |
314 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
315 | | T: Scalar + $bound, |
316 | | SA: Storage<T, R1, C1>, |
317 | | SB: Storage<T, R2, C2>, |
318 | | DefaultAllocator: SameShapeAllocator<R1, C1, R2, C2>, |
319 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> { |
320 | | type Output = MatrixSum<T, R1, C1, R2, C2>; |
321 | | |
322 | | #[inline] |
323 | | fn $method(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { |
324 | | let (nrows, ncols) = self.shape(); |
325 | | let nrows: SameShapeR<R1, R2> = Dim::from_usize(nrows); |
326 | | let ncols: SameShapeC<C1, C2> = Dim::from_usize(ncols); |
327 | | let mut res = Matrix::uninit(nrows, ncols); |
328 | | self.$method_to_statically_unchecked_uninit(Uninit, rhs, &mut res); |
329 | | // SAFETY: the output has been initialized above. |
330 | | unsafe { res.assume_init() } |
331 | | } |
332 | | } |
333 | | |
334 | | impl<'b, T, R1, C1, R2, C2, SA, SB> $TraitAssign<&'b Matrix<T, R2, C2, SB>> for Matrix<T, R1, C1, SA> |
335 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
336 | | T: Scalar + $bound, |
337 | | SA: StorageMut<T, R1, C1>, |
338 | | SB: Storage<T, R2, C2>, |
339 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> { |
340 | | |
341 | | #[inline] |
342 | 0 | fn $method_assign(&mut self, rhs: &'b Matrix<T, R2, C2, SB>) { |
343 | 0 | self.$method_assign_statically_unchecked(rhs) |
344 | 0 | } |
345 | | } |
346 | | |
347 | | impl<T, R1, C1, R2, C2, SA, SB> $TraitAssign<Matrix<T, R2, C2, SB>> for Matrix<T, R1, C1, SA> |
348 | | where R1: Dim, C1: Dim, R2: Dim, C2: Dim, |
349 | | T: Scalar + $bound, |
350 | | SA: StorageMut<T, R1, C1>, |
351 | | SB: Storage<T, R2, C2>, |
352 | | ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> { |
353 | | |
354 | | #[inline] |
355 | 0 | fn $method_assign(&mut self, rhs: Matrix<T, R2, C2, SB>) { |
356 | 0 | self.$method_assign(&rhs) |
357 | 0 | } |
358 | | } |
359 | | } |
360 | | ); |
361 | | |
362 | | componentwise_binop_impl!(Add, add, ClosedAddAssign; |
363 | | AddAssign, add_assign, add_assign_statically_unchecked, add_assign_statically_unchecked_mut; |
364 | | add_to, add_to_statically_unchecked_uninit); |
365 | | componentwise_binop_impl!(Sub, sub, ClosedSubAssign; |
366 | | SubAssign, sub_assign, sub_assign_statically_unchecked, sub_assign_statically_unchecked_mut; |
367 | | sub_to, sub_to_statically_unchecked_uninit); |
368 | | |
369 | | impl<T, R: DimName, C: DimName> iter::Sum for OMatrix<T, R, C> |
370 | | where |
371 | | T: Scalar + ClosedAddAssign + Zero, |
372 | | DefaultAllocator: Allocator<R, C>, |
373 | | { |
374 | | fn sum<I: Iterator<Item = OMatrix<T, R, C>>>(iter: I) -> OMatrix<T, R, C> { |
375 | | iter.fold(Matrix::zero(), |acc, x| acc + x) |
376 | | } |
377 | | } |
378 | | |
379 | | impl<T, C: Dim> iter::Sum for OMatrix<T, Dyn, C> |
380 | | where |
381 | | T: Scalar + ClosedAddAssign + Zero, |
382 | | DefaultAllocator: Allocator<Dyn, C>, |
383 | | { |
384 | | /// # Example |
385 | | /// ``` |
386 | | /// # use nalgebra::DVector; |
387 | | /// assert_eq!(vec![DVector::repeat(3, 1.0f64), |
388 | | /// DVector::repeat(3, 1.0f64), |
389 | | /// DVector::repeat(3, 1.0f64)].into_iter().sum::<DVector<f64>>(), |
390 | | /// DVector::repeat(3, 1.0f64) + DVector::repeat(3, 1.0f64) + DVector::repeat(3, 1.0f64)); |
391 | | /// ``` |
392 | | /// |
393 | | /// # Panics |
394 | | /// Panics if the iterator is empty: |
395 | | /// ```should_panic |
396 | | /// # use std::iter; |
397 | | /// # use nalgebra::DMatrix; |
398 | | /// iter::empty::<DMatrix<f64>>().sum::<DMatrix<f64>>(); // panics! |
399 | | /// ``` |
400 | | fn sum<I: Iterator<Item = OMatrix<T, Dyn, C>>>(mut iter: I) -> OMatrix<T, Dyn, C> { |
401 | | match iter.next() { |
402 | | Some(first) => iter.fold(first, |acc, x| acc + x), |
403 | | None => { |
404 | | panic!("Cannot compute `sum` of empty iterator.") |
405 | | } |
406 | | } |
407 | | } |
408 | | } |
409 | | |
410 | | impl<'a, T, R: DimName, C: DimName> iter::Sum<&'a OMatrix<T, R, C>> for OMatrix<T, R, C> |
411 | | where |
412 | | T: Scalar + ClosedAddAssign + Zero, |
413 | | DefaultAllocator: Allocator<R, C>, |
414 | | { |
415 | | fn sum<I: Iterator<Item = &'a OMatrix<T, R, C>>>(iter: I) -> OMatrix<T, R, C> { |
416 | | iter.fold(Matrix::zero(), |acc, x| acc + x) |
417 | | } |
418 | | } |
419 | | |
420 | | impl<'a, T, C: Dim> iter::Sum<&'a OMatrix<T, Dyn, C>> for OMatrix<T, Dyn, C> |
421 | | where |
422 | | T: Scalar + ClosedAddAssign + Zero, |
423 | | DefaultAllocator: Allocator<Dyn, C>, |
424 | | { |
425 | | /// # Example |
426 | | /// ``` |
427 | | /// # use nalgebra::DVector; |
428 | | /// let v = &DVector::repeat(3, 1.0f64); |
429 | | /// |
430 | | /// assert_eq!(vec![v, v, v].into_iter().sum::<DVector<f64>>(), |
431 | | /// v + v + v); |
432 | | /// ``` |
433 | | /// |
434 | | /// # Panics |
435 | | /// Panics if the iterator is empty: |
436 | | /// ```should_panic |
437 | | /// # use std::iter; |
438 | | /// # use nalgebra::DMatrix; |
439 | | /// iter::empty::<&DMatrix<f64>>().sum::<DMatrix<f64>>(); // panics! |
440 | | /// ``` |
441 | | fn sum<I: Iterator<Item = &'a OMatrix<T, Dyn, C>>>(mut iter: I) -> OMatrix<T, Dyn, C> { |
442 | | if let Some(first) = iter.next() { |
443 | | iter.fold(first.clone(), |acc, x| acc + x) |
444 | | } else { |
445 | | panic!("Cannot compute `sum` of empty iterator.") |
446 | | } |
447 | | } |
448 | | } |
449 | | |
450 | | /* |
451 | | * |
452 | | * Multiplication |
453 | | * |
454 | | */ |
455 | | |
456 | | // Matrix × Scalar |
457 | | // Matrix / Scalar |
458 | | macro_rules! componentwise_scalarop_impl( |
459 | | ($Trait: ident, $method: ident, $bound: ident; |
460 | | $TraitAssign: ident, $method_assign: ident) => { |
461 | | impl<T, R: Dim, C: Dim, S> $Trait<T> for Matrix<T, R, C, S> |
462 | | where T: Scalar + $bound, |
463 | | S: Storage<T, R, C>, |
464 | | DefaultAllocator: Allocator<R, C> { |
465 | | type Output = OMatrix<T, R, C>; |
466 | | |
467 | | #[inline] |
468 | 0 | fn $method(self, rhs: T) -> Self::Output { |
469 | 0 | let mut res = self.into_owned(); |
470 | | |
471 | | // XXX: optimize our iterator! |
472 | | // |
473 | | // Using our own iterator prevents loop unrolling, which breaks some optimization |
474 | | // (like SIMD). On the other hand, using the slice iterator is 4x faster. |
475 | | |
476 | | // for left in res.iter_mut() { |
477 | 0 | for left in res.as_mut_slice().iter_mut() { |
478 | 0 | *left = left.clone().$method(rhs.clone()) |
479 | | } |
480 | | |
481 | 0 | res |
482 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Mul<f64>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Mul<f64>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Mul<f64>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Div<f64>>::div |
483 | | } |
484 | | |
485 | | impl<'a, T, R: Dim, C: Dim, S> $Trait<T> for &'a Matrix<T, R, C, S> |
486 | | where T: Scalar + $bound, |
487 | | S: Storage<T, R, C>, |
488 | | DefaultAllocator: Allocator<R, C> { |
489 | | type Output = OMatrix<T, R, C>; |
490 | | |
491 | | #[inline] |
492 | 0 | fn $method(self, rhs: T) -> Self::Output { |
493 | 0 | self.clone_owned().$method(rhs) |
494 | 0 | } Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Div<f64>>::div Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::Mul<f64>>::mul |
495 | | } |
496 | | |
497 | | impl<T, R: Dim, C: Dim, S> $TraitAssign<T> for Matrix<T, R, C, S> |
498 | | where T: Scalar + $bound, |
499 | | S: StorageMut<T, R, C> { |
500 | | #[inline] |
501 | 0 | fn $method_assign(&mut self, rhs: T) { |
502 | 0 | for j in 0 .. self.ncols() { |
503 | 0 | for i in 0 .. self.nrows() { |
504 | 0 | unsafe { self.get_unchecked_mut((i, j)).$method_assign(rhs.clone()) }; |
505 | 0 | } |
506 | | } |
507 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>> as core::ops::arith::DivAssign<f64>>::div_assign Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>> as core::ops::arith::MulAssign<f64>>::mul_assign |
508 | | } |
509 | | } |
510 | | ); |
511 | | |
512 | | componentwise_scalarop_impl!(Mul, mul, ClosedMulAssign; MulAssign, mul_assign); |
513 | | componentwise_scalarop_impl!(Div, div, ClosedDivAssign; DivAssign, div_assign); |
514 | | |
515 | | macro_rules! left_scalar_mul_impl( |
516 | | ($($T: ty),* $(,)*) => {$( |
517 | | impl<R: Dim, C: Dim, S: Storage<$T, R, C>> Mul<Matrix<$T, R, C, S>> for $T |
518 | | where DefaultAllocator: Allocator<R, C> { |
519 | | type Output = OMatrix<$T, R, C>; |
520 | | |
521 | | #[inline] |
522 | 210 | fn mul(self, rhs: Matrix<$T, R, C, S>) -> Self::Output { |
523 | 210 | let mut res = rhs.into_owned(); |
524 | | |
525 | | // XXX: optimize our iterator! |
526 | | // |
527 | | // Using our own iterator prevents loop unrolling, which breaks some optimization |
528 | | // (like SIMD). On the other hand, using the slice iterator is 4x faster. |
529 | | |
530 | | // for rhs in res.iter_mut() { |
531 | 630 | for rhs in res.as_mut_slice().iter_mut() { |
532 | 630 | *rhs *= self |
533 | | } |
534 | | |
535 | 210 | res |
536 | 210 | } Unexecuted instantiation: <f64 as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>>>>::mul <f64 as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::mul Line | Count | Source | 522 | 210 | fn mul(self, rhs: Matrix<$T, R, C, S>) -> Self::Output { | 523 | 210 | let mut res = rhs.into_owned(); | 524 | | | 525 | | // XXX: optimize our iterator! | 526 | | // | 527 | | // Using our own iterator prevents loop unrolling, which breaks some optimization | 528 | | // (like SIMD). On the other hand, using the slice iterator is 4x faster. | 529 | | | 530 | | // for rhs in res.iter_mut() { | 531 | 630 | for rhs in res.as_mut_slice().iter_mut() { | 532 | 630 | *rhs *= self | 533 | | } | 534 | | | 535 | 210 | res | 536 | 210 | } |
Unexecuted instantiation: <f64 as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<4>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 4, 3>>>>::mul |
537 | | } |
538 | | |
539 | | impl<'b, R: Dim, C: Dim, S: Storage<$T, R, C>> Mul<&'b Matrix<$T, R, C, S>> for $T |
540 | | where DefaultAllocator: Allocator<R, C> { |
541 | | type Output = OMatrix<$T, R, C>; |
542 | | |
543 | | #[inline] |
544 | | fn mul(self, rhs: &'b Matrix<$T, R, C, S>) -> Self::Output { |
545 | | self * rhs.clone_owned() |
546 | | } |
547 | | } |
548 | | )*} |
549 | | ); |
550 | | |
551 | | left_scalar_mul_impl!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64); |
552 | | |
553 | | // Matrix × Matrix |
554 | | impl<'b, T, R1: Dim, C1: Dim, R2: Dim, C2: Dim, SA, SB> Mul<&'b Matrix<T, R2, C2, SB>> |
555 | | for &Matrix<T, R1, C1, SA> |
556 | | where |
557 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
558 | | SA: Storage<T, R1, C1>, |
559 | | SB: Storage<T, R2, C2>, |
560 | | DefaultAllocator: Allocator<R1, C2>, |
561 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C2>, |
562 | | { |
563 | | type Output = OMatrix<T, R1, C2>; |
564 | | |
565 | | #[inline] |
566 | 3.23k | fn mul(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { |
567 | 3.23k | let mut res = Matrix::uninit(self.shape_generic().0, rhs.shape_generic().1); |
568 | | unsafe { |
569 | | // SAFETY: this is OK because status = Uninit && bevy == 0 |
570 | 3.23k | gemm_uninit(Uninit, &mut res, T::one(), self, rhs, T::zero()); |
571 | 3.23k | res.assume_init() |
572 | | } |
573 | 3.23k | } Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 1, 6>> as core::ops::arith::Mul<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>>::mul Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 1, 6>> as core::ops::arith::Mul<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>>>>::mul Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Mul<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::mul <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Mul>::mul Line | Count | Source | 566 | 3.23k | fn mul(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { | 567 | 3.23k | let mut res = Matrix::uninit(self.shape_generic().0, rhs.shape_generic().1); | 568 | | unsafe { | 569 | | // SAFETY: this is OK because status = Uninit && bevy == 0 | 570 | 3.23k | gemm_uninit(Uninit, &mut res, T::one(), self, rhs, T::zero()); | 571 | 3.23k | res.assume_init() | 572 | | } | 573 | 3.23k | } |
Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<4>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 4, 3>> as core::ops::arith::Mul<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::mul Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Mul<&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>>::mul Unexecuted instantiation: <&nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Mul>::mul |
574 | | } |
575 | | |
576 | | impl<T, R1: Dim, C1: Dim, R2: Dim, C2: Dim, SA, SB> Mul<Matrix<T, R2, C2, SB>> |
577 | | for &Matrix<T, R1, C1, SA> |
578 | | where |
579 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
580 | | SB: Storage<T, R2, C2>, |
581 | | SA: Storage<T, R1, C1>, |
582 | | DefaultAllocator: Allocator<R1, C2>, |
583 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C2>, |
584 | | { |
585 | | type Output = OMatrix<T, R1, C2>; |
586 | | |
587 | | #[inline] |
588 | 3.23k | fn mul(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { |
589 | 3.23k | self * &rhs |
590 | 3.23k | } |
591 | | } |
592 | | |
593 | | impl<'b, T, R1: Dim, C1: Dim, R2: Dim, C2: Dim, SA, SB> Mul<&'b Matrix<T, R2, C2, SB>> |
594 | | for Matrix<T, R1, C1, SA> |
595 | | where |
596 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
597 | | SB: Storage<T, R2, C2>, |
598 | | SA: Storage<T, R1, C1>, |
599 | | DefaultAllocator: Allocator<R1, C2>, |
600 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C2>, |
601 | | { |
602 | | type Output = OMatrix<T, R1, C2>; |
603 | | |
604 | | #[inline] |
605 | | fn mul(self, rhs: &'b Matrix<T, R2, C2, SB>) -> Self::Output { |
606 | | &self * rhs |
607 | | } |
608 | | } |
609 | | |
610 | | impl<T, R1: Dim, C1: Dim, R2: Dim, C2: Dim, SA, SB> Mul<Matrix<T, R2, C2, SB>> |
611 | | for Matrix<T, R1, C1, SA> |
612 | | where |
613 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
614 | | SB: Storage<T, R2, C2>, |
615 | | SA: Storage<T, R1, C1>, |
616 | | DefaultAllocator: Allocator<R1, C2>, |
617 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C2>, |
618 | | { |
619 | | type Output = OMatrix<T, R1, C2>; |
620 | | |
621 | | #[inline] |
622 | 0 | fn mul(self, rhs: Matrix<T, R2, C2, SB>) -> Self::Output { |
623 | 0 | &self * &rhs |
624 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 1, 6>> as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 1, 6>> as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>>>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 3>> as core::ops::arith::Mul>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<4>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 4, 3>> as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Mul<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 1>>>>::mul Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<6>, nalgebra::base::array_storage::ArrayStorage<f64, 6, 6>> as core::ops::arith::Mul>::mul |
625 | | } |
626 | | |
627 | | // TODO: this is too restrictive: |
628 | | // − we can't use `a *= b` when `a` is a mutable slice. |
629 | | // − we can't use `a *= b` when C2 is not equal to C1. |
630 | | impl<T, R1, C1, R2, SA, SB> MulAssign<Matrix<T, R2, C1, SB>> for Matrix<T, R1, C1, SA> |
631 | | where |
632 | | R1: Dim, |
633 | | C1: Dim, |
634 | | R2: Dim, |
635 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
636 | | SB: Storage<T, R2, C1>, |
637 | | SA: StorageMut<T, R1, C1> + IsContiguous + Clone, // TODO: get rid of the IsContiguous |
638 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C1>, |
639 | | DefaultAllocator: Allocator<R1, C1, Buffer<T> = SA>, |
640 | | { |
641 | | #[inline] |
642 | 3.23k | fn mul_assign(&mut self, rhs: Matrix<T, R2, C1, SB>) { |
643 | 3.23k | *self = &*self * rhs |
644 | 3.23k | } |
645 | | } |
646 | | |
647 | | impl<'b, T, R1, C1, R2, SA, SB> MulAssign<&'b Matrix<T, R2, C1, SB>> for Matrix<T, R1, C1, SA> |
648 | | where |
649 | | R1: Dim, |
650 | | C1: Dim, |
651 | | R2: Dim, |
652 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
653 | | SB: Storage<T, R2, C1>, |
654 | | SA: StorageMut<T, R1, C1> + IsContiguous + Clone, // TODO: get rid of the IsContiguous |
655 | | ShapeConstraint: AreMultipliable<R1, C1, R2, C1>, |
656 | | // TODO: this is too restrictive. See comments for the non-ref version. |
657 | | DefaultAllocator: Allocator<R1, C1, Buffer<T> = SA>, |
658 | | { |
659 | | #[inline] |
660 | | fn mul_assign(&mut self, rhs: &'b Matrix<T, R2, C1, SB>) { |
661 | | *self = &*self * rhs |
662 | | } |
663 | | } |
664 | | |
665 | | /// # Special multiplications. |
666 | | impl<T, R1: Dim, C1: Dim, SA> Matrix<T, R1, C1, SA> |
667 | | where |
668 | | T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, |
669 | | SA: Storage<T, R1, C1>, |
670 | | { |
671 | | /// Equivalent to `self.transpose() * rhs`. |
672 | | #[inline] |
673 | | #[must_use] |
674 | | pub fn tr_mul<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> OMatrix<T, C1, C2> |
675 | | where |
676 | | SB: Storage<T, R2, C2>, |
677 | | DefaultAllocator: Allocator<C1, C2>, |
678 | | ShapeConstraint: SameNumberOfRows<R1, R2>, |
679 | | { |
680 | | let mut res = Matrix::uninit(self.shape_generic().1, rhs.shape_generic().1); |
681 | | self.xx_mul_to_uninit(Uninit, rhs, &mut res, |a, b| a.dot(b)); |
682 | | // SAFETY: this is OK because the result is now initialized. |
683 | | unsafe { res.assume_init() } |
684 | | } |
685 | | |
686 | | /// Equivalent to `self.adjoint() * rhs`. |
687 | | #[inline] |
688 | | #[must_use] |
689 | | pub fn ad_mul<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> OMatrix<T, C1, C2> |
690 | | where |
691 | | T: SimdComplexField, |
692 | | SB: Storage<T, R2, C2>, |
693 | | DefaultAllocator: Allocator<C1, C2>, |
694 | | ShapeConstraint: SameNumberOfRows<R1, R2>, |
695 | | { |
696 | | let mut res = Matrix::uninit(self.shape_generic().1, rhs.shape_generic().1); |
697 | | self.xx_mul_to_uninit(Uninit, rhs, &mut res, |a, b| a.dotc(b)); |
698 | | // SAFETY: this is OK because the result is now initialized. |
699 | | unsafe { res.assume_init() } |
700 | | } |
701 | | |
702 | | #[inline(always)] |
703 | | fn xx_mul_to_uninit<Status, R2: Dim, C2: Dim, SB, R3: Dim, C3: Dim, SC>( |
704 | | &self, |
705 | | _status: Status, |
706 | | rhs: &Matrix<T, R2, C2, SB>, |
707 | | out: &mut Matrix<Status::Value, R3, C3, SC>, |
708 | | dot: impl Fn( |
709 | | &VectorView<'_, T, R1, SA::RStride, SA::CStride>, |
710 | | &VectorView<'_, T, R2, SB::RStride, SB::CStride>, |
711 | | ) -> T, |
712 | | ) where |
713 | | Status: InitStatus<T>, |
714 | | SB: RawStorage<T, R2, C2>, |
715 | | SC: RawStorageMut<Status::Value, R3, C3>, |
716 | | ShapeConstraint: SameNumberOfRows<R1, R2> + DimEq<C1, R3> + DimEq<C2, C3>, |
717 | | { |
718 | | let (nrows1, ncols1) = self.shape(); |
719 | | let (nrows2, ncols2) = rhs.shape(); |
720 | | let (nrows3, ncols3) = out.shape(); |
721 | | |
722 | | assert!( |
723 | | nrows1 == nrows2, |
724 | | "Matrix multiplication dimensions mismatch {:?} and {:?}: left rows != right rows.", |
725 | | self.shape(), |
726 | | rhs.shape() |
727 | | ); |
728 | | assert!( |
729 | | ncols1 == nrows3, |
730 | | "Matrix multiplication output dimensions mismatch {:?} and {:?}: left cols != right rows.", |
731 | | self.shape(), |
732 | | out.shape() |
733 | | ); |
734 | | assert!( |
735 | | ncols2 == ncols3, |
736 | | "Matrix multiplication output dimensions mismatch {:?} and {:?}: left cols != right cols", |
737 | | rhs.shape(), |
738 | | out.shape() |
739 | | ); |
740 | | |
741 | | for i in 0..ncols1 { |
742 | | for j in 0..ncols2 { |
743 | | let dot = dot(&self.column(i), &rhs.column(j)); |
744 | | let elt = unsafe { out.get_unchecked_mut((i, j)) }; |
745 | | Status::init(elt, dot); |
746 | | } |
747 | | } |
748 | | } |
749 | | |
750 | | /// Equivalent to `self.transpose() * rhs` but stores the result into `out` to avoid |
751 | | /// allocations. |
752 | | #[inline] |
753 | | pub fn tr_mul_to<R2: Dim, C2: Dim, SB, R3: Dim, C3: Dim, SC>( |
754 | | &self, |
755 | | rhs: &Matrix<T, R2, C2, SB>, |
756 | | out: &mut Matrix<T, R3, C3, SC>, |
757 | | ) where |
758 | | SB: Storage<T, R2, C2>, |
759 | | SC: StorageMut<T, R3, C3>, |
760 | | ShapeConstraint: SameNumberOfRows<R1, R2> + DimEq<C1, R3> + DimEq<C2, C3>, |
761 | | { |
762 | | self.xx_mul_to_uninit(Init, rhs, out, |a, b| a.dot(b)) |
763 | | } |
764 | | |
765 | | /// Equivalent to `self.adjoint() * rhs` but stores the result into `out` to avoid |
766 | | /// allocations. |
767 | | #[inline] |
768 | | pub fn ad_mul_to<R2: Dim, C2: Dim, SB, R3: Dim, C3: Dim, SC>( |
769 | | &self, |
770 | | rhs: &Matrix<T, R2, C2, SB>, |
771 | | out: &mut Matrix<T, R3, C3, SC>, |
772 | | ) where |
773 | | T: SimdComplexField, |
774 | | SB: Storage<T, R2, C2>, |
775 | | SC: StorageMut<T, R3, C3>, |
776 | | ShapeConstraint: SameNumberOfRows<R1, R2> + DimEq<C1, R3> + DimEq<C2, C3>, |
777 | | { |
778 | | self.xx_mul_to_uninit(Init, rhs, out, |a, b| a.dotc(b)) |
779 | | } |
780 | | |
781 | | /// Equivalent to `self * rhs` but stores the result into `out` to avoid allocations. |
782 | | #[inline] |
783 | 0 | pub fn mul_to<R2: Dim, C2: Dim, SB, R3: Dim, C3: Dim, SC>( |
784 | 0 | &self, |
785 | 0 | rhs: &Matrix<T, R2, C2, SB>, |
786 | 0 | out: &mut Matrix<T, R3, C3, SC>, |
787 | 0 | ) where |
788 | 0 | SB: Storage<T, R2, C2>, |
789 | 0 | SC: StorageMut<T, R3, C3>, |
790 | 0 | ShapeConstraint: SameNumberOfRows<R3, R1> |
791 | 0 | + SameNumberOfColumns<C3, C2> |
792 | 0 | + AreMultipliable<R1, C1, R2, C2>, |
793 | | { |
794 | 0 | out.gemm(T::one(), self, rhs, T::zero()); |
795 | 0 | } Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::mul_to::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<3>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::mul_to::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::mul_to::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>> Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<2>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::mul_to::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>> Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<3>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::mul_to::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>> |
796 | | |
797 | | /// The kronecker product of two matrices (aka. tensor product of the corresponding linear |
798 | | /// maps). |
799 | | #[must_use] |
800 | | pub fn kronecker<R2: Dim, C2: Dim, SB>( |
801 | | &self, |
802 | | rhs: &Matrix<T, R2, C2, SB>, |
803 | | ) -> OMatrix<T, DimProd<R1, R2>, DimProd<C1, C2>> |
804 | | where |
805 | | T: ClosedMulAssign, |
806 | | R1: DimMul<R2>, |
807 | | C1: DimMul<C2>, |
808 | | SB: Storage<T, R2, C2>, |
809 | | DefaultAllocator: Allocator<DimProd<R1, R2>, DimProd<C1, C2>>, |
810 | | { |
811 | | let (nrows1, ncols1) = self.shape_generic(); |
812 | | let (nrows2, ncols2) = rhs.shape_generic(); |
813 | | |
814 | | let mut res = Matrix::uninit(nrows1.mul(nrows2), ncols1.mul(ncols2)); |
815 | | let mut data_res = res.data.ptr_mut(); |
816 | | |
817 | | unsafe { |
818 | | for j1 in 0..ncols1.value() { |
819 | | for j2 in 0..ncols2.value() { |
820 | | for i1 in 0..nrows1.value() { |
821 | | let coeff = self.get_unchecked((i1, j1)).clone(); |
822 | | |
823 | | for i2 in 0..nrows2.value() { |
824 | | *data_res = MaybeUninit::new( |
825 | | coeff.clone() * rhs.get_unchecked((i2, j2)).clone(), |
826 | | ); |
827 | | data_res = data_res.offset(1); |
828 | | } |
829 | | } |
830 | | } |
831 | | } |
832 | | |
833 | | // SAFETY: the result matrix has been initialized by the loop above. |
834 | | res.assume_init() |
835 | | } |
836 | | } |
837 | | } |
838 | | |
839 | | impl<T, D: DimName> iter::Product for OMatrix<T, D, D> |
840 | | where |
841 | | T: Scalar + Zero + One + ClosedMulAssign + ClosedAddAssign, |
842 | | DefaultAllocator: Allocator<D, D>, |
843 | | { |
844 | | fn product<I: Iterator<Item = OMatrix<T, D, D>>>(iter: I) -> OMatrix<T, D, D> { |
845 | | iter.fold(Matrix::one(), |acc, x| acc * x) |
846 | | } |
847 | | } |
848 | | |
849 | | impl<'a, T, D: DimName> iter::Product<&'a OMatrix<T, D, D>> for OMatrix<T, D, D> |
850 | | where |
851 | | T: Scalar + Zero + One + ClosedMulAssign + ClosedAddAssign, |
852 | | DefaultAllocator: Allocator<D, D>, |
853 | | { |
854 | | fn product<I: Iterator<Item = &'a OMatrix<T, D, D>>>(iter: I) -> OMatrix<T, D, D> { |
855 | | iter.fold(Matrix::one(), |acc, x| acc * x) |
856 | | } |
857 | | } |