1#![allow(non_snake_case)]
2use crate::algebra::*;
3
4
5impl<T: FloatT> MatrixMath<T> for Matrix<T> {
13
14    fn col_sums(&self, sums: &mut [T]) {
15        assert_eq!(self.ncols(), sums.len());
16        for (col, sum) in sums.iter_mut().enumerate() {
17            *sum = self.col_slice(col).sum();
18        }
19    }
20
21    fn row_sums(&self, sums: &mut [T]) {
22        assert_eq!(self.nrows(), sums.len());
23        sums.fill(T::zero());
24        for col in 0..self.ncols() {
25            let slice = self.col_slice(col);
26            for (row, &v) in slice.iter().enumerate() {
27                sums[row] += v;
28            }
29        }
30    }
31
32    fn col_norms(&self, norms: &mut [T]) {
33        norms.fill(T::zero());
34        self.col_norms_no_reset(norms);
35    }
36
37    fn col_norms_no_reset(&self, norms: &mut [T]) {
38        for (i, norm) in norms.iter_mut().enumerate() {
39            let colnorm = self.col_slice(i).norm_inf();
40            *norm = T::max(*norm, colnorm);
41        }
42    }
43
44    fn col_norms_sym(&self, norms: &mut [T]) {
45        norms.fill(T::zero());
46        self.col_norms_sym_no_reset(norms);
47    }
48
49    fn col_norms_sym_no_reset(&self, norms: &mut [T]) {
50        for c in 0..self.ncols() {
51            for r in 0..=c {
52                let tmp = self[(r, c)];
53                norms[r] = T::max(norms[r], tmp);
54                norms[c] = T::max(norms[c], tmp);
55            }
56        }
57    }
58
59    fn row_norms(&self, norms: &mut [T]) {
60        norms.fill(T::zero());
61        self.row_norms_no_reset(norms);
62    }
63
64    fn row_norms_no_reset(&self, norms: &mut [T]) {
65        for r in 0..self.nrows() {
66            for c in 0..self.ncols() {
67                norms[r] = T::max(norms[r], T::abs(self[(r, c)]))
68            }
69        }
70    }
71}
72
73impl<T: FloatT> MatrixMathMut<T> for Matrix<T> {
74
75    fn scale(&mut self, c: T) {
77        self.data.scale(c);
78    }
79
80    fn negate(&mut self) {
81        self.data.negate();
82    }
83
84    fn lscale(&mut self, l: &[T]) {
85        for col in 0..self.ncols() {
86            self.col_slice_mut(col).hadamard(l);
87        }
88    }
89
90    fn rscale(&mut self, r: &[T]) {
91        for (col, val) in r.iter().enumerate() {
92            self.col_slice_mut(col).scale(*val);
93        }
94    }
95
96    fn lrscale(&mut self, l: &[T], r: &[T]) {
97        for i in 0..self.nrows() {
98            for j in 0..self.ncols() {
99                self[(i, j)] *= l[i] * r[j];
100            }
101        }
102    }
103
104}
105
106impl<T> Matrix<T>
107where
108    T: FloatT,
109{
110    #[allow(dead_code)]
111    pub(crate) fn kron<MATA, MATB>(&mut self, A: &MATA, B: &MATB)
112    where
113        MATA: DenseMatrix<T>,
114        MATB: DenseMatrix<T>,
115    {
116        let (pp, qq) = A.size();
117        let (rr, ss) = B.size();
118        assert!(self.nrows() == pp * rr);
119        assert!(self.ncols() == qq * ss);
120
121        let mut i = 0;
122        for q in 0..qq {
123            for s in 0..ss {
124                for p in 0..pp {
125                    let Apq = A[(p, q)];
126                    for r in 0..rr {
127                        self.data_mut()[i] = (Apq) * B[(r, s)];
128                        i += 1;
129                    }
130                }
131            }
132        }
133    }
134}
135
136
137#[allow(dead_code)]
142impl<S,T> DenseStorageMatrix<S, T> 
143where 
144    T: FloatT,
145    S: AsRef<[T]> + AsMut<[T]>
146{
147    pub fn symmetric_part(&mut self) -> &mut Self {
149        assert!(self.is_square());
150        let half: T = (0.5_f64).as_T();
151
152        for r in 0..self.nrows() {
153            for c in 0..r {
154                let val = half * (self[(r, c)] + self[(c, r)]);
155                self[(c, r)] = val;
156                self[(r, c)] = val;
157            }
158        }
159        self
160    }
161}
162
163
164
165pub(crate) fn svec_to_mat<S,T>(M: &mut DenseStorageMatrix<S,T>, x: &[T]) 
166where
167    T: FloatT,
168    S: AsRef<[T]> + AsMut<[T]>,
169{
170    let mut idx = 0;
171    for col in 0..M.ncols() {
172        for row in 0..=col {
173            if row == col {
174                M[(row, col)] = x[idx];
175            } else {
176                M[(row, col)] = x[idx] * T::FRAC_1_SQRT_2();
177                M[(col, row)] = x[idx] * T::FRAC_1_SQRT_2();
178            }
179            idx += 1;
180        }
181    }
182}
183
184pub(crate) fn mat_to_svec<T,MATM>(x: &mut [T], M: &MATM)
186where 
187MATM: DenseMatrix<T>,
188     T: FloatT,
189{
190    let mut idx = 0;
191    for col in 0..M.ncols() {
192        for row in 0..=col {
193            x[idx] = {
194                if row == col {
195                    M[(row, col)]
196                } else {
197                    (M[(row, col)] + M[(col, row)]) * T::FRAC_1_SQRT_2()
198                }
199            };
200            idx += 1;
201        }
202    }
203}
204
205
206#[test]
207fn test_row_col_sums_and_norms() {
208    #[rustfmt::skip]
209    let A = Matrix::from(&[
210        [-1.,  4.,  6.], 
211        [ 3., -8.,  7.], 
212        [ 0.,  4.,  9.],
213    ]);
214
215    let mut rsums = vec![0.0; 3];
216    let mut csums = vec![0.0; 3];
217
218    A.row_sums(&mut rsums);
219    assert_eq!(rsums, [9.0, 2.0, 13.0]);
220    A.col_sums(&mut csums);
221    assert_eq!(csums, [2.0, 0.0, 22.0]);
222
223    let mut rnorms = vec![0.0; 3];
224    let mut cnorms = vec![0.0; 3];
225
226    A.row_norms(&mut rnorms);
227    assert!(rnorms == [6.0, 8.0, 9.0]);
228    A.col_norms(&mut cnorms);
229    assert!(cnorms == [3.0, 8.0, 9.0]);
230
231    let mut rnorms = vec![0.0; 3];
233    let mut cnorms = vec![0.0; 3];
234    rnorms[2] = 100.;
235    cnorms[2] = 100.;
236
237    A.row_norms_no_reset(&mut rnorms);
238    assert!(rnorms == [6.0, 8.0, 100.0]);
239    A.col_norms_no_reset(&mut cnorms);
240    assert!(cnorms == [3.0, 8.0, 100.0]);
241}
242
243#[test]
244#[rustfmt::skip]
245fn test_l_r_scalings() {
246
247    let A = Matrix::from(&[
248        [-1.,  4.,  6.], 
249        [ 3., -8.,  7.], 
250        [ 0.,  4.,  9.],
251    ]);
252
253    let lscale = vec![1., -2., 3.];
254    let rscale = vec![-2., 1., -3.];
255
256    let mut B = A.clone();
258    B.rscale(&rscale);
259    let Btest = Matrix::from(&[
260        [ 2.,  4.,  -18.], 
261        [-6., -8.,  -21.], 
262        [ 0.,  4.,  -27.],
263    ]);
264    assert_eq!(B,Btest);
265
266    let mut B = A.clone();
268    B.lscale(&lscale);
269    let Btest = Matrix::from(&[
270        [-1.,  4.,   6.], 
271        [-6., 16., -14.], 
272        [ 0., 12.,  27.],
273    ]);
274    assert_eq!(B,Btest);
275
276    let mut B = A;
278    B.lrscale(&lscale, &rscale);
279    let Btest = Matrix::from(&[
280        [ 2.,  4., -18.], 
281        [12., 16.,  42.], 
282        [ 0., 12., -81.],
283    ]);
284    assert_eq!(B,Btest);
285}
286
287#[test]
288fn test_symmetric_part() {
289
290    let mut A = Matrix::from(&[
291        [-1.,  4.,  6.],
292        [ 2., -8.,  8.],
293        [ 0.,  4.,  9.],
294    ]);
295
296    let B = Matrix::from(&[
297        [-1.,  3.,  3.],
298        [ 3., -8.,  6.],
299        [ 3.,  6.,  9.],
300    ]);
301
302    A.symmetric_part();
303    assert_eq!(B,A);
304}
305
306#[test]
307fn test_col_norms_sym() {
308
309    let A = Matrix::from(&[
310        [-1.,  4.,  6.],
311        [ 2., -8.,  8.],
312        [ 0.,  4.,  9.],
313    ]);
314
315    let mut v = vec![0.0; 3];
316    A.col_norms_sym(&mut v);
317    assert_eq!(v, [6.0, 8.0, 9.0]);
318}
319
320
321
322#[test]
323#[rustfmt::skip]
324fn test_kron() {
325
326    let A = Matrix::from(
327        &[[ 1.,  2.],
328          [ 4.,  5.]]);
329
330    let B = Matrix::from(
331        &[[ 1.,  2.]]);
332
333
334    let (k1, m1) = A.size();
336    let (k2, m2) = B.size();
337    let mut K = Matrix::<f64>::zeros((k1 * k2, m1 * m2));
338    K.kron(&A, &B);
339
340    let Ktest = Matrix::from(
341        &[[ 1.,  2.,  2.,  4.],
342          [ 4.,  8.,  5., 10.]]);
343
344    assert_eq!(K,Ktest);
345
346    let (k1, m1) = A.t().size();
348    let (k2, m2) = B.size();
349    let mut K = Matrix::<f64>::zeros((k1 * k2, m1 * m2));
350    K.kron(&A.t(), &B);
351
352    let Ktest = Matrix::from(
353        &[[ 1.,  2.,  4.,  8.],
354          [ 2.,  4.,  5., 10.]]);
355          
356    assert_eq!(K,Ktest);
357
358    let (k1, m1) = A.size();
360    let (k2, m2) = B.t().size();
361    let mut K = Matrix::<f64>::zeros((k1 * k2, m1 * m2));
362    K.kron(&A, &B.t());
363
364    let Ktest = Matrix::from(
365        &[[1., 2. ],
366          [2., 4. ],
367          [4., 5. ],
368          [8., 10.]]);
369          
370    assert_eq!(K,Ktest);
371
372    let (k1, m1) = A.t().size();
374    let (k2, m2) = B.t().size();  
375    let mut K = Matrix::<f64>::zeros((k1 * k2, m1 * m2));  
376    K.kron(&A.t(), &B.t());
377
378    let Ktest = Matrix::from(
379        &[[1., 4. ],
380          [2., 8. ],
381          [2., 5. ],
382          [4., 10.]]);
383
384    assert_eq!(K,Ktest);
385}
386
387
388
389#[test]
390fn test_svec_conversions() {
391    let n = 3;
392
393    let X = Matrix::from(&[
394        [1., 3., -2.], [3., -4., 7.], [-2., 7., 5.], ]);
398
399    let Y = Matrix::from(&[
400        [2., 5., -4.],  [5., 6., 2.],   [-4., 2., -3.], ]);
404
405    let mut Z = Matrix::zeros((3, 3));
406
407    let mut x = vec![0.; triangular_number(n)];
408    let mut y = vec![0.; triangular_number(n)];
409
410    mat_to_svec(&mut x, &X);
412    mat_to_svec(&mut y, &Y);
413
414    assert!(f64::abs(x.dot(&y) - X.data().dot(Y.data())) < 1e-12);
415
416    mat_to_svec(&mut x, &X);
418    svec_to_mat(&mut Z, &x);
419    assert!(X.data().norm_inf_diff(Z.data()) < 1e-12);
420}