Coverage Report

Created: 2026-03-14 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.34.1/src/base/blas.rs
Line
Count
Source
1
use crate::{RawStorage, SimdComplexField};
2
use num::{One, Zero};
3
use simba::scalar::{ClosedAddAssign, ClosedMulAssign};
4
5
use crate::base::allocator::Allocator;
6
use crate::base::blas_uninit::{axcpy_uninit, gemm_uninit, gemv_uninit};
7
use crate::base::constraint::{
8
    AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
9
};
10
use crate::base::dimension::{Const, Dim, Dyn, U1, U2, U3, U4};
11
use crate::base::storage::{Storage, StorageMut};
12
use crate::base::uninit::Init;
13
use crate::base::{
14
    DVectorView, DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, VectorView,
15
};
16
17
/// # Dot/scalar product
18
impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S>
19
where
20
    T: Scalar + Zero + ClosedAddAssign + ClosedMulAssign,
21
{
22
    #[inline(always)]
23
487
    fn dotx<R2: Dim, C2: Dim, SB>(
24
487
        &self,
25
487
        rhs: &Matrix<T, R2, C2, SB>,
26
487
        conjugate: impl Fn(T) -> T,
27
487
    ) -> T
28
487
    where
29
487
        SB: RawStorage<T, R2, C2>,
30
487
        ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,
31
    {
32
487
        assert!(
33
487
            self.nrows() == rhs.nrows(),
34
0
            "Dot product dimensions mismatch for shapes {:?} and {:?}: left rows != right rows.",
35
0
            self.shape(),
36
0
            rhs.shape(),
37
        );
38
39
487
        assert!(
40
487
            self.ncols() == rhs.ncols(),
41
0
            "Dot product dimensions mismatch for shapes {:?} and {:?}: left cols != right cols.",
42
0
            self.shape(),
43
0
            rhs.shape(),
44
        );
45
46
        // So we do some special cases for common fixed-size vectors of dimension lower than 8
47
        // because the `for` loop below won't be very efficient on those.
48
487
        if (R::is::<U2>() || R2::is::<U2>()) && (C::is::<U1>() || C2::is::<U1>()) {
49
            unsafe {
50
0
                let a = conjugate(self.get_unchecked((0, 0)).clone())
51
0
                    * rhs.get_unchecked((0, 0)).clone();
52
0
                let b = conjugate(self.get_unchecked((1, 0)).clone())
53
0
                    * rhs.get_unchecked((1, 0)).clone();
54
55
0
                return a + b;
56
            }
57
487
        }
58
487
        if (R::is::<U3>() || R2::is::<U3>()) && (C::is::<U1>() || C2::is::<U1>()) {
59
            unsafe {
60
487
                let a = conjugate(self.get_unchecked((0, 0)).clone())
61
487
                    * rhs.get_unchecked((0, 0)).clone();
62
487
                let b = conjugate(self.get_unchecked((1, 0)).clone())
63
487
                    * rhs.get_unchecked((1, 0)).clone();
64
487
                let c = conjugate(self.get_unchecked((2, 0)).clone())
65
487
                    * rhs.get_unchecked((2, 0)).clone();
66
67
487
                return a + b + c;
68
            }
69
0
        }
70
0
        if (R::is::<U4>() || R2::is::<U4>()) && (C::is::<U1>() || C2::is::<U1>()) {
71
            unsafe {
72
0
                let mut a = conjugate(self.get_unchecked((0, 0)).clone())
73
0
                    * rhs.get_unchecked((0, 0)).clone();
74
0
                let mut b = conjugate(self.get_unchecked((1, 0)).clone())
75
0
                    * rhs.get_unchecked((1, 0)).clone();
76
0
                let c = conjugate(self.get_unchecked((2, 0)).clone())
77
0
                    * rhs.get_unchecked((2, 0)).clone();
78
0
                let d = conjugate(self.get_unchecked((3, 0)).clone())
79
0
                    * rhs.get_unchecked((3, 0)).clone();
80
81
0
                a += c;
82
0
                b += d;
83
84
0
                return a + b;
85
            }
86
0
        }
87
88
        // All this is inspired from the "unrolled version" discussed in:
89
        // https://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/
90
        //
91
        // And this comment from bluss:
92
        // https://users.rust-lang.org/t/how-to-zip-two-slices-efficiently/2048/12
93
0
        let mut res = T::zero();
94
95
        // We have to define them outside of the loop (and not inside at first assignment)
96
        // otherwise vectorization won't kick in for some reason.
97
        let mut acc0;
98
        let mut acc1;
99
        let mut acc2;
100
        let mut acc3;
101
        let mut acc4;
102
        let mut acc5;
103
        let mut acc6;
104
        let mut acc7;
105
106
0
        for j in 0..self.ncols() {
107
0
            let mut i = 0;
108
109
0
            acc0 = T::zero();
110
0
            acc1 = T::zero();
111
0
            acc2 = T::zero();
112
0
            acc3 = T::zero();
113
0
            acc4 = T::zero();
114
0
            acc5 = T::zero();
115
0
            acc6 = T::zero();
116
0
            acc7 = T::zero();
117
118
0
            while self.nrows() - i >= 8 {
119
0
                acc0 += unsafe {
120
0
                    conjugate(self.get_unchecked((i, j)).clone())
121
0
                        * rhs.get_unchecked((i, j)).clone()
122
0
                };
123
0
                acc1 += unsafe {
124
0
                    conjugate(self.get_unchecked((i + 1, j)).clone())
125
0
                        * rhs.get_unchecked((i + 1, j)).clone()
126
0
                };
127
0
                acc2 += unsafe {
128
0
                    conjugate(self.get_unchecked((i + 2, j)).clone())
129
0
                        * rhs.get_unchecked((i + 2, j)).clone()
130
0
                };
131
0
                acc3 += unsafe {
132
0
                    conjugate(self.get_unchecked((i + 3, j)).clone())
133
0
                        * rhs.get_unchecked((i + 3, j)).clone()
134
0
                };
135
0
                acc4 += unsafe {
136
0
                    conjugate(self.get_unchecked((i + 4, j)).clone())
137
0
                        * rhs.get_unchecked((i + 4, j)).clone()
138
0
                };
139
0
                acc5 += unsafe {
140
0
                    conjugate(self.get_unchecked((i + 5, j)).clone())
141
0
                        * rhs.get_unchecked((i + 5, j)).clone()
142
0
                };
143
0
                acc6 += unsafe {
144
0
                    conjugate(self.get_unchecked((i + 6, j)).clone())
145
0
                        * rhs.get_unchecked((i + 6, j)).clone()
146
0
                };
147
0
                acc7 += unsafe {
148
0
                    conjugate(self.get_unchecked((i + 7, j)).clone())
149
0
                        * rhs.get_unchecked((i + 7, j)).clone()
150
0
                };
151
0
                i += 8;
152
0
            }
153
154
0
            res += acc0 + acc4;
155
0
            res += acc1 + acc5;
156
0
            res += acc2 + acc6;
157
0
            res += acc3 + acc7;
158
159
0
            for k in i..self.nrows() {
160
0
                res += unsafe {
161
0
                    conjugate(self.get_unchecked((k, j)).clone())
162
0
                        * rhs.get_unchecked((k, j)).clone()
163
0
                }
164
            }
165
        }
166
167
0
        res
168
487
    }
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>>>::dotx::<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>, <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>>>::dot<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>>::{closure#0}>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::dotx::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>::dotx::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>>>::dotx::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
Line
Count
Source
23
487
    fn dotx<R2: Dim, C2: Dim, SB>(
24
487
        &self,
25
487
        rhs: &Matrix<T, R2, C2, SB>,
26
487
        conjugate: impl Fn(T) -> T,
27
487
    ) -> T
28
487
    where
29
487
        SB: RawStorage<T, R2, C2>,
30
487
        ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,
31
    {
32
487
        assert!(
33
487
            self.nrows() == rhs.nrows(),
34
0
            "Dot product dimensions mismatch for shapes {:?} and {:?}: left rows != right rows.",
35
0
            self.shape(),
36
0
            rhs.shape(),
37
        );
38
39
487
        assert!(
40
487
            self.ncols() == rhs.ncols(),
41
0
            "Dot product dimensions mismatch for shapes {:?} and {:?}: left cols != right cols.",
42
0
            self.shape(),
43
0
            rhs.shape(),
44
        );
45
46
        // So we do some special cases for common fixed-size vectors of dimension lower than 8
47
        // because the `for` loop below won't be very efficient on those.
48
487
        if (R::is::<U2>() || R2::is::<U2>()) && (C::is::<U1>() || C2::is::<U1>()) {
49
            unsafe {
50
0
                let a = conjugate(self.get_unchecked((0, 0)).clone())
51
0
                    * rhs.get_unchecked((0, 0)).clone();
52
0
                let b = conjugate(self.get_unchecked((1, 0)).clone())
53
0
                    * rhs.get_unchecked((1, 0)).clone();
54
55
0
                return a + b;
56
            }
57
487
        }
58
487
        if (R::is::<U3>() || R2::is::<U3>()) && (C::is::<U1>() || C2::is::<U1>()) {
59
            unsafe {
60
487
                let a = conjugate(self.get_unchecked((0, 0)).clone())
61
487
                    * rhs.get_unchecked((0, 0)).clone();
62
487
                let b = conjugate(self.get_unchecked((1, 0)).clone())
63
487
                    * rhs.get_unchecked((1, 0)).clone();
64
487
                let c = conjugate(self.get_unchecked((2, 0)).clone())
65
487
                    * rhs.get_unchecked((2, 0)).clone();
66
67
487
                return a + b + c;
68
            }
69
0
        }
70
0
        if (R::is::<U4>() || R2::is::<U4>()) && (C::is::<U1>() || C2::is::<U1>()) {
71
            unsafe {
72
0
                let mut a = conjugate(self.get_unchecked((0, 0)).clone())
73
0
                    * rhs.get_unchecked((0, 0)).clone();
74
0
                let mut b = conjugate(self.get_unchecked((1, 0)).clone())
75
0
                    * rhs.get_unchecked((1, 0)).clone();
76
0
                let c = conjugate(self.get_unchecked((2, 0)).clone())
77
0
                    * rhs.get_unchecked((2, 0)).clone();
78
0
                let d = conjugate(self.get_unchecked((3, 0)).clone())
79
0
                    * rhs.get_unchecked((3, 0)).clone();
80
81
0
                a += c;
82
0
                b += d;
83
84
0
                return a + b;
85
            }
86
0
        }
87
88
        // All this is inspired from the "unrolled version" discussed in:
89
        // https://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/
90
        //
91
        // And this comment from bluss:
92
        // https://users.rust-lang.org/t/how-to-zip-two-slices-efficiently/2048/12
93
0
        let mut res = T::zero();
94
95
        // We have to define them outside of the loop (and not inside at first assignment)
96
        // otherwise vectorization won't kick in for some reason.
97
        let mut acc0;
98
        let mut acc1;
99
        let mut acc2;
100
        let mut acc3;
101
        let mut acc4;
102
        let mut acc5;
103
        let mut acc6;
104
        let mut acc7;
105
106
0
        for j in 0..self.ncols() {
107
0
            let mut i = 0;
108
109
0
            acc0 = T::zero();
110
0
            acc1 = T::zero();
111
0
            acc2 = T::zero();
112
0
            acc3 = T::zero();
113
0
            acc4 = T::zero();
114
0
            acc5 = T::zero();
115
0
            acc6 = T::zero();
116
0
            acc7 = T::zero();
117
118
0
            while self.nrows() - i >= 8 {
119
0
                acc0 += unsafe {
120
0
                    conjugate(self.get_unchecked((i, j)).clone())
121
0
                        * rhs.get_unchecked((i, j)).clone()
122
0
                };
123
0
                acc1 += unsafe {
124
0
                    conjugate(self.get_unchecked((i + 1, j)).clone())
125
0
                        * rhs.get_unchecked((i + 1, j)).clone()
126
0
                };
127
0
                acc2 += unsafe {
128
0
                    conjugate(self.get_unchecked((i + 2, j)).clone())
129
0
                        * rhs.get_unchecked((i + 2, j)).clone()
130
0
                };
131
0
                acc3 += unsafe {
132
0
                    conjugate(self.get_unchecked((i + 3, j)).clone())
133
0
                        * rhs.get_unchecked((i + 3, j)).clone()
134
0
                };
135
0
                acc4 += unsafe {
136
0
                    conjugate(self.get_unchecked((i + 4, j)).clone())
137
0
                        * rhs.get_unchecked((i + 4, j)).clone()
138
0
                };
139
0
                acc5 += unsafe {
140
0
                    conjugate(self.get_unchecked((i + 5, j)).clone())
141
0
                        * rhs.get_unchecked((i + 5, j)).clone()
142
0
                };
143
0
                acc6 += unsafe {
144
0
                    conjugate(self.get_unchecked((i + 6, j)).clone())
145
0
                        * rhs.get_unchecked((i + 6, j)).clone()
146
0
                };
147
0
                acc7 += unsafe {
148
0
                    conjugate(self.get_unchecked((i + 7, j)).clone())
149
0
                        * rhs.get_unchecked((i + 7, j)).clone()
150
0
                };
151
0
                i += 8;
152
0
            }
153
154
0
            res += acc0 + acc4;
155
0
            res += acc1 + acc5;
156
0
            res += acc2 + acc6;
157
0
            res += acc3 + acc7;
158
159
0
            for k in i..self.nrows() {
160
0
                res += unsafe {
161
0
                    conjugate(self.get_unchecked((k, j)).clone())
162
0
                        * rhs.get_unchecked((k, j)).clone()
163
0
                }
164
            }
165
        }
166
167
0
        res
168
487
    }
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>>>::dotx::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>, <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>>::dot<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>::{closure#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>>>::dotx::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>::dotx::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>>::dotx::<nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::dotx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>>::dotx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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<2>>>>::dotx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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<6>>>>::dotx::<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>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
169
170
    /// The dot product between two vectors or matrices (seen as vectors).
171
    ///
172
    /// This is equal to `self.transpose() * rhs`. For the sesquilinear complex dot product, use
173
    /// `self.dotc(rhs)`.
174
    ///
175
    /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix
176
    /// multiplication, use one of: `.gemm`, `.mul_to`, `.mul`, the `*` operator.
177
    ///
178
    /// # Example
179
    /// ```
180
    /// # use nalgebra::{Vector3, Matrix2x3};
181
    /// let vec1 = Vector3::new(1.0, 2.0, 3.0);
182
    /// let vec2 = Vector3::new(0.1, 0.2, 0.3);
183
    /// assert_eq!(vec1.dot(&vec2), 1.4);
184
    ///
185
    /// let mat1 = Matrix2x3::new(1.0, 2.0, 3.0,
186
    ///                           4.0, 5.0, 6.0);
187
    /// let mat2 = Matrix2x3::new(0.1, 0.2, 0.3,
188
    ///                           0.4, 0.5, 0.6);
189
    /// assert_eq!(mat1.dot(&mat2), 9.1);
190
    /// ```
191
    ///
192
    #[inline]
193
    #[must_use]
194
0
    pub fn dot<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> T
195
0
    where
196
0
        SB: RawStorage<T, R2, C2>,
197
0
        ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,
198
    {
199
0
        self.dotx(rhs, |e| e)
200
0
    }
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>>>::dot::<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>>
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>>>::dot::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
201
202
    /// The conjugate-linear dot product between two vectors or matrices (seen as vectors).
203
    ///
204
    /// This is equal to `self.adjoint() * rhs`.
205
    /// For real vectors, this is identical to `self.dot(&rhs)`.
206
    /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix
207
    /// multiplication, use one of: `.gemm`, `.mul_to`, `.mul`, the `*` operator.
208
    ///
209
    /// # Example
210
    /// ```
211
    /// # use nalgebra::{Vector2, Complex};
212
    /// let vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0));
213
    /// let vec2 = Vector2::new(Complex::new(0.4, 0.3), Complex::new(0.2, 0.1));
214
    /// assert_eq!(vec1.dotc(&vec2), Complex::new(2.0, -1.0));
215
    ///
216
    /// // Note that for complex vectors, we generally have:
217
    /// // vec1.dotc(&vec2) != vec2.dot(&vec2)
218
    /// assert_ne!(vec1.dotc(&vec2), vec1.dot(&vec2));
219
    /// ```
220
    #[inline]
221
    #[must_use]
222
487
    pub fn dotc<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> T
223
487
    where
224
487
        T: SimdComplexField,
225
487
        SB: RawStorage<T, R2, C2>,
226
487
        ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,
227
    {
228
487
        self.dotx(rhs, T::simd_conjugate)
229
487
    }
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::dotc::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, 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::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>>>::dotc::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>
<nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>>>::dotc::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<3>>>
Line
Count
Source
222
487
    pub fn dotc<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> T
223
487
    where
224
487
        T: SimdComplexField,
225
487
        SB: RawStorage<T, R2, C2>,
226
487
        ShapeConstraint: DimEq<R, R2> + DimEq<C, C2>,
227
    {
228
487
        self.dotx(rhs, T::simd_conjugate)
229
487
    }
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>>>::dotc::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
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>>>::dotc::<nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<3>, 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::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>>::dotc::<nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Const<6>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::dotc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<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<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>>::dotc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<2>>>>::dotc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorage<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<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<6>>>>::dotc::<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>>>
230
231
    /// The dot product between the transpose of `self` and `rhs`.
232
    ///
233
    /// # Example
234
    /// ```
235
    /// # use nalgebra::{Vector3, RowVector3, Matrix2x3, Matrix3x2};
236
    /// let vec1 = Vector3::new(1.0, 2.0, 3.0);
237
    /// let vec2 = RowVector3::new(0.1, 0.2, 0.3);
238
    /// assert_eq!(vec1.tr_dot(&vec2), 1.4);
239
    ///
240
    /// let mat1 = Matrix2x3::new(1.0, 2.0, 3.0,
241
    ///                           4.0, 5.0, 6.0);
242
    /// let mat2 = Matrix3x2::new(0.1, 0.4,
243
    ///                           0.2, 0.5,
244
    ///                           0.3, 0.6);
245
    /// assert_eq!(mat1.tr_dot(&mat2), 9.1);
246
    /// ```
247
    #[inline]
248
    #[must_use]
249
    pub fn tr_dot<R2: Dim, C2: Dim, SB>(&self, rhs: &Matrix<T, R2, C2, SB>) -> T
250
    where
251
        SB: RawStorage<T, R2, C2>,
252
        ShapeConstraint: DimEq<C, R2> + DimEq<R, C2>,
253
    {
254
        let (nrows, ncols) = self.shape();
255
        assert_eq!(
256
            (ncols, nrows),
257
            rhs.shape(),
258
            "Transposed dot product dimension mismatch."
259
        );
260
261
        let mut res = T::zero();
262
263
        for j in 0..self.nrows() {
264
            for i in 0..self.ncols() {
265
                res += unsafe {
266
                    self.get_unchecked((j, i)).clone() * rhs.get_unchecked((i, j)).clone()
267
                }
268
            }
269
        }
270
271
        res
272
    }
273
}
274
275
/// # BLAS functions
276
impl<T, D: Dim, S> Vector<T, D, S>
277
where
278
    T: Scalar + Zero + ClosedAddAssign + ClosedMulAssign,
279
    S: StorageMut<T, D>,
280
{
281
    /// Computes `self = a * x * c + b * self`.
282
    ///
283
    /// If `b` is zero, `self` is never read from.
284
    ///
285
    /// # Example
286
    /// ```
287
    /// # use nalgebra::Vector3;
288
    /// let mut vec1 = Vector3::new(1.0, 2.0, 3.0);
289
    /// let vec2 = Vector3::new(0.1, 0.2, 0.3);
290
    /// vec1.axcpy(5.0, &vec2, 2.0, 5.0);
291
    /// assert_eq!(vec1, Vector3::new(6.0, 12.0, 18.0));
292
    /// ```
293
    #[inline]
294
    #[allow(clippy::many_single_char_names)]
295
0
    pub fn axcpy<D2: Dim, SB>(&mut self, a: T, x: &Vector<T, D2, SB>, c: T, b: T)
296
0
    where
297
0
        SB: Storage<T, D2>,
298
0
        ShapeConstraint: DimEq<D, D2>,
299
    {
300
0
        unsafe { axcpy_uninit(Init, self, a, x, c, b) };
301
0
    }
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::axcpy::<nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::axcpy::<nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
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<2>>>>::axcpy::<nalgebra::base::dimension::Dyn, 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<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>>>>::axcpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<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<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>>>>::axcpy::<nalgebra::base::dimension::Dyn, 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>>>
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>>>>::axcpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<6>>>>::axcpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<6>>>>::axcpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<5>>>
302
303
    /// Computes `self = a * x + b * self`.
304
    ///
305
    /// If `b` is zero, `self` is never read from.
306
    ///
307
    /// # Example
308
    /// ```
309
    /// # use nalgebra::Vector3;
310
    /// let mut vec1 = Vector3::new(1.0, 2.0, 3.0);
311
    /// let vec2 = Vector3::new(0.1, 0.2, 0.3);
312
    /// vec1.axpy(10.0, &vec2, 5.0);
313
    /// assert_eq!(vec1, Vector3::new(6.0, 12.0, 18.0));
314
    /// ```
315
    #[inline]
316
0
    pub fn axpy<D2: Dim, SB>(&mut self, a: T, x: &Vector<T, D2, SB>, b: T)
317
0
    where
318
0
        T: One,
319
0
        SB: Storage<T, D2>,
320
0
        ShapeConstraint: DimEq<D, D2>,
321
    {
322
0
        assert_eq!(self.nrows(), x.nrows(), "Axpy: mismatched vector shapes.");
323
0
        self.axcpy(a, x, T::one(), b)
324
0
    }
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::axpy::<nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>>
Unexecuted instantiation: <nalgebra::base::matrix::Matrix<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<2>>>>::axpy::<nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
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<2>>>>::axpy::<nalgebra::base::dimension::Dyn, 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<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>>>>::axpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<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<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>>>>::axpy::<nalgebra::base::dimension::Dyn, 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>>>
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>>>>::axpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<6>>>>::axpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<6>>>>::axpy::<nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorage<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<5>>>
325
326
    /// Computes `self = alpha * a * x + beta * self`, where `a` is a matrix, `x` a vector, and
327
    /// `alpha, beta` two scalars.
328
    ///
329
    /// If `beta` is zero, `self` is never read.
330
    ///
331
    /// # Example
332
    /// ```
333
    /// # use nalgebra::{Matrix2, Vector2};
334
    /// let mut vec1 = Vector2::new(1.0, 2.0);
335
    /// let vec2 = Vector2::new(0.1, 0.2);
336
    /// let mat = Matrix2::new(1.0, 2.0,
337
    ///                        3.0, 4.0);
338
    /// vec1.gemv(10.0, &mat, &vec2, 5.0);
339
    /// assert_eq!(vec1, Vector2::new(10.0, 21.0));
340
    /// ```
341
    #[inline]
342
    pub fn gemv<R2: Dim, C2: Dim, D3: Dim, SB, SC>(
343
        &mut self,
344
        alpha: T,
345
        a: &Matrix<T, R2, C2, SB>,
346
        x: &Vector<T, D3, SC>,
347
        beta: T,
348
    ) where
349
        T: One,
350
        SB: Storage<T, R2, C2>,
351
        SC: Storage<T, D3>,
352
        ShapeConstraint: DimEq<D, R2> + AreMultipliable<R2, C2, D3, U1>,
353
    {
354
        // Safety: this is safe because we are passing Status == Init.
355
        unsafe { gemv_uninit(Init, self, alpha, a, x, beta) }
356
    }
357
358
    #[inline(always)]
359
0
    fn xxgemv<D2: Dim, D3: Dim, SB, SC>(
360
0
        &mut self,
361
0
        alpha: T,
362
0
        a: &SquareMatrix<T, D2, SB>,
363
0
        x: &Vector<T, D3, SC>,
364
0
        beta: T,
365
0
        dot: impl Fn(
366
0
            &DVectorView<'_, T, SB::RStride, SB::CStride>,
367
0
            &DVectorView<'_, T, SC::RStride, SC::CStride>,
368
0
        ) -> T,
369
0
    ) where
370
0
        T: One,
371
0
        SB: Storage<T, D2, D2>,
372
0
        SC: Storage<T, D3>,
373
0
        ShapeConstraint: DimEq<D, D2> + AreMultipliable<D2, D2, D3, U1>,
374
    {
375
0
        let dim1 = self.nrows();
376
0
        let dim2 = a.nrows();
377
0
        let dim3 = x.nrows();
378
379
0
        assert!(
380
0
            a.is_square(),
381
0
            "Symmetric cgemv: the input matrix must be square."
382
        );
383
0
        assert!(
384
0
            dim2 == dim3 && dim1 == dim2,
385
0
            "Symmetric cgemv: dimensions mismatch."
386
        );
387
388
0
        if dim2 == 0 {
389
0
            return;
390
0
        }
391
392
        // TODO: avoid bound checks.
393
0
        let col2 = a.column(0);
394
0
        let val = unsafe { x.vget_unchecked(0).clone() };
395
0
        self.axpy(alpha.clone() * val, &col2, beta);
396
0
        self[0] += alpha.clone() * dot(&a.view_range(1.., 0), &x.rows_range(1..));
397
398
0
        for j in 1..dim2 {
399
0
            let col2 = a.column(j);
400
0
            let dot = dot(&col2.rows_range(j..), &x.rows_range(j..));
401
0
402
0
            let val;
403
0
            unsafe {
404
0
                val = x.vget_unchecked(j).clone();
405
0
                *self.vget_unchecked_mut(j) += alpha.clone() * dot;
406
0
            }
407
0
            self.rows_range_mut(j + 1..).axpy(
408
0
                alpha.clone() * val,
409
0
                &col2.rows_range(j + 1..),
410
0
                T::one(),
411
0
            );
412
0
        }
413
0
    }
414
415
    /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a
416
    /// vector, and `alpha, beta` two scalars.
417
    ///
418
    /// For hermitian matrices, use `.hegemv` instead.
419
    /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part
420
    /// (including the diagonal) is actually read.
421
    ///
422
    /// # Examples
423
    /// ```
424
    /// # use nalgebra::{Matrix2, Vector2};
425
    /// let mat = Matrix2::new(1.0, 2.0,
426
    ///                        2.0, 4.0);
427
    /// let mut vec1 = Vector2::new(1.0, 2.0);
428
    /// let vec2 = Vector2::new(0.1, 0.2);
429
    /// vec1.sygemv(10.0, &mat, &vec2, 5.0);
430
    /// assert_eq!(vec1, Vector2::new(10.0, 20.0));
431
    ///
432
    ///
433
    /// // The matrix upper-triangular elements can be garbage because it is never
434
    /// // read by this method. Therefore, it is not necessary for the caller to
435
    /// // fill the matrix struct upper-triangle.
436
    /// let mat = Matrix2::new(1.0, 9999999.9999999,
437
    ///                        2.0, 4.0);
438
    /// let mut vec1 = Vector2::new(1.0, 2.0);
439
    /// vec1.sygemv(10.0, &mat, &vec2, 5.0);
440
    /// assert_eq!(vec1, Vector2::new(10.0, 20.0));
441
    /// ```
442
    #[inline]
443
    pub fn sygemv<D2: Dim, D3: Dim, SB, SC>(
444
        &mut self,
445
        alpha: T,
446
        a: &SquareMatrix<T, D2, SB>,
447
        x: &Vector<T, D3, SC>,
448
        beta: T,
449
    ) where
450
        T: One,
451
        SB: Storage<T, D2, D2>,
452
        SC: Storage<T, D3>,
453
        ShapeConstraint: DimEq<D, D2> + AreMultipliable<D2, D2, D3, U1>,
454
    {
455
        self.xxgemv(alpha, a, x, beta, |a, b| a.dot(b))
456
    }
457
458
    /// Computes `self = alpha * a * x + beta * self`, where `a` is an **hermitian** matrix, `x` a
459
    /// vector, and `alpha, beta` two scalars.
460
    ///
461
    /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part
462
    /// (including the diagonal) is actually read.
463
    ///
464
    /// # Examples
465
    /// ```
466
    /// # use nalgebra::{Matrix2, Vector2, Complex};
467
    /// let mat = Matrix2::new(Complex::new(1.0, 0.0), Complex::new(2.0, -0.1),
468
    ///                        Complex::new(2.0, 1.0), Complex::new(4.0, 0.0));
469
    /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0));
470
    /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4));
