Easy3D 2.5.3
matrix.h
1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ********************************************************************/
26
27#ifndef EASY3D_CORE_MATRIX_H
28#define EASY3D_CORE_MATRIX_H
29
30#include <vector>
31#include <complex>
32#include <algorithm> // for std::min, std::max
33#include <cmath> // for std::sqrt
34
35
36namespace easy3d {
37
45 template<typename FT>
46 class Matrix {
47 public:
51 Matrix();
52
58 Matrix(const Matrix<FT> &A);
59
67 Matrix(int rows, int cols, const FT &x = FT(0));
68
78 Matrix(int rows, int cols, const std::vector <FT> &array);
79
91 Matrix(int rows, int cols, const FT *array);
92
93 ~Matrix();
94
96 Matrix<FT> &operator=(const Matrix<FT> &A); // overload evaluate operator = from matrix to matrix
98 Matrix<FT> &operator=(const FT &x); // overload evaluate operator = from scalar to matrix
99
101 FT *operator[](int row);
102
104 const FT *operator[](int row) const;
105
107 FT &operator()(int row, int col);
108
110 const FT &operator()(int row, int col) const;
111
113 void set(int row, int col, FT v);
114
116 const FT &get(int row, int col) const;
117
122 FT *data() { return data_; }
123
128 const FT *data() const { return data_; }
129
131 int rows() const;
132
134 int cols() const;
135
137 Matrix<FT> &resize(int rows, int cols);
138
140 std::vector <FT> get_row(int row) const;
141
143 std::vector <FT> get_column(int col) const;
144
146 void set_row(const std::vector <FT> &v, int row);
147
149 void set_column(const std::vector <FT> &v, int col);
150
152 void load_zero();
153
156 void load_identity(FT v = FT(1));
157
159 Matrix<FT> transpose() const;
160
162 Matrix<FT> inverse() const;
163
165 FT determinant() const;
166
169 FT trace() const;
170
172 Matrix<FT> &operator+=(const FT &v); //compound assignment operators +=
174 Matrix<FT> &operator-=(const FT &v); //compound assignment operators -=
176 template<typename FT2>
177 Matrix<FT> &operator*=(const FT2 &v); //compound assignment operators *=
179 template<typename FT2>
180 Matrix<FT> &operator/=(const FT2 &v); //compound assignment operators /=
183
186
187 private:
188
189 // 0-based data pointer
190 FT *data_;
191
192 // 0-based row pointer's pointer
193 FT **prow_;
194
195 // row number, column number and total number
196 int nRow_;
197 int nColumn_;
198 long nTotal_;
199
200 void init(int rows, int cols);
201
202 void copy_from_array(const FT *v); // copy matrix from normal array
203 void set_by_scalar(const FT &x); // set matrix by a scalar
204 void destroy(); // destroy the matrix
205
206 Matrix<FT> cofactor(int i, int j) const;
207
208 }; // class Matrix
209
210
211
212 //----------------------------- Utilities for Matrix ------------------------------//
213
215 template<typename FT>
216 std::ostream &operator<<(std::ostream &, const Matrix<FT> &); // Overload of the output stream.
217 template<typename FT>
218 std::istream &operator>>(std::istream &, Matrix<FT> &); // Overload of the input stream.
219
221 template<typename FT>
222 Matrix<FT> operator-(const Matrix<FT> &); // get negative matrix
223 template<typename FT>
224 Matrix<FT> operator+(const Matrix<FT> &, const FT &); // matrix-scalar addition
225 template<typename FT>
226 Matrix<FT> operator+(const FT &, const Matrix<FT> &); // scalar-matrix addition
227 template<typename FT>
228 Matrix<FT> operator+(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix addition
229 template<typename FT>
230 Matrix<FT> operator-(const Matrix<FT> &, const FT &); // matrix-scalar subtraction
231 template<typename FT>
232 Matrix<FT> operator-(const FT &, const Matrix<FT> &); // scalar-matrix subtraction
233 template<typename FT>
234 Matrix<FT> operator-(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix subtraction
235 template<typename FT>
236 Matrix<FT> operator*(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix multiplication
237 template<typename FT>
238 std::vector <FT> operator*(const Matrix<FT> &, const std::vector <FT> &); // matrix-vector multiplication
239 template<typename FT1, typename FT2>
240 Matrix<FT1> operator*(const Matrix<FT1> &, const FT2 &); // matrix-scalar multiplication
241 template<typename FT1, typename FT2>
242 Matrix<FT1> operator*(const FT2 &, const Matrix<FT1> &); // scalar-matrix multiplication
243 template<typename FT1, typename FT2>
244 Matrix<FT1> operator/(const Matrix<FT1> &, const FT2 &); // matrix-scalar division
245 template<typename FT1, typename FT2>
246 Matrix<FT1> operator/(const FT2 &, const Matrix<FT1> &); // scalar-matrix division
247
248
250 template<typename FT>
251 void mult(const Matrix<FT> &, const Matrix<FT> &,
252 Matrix<FT> &); // matrix-matrix multiplication (result has already been allocated)
253 template<typename FT>
254 void mult(const Matrix<FT> &, const std::vector <FT> &,
255 std::vector <FT> &); // matrix-vector multiplication (result has already been allocated)
256 template<typename FT>
257 Matrix<FT> mult(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix multiplication
258 template<typename FT>
259 std::vector <FT> mult(const Matrix<FT> &, const std::vector <FT> &); // matrix-vector multiplication
260
262 template<typename FT>
263 Matrix<FT> elem_mult(const Matrix<FT> &, const Matrix<FT> &); // "*"
264 template<typename FT>
265 Matrix<FT> elem_divd(const Matrix<FT> &, const Matrix<FT> &); // "/"
266 template<typename FT>
267 Matrix<FT> &elem_mult_eq(Matrix<FT> &, const Matrix<FT> &); // "*="
268 template<typename FT>
269 Matrix<FT> &elem_divd_eq(Matrix<FT> &, const Matrix<FT> &); // "/="
270
272 template<typename FT>
273 Matrix<FT> transpose(const Matrix<FT> &); // matrix transpose
274 template<typename FT>
275 Matrix<FT> conjugate_transpose(const Matrix<FT> &); // matrix conjugate transpose
276
278 template<typename FT>
279 Matrix<FT> transpose_mult(const Matrix<FT> &, const Matrix<FT> &); // A^T * B
280 template<typename FT>
281 std::vector <FT> transpose_mult(const Matrix<FT> &, const std::vector <FT> &); // A^T * b
282 template<typename FT>
283 Matrix<FT> mult_transpose(const Matrix<FT> &, const Matrix<FT> &); // A * B^T
284 template<typename FT>
285 Matrix<FT> mult_transpose(const std::vector <FT> &, const std::vector <FT> &); // a * b^T
286
288 template<typename FT>
289 Matrix<FT> identity(int, const FT &); // Generate an identity matrix.
290 template<typename FT>
291 Matrix<FT> diagonal(const std::vector <FT> &); // Generate a diagonal matrix by given its diagonal elements.
292 template<typename FT>
293 std::vector <FT> diagonal(const Matrix<FT> &); // Get the diagonal entries of matrix.
294
297 template<typename FT>
298 FT trace(const Matrix<FT> &);
299
301 template<typename FT>
302 FT norm(const Matrix<FT> &); // Compute Frobenius norm of matrix.
303 template<typename FT>
304 void swap(Matrix<FT> &, Matrix<FT> &); // Swap two matrices.
305 template<typename FT>
306 std::vector <FT> sum(const Matrix<FT> &); // Matrix's column vectors sum.
307 template<typename FT>
308 std::vector <FT> min(const Matrix<FT> &); // Minimum of matrix's column vectors.
309 template<typename FT>
310 std::vector <FT> max(const Matrix<FT> &); // Maximum of matrix's column vectors.
311 template<typename FT>
312 std::vector <FT> mean(const Matrix<FT> &); // Matrix's column vectors mean.
313 template<typename FT>
314 Matrix<FT> abs(const Matrix<std::complex < FT>
315
316 > &A);// Get magnitude of a std::complex matrix.
317 template<typename FT>
318 Matrix<FT> arg(const Matrix<std::complex < FT>
319
320 > &A);// Get angle of a std::complex matrix.
321 template<typename FT>
322 Matrix<FT> real(const Matrix<std::complex < FT>
323
324 > &A);// Get real part of a std::complex matrix.
325 template<typename FT>
326 Matrix<FT> imag(const Matrix<std::complex < FT>
327
328 > &A);// Get imaginary part of a std::complex matrix.
329
331 template<typename FT>
332 Matrix<std::complex < FT> >
333
334 complex_matrix(const Matrix<FT> &);
335
336 template<typename FT>
337 Matrix<std::complex < FT> >
338
339 complex_matrix(const Matrix<FT> &, const Matrix<FT> &); // A for real, B for imaginary
340
341
342 //----------------------------- Utilities for std::vector ------------------------------//
343
345 template<typename FT>
346 std::ostream &operator<<(std::ostream &, const std::vector <FT> &);// Overload of the output stream.
347 template<typename FT>
348 std::istream &operator>>(std::istream &, std::vector <FT> &); // Overload of the input stream.
349
351 template<typename FT>
352 std::vector <FT> operator-(const std::vector <FT> &); // get negative vector
353 template<typename FT>
354 std::vector <FT> operator+(const std::vector <FT> &, const std::vector <FT> &); // vector-vector addition
355 template<typename FT>
356 std::vector <FT> operator+(const std::vector <FT> &, const FT &); // vector-scalar addition
357 template<typename FT>
358 std::vector <FT> operator+(const FT &, const std::vector <FT> &); // scalar-vector addition
359 template<typename FT>
360 std::vector <FT> operator-(const std::vector <FT> &, const std::vector <FT> &); // vector-vector subtraction
361 template<typename FT>
362 std::vector <FT> operator-(const std::vector <FT> &, const FT &); // vector-scalar subtraction
363 template<typename FT>
364 std::vector <FT> operator-(const FT &, const std::vector <FT> &); // scalar-vector subtraction
365 template<typename FT1, typename FT2>
366 std::vector <FT1> operator*(const std::vector <FT1> &, const FT2 &); // complex vector-scalar multiplication
367 template<typename FT1, typename FT2>
368 std::vector <FT1> operator*(const FT2 &, const std::vector <FT1> &); // scalar-complex vector multiplication
369 template<typename FT1, typename FT2>
370 std::vector <FT1> operator/(const std::vector <FT1> &, const FT2 &); // complex vector-scalar division
371 template<typename FT1, typename FT2>
372 std::vector <FT1> operator/(const FT2 &, const std::vector <FT1> &); // scalar-complex vector division
373
374
376 template<typename FT>
377 std::vector <FT> elem_mult(const std::vector <FT> &, const std::vector <FT> &); // "*"
378 template<typename FT>
379 std::vector <FT> elem_divd(const std::vector <FT> &, const std::vector <FT> &); // "/"
380 template<typename FT>
381 std::vector <FT> &elem_mult_eq(std::vector <FT> &, const std::vector <FT> &); // "*="
382 template<typename FT>
383 std::vector <FT> &elem_divd_eq(std::vector <FT> &, const std::vector <FT> &); // "/="
384
386 template<typename FT>
387 FT operator*(const std::vector <FT> &, const std::vector <FT> &); // Inner product for vectors.
388 template<typename FT>
389 FT dot(const std::vector <FT> &, const std::vector <FT> &); // Inner product for vectors.
390
392 template<typename FT>
393 FT norm(const std::vector <FT> &); // Euclidean norm.
394 template<typename FT>
395 FT norm(const std::vector <std::complex<FT>> &); // Euclidean norm.
396 template<typename FT>
397 void swap(std::vector <FT> &, std::vector <FT> &);// Swap two vectors.
398 template<typename FT>
399 std::vector <FT>
400 linspace(FT, FT, int);// Generates a vector of n points linearly spaced between and including a and b.
401 template<typename FT>
402 FT sum(const std::vector <FT> &); // vector sum.
403 template<typename FT>
404 FT min(const std::vector <FT> &); // Minimum value of vector.
405 template<typename FT>
406 FT max(const std::vector <FT> &); // Maximum value of vector.
407 template<typename FT>
408 FT mean(const std::vector <FT> &);
409
410 template<typename FT>
411 std::vector <FT> abs(const std::vector <std::complex<FT>> &); // Get magnitude of a complex vector.
412 template<typename FT>
413 std::vector <FT> arg(const std::vector <std::complex<FT>> &); // Get angle of a complex vector.
414 template<typename FT>
415 std::vector <FT> real(const std::vector <std::complex<FT>> &); // Get real part of a complex vector.
416 template<typename FT>
417 std::vector <FT> imag(const std::vector <std::complex<FT>> &); // Get imaginary part of a complex vector.
418
420 template<typename FT>
421 std::vector <std::complex<FT>> complex_vector(const std::vector <FT> &);
422
423 template<typename FT>
424 std::vector <std::complex<FT>>
425 complex_vector(const std::vector <FT> &, const std::vector <FT> &); // A for real, B for imaginary
426}
427
428 //----------------------------- Matrix Implementation ------------------------------------//
429
430#include <cassert>
431
432namespace easy3d {
433
437 template<typename FT>
438 void Matrix<FT>::init(int rows, int cols) {
439 nRow_ = rows;
440 nColumn_ = cols;
441 nTotal_ = nRow_ * nColumn_;
442
443 data_ = new FT[nTotal_];
444 prow_ = new FT *[nRow_];
445
446 assert(data_ != NULL);
447 assert(prow_ != NULL);
448
449 FT *p = data_;
450 for (int i = 0; i < nRow_; ++i) {
451 prow_[i] = p;
452 p += nColumn_;
453 }
454 }
455
456
460 template<typename FT>
461 inline void Matrix<FT>::copy_from_array(const FT *v) {
462 for (long i = 0; i < nTotal_; ++i)
463 data_[i] = v[i];
464 }
465
466
470 template<typename FT>
471 inline void Matrix<FT>::set_by_scalar(const FT &x) {
472 for (long i = 0; i < nTotal_; ++i)
473 data_[i] = x;
474 }
475
476
480 template<typename FT>
481 void Matrix<FT>::destroy() {
482 if (data_ == NULL)
483 return;
484 else
485 delete[] data_;
486
487 if (prow_ != NULL)
488 delete[] prow_;
489 }
490
491
492 template<typename FT>
493 Matrix<FT> Matrix<FT>::cofactor(int _i, int _j) const {
494 assert(0 <= _i && _i < nRow_ && 0 <= _j && _j < nColumn_);
495 Matrix<FT> mat(nRow_ - 1, nColumn_ - 1);
496 for(int i = 0; i < mat.rows(); i++) {
497 for(int j = 0; j < mat.cols(); j++){
498 if(i < _i){
499 if(j < _j){
500 mat.data()[i * mat.cols() + j] = data_[i * nColumn_ + j];
501 } else {
502 mat.data()[i * mat.cols() + j] = data_[i * nColumn_ + (j + 1)];
503 }
504 } else {
505 if(j < _j){
506 mat.data()[i * mat.cols() + j] = data_[(i + 1) * nColumn_ + j];
507 } else {
508 mat.data()[i * mat.cols() + j] = data_[(i + 1) * nColumn_ + (j + 1)];
509 }
510 }
511 }
512 }
513 return mat;
514 }
515
516
517
521 template<typename FT>
523 : data_(0), prow_(0), nRow_(0), nColumn_(0), nTotal_(0) {
524 }
525
526 template<typename FT>
528 init(A.nRow_, A.nColumn_);
529 copy_from_array(A.data_);
530 }
531
532 template<typename FT>
533 Matrix<FT>::Matrix(int rows, int cols, const FT &x) {
534 init(rows, cols);
535 set_by_scalar(x);
536 }
537
538 template<typename FT>
539 Matrix<FT>::Matrix(int rows, int cols, const std::vector<FT> &array) {
540
541 init(rows, cols);
542 copy_from_array(array.data());
543 }
544
545 template<typename FT>
546 Matrix<FT>::Matrix(int rows, int cols, const FT *array) {
547 init(rows, cols);
548 copy_from_array(array);
549 }
550
551 template<typename FT>
553 destroy();
554 }
555
556
560 template<typename FT>
562 if (data_ == A.data_)
563 return *this;
564
565 if (nRow_ == A.nRow_ && nColumn_ == A.nColumn_)
566 copy_from_array(A.data_);
567 else {
568 destroy();
569 init(A.nRow_, A.nColumn_);
570 copy_from_array(A.data_);
571 }
572
573 return *this;
574 }
575
576
580 template<typename FT>
581 inline Matrix<FT> &Matrix<FT>::operator=(const FT &x) {
582 set_by_scalar(x);
583 return *this;
584 }
585
586
590 template<typename FT>
591 inline FT *Matrix<FT>::operator[](int row) {
592 assert(0 <= row);
593 assert(row < nRow_);
594 return prow_[row];
595 }
596
597 template<typename FT>
598 inline const FT *Matrix<FT>::operator[](int row) const {
599 assert(0 <= row);
600 assert(row < nRow_);
601 return prow_[row];
602 }
603
604 template<typename FT>
605 inline FT &Matrix<FT>::operator()(int row, int col) {
606 assert(0 <= row);
607 assert(row < nRow_);
608 assert(0 <= col);
609 assert(col < nColumn_);
610 return prow_[row][col];
611 }
612
613 template<typename FT>
614 inline const FT &Matrix<FT>::operator()(int row, int col) const {
615 assert(0 <= row);
616 assert(row < nRow_);
617 assert(0 <= col);
618 assert(col < nColumn_);
619 return prow_[row][col];
620 }
621
622
623 template<typename FT>
624 inline
625 void Matrix<FT>::set(int row, int col, FT v) {
626 assert(0 <= row);
627 assert(row < nRow_);
628 assert(0 <= col);
629 assert(col < nColumn_);
630 prow_[row][col] = v;
631 }
632
633 template<typename FT>
634 inline
635 const FT &Matrix<FT>::get(int row, int col) const {
636 assert(0 <= row);
637 assert(row < nRow_);
638 assert(0 <= col);
639 assert(col < nColumn_);
640 return prow_[row][col];
641 }
642
643
648 template<typename FT>
649 inline
651 for (int i = 0; i < nRow_; i++) {
652 for (int j = 0; j < nColumn_; j++) {
653 prow_[i][j] = FT(0);
654 }
655 }
656 }
657
663 template<typename FT>
664 inline
665 void Matrix<FT>::load_identity(FT v /* = FT(1.0)*/) {
666 for (int i = 0; i < nRow_; i++) {
667 for (int j = 0; j < nColumn_; j++) {
668 prow_[i][j] = (i == j) ? v : FT(0);
669 }
670 }
671 }
672
673
674 template<typename FT>
675 inline int Matrix<FT>::rows() const {
676 return nRow_;
677 }
678
679 template<typename FT>
680 inline int Matrix<FT>::cols() const {
681 return nColumn_;
682 }
683
684
688 template<typename FT>
689 Matrix<FT> &Matrix<FT>::resize(int rows, int cols) {
690 if (rows == nRow_ && cols == nColumn_)
691 return *this;
692
693 destroy();
694 init(rows, cols);
695
696 return *this;
697 }
698
699
703 template<typename FT>
704 std::vector<FT> Matrix<FT>::get_row(int row) const {
705 assert(0 <= row);
706 assert(row < nRow_);
707 std::vector<FT> tmp(nColumn_);
708 for (int j = 0; j < nColumn_; ++j)
709 tmp[j] = prow_[row][j];
710
711 return tmp;
712 }
713
714
718 template<typename FT>
719 std::vector<FT> Matrix<FT>::get_column(int col) const {
720 assert(0 <= col);
721 assert(col < nColumn_);
722 std::vector<FT> tmp(nRow_);
723 for (int i = 0; i < nRow_; ++i)
724 tmp[i] = prow_[i][col];
725
726 return tmp;
727 }
728
729
733 template<typename FT>
734 void Matrix<FT>::set_row(const std::vector<FT> &v, int row) {
735 assert(0 <= row);
736 assert(row < nRow_);
737 assert(v.size() == nColumn_);
738 for (int j = 0; j < nColumn_; ++j)
739 prow_[row][j] = v[j];
740 }
741
742
746 template<typename FT>
747 void Matrix<FT>::set_column(const std::vector<FT> &v, int col) {
748 assert(0 <= col);
749 assert(col < nColumn_);
750 assert(v.size() == nRow_);
751 for (int i = 0; i < nRow_; ++i)
752 prow_[i][col] = v[i];
753 }
754
755
756 template<typename FT>
758 Matrix<FT> t(nColumn_, nRow_);
759 for (int r = 0; r < nRow_; r++) {
760 for (int c = 0; c < nColumn_; c++) {
761 t(c, r) = (*this)(r, c);
762 }
763 }
764 return t;
765 }
766
767
768 template<typename FT>
770 assert(nRow_ == nColumn_ && nRow_ != 0);
771 if(nRow_ == 1) {
772 return data_[0];
773 } else if(nRow_ == 2) {
774 return data_[0]*data_[3] - data_[1]*data_[2];
775 } else if(nRow_ == 3) {
776 return - data_[8]*data_[1]*data_[3] - data_[7]*data_[5]*data_[0] - data_[2]*data_[4]*data_[6]
777 + data_[6]*data_[1]*data_[5] + data_[7]*data_[3]*data_[2] + data_[0]*data_[4]*data_[8];
778 } else {
779 FT value = FT();
780 for(int i = 0; i < nRow_; i++){
781 value += std::pow(-1.0, i) * data_[i * nColumn_] * cofactor(i, 0).determinant();
782 }
783 return value;
784 }
785 }
786
787
788 template<typename FT>
790 assert(nRow_ == nColumn_);
791 Matrix<FT> mat = Matrix<FT>(nRow_, nColumn_);
792 if(nRow_ == 1){
793 mat.data()[0] = 1.0 / data_[0];
794 return mat;
795 } else {
796 for(int i = 0; i < nRow_; i++){
797 for(int j = 0; j < nColumn_; j++){
798 mat.data()[i * mat.cols() + j] = std::pow(-1.0, i + j) * cofactor(j, i).determinant();
799 }
800 }
801 return mat / determinant();
802 }
803 }
804
805
806 template<typename FT>
807 FT Matrix<FT>::trace() const {
808 int range = std::min(nRow_, nColumn_);
809 FT trac = 0.0;
810 for (int i = 0; i < range; i++) {
811 trac += (*this)[i][i];
812 }
813 return trac;
814 }
815
819 template<typename FT>
821 FT **rowPtr = prow_;
822 FT *colPtr = 0;
823
824 for (int i = 0; i < nRow_; ++i) {
825 colPtr = *rowPtr++;
826 for (int j = 0; j < nColumn_; ++j)
827 *colPtr++ += x;
828 }
829
830 return *this;
831 }
832
833 template<typename FT>
835 assert(nRow_ == rhs.rows());
836 assert(nColumn_ == rhs.cols());
837
838 FT **rowPtrL = prow_;
839 FT *colPtrL = 0;
840 FT **rowPtrR = rhs.prow_;
841 const FT *colPtrR = 0;
842
843 for (int i = 0; i < nRow_; ++i) {
844 colPtrL = *rowPtrL++;
845 colPtrR = *rowPtrR++;
846 for (int j = 0; j < nColumn_; ++j)
847 *colPtrL++ += *colPtrR++;
848 }
849
850 return *this;
851 }
852
853
857 template<typename FT>
859 FT **rowPtr = prow_;
860 FT *colPtr = 0;
861
862 for (int i = 0; i < nRow_; ++i) {
863 colPtr = *rowPtr++;
864 for (int j = 0; j < nColumn_; ++j)
865 *colPtr++ -= x;
866 }
867
868 return *this;
869 }
870
871 template<typename FT>
873 assert(nRow_ == rhs.rows());
874 assert(nColumn_ == rhs.cols());
875
876 FT **rowPtrL = prow_;
877 FT *colPtrL = 0;
878 FT **rowPtrR = rhs.prow_;
879 const FT *colPtrR = 0;
880
881 for (int i = 0; i < nRow_; ++i) {
882 colPtrL = *rowPtrL++;
883 colPtrR = *rowPtrR++;
884 for (int j = 0; j < nColumn_; ++j)
885 *colPtrL++ -= *colPtrR++;
886 }
887
888 return *this;
889 }
890
891
895 template<typename FT>
896 template<typename FT2>
898 FT **rowPtr = prow_;
899 FT *colPtr = 0;
900
901 for (int i = 0; i < nRow_; ++i) {
902 colPtr = *rowPtr++;
903 for (int j = 0; j < nColumn_; ++j)
904 *colPtr++ *= x;
905 }
906
907 return *this;
908 }
909
910
914 template<typename FT>
915 template<typename FT2>
917 FT **rowPtr = prow_;
918 FT *colPtr = 0;
919
920 for (int i = 0; i < nRow_; ++i) {
921 colPtr = *rowPtr++;
922 for (int j = 0; j < nColumn_; ++j)
923 *colPtr++ /= x;
924 }
925
926 return *this;
927 }
928
932 template<typename FT>
933 std::ostream &operator<<(std::ostream &out, const Matrix<FT> &A) {
934 int rows = A.rows();
935 int cols = A.cols();
936
937 out << "size: " << rows << " by " << cols << "\n";
938 for (int i = 0; i < rows; ++i) {
939 for (int j = 0; j < cols; ++j) {
940 if (std::abs(A[i][j]) < 1e-6)
941 out << 0 << "\t";
942 else
943 out << A[i][j] << "\t";
944 }
945 out << "\n";
946 }
947
948 return out;
949 }
950
951
955 template<typename FT>
956 std::istream &operator>>(std::istream &in, Matrix<FT> &A) {
957 int rows, cols;
958 in >> rows >> cols;
959
960 if (!(rows == A.rows() && cols == A.cols()))
961 A.resize(rows, cols);
962
963 for (int i = 0; i < rows; ++i)
964 for (int j = 0; j < cols; ++j)
965 in >> A[i][j];
966
967 return in;
968 }
969
970
974 template<typename FT>
976 int rows = A.rows();
977 int cols = A.cols();
978
979 Matrix<FT> tmp(rows, cols);
980 for (int i = 0; i < rows; ++i)
981 for (int j = 0; j < cols; ++j)
982 tmp[i][j] = -A[i][j];
983
984 return tmp;
985 }
986
987
989 template<typename FT>
990 inline Matrix<FT> operator+(const Matrix<FT> &A, const FT &x) {
991 Matrix<FT> tmp(A);
992 return tmp += x;
993 }
994
996 template<typename FT>
997 inline Matrix<FT> operator+(const FT &x, const Matrix<FT> &A) {
998 return A + x;
999 }
1000
1001
1005 template<typename FT>
1006 inline Matrix<FT> operator+(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1007 Matrix<FT> tmp(A1);
1008 return tmp += A2;
1009 }
1010
1011
1013 template<typename FT>
1014 inline Matrix<FT> operator-(const Matrix<FT> &A, const FT &x) {
1015 Matrix<FT> tmp(A);
1016 return tmp -= x;
1017 }
1018
1020 template<typename FT>
1021 inline Matrix<FT> operator-(const FT &x, const Matrix<FT> &A) {
1022 Matrix<FT> tmp(A);
1023 return -tmp += x;
1024 }
1025
1026
1028 template<typename FT>
1029 inline Matrix<FT> operator-(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1030 Matrix<FT> tmp(A1);
1031 return tmp -= A2;
1032 }
1033
1037 template<typename FT>
1039 assert(A1.cols() == A2.rows());
1040
1041 int rows = A1.rows();
1042 int cols = A2.cols();
1043 // int K = A1.cols();
1044
1045 Matrix<FT> tmp(rows, cols);
1046 // for( int i=0; i<rows; ++i )
1047 // for( int j=0; j<cols; ++j )
1048 // {
1049 // tmp[i][j] = 0;
1050 // for( int k=0; k<K; ++k )
1051 // tmp[i][j] += A1[i][k] * A2[k][j];
1052 // }
1053
1054 mult(A1, A2, tmp);
1055
1056 return tmp;
1057 }
1058
1059
1063 template<typename FT>
1064 std::vector<FT> operator*(const Matrix<FT> &A, const std::vector<FT> &b) {
1065 assert(A.cols() == b.size());
1066
1067 int rows = A.rows();
1068 // int cols = A.cols();
1069
1070 std::vector<FT> tmp(rows);
1071 mult(A, b, tmp);
1072
1073 return tmp;
1074 }
1075
1077 template<typename FT1, typename FT2>
1078 inline
1079 Matrix<FT1> operator*(const Matrix<FT1> &A, const FT2 &s) {
1080 Matrix<FT1> tmp(A);
1081 return tmp *= s;
1082 }
1083
1085 template<typename FT1, typename FT2>
1086 inline
1087 Matrix<FT1> operator*(const FT2 &s, const Matrix<FT1> &A) {
1088 return A * s;
1089 }
1090
1092 template<typename FT1, typename FT2>
1093 inline
1094 Matrix<FT1> operator/(const Matrix<FT1> &A, const FT2 &s) {
1095 Matrix<FT1> tmp(A);
1096 return tmp /= s;
1097 }
1098
1100 template<typename FT1, typename FT2>
1101 inline
1102 Matrix<FT1> operator/(const FT2 &s, const Matrix<FT1> &A) {
1103 int rows = A.rows();
1104 int clumns = A.cols();
1105
1106 Matrix<FT1> tmp(rows, clumns);
1107 for (int i = 0; i < rows; ++i)
1108 for (int j = 0; j < clumns; ++j)
1109 tmp[i][j] = s / A[i][j];
1110
1111 return tmp;
1112 }
1113
1118 template<typename FT>
1119 void mult(const Matrix<FT> &A, const Matrix<FT> &B, Matrix<FT> &C) {
1120 int M = A.rows();
1121 int N = B.cols();
1122 int K = A.cols();
1123
1124 assert(B.rows() == K);
1125
1126 C.resize(M, N);
1127 FT sum = 0;
1128 const FT *pRow, *pCol;
1129
1130 for (int i = 0; i < M; i++)
1131 for (int j = 0; j < N; ++j) {
1132 pRow = &A[i][0];
1133 pCol = &B[0][j];
1134 sum = 0;
1135
1136 for (int k = 0; k < K; ++k) {
1137 sum += (*pRow) * (*pCol);
1138 pRow++;
1139 pCol += N;
1140 }
1141 C[i][j] = sum;
1142 }
1143 }
1144
1145
1150 template<typename FT>
1151 void mult(const Matrix<FT> &A, const std::vector<FT> &b, std::vector<FT> &c) {
1152 int M = A.rows();
1153 int N = A.cols();
1154
1155 assert(b.size() == N);
1156
1157 c.resize(M);
1158 FT sum = 0;
1159 const FT *pRow, *pCol;
1160
1161 for (int i = 0; i < M; i++) {
1162 pRow = &A[i][0];
1163 pCol = &b[0];
1164 sum = 0;
1165
1166 for (int j = 0; j < N; ++j) {
1167 sum += (*pRow) * (*pCol);
1168 pRow++;
1169 pCol++;
1170 }
1171 c[i] = sum;
1172 }
1173 }
1174
1175
1180 template<typename FT>
1181 Matrix<FT> mult(const Matrix<FT> &A, const Matrix<FT> &B) {
1182 int M = A.rows();
1183 int N = B.cols();
1184 int K = A.cols();
1185
1186 assert(B.rows() == K);
1187
1188 Matrix<FT> C(M, N);
1189 FT sum = 0;
1190 const FT *pRow, *pCol;
1191
1192 for (int i = 0; i < M; i++)
1193 for (int j = 0; j < N; ++j) {
1194 pRow = &A[i][0];
1195 pCol = &B[0][j];
1196 sum = 0;
1197
1198 for (int k = 0; k < K; ++k) {
1199 sum += (*pRow) * (*pCol);
1200 pRow++;
1201 pCol += N;
1202 }
1203 C[i][j] = sum;
1204 }
1205 return C;
1206 }
1207
1208
1213 template<typename FT>
1214 std::vector<FT> mult(const Matrix<FT> &A, const std::vector<FT> &b) {
1215 int M = A.rows();
1216 int N = A.cols();
1217
1218 assert(b.size() == N);
1219
1220 std::vector<FT> c(M);
1221 FT sum = 0;
1222 const FT *pRow, *pCol;
1223
1224 for (int i = 0; i < M; i++) {
1225 pRow = &A[i][0];
1226 pCol = &b[0];
1227 sum = 0;
1228
1229 for (int j = 0; j < N; ++j) {
1230 sum += (*pRow) * (*pCol);
1231 pRow++;
1232 pCol++;
1233 }
1234 c[i] = sum;
1235 }
1236 return c;
1237 }
1238
1239
1241 template<typename FT>
1242 inline Matrix<FT> elem_mult(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1243 Matrix<FT> tmp(A1);
1244 return tmp *= A2;
1245 }
1246
1248 template<typename FT>
1250 return A1 *= A2;
1251 }
1252
1253
1255 template<typename FT>
1256 inline Matrix<FT> elem_divd(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1257 Matrix<FT> tmp(A1);
1258 return tmp /= A2;
1259 }
1260
1262 template<typename FT>
1264 return A1 /= A2;
1265 }
1266
1267
1269 template<typename FT>
1271 int rows = A.cols();
1272 int clumns = A.rows();
1273
1274 Matrix<FT> tmp(rows, clumns);
1275 for (int i = 0; i < rows; ++i)
1276 for (int j = 0; j < clumns; ++j)
1277 tmp[i][j] = A[j][i];
1278
1279 return tmp;
1280 }
1281
1282
1284 template<typename FT>
1286 int rows = A.cols();
1287 int clumns = A.rows();
1288
1289 Matrix<FT> tmp(rows, clumns);
1290 for (int i = 0; i < rows; ++i)
1291 for (int j = 0; j < clumns; ++j)
1292 tmp[i][j] = conj(A[j][i]);
1293
1294 return tmp;
1295 }
1296
1297
1299 template<typename FT>
1301 assert(A1.rows() == A2.rows());
1302
1303 int rows = A1.cols();
1304 int cols = A2.cols();
1305 int K = A1.rows();
1306
1307 Matrix<FT> tmp(rows, cols);
1308 for (int i = 0; i < rows; ++i)
1309 for (int j = 0; j < cols; ++j)
1310 for (int k = 0; k < K; ++k)
1311 tmp[i][j] += A1[k][i] * A2[k][j];
1312
1313 return tmp;
1314 }
1315
1316
1318 template<typename FT>
1319 std::vector<FT> transpose_mult(const Matrix<FT> &A, const std::vector<FT> &v) {
1320 assert(A.rows() == v.size());
1321
1322 int rows = A.rows();
1323 int cols = A.cols();
1324
1325 std::vector<FT> tmp(cols);
1326 for (int i = 0; i < cols; ++i)
1327 for (int j = 0; j < rows; ++j)
1328 tmp[i] += A[j][i] * v[j];
1329
1330 return tmp;
1331 }
1332
1333
1335 template<typename FT>
1337 assert(A1.cols() == A2.cols());
1338
1339 int rows = A1.rows();
1340 int cols = A2.rows();
1341 int K = A1.cols();
1342
1343 Matrix<FT> tmp(rows, cols);
1344 for (int i = 0; i < rows; ++i)
1345 for (int j = 0; j < cols; ++j)
1346 for (int k = 0; k < K; ++k)
1347 tmp[i][j] += A1[i][k] * A2[j][k];
1348
1349 return tmp;
1350 }
1351
1352
1354 template<typename FT>
1355 Matrix<FT> mult_transpose(const std::vector<FT> &a, const std::vector<FT> &b) {
1356 int rows = a.size();
1357 int cols = b.size();
1358
1359 Matrix<FT> tmp(rows, cols);
1360 for (int i = 0; i < rows; ++i)
1361 for (int j = 0; j < cols; ++j)
1362 tmp[i][j] = a[i] * b[j];
1363
1364 return tmp;
1365 }
1366
1367
1369 template<typename FT>
1370 Matrix<FT> identity(int N, const FT &x) {
1371 Matrix<FT> tmp(N, N);
1372 for (int i = 0; i < N; ++i)
1373 tmp[i][i] = x;
1374
1375 return tmp;
1376 }
1377
1378
1380 template<typename FT>
1381 std::vector<FT> diagonal(const Matrix<FT> &A) {
1382 int nColumn_ = A.rows();
1383 if (nColumn_ > A.cols())
1384 nColumn_ = A.cols();
1385
1386 std::vector<FT> tmp(nColumn_);
1387 for (int i = 0; i < nColumn_; ++i)
1388 tmp[i] = A[i][i];
1389
1390 return tmp;
1391 }
1392
1393
1395 template<typename FT>
1396 Matrix<FT> diagonal(const std::vector<FT> &d) {
1397 int N = static_cast<int>(d.size());
1398
1399 Matrix<FT> tmp(N, N);
1400 for (int i = 0; i < N; ++i)
1401 tmp[i][i] = d[i];
1402
1403 return tmp;
1404 }
1405
1406
1411 template<typename FT>
1412 FT trace(const Matrix<FT> &A) {
1413 int range = std::min(A.rows(), A.cols());
1414 FT trac = 0.0;
1415 for (int i = 0; i < range; i++) {
1416 trac += A[i][i];
1417 }
1418 return trac;
1419 }
1420
1421
1423 template<typename FT>
1424 FT norm(const Matrix<FT> &A) {
1425 int m = A.rows();
1426 int n = A.cols();
1427
1428 FT sum = 0;
1429 for (int i = 0; i < m; ++i)
1430 for (int j = 0; j < n; ++j)
1431 sum += A[i][j] * A[i][j];
1432
1433 return std::sqrt(sum);
1434 }
1435
1436
1438 template<typename FT>
1439 void swap(Matrix<FT> &lhs, Matrix<FT> &rhs) {
1440 int m = lhs.rows();
1441 int n = lhs.cols();
1442
1443 assert(m == rhs.rows());
1444 assert(n == rhs.cols());
1445
1446 for (int i = 0; i < m; ++i)
1447 for (int j = 0; j < n; ++j)
1448 std::swap(lhs(i, j), rhs(i, j));
1449 }
1450
1451
1453 template<typename FT>
1454 std::vector<FT> sum(const Matrix<FT> &A) {
1455 int m = A.rows();
1456 int n = A.cols();
1457 std::vector<FT> s(n);
1458
1459 for (int j = 0; j < n; ++j)
1460 for (int i = 0; i < m; ++i)
1461 s[j] += A[i][j];
1462 return s;
1463 }
1464
1465
1467 template<typename FT>
1468 std::vector<FT> min(const Matrix<FT> &A) {
1469 int m = A.rows();
1470 int n = A.cols();
1471 std::vector<FT> sum(n);
1472
1473 for (int j = 0; j < n; ++j) {
1474 FT tmp = A[0][j];
1475 for (int i = 1; i < m; ++i)
1476 if (tmp > A[i][j])
1477 tmp = A[i][j];
1478 sum[j] = tmp;
1479 }
1480
1481 return sum;
1482 }
1483
1484
1486 template<typename FT>
1487 std::vector<FT> max(const Matrix<FT> &A) {
1488 int m = A.rows();
1489 int n = A.cols();
1490 std::vector<FT> sum(n);
1491
1492 for (int j = 0; j < n; ++j) {
1493 FT tmp = A[0][j];
1494 for (int i = 1; i < m; ++i)
1495 if (tmp < A[i][j])
1496 tmp = A[i][j];
1497 sum[j] = tmp;
1498 }
1499
1500 return sum;
1501 }
1502
1503
1505 template<typename FT>
1506 inline std::vector<FT> mean(const Matrix<FT> &A) {
1507 return sum(A) / FT(A.rows());
1508 }
1509
1510
1512 template<typename FT>
1513 Matrix<FT> abs(const Matrix<std::complex<FT> > &A) {
1514 int m = A.rows(),
1515 n = A.cols();
1516 Matrix<FT> tmp(m, n);
1517
1518 for (int i = 0; i < m; ++i)
1519 for (int j = 0; j < n; ++j)
1520 tmp[i][j] = std::abs(A[i][j]);
1521
1522 return tmp;
1523 }
1524
1526 template<typename FT>
1527 Matrix<FT> arg(const Matrix<std::complex<FT> > &A) {
1528 int m = A.rows(),
1529 n = A.cols();
1530 Matrix<FT> tmp(m, n);
1531
1532 for (int i = 0; i < m; ++i)
1533 for (int j = 0; j < n; ++j)
1534 tmp[i][j] = arg(A[i][j]);
1535
1536 return tmp;
1537 }
1538
1540 template<typename FT>
1541 Matrix<FT> real(const Matrix<std::complex<FT> > &A) {
1542 int m = A.rows(),
1543 n = A.cols();
1544 Matrix<FT> tmp(m, n);
1545
1546 for (int i = 0; i < m; ++i)
1547 for (int j = 0; j < n; ++j)
1548 tmp[i][j] = A[i][j].real();
1549
1550 return tmp;
1551 }
1552
1553
1555 template<typename FT>
1556 Matrix<FT> imag(const Matrix<std::complex<FT> > &A) {
1557 int m = A.rows(),
1558 n = A.cols();
1559 Matrix<FT> tmp(m, n);
1560
1561 for (int i = 0; i < m; ++i)
1562 for (int j = 0; j < n; ++j)
1563 tmp[i][j] = A[i][j].imag();
1564
1565 return tmp;
1566 }
1567
1568
1570 template<typename FT>
1572 int rows = rA.rows();
1573 int cols = rA.cols();
1574
1575 Matrix<std::complex<FT> > cA(rows, cols);
1576 for (int i = 0; i < rows; ++i)
1577 for (int j = 0; j < cols; ++j)
1578 cA[i][j] = rA[i][j];
1579
1580 return cA;
1581 }
1582
1584 template<typename FT>
1586 int rows = mR.rows();
1587 int cols = mR.cols();
1588
1589 assert(rows == mI.rows());
1590 assert(cols == mI.cols());
1591
1592 Matrix<std::complex<FT> > cA(rows, cols);
1593 for (int i = 0; i < rows; ++i)
1594 for (int j = 0; j < cols; ++j)
1595 cA[i][j] = std::complex<FT>(mR[i][j], mI[i][j]);
1596
1597 return cA;
1598 }
1599
1600
1601 //----------------------------- std::vector Implementation ------------------------------------//
1602
1603
1605 template<typename FT>
1606 std::ostream &operator<<(std::ostream &out, const std::vector<FT> &A) {
1607 out << "size: " << A.size() << "\n";
1608 for (std::size_t i = 0; i < A.size(); ++i)
1609 out << A[i] << "\t";
1610 out << "\n";
1611 return out;
1612 }
1613
1614
1616 template<typename FT>
1617 std::istream &operator>>(std::istream &in, std::vector<FT> &A) {
1618 int size;
1619 in >> size;
1620 A.resize(size);
1621 for (int i = 0; i < size; ++i)
1622 in >> A[i];
1623 return in;
1624 }
1625
1626
1628 template<typename FT>
1629 std::vector<FT> operator-(const std::vector<FT> &A) {
1630 std::vector<FT> tmp = A;
1631 for (std::size_t i = 0; i < tmp.size(); ++i)
1632 tmp[i] = -tmp[i];
1633
1634 return tmp;
1635 }
1636
1637
1639 template<typename FT>
1640 std::vector<FT> operator+(const std::vector<FT> &A, const std::vector<FT> &B) {
1641 assert(A.size() == B.size());
1642
1643 std::vector<FT> tmp = A;
1644 for (std::size_t i = 0; i < B.size(); ++i)
1645 tmp[i] += B[i];
1646
1647 return tmp;
1648 }
1649
1651 template<typename FT>
1652 std::vector<FT> operator+(const std::vector<FT> &A, const FT &s) {
1653 std::vector<FT> tmp = A;
1654 for (std::size_t i = 0; i < A.size(); ++i)
1655 tmp[i] += s;
1656
1657 return tmp;
1658 }
1659
1661 template<typename FT>
1662 std::vector<FT> operator+(const FT &s, const std::vector<FT> &A) {
1663 std::vector<FT> tmp = A;
1664 for (std::size_t i = 0; i < A.size(); ++i)
1665 tmp[i] += s;
1666
1667 return tmp;
1668 }
1669
1671 template<typename FT>
1672 std::vector<FT> operator-(const std::vector<FT> &A, const std::vector<FT> &B) {
1673 assert(A.size() == B.size());
1674
1675 std::vector<FT> tmp = A;
1676 for (std::size_t i = 0; i < B.size(); ++i)
1677 tmp[i] -= B[i];
1678
1679 return tmp;
1680 }
1681
1683 template<typename FT>
1684 std::vector<FT> operator-(const std::vector<FT> &A, const FT &s) {
1685 std::vector<FT> tmp = A;
1686 for (std::size_t i = 0; i < A.size(); ++i)
1687 tmp[i] -= s;
1688
1689 return tmp;
1690 }
1691
1693 template<typename FT>
1694 std::vector<FT> operator-(const FT &s, const std::vector<FT> &A) {
1695 std::vector<FT> tmp = A;
1696 for (std::size_t i = 0; i < A.size(); ++i)
1697 tmp[i] = s - tmp[i];
1698
1699 return tmp;
1700 }
1701
1703 template<typename FT1, typename FT2>
1704 std::vector<FT1> operator*(const std::vector<FT1> &A, const FT2 &s) {
1705 std::vector<FT1> tmp = A;
1706 for (std::size_t i = 0; i < A.size(); ++i)
1707 tmp[i] *= s;
1708
1709 return tmp;
1710 }
1711
1713 template<typename FT1, typename FT2>
1714 std::vector<FT1> operator*(const FT2 &s, const std::vector<FT1> &A) {
1715 return A * s;
1716 }
1717
1719 template<typename FT1, typename FT2>
1720 std::vector<FT1> operator/(const std::vector<FT1> &A, const FT2 &s) {
1721 std::vector<FT1> tmp = A;
1722 for (std::size_t i = 0; i < A.size(); ++i)
1723 tmp[i] /= s;
1724
1725 return tmp;
1726 }
1727
1729 template<typename FT1, typename FT2>
1730 std::vector<FT1> operator/(const FT2 &s, const std::vector<FT1> &A) {
1731 std::vector<FT1> tmp = A;
1732 for (std::size_t i = 0; i < A.size(); ++i)
1733 tmp[i] = s / tmp[i];
1734
1735 return tmp;
1736 }
1737
1739 template<typename FT>
1740 inline std::vector<FT> elem_mult(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1741 assert(v1.size() == v2.size());
1742 std::vector<FT> result = v1;
1743 for (std::size_t i = 0; i < v2.size(); ++i) {
1744 result[i] *= v2[i];
1745 }
1746
1747 return result;
1748 }
1749
1751 template<typename FT>
1752 inline std::vector<FT> &elem_mult_eq(std::vector<FT> &v1, const std::vector<FT> &v2) {
1753 assert(v1.size() == v2.size());
1754 for (std::size_t i = 0; i < v2.size(); ++i) {
1755 v1[i] *= v2[i];
1756 }
1757
1758 return v1;
1759 }
1760
1761
1763 template<typename FT>
1764 inline std::vector<FT> elem_divd(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1765 assert(v1.size() == v2.size());
1766 std::vector<FT> result = v1;
1767 for (std::size_t i = 0; i < v2.size(); ++i) {
1768 result[i] /= v2[i];
1769 }
1770
1771 return result;
1772 }
1773
1775 template<typename FT>
1776 inline std::vector<FT> &elem_divd_eq(std::vector<FT> &v1, const std::vector<FT> &v2) {
1777 assert(v1.size() == v2.size());
1778 for (std::size_t i = 0; i < v2.size(); ++i) {
1779 v1[i] /= v2[i];
1780 }
1781
1782 return v1;
1783 }
1784
1785
1787 template<typename FT>
1788 FT operator*(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1789 assert(v1.size() == v2.size());
1790
1791 FT sum = 0;
1792 typename std::vector<FT>::const_iterator itr1 = v1.begin();
1793 typename std::vector<FT>::const_iterator itr2 = v2.begin();
1794
1795 while (itr1 != v1.end())
1796 sum += (*itr1++) * (*itr2++);
1797
1798 return sum;
1799 }
1800
1802 template<typename FT>
1803 FT dot(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1804 assert(v1.size() == v2.size());
1805
1806 FT sum = 0;
1807 typename std::vector<FT>::const_iterator itr1 = v1.begin();
1808 typename std::vector<FT>::const_iterator itr2 = v2.begin();
1809
1810 while (itr1 != v1.end())
1811 sum += (*itr1++) * (*itr2++);
1812
1813 return sum;
1814 }
1815
1816
1818 template<typename FT>
1819 FT sum(const std::vector<FT> &v) {
1820 FT sum = 0;
1821 typename std::vector<FT>::const_iterator itr = v.begin();
1822
1823 while (itr != v.end())
1824 sum += *itr++;
1825
1826 return sum;
1827 }
1828
1830 template<typename FT>
1831 FT min(const std::vector<FT> &v) {
1832 FT m = v[0];
1833 for (std::size_t i = 1; i < v.size(); ++i)
1834 if (m > v[i])
1835 m = v[i];
1836
1837 return m;
1838 }
1839
1841 template<typename FT>
1842 FT max(const std::vector<FT> &v) {
1843 FT M = v[0];
1844 for (std::size_t i = 1; i < v.size(); ++i)
1845 if (M < v[i])
1846 M = v[i];
1847
1848 return M;
1849 }
1850
1852 template<typename FT>
1853 FT mean(const std::vector<FT> &v) {
1854 return sum(v) / FT(v.size());
1855 }
1856
1858 template<typename FT>
1859 FT norm(const std::vector<FT> &v) {
1860 FT sum = 0;
1861 typename std::vector<FT>::const_iterator itr = v.begin();
1862
1863 while (itr != v.end()) {
1864 sum += (*itr) * (*itr);
1865 itr++;
1866 }
1867
1868 return FT(std::sqrt(sum));
1869 }
1870
1872 template<typename FT>
1873 FT norm(const std::vector<std::complex<FT> > &v) {
1874 FT sum = 0;
1875 typename std::vector<std::complex<FT> >::const_iterator itr = v.begin();
1876
1877 while (itr != v.end()) {
1878 sum += std::norm(*itr++);
1879 }
1880
1881 return FT(std::sqrt(sum));
1882 }
1883
1885 template<typename FT>
1886 void swap(std::vector<FT> &lhs, std::vector<FT> &rhs) {
1887 typename std::vector<FT>::iterator itrL = lhs.begin(),
1888 itrR = rhs.begin();
1889
1890 while (itrL != lhs.end())
1891 std::swap(*itrL++, *itrR++);
1892 }
1893
1895 template<typename FT>
1896 std::vector<FT> linspace(FT a, FT b, int n) {
1897 if (n < 1)
1898 return std::vector<FT>();
1899 else if (n == 1)
1900 return std::vector<FT>(1, a);
1901 else {
1902 FT dx = (b - a) / (n - 1);
1903
1904 std::vector<FT> tmp(n);
1905 for (int i = 0; i < n; ++i)
1906 tmp[i] = a + i * dx;
1907
1908 return tmp;
1909 }
1910 }
1911
1913 template<typename FT>
1914 std::vector<FT> abs(const std::vector<std::complex<FT> > &v) {
1915 std::vector<FT> tmp(v.size());
1916 typename std::vector<FT>::iterator itrL = tmp.begin();
1917 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1918
1919 while (itrL != tmp.end())
1920 *itrL++ = std::abs(*itrR++);
1921
1922 return tmp;
1923 }
1924
1926 template<typename FT>
1927 std::vector<FT> arg(const std::vector<std::complex<FT> > &v) {
1928 std::vector<FT> tmp(v.size());
1929 typename std::vector<FT>::iterator itrL = tmp.begin();
1930 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1931
1932 while (itrL != tmp.end())
1933 *itrL++ = std::arg(*itrR++);
1934
1935 return tmp;
1936 }
1937
1939 template<typename FT>
1940 std::vector<FT> real(const std::vector<std::complex<FT> > &v) {
1941 std::vector<FT> tmp(v.size());
1942 typename std::vector<FT>::iterator itrL = tmp.begin();
1943 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1944
1945 while (itrL != tmp.end())
1946 *itrL++ = (*itrR++).real();
1947
1948 return tmp;
1949 }
1950
1952 template<typename FT>
1953 std::vector<FT> imag(const std::vector<std::complex<FT> > &v) {
1954 std::vector<FT> tmp(v.size());
1955 typename std::vector<FT>::iterator itrL = tmp.begin();
1956 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1957
1958 while (itrL != tmp.end())
1959 *itrL++ = (*itrR++).imag();
1960
1961 return tmp;
1962 }
1963
1965 template<typename FT>
1966 std::vector<std::complex<FT> > complex_vector(const std::vector<FT> &rv) {
1967 int N = rv.size();
1968
1969 std::vector<std::complex<FT> > cv(N);
1970 typename std::vector<std::complex<FT> >::iterator itrL = cv.begin();
1971 typename std::vector<FT>::const_iterator itrR = rv.begin();
1972
1973 while (itrR != rv.end())
1974 *itrL++ = *itrR++;
1975
1976 return cv;
1977 }
1978
1980 template<typename FT>
1981 std::vector<std::complex<FT> > complex_vector(const std::vector<FT> &vR, const std::vector<FT> &vI) {
1982 int N = static_cast<int>(vR.size());
1983
1984 assert(N == vI.size());
1985
1986 std::vector<std::complex<FT> > cv(N);
1987 typename std::vector<std::complex<FT> >::iterator itrC = cv.begin();
1988 typename std::vector<FT>::const_iterator itrR = vR.begin(),
1989 itrI = vI.begin();
1990
1991 while (itrC != cv.end())
1992 *itrC++ = std::complex<FT>(*itrR++, *itrI++);
1993
1994 return cv;
1995 }
1996
1997}
1998
1999#endif // EASY3D_CORE_MATRIX_H
A matrix representation, which supports dynamic sizes.
Definition: matrix.h:46
FT * data()
Definition: matrix.h:122
Matrix< FT > & operator*=(const FT2 &v)
computed assignment. Multiply each element by v
Definition: matrix.h:897
Matrix< FT > & operator/=(const FT2 &v)
computed assignment. Divide each element by v
Definition: matrix.h:916
FT & operator()(int row, int col)
Return the element at (row, col).
Definition: matrix.h:605
Matrix()
Definition: matrix.h:522
Matrix< FT > & operator+=(const FT &v)
computed assignment. Add each element by v
Definition: matrix.h:820
Matrix< FT > & operator=(const Matrix< FT > &A)
Assign A to this matrix.
Definition: matrix.h:561
const FT & get(int row, int col) const
Get the value of the element at (row, col).
Definition: matrix.h:635
void load_identity(FT v=FT(1))
Definition: matrix.h:665
std::vector< FT > get_column(int col) const
Get the matrix's column vector as a 1D array.
Definition: matrix.h:719
int cols() const
Return the number of columns.
Definition: matrix.h:680
const FT * data() const
Definition: matrix.h:128
void set_column(const std::vector< FT > &v, int col)
Set the matrix's column vector.
Definition: matrix.h:747
void load_zero()
Set all elements to zero.
Definition: matrix.h:650
Matrix< FT > & resize(int rows, int cols)
Change the size/dimension of the matrix.
Definition: matrix.h:689
FT * operator[](int row)
Return the row_th row as a 1D array.
Definition: matrix.h:591
std::vector< FT > get_row(int row) const
Get the matrix's row vector as a 1D array.
Definition: matrix.h:704
Matrix< FT > inverse() const
Return the inverse of the matrix (for positive square matrices only)
Definition: matrix.h:789
void set_row(const std::vector< FT > &v, int row)
Set the matrix's row vector.
Definition: matrix.h:734
void set(int row, int col, FT v)
Set the value of the element at (row, col).
Definition: matrix.h:625
int rows() const
Return the number of rows.
Definition: matrix.h:675
Matrix< FT > transpose() const
Return the transposed matrix.
Definition: matrix.h:757
Matrix< FT > & operator-=(const FT &v)
computed assignment. Subtract each element by v
Definition: matrix.h:858
FT trace() const
Definition: matrix.h:807
FT determinant() const
Return the determinant of the matrix (for square matrices only)
Definition: matrix.h:769
Definition: collider.cpp:182
Matrix< FT > operator+(const Matrix< FT > &, const FT &)
Definition: matrix.h:990
Mat< M, N, T > transpose(const Mat< N, M, T > &m)
Transpose m.
Definition: mat.h:907
Matrix< FT > operator-(const Matrix< FT > &)
arithmetic operators
Definition: matrix.h:975
Matrix< FT > & elem_divd_eq(Matrix< FT > &, const Matrix< FT > &)
Definition: matrix.h:1263
Matrix< FT > elem_divd(const Matrix< FT > &, const Matrix< FT > &)
Definition: matrix.h:1256
std::vector< FT > mean(const Matrix< FT > &)
Definition: matrix.h:1506
Matrix< FT > transpose_mult(const Matrix< FT > &, const Matrix< FT > &)
transpose multiplication
Definition: matrix.h:1300
Matrix< FT > diagonal(const std::vector< FT > &)
Definition: matrix.h:1396
Matrix< FT > elem_mult(const Matrix< FT > &, const Matrix< FT > &)
element-wise multiplication / division
Definition: matrix.h:1242
Matrix< FT1 > operator/(const Matrix< FT1 > &, const FT2 &)
matrix-scalar division
Definition: matrix.h:1094
Matrix< FT > mult_transpose(const Matrix< FT > &, const Matrix< FT > &)
Definition: matrix.h:1336
FT max()
Function returning maximum representable value for a given type.
T trace(const Mat< N, N, T > &m)
Return the trace (sum of elements on the main diagonal) of N by N (square) matrix m.
void swap(Matrix< FT > &, Matrix< FT > &)
Definition: matrix.h:1439
T determinant(const Mat< N, N, T > &m)
Return the determinant of N x N (square) matrix m.
Matrix< std::complex< FT > > complex_matrix(const Matrix< FT > &)
Convert real matrix to complex matrix.
Definition: matrix.h:1571
Matrix< FT > real(const Matrix< std::complex< FT > > &A)
Get real part of a std::complex matrix.
Definition: matrix.h:1541
std::vector< std::complex< FT > > complex_vector(const std::vector< FT > &)
Convert real vector to complex vector.
Definition: matrix.h:1966
Matrix< FT > imag(const Matrix< std::complex< FT > > &A)
Get imaginary part of a std::complex matrix.
Definition: matrix.h:1556
std::vector< FT > linspace(FT, FT, int)
Generates a vector of n points linearly spaced between and including a and b.
Definition: matrix.h:1896
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Definition: line.h:133
void mult(const Matrix< FT > &, const Matrix< FT > &, Matrix< FT > &)
multiplication
Definition: matrix.h:1119
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Definition: graph.h:920
FT min()
Function returning minimum representable value for a given type.
Matrix< FT > arg(const Matrix< std::complex< FT > > &A)
Get angle of a std::complex matrix.
Definition: matrix.h:1527
Matrix< FT > identity(int, const FT &)
unit and diagonal matrix
Definition: matrix.h:1370
Matrix< FT > abs(const Matrix< std::complex< FT > > &A)
Get magnitude of a std::complex matrix.
Definition: matrix.h:1513
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition: matrix.h:1803
std::vector< FT > sum(const Matrix< FT > &)
Definition: matrix.h:1454
Matrix< FT > conjugate_transpose(const Matrix< FT > &)
Definition: matrix.h:1285
FT norm(const Matrix< FT > &)
utilities
Definition: matrix.h:1424
Matrix< FT > & elem_mult_eq(Matrix< FT > &, const Matrix< FT > &)
Definition: matrix.h:1249
Mat< N, M, T > operator*(T lhs, const Mat< N, M, T > &rhs)
Component-wise scalar-matrix multiplication.
Definition: mat.h:787