b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2matrix_packed.H
1//------------------------------------------------------------------------
2// b2matrix_packed.H --
3//
4// A framework for generic linear algebraic (matrix) computations.
5//
6// written by Mathias Doreille
7// Thomas Blome <thomas.blome@dlr.de>
8//
9// Copyright (c) 2004-2012 SMR Engineering & Development SA
10// 2502 Bienne, Switzerland
11//
12// Copyright (c) 2023 Deutsches Zentrum für Luft- und Raumfahrt (DLR) e.V.
13// Linder Höhe, 51147 Köln
14//
15// All Rights Reserved. Proprietary source code. The contents of
16// this file may not be disclosed to third parties, copied or
17// duplicated in any form, in whole or in part, without the prior
18// written permission of SMR.
19//------------------------------------------------------------------------
20
21#ifndef __B2MATRIX_PACKED_H__
22#define __B2MATRIX_PACKED_H__
23
24#include "b2linear_algebra_def.H"
25
26namespace b2000::b2linalg {
27
28struct Mlower_packed {
29 using base = Mpacked_ref;
30 using const_base = Mpacked_st_constref;
31 using copy = Mlower_packed;
32};
33
34template <typename T>
35class Matrix<T, Mlower_packed> {
36public:
37 Matrix() = default;
38
39 Matrix(size_t s_) : s(s_), m(s_ * (s_ + 1) / 2) {}
40
41 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
42
43 template <typename T1>
44 Matrix(const Matrix<T1, Mlower_packed>& m_)
45 : s(m_.s.begin(), m_.s.end()), m(m_.m.begin(), m_.m.end()) {}
46
47 template <typename T1>
48 Matrix& operator=(const Matrix<T1, Mlower_packed>& m_) {
49 s = m_.s;
50 m.assign(m_.m.begin(), m_.m.end());
51 return *this;
52 }
53
54 template <typename STORAGE>
55 Matrix& operator=(const Matrix<T, STORAGE>& m_) {
56 if (m_.size1() != m_.size2()) { Exception() << "The matrix is not symmetric." << THROW; }
57 s = m_.size1();
58 m.resize(s * (s + 1) / 2);
59 Matrix<T, Mpacked_ref> ref(*this);
60 ref = m_;
61 return *this;
62 }
63
64 Matrix& operator=(const Matrix& m_) {
65 s = m_.s;
66 m = m_.m;
67 return *this;
68 }
69
70 bool is_null() const { return this == &null; }
71
72 void set_zero() { std::fill(m.begin(), m.end(), 0); }
73
74 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
75
76 size_t size1() const { return s; }
77
78 size_t size2() const { return s; }
79
80 size_t esize() const { return s * (s + 1) / 2; }
81
82 void resize(size_t s_) {
83 s = s_;
84 m.resize(s_ * (s_ + 1) / 2);
85 }
86
87 void resize(size_t s1, size_t s2) {
88 if (s1 != s2) { Exception() << THROW; }
89 s = s1;
90 m.resize(s1 * (s1 + 1) / 2);
91 }
92
93 const T& operator()(size_t i, size_t j) const {
94 if (i < j) {
95 return m[(2 * s - i - 1) * i / 2 + j];
96 } else {
97 return m[(2 * s - j - 1) * j / 2 + i];
98 }
99 }
100
101 T& operator()(size_t i, size_t j) {
102 if (i < j) {
103 return m[(2 * s - i - 1) * i / 2 + j];
104 } else {
105 return m[(2 * s - j - 1) * j / 2 + i];
106 }
107 }
108
109 static Matrix null;
110
111 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
112 l << "lower packed matrix ";
113 l.write(m.s * (m.s + 1) / 2, &m.m[0], 1);
114 return l;
115 }
116
117private:
118 size_t s{};
119 std::vector<T> m{};
120 MVFRIEND;
121};
122
123template <typename T>
124Matrix<T, Mlower_packed> Matrix<T, Mlower_packed>::null;
125
126struct Mlower_packed_ref {
127 using base = Mpacked_ref;
128 using const_base = Mpacked_st_constref;
129 using copy = Mlower_packed;
130};
131
132template <typename T>
133class Matrix<T, Mlower_packed_ref> {
134public:
135 Matrix() = default;
136
137 Matrix(size_t s_, T* m_) : s(s_), m(m_) {}
138
139 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
140
141 Matrix(Matrix<T, Mlower_packed>& m_) : s(m_.s), m(&m_.m[0]) {}
142
143 bool is_null() const { return m == 0; }
144
145 void set_zero() { std::fill(m, m + esize(), 0); }
146
147 Matrix& operator=(const Matrix& m_) {
148 if (s != m_.s) { Exception() << "The two matrix do not have the same size." << THROW; }
149 std::copy(m_.m, m_.m + s, m);
150 return *this;
151 }
152
153 template <typename STORAGE>
154 Matrix& operator=(const Matrix<T, STORAGE>& m_) {
155 Matrix<T, Mpacked_ref> ref(*this);
156 ref = m_;
157 return *this;
158 }
159
160 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
161
162 size_t size1() const { return s; }
163
164 size_t size2() const { return s; }
165
166 size_t esize() const { return s * (s + 1) / 2; }
167
168 const T& operator()(size_t i, size_t j) const {
169 if (i < j) {
170 return m[(2 * s - i - 1) * i / 2 + j];
171 } else {
172 return m[(2 * s - j - 1) * j / 2 + i];
173 }
174 }
175
176 T& operator()(size_t i, size_t j) {
177 if (i < j) {
178 return m[(2 * s - i - 1) * i / 2 + j];
179 } else {
180 return m[(2 * s - j - 1) * j / 2 + i];
181 }
182 }
183
184 static Matrix null;
185
186 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
187 l << "lower packed matrix ";
188 l.write(m.s * (m.s + 1) / 2, m.m, 1);
189 return l;
190 }
191
192private:
193 size_t s{};
194 T* m{};
195 MVFRIEND;
196};
197
198template <typename T>
199Matrix<T, Mlower_packed_ref> Matrix<T, Mlower_packed_ref>::null;
200
201struct Mlower_packed_constref {
202 using base = Mpacked_st_constref;
203 using const_base = Mpacked_st_constref;
204 using copy = Mlower_packed;
205};
206
207template <typename T>
208class Matrix<T, Mlower_packed_constref> {
209public:
210 Matrix() = default;
211
212 Matrix(size_t s_, const T* m_) : s(s_), m(m_) {}
213
214 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
215
216 Matrix(const Matrix<T, Mlower_packed>& m_) : s(m_.s), m(&m_.m[0]) {}
217
218 Matrix(const Matrix<T, Mlower_packed_ref>& m_) : s(m_.s), m(m_.m) {}
219
220 bool is_null() const { return m == 0; }
221
222 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
223
224 size_t size1() const { return s; }
225
226 size_t size2() const { return s; }
227
228 size_t esize() const { return s * (s + 1) / 2; }
229
230 const T& operator()(size_t i, size_t j) const {
231 if (i < j) {
232 return m[(2 * s - i - 1) * i / 2 + j];
233 } else {
234 return m[(2 * s - j - 1) * j / 2 + i];
235 }
236 }
237
238 static Matrix null;
239
240 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
241 l << "lower packed matrix ";
242 l.write(m.s * (m.s + 1) / 2, m.m, 1);
243 return l;
244 }
245
246private:
247 size_t s{};
248 const T* m{};
249 MVFRIEND;
250};
251
252template <typename T>
253Matrix<T, Mlower_packed_constref> Matrix<T, Mlower_packed_constref>::null;
254
255struct Mupper_packed {
256 using base = Mpacked_ref;
257 using const_base = Mpacked_st_constref;
258 using copy = Mupper_packed;
259};
260
261template <typename T>
262class Matrix<T, Mupper_packed> {
263public:
264 Matrix() = default;
265
266 Matrix(size_t s_) : s(s_), m(s_ * (s_ + 1) / 2) {}
267
268 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
269
270 template <typename T1>
271 Matrix(const Matrix<T1, Mupper_packed>& m_)
272 : s(m_.s.begin(), m_.s.end()), m(m_.m.begin(), m_.m.end()) {}
273
274 template <typename T1>
275 Matrix& operator=(const Matrix<T1, Mupper_packed>& m_) {
276 s = m_.s;
277 m.assign(m_.m.begin(), m_.m.end());
278 return *this;
279 }
280
281 Matrix& operator=(const Matrix& m_) {
282 s = m_.s;
283 m = m_.m;
284 return *this;
285 }
286
287 template <typename STORAGE>
288 Matrix& operator=(const Matrix<T, STORAGE>& m_) {
289 if (m_.size1() != m_.size2()) { Exception() << "The matrix is not symmetric." << THROW; }
290 s = m_.size1();
291 m.resize(s * (s + 1) / 2);
292 Matrix<T, Mpacked_ref> ref(*this);
293 ref = m_;
294 return *this;
295 }
296
297 bool is_null() const { return this == &null; }
298
299 void set_zero() { std::fill(m.begin(), m.end(), 0); }
300
301 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
302
303 size_t size1() const { return s; }
304
305 size_t size2() const { return s; }
306
307 size_t esize() const { return s * (s + 1) / 2; }
308
309 void resize(size_t s1, size_t s2) {
310 if (s1 != s2) { Exception() << THROW; }
311 s = s1;
312 m.resize(s1 * (s1 + 1) / 2);
313 }
314
315 const T& operator()(size_t i, size_t j) const {
316 if (j < i) {
317 return m[i * (i + 1) / 2 + j];
318 } else {
319 return m[j * (j + 1) / 2 + i];
320 }
321 }
322
323 T& operator()(size_t i, size_t j) {
324 if (j < i) {
325 return m[i * (i + 1) / 2 + j];
326 } else {
327 return m[j * (j + 1) / 2 + i];
328 }
329 }
330
331 static Matrix null;
332
333 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
334 l << "upper packed matrix ";
335 l.write(m.s * (m.s + 1) / 2, &m.m[0], 1);
336 return l;
337 }
338
339private:
340 size_t s{};
341 std::vector<T> m{};
342 MVFRIEND;
343};
344
345template <typename T>
346Matrix<T, Mupper_packed> Matrix<T, Mupper_packed>::null;
347
348struct Mupper_packed_ref {
349 using base = Mpacked_ref;
350 using const_base = Mpacked_st_constref;
351 using copy = Mupper_packed;
352};
353
354template <typename T>
355class Matrix<T, Mupper_packed_ref> {
356public:
357 Matrix() = default;
358
359 Matrix(size_t s_, T* m_) : s(s_), m(m_) {}
360
361 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
362
363 Matrix(Matrix<T, Mupper_packed>& m_) : s(m_.s), m(&m_.m[0]) {}
364
365 bool is_null() const { return m == 0; }
366
367 void set_zero() { std::fill(m, m + esize(), 0); }
368
369 Matrix& operator=(const Matrix& m_) {
370 if (s != m_.s) { Exception() << "The two matrix do not have the same size." << THROW; }
371 std::copy(m_.m, m_.m + s, m);
372 return *this;
373 }
374
375 template <typename STORAGE>
376 Matrix& operator=(const Matrix<T, STORAGE>& m_) {
377 Matrix<T, Mpacked_ref> ref(*this);
378 ref = m_;
379 return *this;
380 }
381
382 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
383
384 size_t size1() const { return s; }
385
386 size_t size2() const { return s; }
387
388 size_t esize() const { return s * (s + 1) / 2; }
389
390 const T& operator()(size_t i, size_t j) const {
391 if (j < i) {
392 return m[i * (i + 1) / 2 + j];
393 } else {
394 return m[j * (j + 1) / 2 + i];
395 }
396 }
397
398 T& operator()(size_t i, size_t j) {
399 if (j < i) {
400 return m[i * (i + 1) / 2 + j];
401 } else {
402 return m[j * (j + 1) / 2 + i];
403 }
404 }
405
406 static Matrix null;
407
408 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
409 l << "upper packed matrix ";
410 l.write(m.s * (m.s + 1) / 2, m.m, 1);
411 return l;
412 }
413
414private:
415 size_t s{};
416 T* m{};
417 MVFRIEND;
418};
419
420template <typename T>
421Matrix<T, Mupper_packed_ref> Matrix<T, Mupper_packed_ref>::null;
422
423struct Mupper_packed_constref {
424 using base = Mpacked_st_constref;
425 using const_base = Mpacked_st_constref;
426 using copy = Mupper_packed;
427};
428
429template <typename T>
430class Matrix<T, Mupper_packed_constref> {
431public:
432 Matrix() = default;
433
434 Matrix(size_t s_, const T* m_) : s(s_), m(m_) {}
435
436 Matrix(const Matrix& m_) : s(m_.s), m(m_.m) {}
437
438 Matrix(const Matrix<T, Mupper_packed>& m_) : s(m_.s), m(&m_.m[0]) {}
439
440 Matrix(const Matrix<T, Mupper_packed_ref>& m_) : s(m_.s), m(m_.m) {}
441
442 bool is_null() const { return m == 0; }
443
444 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
445
446 size_t size1() const { return s; }
447
448 size_t size2() const { return s; }
449
450 size_t esize() const { return s * (s + 1) / 2; }
451
452 const T& operator()(size_t i, size_t j) const {
453 if (j < i) {
454 return m[i * (i + 1) / 2 + j];
455 } else {
456 return m[j * (j + 1) / 2 + i];
457 }
458 }
459
460 static Matrix null;
461
462 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
463 l << "upper packed matrix ";
464 l.write(m.s * (m.s + 1) / 2, m.m, 1);
465 return l;
466 }
467
468private:
469 size_t s{};
470 const T* m{};
471 MVFRIEND;
472};
473
474template <typename T>
475Matrix<T, Mupper_packed_constref> Matrix<T, Mupper_packed_constref>::null;
476
477struct Mpacked {
478 using base = Mpacked_ref;
479 using const_base = Mpacked_st_constref;
480 using copy = Mupper_packed;
481};
482
483template <typename T>
484class Matrix<T, Mpacked> {
485public:
486 Matrix() = default;
487
488 explicit Matrix(size_t s_, bool upper_ = false) : s(s_), m(s_ * (s_ + 1) / 2), upper(upper_) {}
489
490 Matrix(const Matrix& m_) : s(m_.s), m(m_.m), upper(m_.upper) {}
491
492 template <typename T1>
493 Matrix(const Matrix<T1, Mpacked>& m_)
494 : s(m_.s.begin(), m_.s.end()), m(m_.m.begin(), m_.m.end()), upper(m_.upper) {}
495
496 template <typename T1>
497 Matrix& operator=(const Matrix<T1, Mpacked>& m_) {
498 s = m_.s;
499 m.assign(m_.m.begin(), m_.m.end());
500 upper = m_.upper;
501 return *this;
502 }
503
504 double norm_inf() const {
505 double res = 0;
506 for (typename std::vector<T>::const_iterator i = m.begin(); i != m.end(); ++i) {
507 res = std::max(res, norm(*i));
508 }
509 return res;
510 }
511
512 void set_zero() { std::fill(m.begin(), m.end(), 0); }
513
514 bool is_null() const { return this == &null; }
515
516 Matrix& operator=(const Matrix& m_) {
517 s = m_.s;
518 m = m_.m;
519 upper = m_.upper;
520 return *this;
521 }
522
523 template <typename STORAGE>
524 Matrix& operator=(const Matrix<T, STORAGE>& m_) {
525 s = m_.size1();
526 m.resize(s * (s + 1) / 2);
527 Matrix<T, Mpacked_ref>(*this) = m_;
528 return *this;
529 }
530
531 template <typename STORAGE>
532 Matrix& operator+=(const Matrix<T, STORAGE>& m_) {
533 *this = *this + m_;
534 return *this;
535 }
536
537 template <typename STORAGE>
538 Matrix& operator-=(const Matrix<T, STORAGE>& m_) {
539 *this = *this - m_;
540 return *this;
541 }
542
543 Matrix& operator*=(const T& scalar) {
544 blas::scal(m.size(), scalar, &m[0], 1);
545 return *this;
546 }
547
548 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
549
550 size_t size1() const { return s; }
551
552 size_t size2() const { return s; }
553
554 size_t esize() const { return s * (s + 1) / 2; }
555
556 bool is_upper() const { return upper; }
557
558 void resize(size_t s_, bool upper_ = false) {
559 s = s_;
560 m.resize(s_ * (s_ + 1) / 2);
561 upper = upper_;
562 }
563
564 void resize(size_t s1, size_t s2, bool upper_ = false) {
565 if (s1 != s2) { Exception() << THROW; }
566 s = s1;
567 m.resize(s1 * (s1 + 1) / 2);
568 upper = upper_;
569 }
570
571 const T& operator()(size_t i, size_t j) const {
572 if (j < i) {
573 if (upper) {
574 return m[i * (i + 1) / 2 + j];
575 } else {
576 return m[(2 * s - j - 1) * j / 2 + i];
577 }
578 } else if (upper) {
579 return m[j * (j + 1) / 2 + i];
580 } else {
581 return m[(2 * s - i - 1) * i / 2 + j];
582 }
583 }
584
585 T& operator()(size_t i, size_t j) {
586 if (j < i) {
587 if (upper) {
588 return m[i * (i + 1) / 2 + j];
589 } else {
590 return m[(2 * s - j - 1) * j / 2 + i];
591 }
592 } else if (upper) {
593 return m[j * (j + 1) / 2 + i];
594 } else {
595 return m[(2 * s - i - 1) * i / 2 + j];
596 }
597 }
598
599 Matrix operator=(const Matrix<T, Sum<Mpacked_st_constref, Mpacked_st_constref> >& m_) {
600 if (m_.m1.upper != m_.m2.upper) { UnimplementedError() << THROW; }
601 resize(m_.size1(), m_.size2(), m_.m1.upper);
602 for (size_t i = 0; i != m.size(); ++i) {
603 m[i] = m_.scale * (m_.m1.scale * m_.m1.m[i] + m_.m2.scale * m_.m2.m[i]);
604 }
605 return *this;
606 }
607
608 void swap(Matrix& m_) {
609 std::swap(s, m_.s);
610 m.swap(m_.m);
611 std::swap(upper, m_.upper);
612 }
613
614 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
615 if (m.upper) {
616 l << "upper packed matrix ";
617 } else {
618 l << "lower packed matrix ";
619 }
620 l.write(m.s * (m.s + 1) / 2, &m.m[0], 1);
621 return l;
622 }
623
624 static Matrix null;
625
626private:
627 size_t s{};
628 std::vector<T> m{};
629 bool upper{};
630 MVFRIEND;
631};
632
633template <typename T>
634Matrix<T, Mpacked> Matrix<T, Mpacked>::null;
635
636struct Mpacked_ref {
637 using base = Mpacked_ref;
638 using const_base = Mpacked_st_constref;
639 using copy = Mlower_packed;
640};
641
642template <typename T>
643class Matrix<T, Mpacked_ref> {
644public:
645 Matrix() = default;
646
647 Matrix(size_t s_, T* m_, bool upper_) : s(s_), m(m_), upper(upper_) {}
648
649 Matrix(const Matrix& m_) : s(m_.s), m(m_.m), upper(m_.upper) {}
650
651 Matrix(Matrix<T, Mupper_packed>& m_) : s(m_.s), m(&m_.m[0]), upper(true) {}
652
653 Matrix(Matrix<T, Mupper_packed_ref>& m_) : s(m_.s), m(m_.m), upper(true) {}
654
655 Matrix(Matrix<T, Mlower_packed>& m_) : s(m_.s), m(&m_.m[0]), upper(false) {}
656
657 Matrix(Matrix<T, Mlower_packed_ref>& m_) : s(m_.s), m(m_.m), upper(false) {}
658
659 Matrix(Matrix<T, Mpacked>& m_) : s(m_.s), m(&m_.m[0]), upper(m_.upper) {}
660
661 bool is_null() const { return m == 0; }
662
663 void set_zero() { std::fill(m, m + esize(), 0); }
664
665 Matrix& operator=(const Matrix& m_) {
666 if (s != m_.s) { Exception() << "The two matrix do not have the same size." << THROW; }
667 if (upper == m_.upper) {
668 std::copy(m_.m, m_.m + s, m);
669 } else {
671 }
672 return *this;
673 }
674
675 Matrix& operator=(const Matrix<T, Mrectangle_increment_st_constref>& m_) {
676 if (s != m_.s1 || s != m_.s2) {
677 Exception() << "The two matrix do not have the same size." << THROW;
678 }
679 const T* ms1 = m_.m;
680 const T* ms2 = ms1;
681 T* md = m;
682 const double scale = 0.5 * m_.scale;
683 if (upper) {
684 for (size_t j = 0; j != s; ++j, ++ms2) {
685 const T* ms2_tmp = ms2;
686 size_t i = 0;
687 for (; i <= j; ++i, ++md, ms2_tmp += m_.ldm) { *md = scale * (ms1[i] + *ms2_tmp); }
688 ms1 += m_.ldm;
689 }
690 } else {
691 for (size_t j = 0; j != s; ++j, ms2 += m_.ldm + 1) {
692 const T* ms2_tmp = ms2;
693 for (size_t i = j; i != s; ++i, ++md, ms2_tmp += m_.ldm) {
694 *md = scale * (ms1[i] + *ms2_tmp);
695 }
696 ms1 += m_.ldm;
697 }
698 }
699 return *this;
700 }
701
702 Matrix& operator=(const Matrix<T, Mpacked_st_constref>& m_) {
703 if (s != m_.s) { Exception() << "The two matrix do not have the same size." << THROW; }
704 if (upper == m_.upper) {
705 size_t ss = s * (s + 1) / 2;
706 std::copy(m_.m, m_.m + ss, m);
707 if (m_.scale != T(1)) { blas::scal(ss, T(m_.scale), m, 1); }
708 } else {
710 }
711 return *this;
712 }
713
714 Matrix& operator=(const Matrix<
715 T, MMProd<
716 MMProd<Mrectangle_increment_st_constref, Mpacked_st_constref>,
717 Mrectangle_increment_st_constref> >& m_) {
718 if (size() != m_.size()) {
719 Exception() << "The two matrix do not have the same size." << THROW;
720 }
721 if (m_.m1.m1.m != m_.m2.m || m_.m1.m1.s1 != m_.m2.s1 || m_.m1.m1.s2 != m_.m2.s2
722 || m_.m1.m1.ldm != m_.m2.ldm || m_.m1.m1.trans == m_.m2.trans) {
723 UnimplementedError() << "Not implemented (the product is not a symmetric matrix)."
724 << THROW;
725 }
726
727 std::vector<T> tmp(m_.m1.m2.s);
728 T* ptr = &m[0];
729 const char m_m1_m2_uplo = m_.m1.m2.upper ? 'U' : 'L';
730 const T alpha = m_.m1.m1.scale * m_.m1.m2.scale * m_.m2.scale * m_.scale;
731 if (upper) {
732 if (m_.m2.trans) {
733 for (size_t j = 0; j != s; ++j) {
734 blas::spmv(
735 m_m1_m2_uplo, tmp.size(), 1, m_.m1.m2.m, &m_.m2.m[j], m_.m2.ldm, 0,
736 &tmp[0], 1);
737 blas::gemv(
738 'N', j + 1, tmp.size(), alpha, &m_.m2.m[0], m_.m2.ldm, &tmp[0], 1, T(0),
739 ptr, 1);
740 ptr += j + 1;
741 }
742 } else {
743 for (size_t j = 0; j != s; ++j) {
744 blas::spmv(
745 m_m1_m2_uplo, tmp.size(), 1, m_.m1.m2.m, &m_.m2.m[j * m_.m2.ldm], 1, 0,
746 &tmp[0], 1);
747 blas::gemv(
748 'T', tmp.size(), j + 1, alpha, &m_.m2.m[0], m_.m2.ldm, &tmp[0], 1, T(0),
749 ptr, 1);
750 ptr += j + 1;
751 }
752 }
753 } else if (m_.m2.trans) {
754 for (size_t j = 0; j != s; ++j) {
755 blas::spmv(
756 m_m1_m2_uplo, tmp.size(), 1, m_.m1.m2.m, &m_.m2.m[j], m_.m2.ldm, 0, &tmp[0],
757 1);
758 blas::gemv(
759 'N', s - j, tmp.size(), alpha, &m_.m2.m[j], m_.m2.ldm, &tmp[0], 1, T(0), ptr,
760 1);
761 ptr += s - j;
762 }
763 } else {
764 for (size_t j = 0; j != s; ++j) {
765 blas::spmv(
766 m_m1_m2_uplo, tmp.size(), 1, m_.m1.m2.m, &m_.m2.m[j * m_.m2.ldm], 1, 0,
767 &tmp[0], 1);
768 blas::gemv(
769 'T', tmp.size(), s - j, alpha, &m_.m2.m[j * m_.m2.ldm], m_.m2.ldm, &tmp[0], 1,
770 T(0), ptr, 1);
771 ptr += s - j;
772 }
773 }
774 return *this;
775 }
776
777 Matrix& operator=(
778 const Matrix<
779 T, MMProd<
780 MMProd<Mrectangle_increment_st_constref, Msym_compressed_col_st_constref>,
781 Mrectangle_increment_st_constref> >& m_) {
782 if (size() != m_.size()) {
783 Exception() << "The two matrix do not have the same size." << THROW;
784 }
785 if (m_.m1.m1.m != m_.m2.m || m_.m1.m1.s1 != m_.m2.s1 || m_.m1.m1.s2 != m_.m2.s2
786 || m_.m1.m1.ldm != m_.m2.ldm || m_.m1.m1.trans == m_.m2.trans) {
787 UnimplementedError() << "Not implemented (the product is not a symmetric matrix)."
788 << THROW;
789 }
790
791 Vector<T> v1;
792 T* m_ptr = m;
793 const T scale = m_.scale * m_.m1.scale * m_.m1.m1.scale;
794 for (size_t j = 0; j != m_.m2.s2; ++j) {
795 v1 = m_.m1.m2 * m_.m2[j];
796 if (upper) {
797 Vector<T, Vdense_ref> v2(j + 1, m_ptr);
798 v2 = scale * m_.m1.m1(Interval(0, j + 1), Interval(0, v1.size())) * v1;
799 m_ptr += j + 1;
800 } else {
801 Vector<T, Vdense_ref> v2(s - j, m_ptr);
802 v2 = scale * m_.m1.m1(Interval(j, s), Interval(0, v1.size())) * v1;
803 m_ptr += s - j;
804 }
805 }
806 return *this;
807 }
808
809 template <typename STORAGE>
810 Matrix& operator+=(const Matrix<T, STORAGE>& m_) {
811 *this = *this + m_;
812 return *this;
813 }
814
815 template <typename STORAGE>
816 Matrix& operator-=(const Matrix<T, STORAGE>& m_) {
817 *this = *this - m_;
818 return *this;
819 }
820
821 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
822
823 size_t size1() const { return s; }
824
825 size_t size2() const { return s; }
826
827 size_t esize() const { return s * (s + 1) / 2; }
828
829 const T& operator()(size_t i, size_t j) const {
830 if (j < i) {
831 if (upper) {
832 return m[i * (i + 1) / 2 + j];
833 } else {
834 return m[(2 * s - j - 1) * j / 2 + i];
835 }
836 } else if (upper) {
837 return m[j * (j + 1) / 2 + i];
838 } else {
839 return m[(2 * s - i - 1) * i / 2 + j];
840 }
841 }
842
843 T& operator()(size_t i, size_t j) {
844 if (j < i) {
845 if (upper) {
846 return m[i * (i + 1) / 2 + j];
847 } else {
848 return m[(2 * s - j - 1) * j / 2 + i];
849 }
850 } else if (upper) {
851 return m[j * (j + 1) / 2 + i];
852 } else {
853 return m[(2 * s - i - 1) * i / 2 + j];
854 }
855 }
856
857 static Matrix null;
858
859 friend logging::Logger& operator<<(logging::Logger& l, const Matrix& m) {
860 if (m.upper) {
861 l << "upper packed matrix ";
862 } else {
863 l << "lower packed matrix ";
864 }
865 l.write(m.s * (m.s + 1) / 2, m.m, 1);
866 return l;
867 }
868
869private:
870 size_t s{};
871 T* m{};
872 bool upper{};
873 MVFRIEND;
874};
875
876template <typename T>
877Matrix<T, Mpacked_ref> Matrix<T, Mpacked_ref>::null;
878
879struct Mpacked_st_constref {
880 using base = Mpacked_st_constref;
881 using const_base = Mpacked_st_constref;
882 using copy = Mlower_packed;
883};
884
885template <typename T>
886class Matrix<T, Mpacked_st_constref> {
887public:
888 Matrix() = default;
889
890 Matrix(size_t s_, const T* m_, bool scale_, bool upper_)
891 : s(s_), m(m_), scale(scale_), upper(upper_) {}
892
893 Matrix(const Matrix& m_) : s(m_.s), m(m_.m), scale(m_.scale), upper(m_.upper) {}
894
895 Matrix(const Matrix<T, Mupper_packed>& m_) : s(m_.s), m(&m_.m[0]), scale(1), upper(true) {}
896
897 Matrix(const Matrix<T, Mupper_packed_ref>& m_) : s(m_.s), m(m_.m), scale(1), upper(true) {}
898
899 Matrix(const Matrix<T, Mupper_packed_constref>& m_) : s(m_.s), m(m_.m), scale(1), upper(true) {}
900
901 Matrix(const Matrix<T, Mlower_packed>& m_) : s(m_.s), m(&m_.m[0]), scale(1), upper(false) {}
902
903 Matrix(const Matrix<T, Mlower_packed_ref>& m_) : s(m_.s), m(m_.m), scale(1), upper(false) {}
904
905 Matrix(const Matrix<T, Mlower_packed_constref>& m_)
906 : s(m_.s), m(m_.m), scale(1), upper(false) {}
907
908 Matrix(const Matrix<T, Mpacked>& m_) : s(m_.s), m(&m_.m[0]), scale(1), upper(m_.upper) {}
909
910 Matrix(const Matrix<T, Mpacked_ref>& m_) : s(m_.s), m(m_.m), scale(1), upper(m_.upper) {}
911
912 bool is_null() const { return m == 0; }
913
914 std::pair<size_t, size_t> size() const { return std::pair<size_t, size_t>(s, s); }
915
916 size_t size1() const { return s; }
917
918 size_t size2() const { return s; }
919
920 size_t esize() const { return s * (s + 1) / 2; }
921
922 const T& operator()(size_t i, size_t j) const {
923 if (j < i) {
924 if (upper) {
925 return m[i * (i + 1) / 2 + j];
926 } else {
927 return m[(2 * s - j - 1) * j / 2 + i];
928 }
929 } else if (upper) {
930 return m[j * (j + 1) / 2 + i];
931 } else {
932 return m[(2 * s - i - 1) * i / 2 + j];
933 }
934 }
935
936 Matrix& operator*(T scale_) {
937 scale *= scale_;
938 return *this;
939 }
940
941 static Matrix null;
942
943private:
944 size_t s{};
945 const T* m{};
946 T scale{};
947 bool upper{};
948 MVFRIEND;
949};
950
951template <typename T>
952Matrix<T, Mpacked_st_constref> Matrix<T, Mpacked_st_constref>::null;
953
954} // namespace b2000::b2linalg
955
956#endif
csda< T > norm(const csda< T > &a)
Definition b2csda.H:343
#define THROW
Definition b2exception.H:198
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314