471
    /// vec1.sygemv(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0));
472
    /// assert_eq!(vec1, Vector2::new(Complex::new(-48.0, 44.0), Complex::new(-75.0, 110.0)));
473
    ///
474
    ///
475
    /// // The matrix upper-triangular elements can be garbage because it is never
476
    /// // read by this method. Therefore, it is not necessary for the caller to
477
    /// // fill the matrix struct upper-triangle.
478
    ///
479
    /// let mat = Matrix2::new(Complex::new(1.0, 0.0), Complex::new(99999999.9, 999999999.9),
480
    ///                        Complex::new(2.0, 1.0), Complex::new(4.0, 0.0));
481
    /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0));
482
    /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4));
483
    /// vec1.sygemv(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0));
484
    /// assert_eq!(vec1, Vector2::new(Complex::new(-48.0, 44.0), Complex::new(-75.0, 110.0)));
485
    /// ```
486
    #[inline]
487
0
    pub fn hegemv<D2: Dim, D3: Dim, SB, SC>(
488
0
        &mut self,
489
0
        alpha: T,
490
0
        a: &SquareMatrix<T, D2, SB>,
491
0
        x: &Vector<T, D3, SC>,
492
0
        beta: T,
493
0
    ) where
494
0
        T: SimdComplexField,
495
0
        SB: Storage<T, D2, D2>,
496
0
        SC: Storage<T, D3>,
497
0
        ShapeConstraint: DimEq<D, D2> + AreMultipliable<D2, D2, D3, U1>,
498
    {
499
0
        self.xxgemv(alpha, a, x, beta, |a, b| a.dotc(b))
500
0
    }
501
502
    #[inline(always)]
503
    fn gemv_xx<R2: Dim, C2: Dim, D3: Dim, SB, SC>(
504
        &mut self,
505
        alpha: T,
506
        a: &Matrix<T, R2, C2, SB>,
507
        x: &Vector<T, D3, SC>,
508
        beta: T,
509
        dot: impl Fn(&VectorView<'_, T, R2, SB::RStride, SB::CStride>, &Vector<T, D3, SC>) -> T,
510
    ) where
511
        T: One,
512
        SB: Storage<T, R2, C2>,
513
        SC: Storage<T, D3>,
514
        ShapeConstraint: DimEq<D, C2> + AreMultipliable<C2, R2, D3, U1>,
515
    {
516
        let dim1 = self.nrows();
517
        let (nrows2, ncols2) = a.shape();
518
        let dim3 = x.nrows();
519
520
        assert!(
521
            nrows2 == dim3 && dim1 == ncols2,
522
            "Gemv: dimensions mismatch."
523
        );
524
525
        if ncols2 == 0 {
526
            return;
527
        }
528
529
        if beta.is_zero() {
530
            for j in 0..ncols2 {
531
                let val = unsafe { self.vget_unchecked_mut(j) };
532
                *val = alpha.clone() * dot(&a.column(j), x)
533
            }
534
        } else {
535
            for j in 0..ncols2 {
536
                let val = unsafe { self.vget_unchecked_mut(j) };
537
                *val = alpha.clone() * dot(&a.column(j), x) + beta.clone() * val.clone();
538
            }
539
        }
540
    }
541
542
    /// Computes `self = alpha * a.transpose() * x + beta * self`, where `a` is a matrix, `x` a vector, and
543
    /// `alpha, beta` two scalars.
544
    ///
545
    /// If `beta` is zero, `self` is never read.
546
    ///
547
    /// # Example
548
    /// ```
549
    /// # use nalgebra::{Matrix2, Vector2};
550
    /// let mat = Matrix2::new(1.0, 3.0,
551
    ///                        2.0, 4.0);
552
    /// let mut vec1 = Vector2::new(1.0, 2.0);
553
    /// let vec2 = Vector2::new(0.1, 0.2);
554
    /// let expected = mat.transpose() * vec2 * 10.0 + vec1 * 5.0;
555
    ///
556
    /// vec1.gemv_tr(10.0, &mat, &vec2, 5.0);
557
    /// assert_eq!(vec1, expected);
558
    /// ```
559
    #[inline]
560
    pub fn gemv_tr<R2: Dim, C2: Dim, D3: Dim, SB, SC>(
561
        &mut self,
562
        alpha: T,
563
        a: &Matrix<T, R2, C2, SB>,
564
        x: &Vector<T, D3, SC>,
565
        beta: T,
566
    ) where
567
        T: One,
568
        SB: Storage<T, R2, C2>,
569
        SC: Storage<T, D3>,
570
        ShapeConstraint: DimEq<D, C2> + AreMultipliable<C2, R2, D3, U1>,
571
    {
572
        self.gemv_xx(alpha, a, x, beta, |a, b| a.dot(b))
573
    }
574
575
    /// Computes `self = alpha * a.adjoint() * x + beta * self`, where `a` is a matrix, `x` a vector, and
576
    /// `alpha, beta` two scalars.
577
    ///
578
    /// For real matrices, this is the same as `.gemv_tr`.
579
    /// If `beta` is zero, `self` is never read.
580
    ///
581
    /// # Example
582
    /// ```
583
    /// # use nalgebra::{Matrix2, Vector2, Complex};
584
    /// let mat = Matrix2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0),
585
    ///                        Complex::new(5.0, 6.0), Complex::new(7.0, 8.0));
586
    /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0));
587
    /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4));
588
    /// let expected = mat.adjoint() * vec2 * Complex::new(10.0, 20.0) + vec1 * Complex::new(5.0, 15.0);
589
    ///
590
    /// vec1.gemv_ad(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0));
591
    /// assert_eq!(vec1, expected);
592
    /// ```
593
    #[inline]
594
    pub fn gemv_ad<R2: Dim, C2: Dim, D3: Dim, SB, SC>(
595
        &mut self,
596
        alpha: T,
597
        a: &Matrix<T, R2, C2, SB>,
598
        x: &Vector<T, D3, SC>,
599
        beta: T,
600
    ) where
601
        T: SimdComplexField,
602
        SB: Storage<T, R2, C2>,
603
        SC: Storage<T, D3>,
604
        ShapeConstraint: DimEq<D, C2> + AreMultipliable<C2, R2, D3, U1>,
605
    {
606
        self.gemv_xx(alpha, a, x, beta, |a, b| a.dotc(b))
607
    }
608
}
609
610
impl<T, R1: Dim, C1: Dim, S: StorageMut<T, R1, C1>> Matrix<T, R1, C1, S>
611
where
612
    T: Scalar + Zero + ClosedAddAssign + ClosedMulAssign,
613
{
614
    #[inline(always)]
615
0
    fn gerx<D2: Dim, D3: Dim, SB, SC>(
616
0
        &mut self,
617
0
        alpha: T,
618
0
        x: &Vector<T, D2, SB>,
619
0
        y: &Vector<T, D3, SC>,
620
0
        beta: T,
621
0
        conjugate: impl Fn(T) -> T,
622
0
    ) where
623
0
        T: One,
624
0
        SB: Storage<T, D2>,
625
0
        SC: Storage<T, D3>,
626
0
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
627
    {
628
0
        let (nrows1, ncols1) = self.shape();
629
0
        let dim2 = x.nrows();
630
0
        let dim3 = y.nrows();
631
632
0
        assert!(
633
0
            nrows1 == dim2 && ncols1 == dim3,
634
0
            "ger: dimensions mismatch."
635
        );
636
637
0
        for j in 0..ncols1 {
638
0
            // TODO: avoid bound checks.
639
0
            let val = unsafe { conjugate(y.vget_unchecked(j).clone()) };
640
0
            self.column_mut(j)
641
0
                .axpy(alpha.clone() * val, x, beta.clone());
642
0
        }
643
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>>>>::gerx::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>>::gerx::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>>::gerx::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Dyn, nalgebra::base::array_storage::ArrayStorage<f64, 2, 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>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>>::gerx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<2>, 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::array_storage::ArrayStorage<f64, 2, 1>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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>>>>::gerx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<3>, 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::array_storage::ArrayStorage<f64, 3, 1>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
644
645
    /// Computes `self = alpha * x * y.transpose() + beta * self`.
646
    ///
647
    /// If `beta` is zero, `self` is never read.
648
    ///
649
    /// # Example
650
    /// ```
651
    /// # use nalgebra::{Matrix2x3, Vector2, Vector3};
652
    /// let mut mat = Matrix2x3::repeat(4.0);
653
    /// let vec1 = Vector2::new(1.0, 2.0);
654
    /// let vec2 = Vector3::new(0.1, 0.2, 0.3);
655
    /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0;
656
    ///
657
    /// mat.ger(10.0, &vec1, &vec2, 5.0);
658
    /// assert_eq!(mat, expected);
659
    /// ```
660
    #[inline]
661
    pub fn ger<D2: Dim, D3: Dim, SB, SC>(
662
        &mut self,
663
        alpha: T,
664
        x: &Vector<T, D2, SB>,
665
        y: &Vector<T, D3, SC>,
666
        beta: T,
667
    ) where
668
        T: One,
669
        SB: Storage<T, D2>,
670
        SC: Storage<T, D3>,
671
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
672
    {
673
        self.gerx(alpha, x, y, beta, |e| e)
674
    }
675
676
    /// Computes `self = alpha * x * y.adjoint() + beta * self`.
677
    ///
678
    /// If `beta` is zero, `self` is never read.
679
    ///
680
    /// # Example
681
    /// ```
682
    /// # #[macro_use] extern crate approx;
683
    /// # use nalgebra::{Matrix2x3, Vector2, Vector3, Complex};
684
    /// let mut mat = Matrix2x3::repeat(Complex::new(4.0, 5.0));
685
    /// let vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0));
686
    /// let vec2 = Vector3::new(Complex::new(0.6, 0.5), Complex::new(0.4, 0.5), Complex::new(0.2, 0.1));
687
    /// let expected = vec1 * vec2.adjoint() * Complex::new(10.0, 20.0) + mat * Complex::new(5.0, 15.0);
688
    ///
689
    /// mat.gerc(Complex::new(10.0, 20.0), &vec1, &vec2, Complex::new(5.0, 15.0));
690
    /// assert_eq!(mat, expected);
691
    /// ```
692
    #[inline]
693
0
    pub fn gerc<D2: Dim, D3: Dim, SB, SC>(
694
0
        &mut self,
695
0
        alpha: T,
696
0
        x: &Vector<T, D2, SB>,
697
0
        y: &Vector<T, D3, SC>,
698
0
        beta: T,
699
0
    ) where
700
0
        T: SimdComplexField,
701
0
        SB: Storage<T, D2>,
702
0
        SC: Storage<T, D3>,
703
0
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
704
    {
705
0
        self.gerx(alpha, x, y, beta, SimdComplexField::simd_conjugate)
706
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>>>>::gerc::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 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>>>>::gerc::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<3>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 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>>>>::gerc::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Dyn, nalgebra::base::array_storage::ArrayStorage<f64, 2, 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<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>>>>::gerc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<2>, 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::array_storage::ArrayStorage<f64, 2, 1>>
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>>>>::gerc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<3>, 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::array_storage::ArrayStorage<f64, 3, 1>>
707
708
    /// Computes `self = alpha * a * b + beta * self`, where `a, b, self` are matrices.
709
    /// `alpha` and `beta` are scalar.
710
    ///
711
    /// If `beta` is zero, `self` is never read.
712
    ///
713
    /// # Example
714
    /// ```
715
    /// # #[macro_use] extern crate approx;
716
    /// # use nalgebra::{Matrix2x3, Matrix3x4, Matrix2x4};
717
    /// let mut mat1 = Matrix2x4::identity();
718
    /// let mat2 = Matrix2x3::new(1.0, 2.0, 3.0,
719
    ///                           4.0, 5.0, 6.0);
720
    /// let mat3 = Matrix3x4::new(0.1, 0.2, 0.3, 0.4,
721
    ///                           0.5, 0.6, 0.7, 0.8,
722
    ///                           0.9, 1.0, 1.1, 1.2);
723
    /// let expected = mat2 * mat3 * 10.0 + mat1 * 5.0;
724
    ///
725
    /// mat1.gemm(10.0, &mat2, &mat3, 5.0);
726
    /// assert_relative_eq!(mat1, expected);
727
    /// ```
728
    #[inline]
729
0
    pub fn gemm<R2: Dim, C2: Dim, R3: Dim, C3: Dim, SB, SC>(
730
0
        &mut self,
731
0
        alpha: T,
732
0
        a: &Matrix<T, R2, C2, SB>,
733
0
        b: &Matrix<T, R3, C3, SC>,
734
0
        beta: T,
735
0
    ) where
736
0
        T: One,
737
0
        SB: Storage<T, R2, C2>,
738
0
        SC: Storage<T, R3, C3>,
739
0
        ShapeConstraint: SameNumberOfRows<R1, R2>
740
0
            + SameNumberOfColumns<C1, C3>
741
0
            + AreMultipliable<R2, C2, R3, C3>,
742
    {
743
        // SAFETY: this is valid because our matrices are initialized and
744
        // we are using status = Init.
745
0
        unsafe { gemm_uninit(Init, self, alpha, a, b, beta) }
746
0
    }
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>>>::gemm::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, 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>>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>>
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>>>::gemm::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, 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>>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
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>>>::gemm::<nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, 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>>, 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<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>>>>::gemm::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<2>, nalgebra::base::dimension::Const<1>, 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>>, nalgebra::base::array_storage::ArrayStorage<f64, 2, 1>>
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<2>>>>::gemm::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<3>, nalgebra::base::dimension::Const<1>, 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>>, nalgebra::base::array_storage::ArrayStorage<f64, 3, 1>>
747
748
    /// Computes `self = alpha * a.transpose() * b + beta * self`, where `a, b, self` are matrices.
749
    /// `alpha` and `beta` are scalar.
750
    ///
751
    /// If `beta` is zero, `self` is never read.
752
    ///
753
    /// # Example
754
    /// ```
755
    /// # #[macro_use] extern crate approx;
756
    /// # use nalgebra::{Matrix3x2, Matrix3x4, Matrix2x4};
757
    /// let mut mat1 = Matrix2x4::identity();
758
    /// let mat2 = Matrix3x2::new(1.0, 4.0,
759
    ///                           2.0, 5.0,
760
    ///                           3.0, 6.0);
761
    /// let mat3 = Matrix3x4::new(0.1, 0.2, 0.3, 0.4,
762
    ///                           0.5, 0.6, 0.7, 0.8,
763
    ///                           0.9, 1.0, 1.1, 1.2);
764
    /// let expected = mat2.transpose() * mat3 * 10.0 + mat1 * 5.0;
765
    ///
766
    /// mat1.gemm_tr(10.0, &mat2, &mat3, 5.0);
767
    /// assert_eq!(mat1, expected);
768
    /// ```
769
    #[inline]
770
    pub fn gemm_tr<R2: Dim, C2: Dim, R3: Dim, C3: Dim, SB, SC>(
771
        &mut self,
772
        alpha: T,
773
        a: &Matrix<T, R2, C2, SB>,
774
        b: &Matrix<T, R3, C3, SC>,
775
        beta: T,
776
    ) where
777
        T: One,
778
        SB: Storage<T, R2, C2>,
779
        SC: Storage<T, R3, C3>,
780
        ShapeConstraint: SameNumberOfRows<R1, C2>
781
            + SameNumberOfColumns<C1, C3>
782
            + AreMultipliable<C2, R2, R3, C3>,
783
    {
784
        let (nrows1, ncols1) = self.shape();
785
        let (nrows2, ncols2) = a.shape();
786
        let (nrows3, ncols3) = b.shape();
787
788
        assert_eq!(
789
            nrows2, nrows3,
790
            "gemm: dimensions mismatch for multiplication."
791
        );
792
        assert_eq!(
793
            (nrows1, ncols1),
794
            (ncols2, ncols3),
795
            "gemm: dimensions mismatch for addition."
796
        );
797
798
        for j1 in 0..ncols1 {
799
            // TODO: avoid bound checks.
800
            self.column_mut(j1)
801
                .gemv_tr(alpha.clone(), a, &b.column(j1), beta.clone());
802
        }
803
    }
804
805
    /// Computes `self = alpha * a.adjoint() * b + beta * self`, where `a, b, self` are matrices.
806
    /// `alpha` and `beta` are scalar.
807
    ///
808
    /// If `beta` is zero, `self` is never read.
809
    ///
810
    /// # Example
811
    /// ```
812
    /// # #[macro_use] extern crate approx;
813
    /// # use nalgebra::{Matrix3x2, Matrix3x4, Matrix2x4, Complex};
814
    /// let mut mat1 = Matrix2x4::identity();
815
    /// let mat2 = Matrix3x2::new(Complex::new(1.0, 4.0), Complex::new(7.0, 8.0),
816
    ///                           Complex::new(2.0, 5.0), Complex::new(9.0, 10.0),
817
    ///                           Complex::new(3.0, 6.0), Complex::new(11.0, 12.0));
818
    /// let mat3 = Matrix3x4::new(Complex::new(0.1, 1.3), Complex::new(0.2, 1.4), Complex::new(0.3, 1.5), Complex::new(0.4, 1.6),
819
    ///                           Complex::new(0.5, 1.7), Complex::new(0.6, 1.8), Complex::new(0.7, 1.9), Complex::new(0.8, 2.0),
820
    ///                           Complex::new(0.9, 2.1), Complex::new(1.0, 2.2), Complex::new(1.1, 2.3), Complex::new(1.2, 2.4));
821
    /// let expected = mat2.adjoint() * mat3 * Complex::new(10.0, 20.0) + mat1 * Complex::new(5.0, 15.0);
822
    ///
823
    /// mat1.gemm_ad(Complex::new(10.0, 20.0), &mat2, &mat3, Complex::new(5.0, 15.0));
824
    /// assert_eq!(mat1, expected);
825
    /// ```
826
    #[inline]
827
    pub fn gemm_ad<R2: Dim, C2: Dim, R3: Dim, C3: Dim, SB, SC>(
828
        &mut self,
829
        alpha: T,
830
        a: &Matrix<T, R2, C2, SB>,
831
        b: &Matrix<T, R3, C3, SC>,
832
        beta: T,
833
    ) where
834
        T: SimdComplexField,
835
        SB: Storage<T, R2, C2>,
836
        SC: Storage<T, R3, C3>,
837
        ShapeConstraint: SameNumberOfRows<R1, C2>
838
            + SameNumberOfColumns<C1, C3>
839
            + AreMultipliable<C2, R2, R3, C3>,
840
    {
841
        let (nrows1, ncols1) = self.shape();
842
        let (nrows2, ncols2) = a.shape();
843
        let (nrows3, ncols3) = b.shape();
844
845
        assert_eq!(
846
            nrows2, nrows3,
847
            "gemm: dimensions mismatch for multiplication."
848
        );
849
        assert_eq!(
850
            (nrows1, ncols1),
851
            (ncols2, ncols3),
852
            "gemm: dimensions mismatch for addition."
853
        );
854
855
        for j1 in 0..ncols1 {
856
            // TODO: avoid bound checks.
857
            self.column_mut(j1)
858
                .gemv_ad(alpha.clone(), a, &b.column(j1), beta.clone());
859
        }
860
    }
861
}
862
863
impl<T, R1: Dim, C1: Dim, S: StorageMut<T, R1, C1>> Matrix<T, R1, C1, S>
864
where
865
    T: Scalar + Zero + ClosedAddAssign + ClosedMulAssign,
866
{
867
    #[inline(always)]
868
0
    fn xxgerx<D2: Dim, D3: Dim, SB, SC>(
869
0
        &mut self,
870
0
        alpha: T,
871
0
        x: &Vector<T, D2, SB>,
872
0
        y: &Vector<T, D3, SC>,
873
0
        beta: T,
874
0
        conjugate: impl Fn(T) -> T,
875
0
    ) where
876
0
        T: One,
877
0
        SB: Storage<T, D2>,
878
0
        SC: Storage<T, D3>,
879
0
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
880
    {
881
0
        let dim1 = self.nrows();
882
0
        let dim2 = x.nrows();
883
0
        let dim3 = y.nrows();
884
885
0
        assert!(
886
0
            self.is_square(),
887
0
            "Symmetric ger: the input matrix must be square."
888
        );
889
0
        assert!(dim1 == dim2 && dim1 == dim3, "ger: dimensions mismatch.");
890
891
0
        for j in 0..dim1 {
892
0
            let val = unsafe { conjugate(y.vget_unchecked(j).clone()) };
893
0
            let subdim = Dyn(dim1 - j);
894
0
            // TODO: avoid bound checks.
895
0
            self.generic_view_mut((j, j), (subdim, Const::<1>)).axpy(
896
0
                alpha.clone() * val,
897
0
                &x.rows_range(j..),
898
0
                beta.clone(),
899
0
            );
900
0
        }
901
0
    }
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<6>>>>::xxgerx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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<6>>>>::xxgerx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, 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>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
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<6>>>>::xxgerx::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, 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>>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, <f64 as simba::simd::simd_complex::SimdComplexField>::simd_conjugate>
902
903
    /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric**
904
    /// matrix.
905
    ///
906
    /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular
907
    /// (including the diagonal) part of `self` is read/written.
908
    ///
909
    /// # Example
910
    /// ```
911
    /// # use nalgebra::{Matrix2, Vector2};
912
    /// let mut mat = Matrix2::identity();
913
    /// let vec1 = Vector2::new(1.0, 2.0);
914
    /// let vec2 = Vector2::new(0.1, 0.2);
915
    /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0;
916
    /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written.
917
    ///
918
    /// mat.ger_symm(10.0, &vec1, &vec2, 5.0);
919
    /// assert_eq!(mat.lower_triangle(), expected.lower_triangle());
920
    /// assert_eq!(mat.m12, 99999.99999); // This was untouched.
921
    /// ```
922
    #[inline]
923
    #[deprecated(note = "This is renamed `syger` to match the original BLAS terminology.")]
924
    pub fn ger_symm<D2: Dim, D3: Dim, SB, SC>(
925
        &mut self,
926
        alpha: T,
927
        x: &Vector<T, D2, SB>,
928
        y: &Vector<T, D3, SC>,
929
        beta: T,
930
    ) where
931
        T: One,
932
        SB: Storage<T, D2>,
933
        SC: Storage<T, D3>,
934
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
935
    {
936
        self.syger(alpha, x, y, beta)
937
    }
938
939
    /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric**
940
    /// matrix.
941
    ///
942
    /// For hermitian complex matrices, use `.hegerc` instead.
943
    /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular
944
    /// (including the diagonal) part of `self` is read/written.
945
    ///
946
    /// # Example
947
    /// ```
948
    /// # use nalgebra::{Matrix2, Vector2};
949
    /// let mut mat = Matrix2::identity();
950
    /// let vec1 = Vector2::new(1.0, 2.0);
951
    /// let vec2 = Vector2::new(0.1, 0.2);
952
    /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0;
953
    /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written.
954
    ///
955
    /// mat.syger(10.0, &vec1, &vec2, 5.0);
956
    /// assert_eq!(mat.lower_triangle(), expected.lower_triangle());
957
    /// assert_eq!(mat.m12, 99999.99999); // This was untouched.
958
    /// ```
959
    #[inline]
960
    pub fn syger<D2: Dim, D3: Dim, SB, SC>(
961
        &mut self,
962
        alpha: T,
963
        x: &Vector<T, D2, SB>,
964
        y: &Vector<T, D3, SC>,
965
        beta: T,
966
    ) where
967
        T: One,
968
        SB: Storage<T, D2>,
969
        SC: Storage<T, D3>,
970
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
971
    {
972
        self.xxgerx(alpha, x, y, beta, |e| e)
973
    }
974
975
    /// Computes `self = alpha * x * y.adjoint() + beta * self`, where `self` is an **hermitian**
976
    /// matrix.
977
    ///
978
    /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular
979
    /// (including the diagonal) part of `self` is read/written.
980
    ///
981
    /// # Example
982
    /// ```
983
    /// # use nalgebra::{Matrix2, Vector2, Complex};
984
    /// let mut mat = Matrix2::identity();
985
    /// let vec1 = Vector2::new(Complex::new(1.0, 3.0), Complex::new(2.0, 4.0));
986
    /// let vec2 = Vector2::new(Complex::new(0.2, 0.4), Complex::new(0.1, 0.3));
987
    /// let expected = vec1 * vec2.adjoint() * Complex::new(10.0, 20.0) + mat * Complex::new(5.0, 15.0);
988
    /// mat.m12 = Complex::new(99999.99999, 88888.88888); // This component is on the upper-triangular part and will not be read/written.
989
    ///
990
    /// mat.hegerc(Complex::new(10.0, 20.0), &vec1, &vec2, Complex::new(5.0, 15.0));
991
    /// assert_eq!(mat.lower_triangle(), expected.lower_triangle());
992
    /// assert_eq!(mat.m12, Complex::new(99999.99999, 88888.88888)); // This was untouched.
993
    /// ```
994
    #[inline]
995
0
    pub fn hegerc<D2: Dim, D3: Dim, SB, SC>(
996
0
        &mut self,
997
0
        alpha: T,
998
0
        x: &Vector<T, D2, SB>,
999
0
        y: &Vector<T, D3, SC>,
1000
0
        beta: T,
1001
0
    ) where
1002
0
        T: SimdComplexField,
1003
0
        SB: Storage<T, D2>,
1004
0
        SC: Storage<T, D3>,
1005
0
        ShapeConstraint: DimEq<R1, D2> + DimEq<C1, D3>,
1006
    {
1007
0
        self.xxgerx(alpha, x, y, beta, SimdComplexField::simd_conjugate)
1008
0
    }
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<6>>>>::hegerc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
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<6>>>>::hegerc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>, 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>>>
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<6>>>>::hegerc::<nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Dyn, 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>>, nalgebra::base::matrix_view::ViewStorageMut<f64, nalgebra::base::dimension::Dyn, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<1>, nalgebra::base::dimension::Const<6>>>
1009
}
1010
1011
impl<T, D1: Dim, S: StorageMut<T, D1, D1>> SquareMatrix<T, D1, S>
1012
where
1013
    T: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign,
1014
{
1015
    /// Computes the quadratic form `self = alpha * lhs * mid * lhs.transpose() + beta * self`.
1016
    ///
1017
    /// This uses the provided workspace `work` to avoid allocations for intermediate results.
1018
    ///
1019
    /// # Example
1020
    /// ```
1021
    /// # #[macro_use] extern crate approx;
1022
    /// # use nalgebra::{DMatrix, DVector};
1023
    /// // Note that all those would also work with statically-sized matrices.
1024
    /// // We use DMatrix/DVector since that's the only case where pre-allocating the
1025
    /// // workspace is actually useful (assuming the same workspace is re-used for
1026
    /// // several computations) because it avoids repeated dynamic allocations.
1027
    /// let mut mat = DMatrix::identity(2, 2);
1028
    /// let lhs = DMatrix::from_row_slice(2, 3, &[1.0, 2.0, 3.0,
1029
    ///                                           4.0, 5.0, 6.0]);
1030
    /// let mid = DMatrix::from_row_slice(3, 3, &[0.1, 0.2, 0.3,
1031
    ///                                           0.5, 0.6, 0.7,
1032
    ///                                           0.9, 1.0, 1.1]);
1033
    /// // The random shows that values on the workspace do not
1034
    /// // matter as they will be overwritten.
1035
    /// let mut workspace = DVector::new_random(2);
1036
    /// let expected = &lhs * &mid * lhs.transpose() * 10.0 + &mat * 5.0;
1037
    ///
1038
    /// mat.quadform_tr_with_workspace(&mut workspace, 10.0, &lhs, &mid, 5.0);
1039
    /// assert_relative_eq!(mat, expected);
1040
    /// ```
1041
    pub fn quadform_tr_with_workspace<D2, S2, R3, C3, S3, D4, S4>(
1042
        &mut self,
1043
        work: &mut Vector<T, D2, S2>,
1044
        alpha: T,
1045
        lhs: &Matrix<T, R3, C3, S3>,
1046
        mid: &SquareMatrix<T, D4, S4>,
1047
        beta: T,
1048
    ) where
1049
        D2: Dim,
1050
        R3: Dim,
1051
        C3: Dim,
1052
        D4: Dim,
1053
        S2: StorageMut<T, D2>,
1054
        S3: Storage<T, R3, C3>,
1055
        S4: Storage<T, D4, D4>,
1056
        ShapeConstraint: DimEq<D1, D2> + DimEq<D1, R3> + DimEq<D2, R3> + DimEq<C3, D4>,
1057
    {
1058
        work.gemv(T::one(), lhs, &mid.column(0), T::zero());
1059
        self.ger(alpha.clone(), work, &lhs.column(0), beta);
1060
1061
        for j in 1..mid.ncols() {
1062
            work.gemv(T::one(), lhs, &mid.column(j), T::zero());
1063
            self.ger(alpha.clone(), work, &lhs.column(j), T::one());
1064
        }
1065
    }
1066
1067
    /// Computes the quadratic form `self = alpha * lhs * mid * lhs.transpose() + beta * self`.
1068
    ///
1069
    /// This allocates a workspace vector of dimension D1 for intermediate results.
1070
    /// If `D1` is a type-level integer, then the allocation is performed on the stack.
1071
    /// Use `.quadform_tr_with_workspace(...)` instead to avoid allocations.
1072
    ///
1073
    /// # Example
1074
    /// ```
1075
    /// # #[macro_use] extern crate approx;
1076
    /// # use nalgebra::{Matrix2, Matrix3, Matrix2x3, Vector2};
1077
    /// let mut mat = Matrix2::identity();
1078
    /// let lhs = Matrix2x3::new(1.0, 2.0, 3.0,
1079
    ///                          4.0, 5.0, 6.0);
1080
    /// let mid = Matrix3::new(0.1, 0.2, 0.3,
1081
    ///                        0.5, 0.6, 0.7,
1082
    ///                        0.9, 1.0, 1.1);
1083
    /// let expected = lhs * mid * lhs.transpose() * 10.0 + mat * 5.0;
1084
    ///
1085
    /// mat.quadform_tr(10.0, &lhs, &mid, 5.0);
1086
    /// assert_relative_eq!(mat, expected);
1087
    /// ```
1088
    pub fn quadform_tr<R3, C3, S3, D4, S4>(
1089
        &mut self,
1090
        alpha: T,
1091
        lhs: &Matrix<T, R3, C3, S3>,
1092
        mid: &SquareMatrix<T, D4, S4>,
1093
        beta: T,
1094
    ) where
1095
        R3: Dim,
1096
        C3: Dim,
1097
        D4: Dim,
1098
        S3: Storage<T, R3, C3>,
1099
        S4: Storage<T, D4, D4>,
1100
        ShapeConstraint: DimEq<D1, D1> + DimEq<D1, R3> + DimEq<C3, D4>,
1101
        DefaultAllocator: Allocator<D1>,
1102
    {
1103
        // TODO: would it be useful to avoid the zero-initialization of the workspace data?
1104
        let mut work = Matrix::zeros_generic(self.shape_generic().0, Const::<1>);
1105
        self.quadform_tr_with_workspace(&mut work, alpha, lhs, mid, beta)
1106
    }
1107
1108
    /// Computes the quadratic form `self = alpha * rhs.transpose() * mid * rhs + beta * self`.
1109
    ///
1110
    /// This uses the provided workspace `work` to avoid allocations for intermediate results.
1111
    ///
1112
    /// # Example
1113
    /// ```
1114
    /// # #[macro_use] extern crate approx;
1115
    /// # use nalgebra::{DMatrix, DVector};
1116
    /// // Note that all those would also work with statically-sized matrices.
1117
    /// // We use DMatrix/DVector since that's the only case where pre-allocating the
1118
    /// // workspace is actually useful (assuming the same workspace is re-used for
1119
    /// // several computations) because it avoids repeated dynamic allocations.
1120
    /// let mut mat = DMatrix::identity(2, 2);
1121
    /// let rhs = DMatrix::from_row_slice(3, 2, &[1.0, 2.0,
1122
    ///                                           3.0, 4.0,
1123
    ///                                           5.0, 6.0]);
1124
    /// let mid = DMatrix::from_row_slice(3, 3, &[0.1, 0.2, 0.3,
1125
    ///                                           0.5, 0.6, 0.7,
1126
    ///                                           0.9, 1.0, 1.1]);
1127
    /// // The random shows that values on the workspace do not
1128
    /// // matter as they will be overwritten.
1129
    /// let mut workspace = DVector::new_random(3);
1130
    /// let expected = rhs.transpose() * &mid * &rhs * 10.0 + &mat * 5.0;
1131
    ///
1132
    /// mat.quadform_with_workspace(&mut workspace, 10.0, &mid, &rhs, 5.0);
1133
    /// assert_relative_eq!(mat, expected);
1134
    /// ```
1135
    pub fn quadform_with_workspace<D2, S2, D3, S3, R4, C4, S4>(
1136
        &mut self,
1137
        work: &mut Vector<T, D2, S2>,
1138
        alpha: T,
1139
        mid: &SquareMatrix<T, D3, S3>,
1140
        rhs: &Matrix<T, R4, C4, S4>,
1141
        beta: T,
1142
    ) where
1143
        D2: Dim,
1144
        D3: Dim,
1145
        R4: Dim,
1146
        C4: Dim,
1147
        S2: StorageMut<T, D2>,
1148
        S3: Storage<T, D3, D3>,
1149
        S4: Storage<T, R4, C4>,
1150
        ShapeConstraint:
1151
            DimEq<D3, R4> + DimEq<D1, C4> + DimEq<D2, D3> + AreMultipliable<C4, R4, D2, U1>,
1152
    {
1153
        work.gemv(T::one(), mid, &rhs.column(0), T::zero());
1154
        self.column_mut(0)
1155
            .gemv_tr(alpha.clone(), rhs, work, beta.clone());
1156
1157
        for j in 1..rhs.ncols() {
1158
            work.gemv(T::one(), mid, &rhs.column(j), T::zero());
1159
            self.column_mut(j)
1160
                .gemv_tr(alpha.clone(), rhs, work, beta.clone());
1161
        }
1162
    }
1163
1164
    /// Computes the quadratic form `self = alpha * rhs.transpose() * mid * rhs + beta * self`.
1165
    ///
1166
    /// This allocates a workspace vector of dimension D2 for intermediate results.
1167
    /// If `D2` is a type-level integer, then the allocation is performed on the stack.
1168
    /// Use `.quadform_with_workspace(...)` instead to avoid allocations.
1169
    ///
1170
    /// # Example
1171
    /// ```
1172
    /// # #[macro_use] extern crate approx;
1173
    /// # use nalgebra::{Matrix2, Matrix3x2, Matrix3};
1174
    /// let mut mat = Matrix2::identity();
1175
    /// let rhs = Matrix3x2::new(1.0, 2.0,
1176
    ///                          3.0, 4.0,
1177
    ///                          5.0, 6.0);
1178
    /// let mid = Matrix3::new(0.1, 0.2, 0.3,
1179
    ///                        0.5, 0.6, 0.7,
1180
    ///                        0.9, 1.0, 1.1);
1181
    /// let expected = rhs.transpose() * mid * rhs * 10.0 + mat * 5.0;
1182
    ///
1183
    /// mat.quadform(10.0, &mid, &rhs, 5.0);
1184
    /// assert_relative_eq!(mat, expected);
1185
    /// ```
1186
    pub fn quadform<D2, S2, R3, C3, S3>(
1187
        &mut self,
1188
        alpha: T,
1189
        mid: &SquareMatrix<T, D2, S2>,
1190
        rhs: &Matrix<T, R3, C3, S3>,
1191
        beta: T,
1192
    ) where
1193
        D2: Dim,
1194
        R3: Dim,
1195
        C3: Dim,
1196
        S2: Storage<T, D2, D2>,
1197
        S3: Storage<T, R3, C3>,
1198
        ShapeConstraint: DimEq<D2, R3> + DimEq<D1, C3> + AreMultipliable<C3, R3, D2, U1>,
1199
        DefaultAllocator: Allocator<D2>,
1200
    {
1201
        // TODO: would it be useful to avoid the zero-initialization of the workspace data?
1202
        let mut work = Vector::zeros_generic(mid.shape_generic().0, Const::<1>);
1203
        self.quadform_with_workspace(&mut work, alpha, mid, rhs, beta)
1204
    }
1205
}