Easy3D 2.6.1
Loading...
Searching...
No Matches
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#include <easy3d/core/random.h>
36
37
38namespace easy3d {
39
47 template<typename FT>
48 class Matrix {
49 public:
54
60 Matrix(const Matrix<FT> &A);
61
69 Matrix(int rows, int cols, const FT &x = FT(0));
70
80 Matrix(int rows, int cols, const std::vector<FT> &array);
81
93 Matrix(int rows, int cols, const FT *array);
94
95 ~Matrix();
96
98 Matrix<FT> &operator=(const Matrix<FT> &A); // overload evaluate operator = from matrix to matrix
100 Matrix<FT> &operator=(const FT &x); // overload evaluate operator = from scalar to matrix
101
103 FT *operator[](int row);
104
106 const FT *operator[](int row) const;
107
109 FT &operator()(int row, int col);
110
112 const FT &operator()(int row, int col) const;
113
115 void set(int row, int col, FT v);
116
118 const FT &get(int row, int col) const;
119
124 FT *data() { return data_; }
125
130 const FT *data() const { return data_; }
131
133 int rows() const;
134
136 int cols() const;
137
140
142 std::vector<FT> get_row(int row) const;
143
145 std::vector<FT> get_column(int col) const;
146
148 void set_row(const std::vector<FT> &v, int row);
149
151 void set_column(const std::vector<FT> &v, int col);
152
154 void load_zero();
155
158 void load_identity(FT v = FT(1));
159
162
165
168
170 FT determinant() const;
171
174 FT trace() const;
175
177 Matrix<FT> &operator+=(const FT &v); //compound assignment operators +=
179 Matrix<FT> &operator-=(const FT &v); //compound assignment operators -=
181 template<typename FT2>
182 Matrix<FT> &operator*=(const FT2 &v); //compound assignment operators *=
184 template<typename FT2>
185 Matrix<FT> &operator/=(const FT2 &v); //compound assignment operators /=
188
191
192 private:
193
194 // 0-based data pointer
195 FT *data_;
196
197 // 0-based row pointer's pointer
198 FT **prow_;
199
200 // row number, column number and total number
201 int nRow_;
202 int nColumn_;
203 long nTotal_;
204
205 void init(int rows, int cols);
206
207 void copy_from_array(const FT *v); // copy matrix from normal array
208 void set_by_scalar(const FT &x); // set matrix by a scalar
209 void destroy(); // destroy the matrix
210
211 Matrix<FT> cofactor(int i, int j) const;
212
213 }; // class Matrix
214
215
216
217 //----------------------------- Utilities for Matrix ------------------------------//
218
220 template<typename FT>
221 std::ostream &operator<<(std::ostream &, const Matrix<FT> &); // Overload of the output stream.
222 template<typename FT>
223 std::istream &operator>>(std::istream &, Matrix<FT> &); // Overload of the input stream.
224
226 template<typename FT>
227 Matrix<FT> operator-(const Matrix<FT> &); // get negative matrix
228 template<typename FT>
229 Matrix<FT> operator+(const Matrix<FT> &, const FT &); // matrix-scalar addition
230 template<typename FT>
231 Matrix<FT> operator+(const FT &, const Matrix<FT> &); // scalar-matrix addition
232 template<typename FT>
233 Matrix<FT> operator+(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix addition
234 template<typename FT>
235 Matrix<FT> operator-(const Matrix<FT> &, const FT &); // matrix-scalar subtraction
236 template<typename FT>
237 Matrix<FT> operator-(const FT &, const Matrix<FT> &); // scalar-matrix subtraction
238 template<typename FT>
239 Matrix<FT> operator-(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix subtraction
240 template<typename FT>
241 Matrix<FT> operator*(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix multiplication
242 template<typename FT>
243 std::vector<FT> operator*(const Matrix<FT> &, const std::vector<FT> &); // matrix-vector multiplication
244 template<typename FT1, typename FT2>
245 Matrix<FT1> operator*(const Matrix<FT1> &, const FT2 &); // matrix-scalar multiplication
246 template<typename FT1, typename FT2>
247 Matrix<FT1> operator*(const FT2 &, const Matrix<FT1> &); // scalar-matrix multiplication
248 template<typename FT1, typename FT2>
249 Matrix<FT1> operator/(const Matrix<FT1> &, const FT2 &); // matrix-scalar division
250 template<typename FT1, typename FT2>
251 Matrix<FT1> operator/(const FT2 &, const Matrix<FT1> &); // scalar-matrix division
252
253
255 template<typename FT>
256 void mult(const Matrix<FT> &, const Matrix<FT> &,
257 Matrix<FT> &); // matrix-matrix multiplication (result has already been allocated)
258 template<typename FT>
259 void mult(const Matrix<FT> &, const std::vector<FT> &,
260 std::vector<FT> &); // matrix-vector multiplication (result has already been allocated)
261 template<typename FT>
262 Matrix<FT> mult(const Matrix<FT> &, const Matrix<FT> &); // matrix-matrix multiplication
263 template<typename FT>
264 std::vector<FT> mult(const Matrix<FT> &, const std::vector<FT> &); // matrix-vector multiplication
265
267 template<typename FT>
268 Matrix<FT> elem_mult(const Matrix<FT> &, const Matrix<FT> &); // "*"
269 template<typename FT>
270 Matrix<FT> elem_divd(const Matrix<FT> &, const Matrix<FT> &); // "/"
271 template<typename FT>
272 Matrix<FT> &elem_mult_eq(Matrix<FT> &, const Matrix<FT> &); // "*="
273 template<typename FT>
274 Matrix<FT> &elem_divd_eq(Matrix<FT> &, const Matrix<FT> &); // "/="
275
277 template<typename FT>
278 Matrix<FT> transpose(const Matrix<FT> &); // matrix transpose
279 template<typename FT>
280 Matrix<FT> conjugate_transpose(const Matrix<FT> &); // matrix conjugate transpose
281
283 template<typename FT>
284 Matrix<FT> transpose_mult(const Matrix<FT> &, const Matrix<FT> &); // A^T * B
285 template<typename FT>
286 std::vector<FT> transpose_mult(const Matrix<FT> &, const std::vector<FT> &); // A^T * b
287 template<typename FT>
288 Matrix<FT> mult_transpose(const Matrix<FT> &, const Matrix<FT> &); // A * B^T
289 template<typename FT>
290 Matrix<FT> mult_transpose(const std::vector<FT> &, const std::vector<FT> &); // a * b^T
291
293 template<typename FT>
294 Matrix<FT> random(int row, int col);
295
298 template<typename FT>
299 Matrix<FT> identity(int N, const FT& v = FT(1));
300
302 template<typename FT>
303 Matrix<FT> diagonal(const std::vector<FT> &); // Generate a diagonal matrix by given its diagonal elements.
304 template<typename FT>
305 std::vector<FT> diagonal(const Matrix<FT> &); // Get the diagonal entries of matrix.
306
309 template<typename FT>
310 FT trace(const Matrix<FT> &);
311
313 template<typename FT>
314 FT norm(const Matrix<FT> &); // Compute Frobenius norm of matrix.
315 template<typename FT>
316 void swap(Matrix<FT> &, Matrix<FT> &); // Swap two matrices.
317 template<typename FT>
318 std::vector<FT> sum(const Matrix<FT> &); // Matrix's column vectors sum.
319 template<typename FT>
320 std::vector<FT> min(const Matrix<FT> &); // Minimum of matrix's column vectors.
321 template<typename FT>
322 std::vector<FT> max(const Matrix<FT> &); // Maximum of matrix's column vectors.
323 template<typename FT>
324 std::vector<FT> mean(const Matrix<FT> &); // Matrix's column vectors mean.
325 template<typename FT>
326 Matrix<FT> abs(const Matrix<std::complex < FT>
327
328 > &A);// Get magnitude of a std::complex matrix.
329 template<typename FT>
330 Matrix<FT> arg(const Matrix<std::complex < FT>
331
332 > &A);// Get angle of a std::complex matrix.
333 template<typename FT>
334 Matrix<FT> real(const Matrix<std::complex < FT>
335
336 > &A);// Get real part of a std::complex matrix.
337 template<typename FT>
338 Matrix<FT> imag(const Matrix<std::complex < FT>
339
340 > &A);// Get imaginary part of a std::complex matrix.
341
343 template<typename FT>
345
346 complex_matrix(const Matrix<FT> &);
347
348 template<typename FT>
350
351 complex_matrix(const Matrix<FT> &, const Matrix<FT> &); // A for real, B for imaginary
352
353
354 //----------------------------- Utilities for std::vector ------------------------------//
355
357 template<typename FT>
358 std::ostream &operator<<(std::ostream &, const std::vector<FT> &);// Overload of the output stream.
359 template<typename FT>
360 std::istream &operator>>(std::istream &, std::vector<FT> &); // Overload of the input stream.
361
363 template<typename FT>
364 std::vector<FT> operator-(const std::vector<FT> &); // get negative vector
365 template<typename FT>
366 std::vector<FT> operator+(const std::vector<FT> &, const std::vector<FT> &); // vector-vector addition
367 template<typename FT>
368 std::vector<FT> operator+(const std::vector<FT> &, const FT &); // vector-scalar addition
369 template<typename FT>
370 std::vector<FT> operator+(const FT &, const std::vector<FT> &); // scalar-vector addition
371 template<typename FT>
372 std::vector<FT> operator-(const std::vector<FT> &, const std::vector<FT> &); // vector-vector subtraction
373 template<typename FT>
374 std::vector<FT> operator-(const std::vector<FT> &, const FT &); // vector-scalar subtraction
375 template<typename FT>
376 std::vector<FT> operator-(const FT &, const std::vector<FT> &); // scalar-vector subtraction
377 template<typename FT1, typename FT2>
378 std::vector<FT1> operator*(const std::vector<FT1> &, const FT2 &); // complex vector-scalar multiplication
379 template<typename FT1, typename FT2>
380 std::vector<FT1> operator*(const FT2 &, const std::vector<FT1> &); // scalar-complex vector multiplication
381 template<typename FT1, typename FT2>
382 std::vector<FT1> operator/(const std::vector<FT1> &, const FT2 &); // complex vector-scalar division
383 template<typename FT1, typename FT2>
384 std::vector<FT1> operator/(const FT2 &, const std::vector<FT1> &); // scalar-complex vector division
385
386
388 template<typename FT>
389 std::vector<FT> elem_mult(const std::vector<FT> &, const std::vector<FT> &); // "*"
390 template<typename FT>
391 std::vector<FT> elem_divd(const std::vector<FT> &, const std::vector<FT> &); // "/"
392 template<typename FT>
393 std::vector<FT> &elem_mult_eq(std::vector<FT> &, const std::vector<FT> &); // "*="
394 template<typename FT>
395 std::vector<FT> &elem_divd_eq(std::vector<FT> &, const std::vector<FT> &); // "/="
396
398 template<typename FT>
399 FT operator*(const std::vector<FT> &, const std::vector<FT> &); // Inner product for vectors.
400 template<typename FT>
401 FT dot(const std::vector<FT> &, const std::vector<FT> &); // Inner product for vectors.
402
404 template<typename FT>
405 std::vector<FT> random(int size);
406
408 template<typename FT>
409 FT norm(const std::vector<FT> &);
410 template<typename FT>
411 FT norm(const std::vector<std::complex<FT>> &);
412 template<typename FT>
413 void swap(std::vector<FT> &, std::vector<FT> &);
414 template<typename FT>
415 std::vector<FT> linspace(FT, FT, int);
416 template<typename FT>
417 FT sum(const std::vector<FT> &);
418 template<typename FT>
419 FT min(const std::vector<FT> &);
420 template<typename FT>
421 FT max(const std::vector<FT> &);
422 template<typename FT>
423 FT mean(const std::vector<FT> &);
424
425 template<typename FT>
426 std::vector<FT> abs(const std::vector<std::complex<FT>> &);
427 template<typename FT>
428 std::vector<FT> arg(const std::vector<std::complex<FT>> &);
429 template<typename FT>
430 std::vector<FT> real(const std::vector<std::complex<FT>> &);
431 template<typename FT>
432 std::vector<FT> imag(const std::vector<std::complex<FT>> &);
433
435 template<typename FT>
436 std::vector<std::complex<FT>> complex_vector(const std::vector<FT> &);
437
438 template<typename FT>
439 std::vector<std::complex<FT>>
440 complex_vector(const std::vector<FT> &, const std::vector<FT> &); // A for real, B for imaginary
441}
442
443 //----------------------------- Matrix Implementation ------------------------------------//
444
445#include <cassert>
446
447namespace easy3d {
448
452 template<typename FT>
453 void Matrix<FT>::init(int rows, int cols) {
454 nRow_ = rows;
455 nColumn_ = cols;
456 nTotal_ = nRow_ * nColumn_;
457
458 data_ = new FT[nTotal_];
459 prow_ = new FT *[nRow_];
460
461 assert(data_ != NULL);
462 assert(prow_ != NULL);
463
464 FT *p = data_;
465 for (int i = 0; i < nRow_; ++i) {
466 prow_[i] = p;
467 p += nColumn_;
468 }
469 }
470
471
475 template<typename FT>
476 inline void Matrix<FT>::copy_from_array(const FT *v) {
477 for (long i = 0; i < nTotal_; ++i)
478 data_[i] = v[i];
479 }
480
481
485 template<typename FT>
486 inline void Matrix<FT>::set_by_scalar(const FT &x) {
487 for (long i = 0; i < nTotal_; ++i)
488 data_[i] = x;
489 }
490
491
495 template<typename FT>
496 void Matrix<FT>::destroy() {
497 if (data_ == NULL)
498 return;
499 else
500 delete[] data_;
501
502 if (prow_ != NULL)
503 delete[] prow_;
504 }
505
506
507 template<typename FT>
508 Matrix<FT> Matrix<FT>::cofactor(int _i, int _j) const {
509 assert(0 <= _i && _i < nRow_ && 0 <= _j && _j < nColumn_);
510 Matrix<FT> mat(nRow_ - 1, nColumn_ - 1);
511 for(int i = 0; i < mat.rows(); i++) {
512 for(int j = 0; j < mat.cols(); j++){
513 if(i < _i){
514 if(j < _j){
515 mat.data()[i * mat.cols() + j] = data_[i * nColumn_ + j];
516 } else {
517 mat.data()[i * mat.cols() + j] = data_[i * nColumn_ + (j + 1)];
518 }
519 } else {
520 if(j < _j){
521 mat.data()[i * mat.cols() + j] = data_[(i + 1) * nColumn_ + j];
522 } else {
523 mat.data()[i * mat.cols() + j] = data_[(i + 1) * nColumn_ + (j + 1)];
524 }
525 }
526 }
527 }
528 return mat;
529 }
530
531
532
536 template<typename FT>
538 : data_(0), prow_(0), nRow_(0), nColumn_(0), nTotal_(0) {
539 }
540
541 template<typename FT>
543 init(A.nRow_, A.nColumn_);
544 copy_from_array(A.data_);
545 }
546
547 template<typename FT>
548 Matrix<FT>::Matrix(int rows, int cols, const FT &x) {
549 init(rows, cols);
550 set_by_scalar(x);
551 }
552
553 template<typename FT>
554 Matrix<FT>::Matrix(int rows, int cols, const std::vector<FT> &array) {
555
556 init(rows, cols);
557 copy_from_array(array.data());
558 }
559
560 template<typename FT>
561 Matrix<FT>::Matrix(int rows, int cols, const FT *array) {
562 init(rows, cols);
563 copy_from_array(array);
564 }
565
566 template<typename FT>
567 Matrix<FT>::~Matrix() {
568 destroy();
569 }
570
571
575 template<typename FT>
577 if (data_ == A.data_)
578 return *this;
579
580 if (nRow_ == A.nRow_ && nColumn_ == A.nColumn_)
581 copy_from_array(A.data_);
582 else {
583 destroy();
584 init(A.nRow_, A.nColumn_);
585 copy_from_array(A.data_);
586 }
587
588 return *this;
589 }
590
591
595 template<typename FT>
596 inline Matrix<FT> &Matrix<FT>::operator=(const FT &x) {
597 set_by_scalar(x);
598 return *this;
599 }
600
601
605 template<typename FT>
606 inline FT *Matrix<FT>::operator[](int row) {
607 assert(0 <= row);
608 assert(row < nRow_);
609 return prow_[row];
610 }
611
612 template<typename FT>
613 inline const FT *Matrix<FT>::operator[](int row) const {
614 assert(0 <= row);
615 assert(row < nRow_);
616 return prow_[row];
617 }
618
619 template<typename FT>
620 inline FT &Matrix<FT>::operator()(int row, int col) {
621 assert(0 <= row);
622 assert(row < nRow_);
623 assert(0 <= col);
624 assert(col < nColumn_);
625 return prow_[row][col];
626 }
627
628 template<typename FT>
629 inline const FT &Matrix<FT>::operator()(int row, int col) const {
630 assert(0 <= row);
631 assert(row < nRow_);
632 assert(0 <= col);
633 assert(col < nColumn_);
634 return prow_[row][col];
635 }
636
637
638 template<typename FT>
639 inline
640 void Matrix<FT>::set(int row, int col, FT v) {
641 assert(0 <= row);
642 assert(row < nRow_);
643 assert(0 <= col);
644 assert(col < nColumn_);
645 prow_[row][col] = v;
646 }
647
648 template<typename FT>
649 inline
650 const FT &Matrix<FT>::get(int row, int col) const {
651 assert(0 <= row);
652 assert(row < nRow_);
653 assert(0 <= col);
654 assert(col < nColumn_);
655 return prow_[row][col];
656 }
657
661 template<typename FT>
662 inline void Matrix<FT>::load_zero() {
663 for (int i = 0; i < nRow_; i++) {
664 for (int j = 0; j < nColumn_; j++) {
665 prow_[i][j] = FT(0);
666 }
667 }
668 }
669
675 template<typename FT>
676 inline void Matrix<FT>::load_identity(FT v /* = FT(1.0)*/) {
677 for (int i = 0; i < nRow_; i++) {
678 for (int j = 0; j < nColumn_; j++) {
679 prow_[i][j] = (i == j) ? v : FT(0);
680 }
681 }
682 }
683
685 template<typename FT>
687 for (int i = 0; i < nRow_; i++) {
688 for (int j = 0; j < nColumn_; j++) {
689 prow_[i][j] = random_float();
690 }
691 }
692 }
693
694 template<typename FT>
695 inline int Matrix<FT>::rows() const {
696 return nRow_;
697 }
698
699 template<typename FT>
700 inline int Matrix<FT>::cols() const {
701 return nColumn_;
702 }
703
704
708 template<typename FT>
710 if (rows == nRow_ && cols == nColumn_)
711 return *this;
712
713 destroy();
714 init(rows, cols);
715
716 return *this;
717 }
718
719
723 template<typename FT>
724 std::vector<FT> Matrix<FT>::get_row(int row) const {
725 assert(0 <= row);
726 assert(row < nRow_);
727 std::vector<FT> tmp(nColumn_);
728 for (int j = 0; j < nColumn_; ++j)
729 tmp[j] = prow_[row][j];
730
731 return tmp;
732 }
733
734
738 template<typename FT>
739 std::vector<FT> Matrix<FT>::get_column(int col) const {
740 assert(0 <= col);
741 assert(col < nColumn_);
742 std::vector<FT> tmp(nRow_);
743 for (int i = 0; i < nRow_; ++i)
744 tmp[i] = prow_[i][col];
745
746 return tmp;
747 }
748
749
753 template<typename FT>
754 void Matrix<FT>::set_row(const std::vector<FT> &v, int row) {
755 assert(0 <= row);
756 assert(row < nRow_);
757 assert(v.size() == nColumn_);
758 for (int j = 0; j < nColumn_; ++j)
759 prow_[row][j] = v[j];
760 }
761
762
766 template<typename FT>
767 void Matrix<FT>::set_column(const std::vector<FT> &v, int col) {
768 assert(0 <= col);
769 assert(col < nColumn_);
770 assert(v.size() == nRow_);
771 for (int i = 0; i < nRow_; ++i)
772 prow_[i][col] = v[i];
773 }
774
775
776 template<typename FT>
778 Matrix<FT> t(nColumn_, nRow_);
779 for (int r = 0; r < nRow_; r++) {
780 for (int c = 0; c < nColumn_; c++) {
781 t(c, r) = (*this)(r, c);
782 }
783 }
784 return t;
785 }
786
787
788 template<typename FT>
790 assert(nRow_ == nColumn_ && nRow_ != 0);
791 if(nRow_ == 1) {
792 return data_[0];
793 } else if(nRow_ == 2) {
794 return data_[0]*data_[3] - data_[1]*data_[2];
795 } else if(nRow_ == 3) {
796 return - data_[8]*data_[1]*data_[3] - data_[7]*data_[5]*data_[0] - data_[2]*data_[4]*data_[6]
797 + data_[6]*data_[1]*data_[5] + data_[7]*data_[3]*data_[2] + data_[0]*data_[4]*data_[8];
798 } else {
799 FT value = FT();
800 for(int i = 0; i < nRow_; i++){
801 value += std::pow(-1.0, i) * data_[i * nColumn_] * cofactor(i, 0).determinant();
802 }
803 return value;
804 }
805 }
806
807
808 template<typename FT>
810 assert(nRow_ == nColumn_);
811 Matrix<FT> mat = Matrix<FT>(nRow_, nColumn_);
812 if(nRow_ == 1){
813 mat.data()[0] = 1.0 / data_[0];
814 return mat;
815 } else {
816 for(int i = 0; i < nRow_; i++){
817 for(int j = 0; j < nColumn_; j++){
818 mat.data()[i * mat.cols() + j] = std::pow(-1.0, i + j) * cofactor(j, i).determinant();
819 }
820 }
821 return mat / determinant();
822 }
823 }
824
825
826 template<typename FT>
827 FT Matrix<FT>::trace() const {
828 int range = std::min(nRow_, nColumn_);
829 FT trac = 0.0;
830 for (int i = 0; i < range; i++) {
831 trac += (*this)[i][i];
832 }
833 return trac;
834 }
835
839 template<typename FT>
841 FT **rowPtr = prow_;
842 FT *colPtr = 0;
843
844 for (int i = 0; i < nRow_; ++i) {
845 colPtr = *rowPtr++;
846 for (int j = 0; j < nColumn_; ++j)
847 *colPtr++ += x;
848 }
849
850 return *this;
851 }
852
853 template<typename FT>
855 assert(nRow_ == rhs.rows());
856 assert(nColumn_ == rhs.cols());
857
858 FT **rowPtrL = prow_;
859 FT *colPtrL = 0;
860 FT **rowPtrR = rhs.prow_;
861 const FT *colPtrR = 0;
862
863 for (int i = 0; i < nRow_; ++i) {
864 colPtrL = *rowPtrL++;
865 colPtrR = *rowPtrR++;
866 for (int j = 0; j < nColumn_; ++j)
867 *colPtrL++ += *colPtrR++;
868 }
869
870 return *this;
871 }
872
873
877 template<typename FT>
879 FT **rowPtr = prow_;
880 FT *colPtr = 0;
881
882 for (int i = 0; i < nRow_; ++i) {
883 colPtr = *rowPtr++;
884 for (int j = 0; j < nColumn_; ++j)
885 *colPtr++ -= x;
886 }
887
888 return *this;
889 }
890
891 template<typename FT>
893 assert(nRow_ == rhs.rows());
894 assert(nColumn_ == rhs.cols());
895
896 FT **rowPtrL = prow_;
897 FT *colPtrL = 0;
898 FT **rowPtrR = rhs.prow_;
899 const FT *colPtrR = 0;
900
901 for (int i = 0; i < nRow_; ++i) {
902 colPtrL = *rowPtrL++;
903 colPtrR = *rowPtrR++;
904 for (int j = 0; j < nColumn_; ++j)
905 *colPtrL++ -= *colPtrR++;
906 }
907
908 return *this;
909 }
910
911
915 template<typename FT>
916 template<typename FT2>
918 FT **rowPtr = prow_;
919 FT *colPtr = 0;
920
921 for (int i = 0; i < nRow_; ++i) {
922 colPtr = *rowPtr++;
923 for (int j = 0; j < nColumn_; ++j)
924 *colPtr++ *= x;
925 }
926
927 return *this;
928 }
929
930
934 template<typename FT>
935 template<typename FT2>
937 FT **rowPtr = prow_;
938 FT *colPtr = 0;
939
940 for (int i = 0; i < nRow_; ++i) {
941 colPtr = *rowPtr++;
942 for (int j = 0; j < nColumn_; ++j)
943 *colPtr++ /= x;
944 }
945
946 return *this;
947 }
948
952 template<typename FT>
953 std::ostream &operator<<(std::ostream &out, const Matrix<FT> &A) {
954 int rows = A.rows();
955 int cols = A.cols();
956
957 out << "size: " << rows << " by " << cols << "\n";
958 for (int i = 0; i < rows; ++i) {
959 for (int j = 0; j < cols; ++j) {
960 if (std::abs(A[i][j]) < 1e-6)
961 out << 0 << "\t";
962 else
963 out << A[i][j] << "\t";
964 }
965 out << "\n";
966 }
967
968 return out;
969 }
970
971
975 template<typename FT>
976 std::istream &operator>>(std::istream &in, Matrix<FT> &A) {
977 int rows, cols;
978 in >> rows >> cols;
979
980 if (!(rows == A.rows() && cols == A.cols()))
981 A.resize(rows, cols);
982
983 for (int i = 0; i < rows; ++i)
984 for (int j = 0; j < cols; ++j)
985 in >> A[i][j];
986
987 return in;
988 }
989
990
994 template<typename FT>
996 int rows = A.rows();
997 int cols = A.cols();
998
999 Matrix<FT> tmp(rows, cols);
1000 for (int i = 0; i < rows; ++i)
1001 for (int j = 0; j < cols; ++j)
1002 tmp[i][j] = -A[i][j];
1003
1004 return tmp;
1005 }
1006
1007
1009 template<typename FT>
1010 inline Matrix<FT> operator+(const Matrix<FT> &A, const FT &x) {
1011 Matrix<FT> tmp(A);
1012 return tmp += x;
1013 }
1014
1016 template<typename FT>
1017 inline Matrix<FT> operator+(const FT &x, const Matrix<FT> &A) {
1018 return A + x;
1019 }
1020
1021
1025 template<typename FT>
1026 inline Matrix<FT> operator+(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1027 Matrix<FT> tmp(A1);
1028 return tmp += A2;
1029 }
1030
1031
1033 template<typename FT>
1034 inline Matrix<FT> operator-(const Matrix<FT> &A, const FT &x) {
1035 Matrix<FT> tmp(A);
1036 return tmp -= x;
1037 }
1038
1040 template<typename FT>
1041 inline Matrix<FT> operator-(const FT &x, const Matrix<FT> &A) {
1042 Matrix<FT> tmp(A);
1043 return -tmp += x;
1044 }
1045
1046
1048 template<typename FT>
1049 inline Matrix<FT> operator-(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1050 Matrix<FT> tmp(A1);
1051 return tmp -= A2;
1052 }
1053
1057 template<typename FT>
1059 assert(A1.cols() == A2.rows());
1060
1061 int rows = A1.rows();
1062 int cols = A2.cols();
1063 // int K = A1.cols();
1064
1065 Matrix<FT> tmp(rows, cols);
1066 // for( int i=0; i<rows; ++i )
1067 // for( int j=0; j<cols; ++j )
1068 // {
1069 // tmp[i][j] = 0;
1070 // for( int k=0; k<K; ++k )
1071 // tmp[i][j] += A1[i][k] * A2[k][j];
1072 // }
1073
1074 mult(A1, A2, tmp);
1075
1076 return tmp;
1077 }
1078
1079
1083 template<typename FT>
1084 std::vector<FT> operator*(const Matrix<FT> &A, const std::vector<FT> &b) {
1085 assert(A.cols() == b.size());
1086
1087 int rows = A.rows();
1088 // int cols = A.cols();
1089
1090 std::vector<FT> tmp(rows);
1091 mult(A, b, tmp);
1092
1093 return tmp;
1094 }
1095
1097 template<typename FT1, typename FT2>
1098 inline
1099 Matrix<FT1> operator*(const Matrix<FT1> &A, const FT2 &s) {
1100 Matrix<FT1> tmp(A);
1101 return tmp *= s;
1102 }
1103
1105 template<typename FT1, typename FT2>
1106 inline
1107 Matrix<FT1> operator*(const FT2 &s, const Matrix<FT1> &A) {
1108 return A * s;
1109 }
1110
1112 template<typename FT1, typename FT2>
1113 inline
1114 Matrix<FT1> operator/(const Matrix<FT1> &A, const FT2 &s) {
1115 Matrix<FT1> tmp(A);
1116 return tmp /= s;
1117 }
1118
1120 template<typename FT1, typename FT2>
1121 inline
1122 Matrix<FT1> operator/(const FT2 &s, const Matrix<FT1> &A) {
1123 int rows = A.rows();
1124 int clumns = A.cols();
1125
1126 Matrix<FT1> tmp(rows, clumns);
1127 for (int i = 0; i < rows; ++i)
1128 for (int j = 0; j < clumns; ++j)
1129 tmp[i][j] = s / A[i][j];
1130
1131 return tmp;
1132 }
1133
1138 template<typename FT>
1139 void mult(const Matrix<FT> &A, const Matrix<FT> &B, Matrix<FT> &C) {
1140 int M = A.rows();
1141 int N = B.cols();
1142 int K = A.cols();
1143
1144 assert(B.rows() == K);
1145
1146 C.resize(M, N);
1147 FT sum = 0;
1148 const FT *pRow, *pCol;
1149
1150 for (int i = 0; i < M; i++)
1151 for (int j = 0; j < N; ++j) {
1152 pRow = &A[i][0];
1153 pCol = &B[0][j];
1154 sum = 0;
1155
1156 for (int k = 0; k < K; ++k) {
1157 sum += (*pRow) * (*pCol);
1158 pRow++;
1159 pCol += N;
1160 }
1161 C[i][j] = sum;
1162 }
1163 }
1164
1165
1170 template<typename FT>
1171 void mult(const Matrix<FT> &A, const std::vector<FT> &b, std::vector<FT> &c) {
1172 int M = A.rows();
1173 int N = A.cols();
1174
1175 assert(b.size() == N);
1176
1177 c.resize(M);
1178 FT sum = 0;
1179 const FT *pRow, *pCol;
1180
1181 for (int i = 0; i < M; i++) {
1182 pRow = &A[i][0];
1183 pCol = &b[0];
1184 sum = 0;
1185
1186 for (int j = 0; j < N; ++j) {
1187 sum += (*pRow) * (*pCol);
1188 pRow++;
1189 pCol++;
1190 }
1191 c[i] = sum;
1192 }
1193 }
1194
1195
1200 template<typename FT>
1201 Matrix<FT> mult(const Matrix<FT> &A, const Matrix<FT> &B) {
1202 int M = A.rows();
1203 int N = B.cols();
1204 int K = A.cols();
1205
1206 assert(B.rows() == K);
1207
1208 Matrix<FT> C(M, N);
1209 FT sum = 0;
1210 const FT *pRow, *pCol;
1211
1212 for (int i = 0; i < M; i++)
1213 for (int j = 0; j < N; ++j) {
1214 pRow = &A[i][0];
1215 pCol = &B[0][j];
1216 sum = 0;
1217
1218 for (int k = 0; k < K; ++k) {
1219 sum += (*pRow) * (*pCol);
1220 pRow++;
1221 pCol += N;
1222 }
1223 C[i][j] = sum;
1224 }
1225 return C;
1226 }
1227
1228
1233 template<typename FT>
1234 std::vector<FT> mult(const Matrix<FT> &A, const std::vector<FT> &b) {
1235 int M = A.rows();
1236 int N = A.cols();
1237
1238 assert(b.size() == N);
1239
1240 std::vector<FT> c(M);
1241 FT sum = 0;
1242 const FT *pRow, *pCol;
1243
1244 for (int i = 0; i < M; i++) {
1245 pRow = &A[i][0];
1246 pCol = &b[0];
1247 sum = 0;
1248
1249 for (int j = 0; j < N; ++j) {
1250 sum += (*pRow) * (*pCol);
1251 pRow++;
1252 pCol++;
1253 }
1254 c[i] = sum;
1255 }
1256 return c;
1257 }
1258
1259
1261 template<typename FT>
1262 inline Matrix<FT> elem_mult(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1263 Matrix<FT> tmp(A1);
1264 return tmp *= A2;
1265 }
1266
1268 template<typename FT>
1270 return A1 *= A2;
1271 }
1272
1273
1275 template<typename FT>
1276 inline Matrix<FT> elem_divd(const Matrix<FT> &A1, const Matrix<FT> &A2) {
1277 Matrix<FT> tmp(A1);
1278 return tmp /= A2;
1279 }
1280
1282 template<typename FT>
1284 return A1 /= A2;
1285 }
1286
1287
1289 template<typename FT>
1291 int rows = A.cols();
1292 int clumns = A.rows();
1293
1294 Matrix<FT> tmp(rows, clumns);
1295 for (int i = 0; i < rows; ++i)
1296 for (int j = 0; j < clumns; ++j)
1297 tmp[i][j] = A[j][i];
1298
1299 return tmp;
1300 }
1301
1302
1304 template<typename FT>
1306 int rows = A.cols();
1307 int clumns = A.rows();
1308
1309 Matrix<FT> tmp(rows, clumns);
1310 for (int i = 0; i < rows; ++i)
1311 for (int j = 0; j < clumns; ++j)
1312 tmp[i][j] = conj(A[j][i]);
1313
1314 return tmp;
1315 }
1316
1317
1319 template<typename FT>
1321 assert(A1.rows() == A2.rows());
1322
1323 int rows = A1.cols();
1324 int cols = A2.cols();
1325 int K = A1.rows();
1326
1327 Matrix<FT> tmp(rows, cols);
1328 for (int i = 0; i < rows; ++i)
1329 for (int j = 0; j < cols; ++j)
1330 for (int k = 0; k < K; ++k)
1331 tmp[i][j] += A1[k][i] * A2[k][j];
1332
1333 return tmp;
1334 }
1335
1336
1338 template<typename FT>
1339 std::vector<FT> transpose_mult(const Matrix<FT> &A, const std::vector<FT> &v) {
1340 assert(A.rows() == v.size());
1341
1342 int rows = A.rows();
1343 int cols = A.cols();
1344
1345 std::vector<FT> tmp(cols);
1346 for (int i = 0; i < cols; ++i)
1347 for (int j = 0; j < rows; ++j)
1348 tmp[i] += A[j][i] * v[j];
1349
1350 return tmp;
1351 }
1352
1353
1355 template<typename FT>
1357 assert(A1.cols() == A2.cols());
1358
1359 int rows = A1.rows();
1360 int cols = A2.rows();
1361 int K = A1.cols();
1362
1363 Matrix<FT> tmp(rows, cols);
1364 for (int i = 0; i < rows; ++i)
1365 for (int j = 0; j < cols; ++j)
1366 for (int k = 0; k < K; ++k)
1367 tmp[i][j] += A1[i][k] * A2[j][k];
1368
1369 return tmp;
1370 }
1371
1372
1374 template<typename FT>
1375 Matrix<FT> mult_transpose(const std::vector<FT> &a, const std::vector<FT> &b) {
1376 int rows = a.size();
1377 int cols = b.size();
1378
1379 Matrix<FT> tmp(rows, cols);
1380 for (int i = 0; i < rows; ++i)
1381 for (int j = 0; j < cols; ++j)
1382 tmp[i][j] = a[i] * b[j];
1383
1384 return tmp;
1385 }
1386
1387
1389 template<typename FT>
1390 Matrix<FT> random(int row, int col) {
1391 Matrix<FT> tmp(row, col);
1392 for (int i = 0; i < row; i++) {
1393 for (int j = 0; j < col; j++) {
1394 tmp[i][j] = random_float();
1395 }
1396 }
1397 }
1398
1400 template<typename FT>
1401 Matrix<FT> identity(int N, const FT& x /*= FT(1)*/) {
1402 Matrix<FT> tmp(N, N);
1403 for (int i = 0; i < N; ++i)
1404 tmp[i][i] = x;
1405
1406 return tmp;
1407 }
1408
1409
1411 template<typename FT>
1412 std::vector<FT> diagonal(const Matrix<FT> &A) {
1413 int nColumn_ = A.rows();
1414 if (nColumn_ > A.cols())
1415 nColumn_ = A.cols();
1416
1417 std::vector<FT> tmp(nColumn_);
1418 for (int i = 0; i < nColumn_; ++i)
1419 tmp[i] = A[i][i];
1420
1421 return tmp;
1422 }
1423
1424
1426 template<typename FT>
1427 Matrix<FT> diagonal(const std::vector<FT> &d) {
1428 int N = static_cast<int>(d.size());
1429
1430 Matrix<FT> tmp(N, N);
1431 for (int i = 0; i < N; ++i)
1432 tmp[i][i] = d[i];
1433
1434 return tmp;
1435 }
1436
1437
1442 template<typename FT>
1443 FT trace(const Matrix<FT> &A) {
1444 int range = std::min(A.rows(), A.cols());
1445 FT trac = 0.0;
1446 for (int i = 0; i < range; i++) {
1447 trac += A[i][i];
1448 }
1449 return trac;
1450 }
1451
1452
1454 template<typename FT>
1455 FT norm(const Matrix<FT> &A) {
1456 int m = A.rows();
1457 int n = A.cols();
1458
1459 FT sum = 0;
1460 for (int i = 0; i < m; ++i)
1461 for (int j = 0; j < n; ++j)
1462 sum += A[i][j] * A[i][j];
1463
1464 return std::sqrt(sum);
1465 }
1466
1467
1469 template<typename FT>
1470 void swap(Matrix<FT> &lhs, Matrix<FT> &rhs) {
1471 int m = lhs.rows();
1472 int n = lhs.cols();
1473
1474 assert(m == rhs.rows());
1475 assert(n == rhs.cols());
1476
1477 for (int i = 0; i < m; ++i)
1478 for (int j = 0; j < n; ++j)
1479 std::swap(lhs(i, j), rhs(i, j));
1480 }
1481
1482
1484 template<typename FT>
1485 std::vector<FT> sum(const Matrix<FT> &A) {
1486 int m = A.rows();
1487 int n = A.cols();
1488 std::vector<FT> s(n);
1489
1490 for (int j = 0; j < n; ++j)
1491 for (int i = 0; i < m; ++i)
1492 s[j] += A[i][j];
1493 return s;
1494 }
1495
1496
1498 template<typename FT>
1499 std::vector<FT> min(const Matrix<FT> &A) {
1500 int m = A.rows();
1501 int n = A.cols();
1502 std::vector<FT> sum(n);
1503
1504 for (int j = 0; j < n; ++j) {
1505 FT tmp = A[0][j];
1506 for (int i = 1; i < m; ++i)
1507 if (tmp > A[i][j])
1508 tmp = A[i][j];
1509 sum[j] = tmp;
1510 }
1511
1512 return sum;
1513 }
1514
1515
1517 template<typename FT>
1518 std::vector<FT> max(const Matrix<FT> &A) {
1519 int m = A.rows();
1520 int n = A.cols();
1521 std::vector<FT> sum(n);
1522
1523 for (int j = 0; j < n; ++j) {
1524 FT tmp = A[0][j];
1525 for (int i = 1; i < m; ++i)
1526 if (tmp < A[i][j])
1527 tmp = A[i][j];
1528 sum[j] = tmp;
1529 }
1530
1531 return sum;
1532 }
1533
1534
1536 template<typename FT>
1537 inline std::vector<FT> mean(const Matrix<FT> &A) {
1538 return sum(A) / FT(A.rows());
1539 }
1540
1541
1543 template<typename FT>
1544 Matrix<FT> abs(const Matrix<std::complex<FT> > &A) {
1545 int m = A.rows(),
1546 n = A.cols();
1547 Matrix<FT> tmp(m, n);
1548
1549 for (int i = 0; i < m; ++i)
1550 for (int j = 0; j < n; ++j)
1551 tmp[i][j] = std::abs(A[i][j]);
1552
1553 return tmp;
1554 }
1555
1557 template<typename FT>
1558 Matrix<FT> arg(const Matrix<std::complex<FT> > &A) {
1559 int m = A.rows(),
1560 n = A.cols();
1561 Matrix<FT> tmp(m, n);
1562
1563 for (int i = 0; i < m; ++i)
1564 for (int j = 0; j < n; ++j)
1565 tmp[i][j] = arg(A[i][j]);
1566
1567 return tmp;
1568 }
1569
1571 template<typename FT>
1572 Matrix<FT> real(const Matrix<std::complex<FT> > &A) {
1573 int m = A.rows(),
1574 n = A.cols();
1575 Matrix<FT> tmp(m, n);
1576
1577 for (int i = 0; i < m; ++i)
1578 for (int j = 0; j < n; ++j)
1579 tmp[i][j] = A[i][j].real();
1580
1581 return tmp;
1582 }
1583
1584
1586 template<typename FT>
1587 Matrix<FT> imag(const Matrix<std::complex<FT> > &A) {
1588 int m = A.rows(),
1589 n = A.cols();
1590 Matrix<FT> tmp(m, n);
1591
1592 for (int i = 0; i < m; ++i)
1593 for (int j = 0; j < n; ++j)
1594 tmp[i][j] = A[i][j].imag();
1595
1596 return tmp;
1597 }
1598
1599
1601 template<typename FT>
1603 int rows = rA.rows();
1604 int cols = rA.cols();
1605
1606 Matrix<std::complex<FT> > cA(rows, cols);
1607 for (int i = 0; i < rows; ++i)
1608 for (int j = 0; j < cols; ++j)
1609 cA[i][j] = rA[i][j];
1610
1611 return cA;
1612 }
1613
1615 template<typename FT>
1617 int rows = mR.rows();
1618 int cols = mR.cols();
1619
1620 assert(rows == mI.rows());
1621 assert(cols == mI.cols());
1622
1623 Matrix<std::complex<FT> > cA(rows, cols);
1624 for (int i = 0; i < rows; ++i)
1625 for (int j = 0; j < cols; ++j)
1626 cA[i][j] = std::complex<FT>(mR[i][j], mI[i][j]);
1627
1628 return cA;
1629 }
1630
1631
1632 //----------------------------- std::vector Implementation ------------------------------------//
1633
1634
1636 template<typename FT>
1637 std::ostream &operator<<(std::ostream &out, const std::vector<FT> &A) {
1638 out << "size: " << A.size() << "\n";
1639 for (std::size_t i = 0; i < A.size(); ++i)
1640 out << A[i] << "\t";
1641 out << "\n";
1642 return out;
1643 }
1644
1645
1647 template<typename FT>
1648 std::istream &operator>>(std::istream &in, std::vector<FT> &A) {
1649 int size;
1650 in >> size;
1651 A.resize(size);
1652 for (int i = 0; i < size; ++i)
1653 in >> A[i];
1654 return in;
1655 }
1656
1657
1659 template<typename FT>
1660 std::vector<FT> operator-(const std::vector<FT> &A) {
1661 std::vector<FT> tmp = A;
1662 for (std::size_t i = 0; i < tmp.size(); ++i)
1663 tmp[i] = -tmp[i];
1664
1665 return tmp;
1666 }
1667
1668
1670 template<typename FT>
1671 std::vector<FT> operator+(const std::vector<FT> &A, const std::vector<FT> &B) {
1672 assert(A.size() == B.size());
1673
1674 std::vector<FT> tmp = A;
1675 for (std::size_t i = 0; i < B.size(); ++i)
1676 tmp[i] += B[i];
1677
1678 return tmp;
1679 }
1680
1682 template<typename FT>
1683 std::vector<FT> operator+(const std::vector<FT> &A, const FT &s) {
1684 std::vector<FT> tmp = A;
1685 for (std::size_t i = 0; i < A.size(); ++i)
1686 tmp[i] += s;
1687
1688 return tmp;
1689 }
1690
1692 template<typename FT>
1693 std::vector<FT> operator+(const FT &s, const std::vector<FT> &A) {
1694 std::vector<FT> tmp = A;
1695 for (std::size_t i = 0; i < A.size(); ++i)
1696 tmp[i] += s;
1697
1698 return tmp;
1699 }
1700
1702 template<typename FT>
1703 std::vector<FT> operator-(const std::vector<FT> &A, const std::vector<FT> &B) {
1704 assert(A.size() == B.size());
1705
1706 std::vector<FT> tmp = A;
1707 for (std::size_t i = 0; i < B.size(); ++i)
1708 tmp[i] -= B[i];
1709
1710 return tmp;
1711 }
1712
1714 template<typename FT>
1715 std::vector<FT> operator-(const std::vector<FT> &A, const FT &s) {
1716 std::vector<FT> tmp = A;
1717 for (std::size_t i = 0; i < A.size(); ++i)
1718 tmp[i] -= s;
1719
1720 return tmp;
1721 }
1722
1724 template<typename FT>
1725 std::vector<FT> operator-(const FT &s, const std::vector<FT> &A) {
1726 std::vector<FT> tmp = A;
1727 for (std::size_t i = 0; i < A.size(); ++i)
1728 tmp[i] = s - tmp[i];
1729
1730 return tmp;
1731 }
1732
1734 template<typename FT1, typename FT2>
1735 std::vector<FT1> operator*(const std::vector<FT1> &A, const FT2 &s) {
1736 std::vector<FT1> tmp = A;
1737 for (std::size_t i = 0; i < A.size(); ++i)
1738 tmp[i] *= s;
1739
1740 return tmp;
1741 }
1742
1744 template<typename FT1, typename FT2>
1745 std::vector<FT1> operator*(const FT2 &s, const std::vector<FT1> &A) {
1746 return A * s;
1747 }
1748
1750 template<typename FT1, typename FT2>
1751 std::vector<FT1> operator/(const std::vector<FT1> &A, const FT2 &s) {
1752 std::vector<FT1> tmp = A;
1753 for (std::size_t i = 0; i < A.size(); ++i)
1754 tmp[i] /= s;
1755
1756 return tmp;
1757 }
1758
1760 template<typename FT1, typename FT2>
1761 std::vector<FT1> operator/(const FT2 &s, const std::vector<FT1> &A) {
1762 std::vector<FT1> tmp = A;
1763 for (std::size_t i = 0; i < A.size(); ++i)
1764 tmp[i] = s / tmp[i];
1765
1766 return tmp;
1767 }
1768
1770 template<typename FT>
1771 inline std::vector<FT> elem_mult(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1772 assert(v1.size() == v2.size());
1773 std::vector<FT> result = v1;
1774 for (std::size_t i = 0; i < v2.size(); ++i) {
1775 result[i] *= v2[i];
1776 }
1777
1778 return result;
1779 }
1780
1782 template<typename FT>
1783 inline std::vector<FT> &elem_mult_eq(std::vector<FT> &v1, const std::vector<FT> &v2) {
1784 assert(v1.size() == v2.size());
1785 for (std::size_t i = 0; i < v2.size(); ++i) {
1786 v1[i] *= v2[i];
1787 }
1788
1789 return v1;
1790 }
1791
1792
1794 template<typename FT>
1795 inline std::vector<FT> elem_divd(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1796 assert(v1.size() == v2.size());
1797 std::vector<FT> result = v1;
1798 for (std::size_t i = 0; i < v2.size(); ++i) {
1799 result[i] /= v2[i];
1800 }
1801
1802 return result;
1803 }
1804
1806 template<typename FT>
1807 inline std::vector<FT> &elem_divd_eq(std::vector<FT> &v1, const std::vector<FT> &v2) {
1808 assert(v1.size() == v2.size());
1809 for (std::size_t i = 0; i < v2.size(); ++i) {
1810 v1[i] /= v2[i];
1811 }
1812
1813 return v1;
1814 }
1815
1816
1818 template<typename FT>
1819 FT operator*(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1820 assert(v1.size() == v2.size());
1821
1822 FT sum = 0;
1823 typename std::vector<FT>::const_iterator itr1 = v1.begin();
1824 typename std::vector<FT>::const_iterator itr2 = v2.begin();
1825
1826 while (itr1 != v1.end())
1827 sum += (*itr1++) * (*itr2++);
1828
1829 return sum;
1830 }
1831
1833 template<typename FT>
1834 FT dot(const std::vector<FT> &v1, const std::vector<FT> &v2) {
1835 assert(v1.size() == v2.size());
1836
1837 FT sum = 0;
1838 typename std::vector<FT>::const_iterator itr1 = v1.begin();
1839 typename std::vector<FT>::const_iterator itr2 = v2.begin();
1840
1841 while (itr1 != v1.end())
1842 sum += (*itr1++) * (*itr2++);
1843
1844 return sum;
1845 }
1846
1847
1849 template<typename FT>
1850 FT sum(const std::vector<FT> &v) {
1851 FT sum = 0;
1852 typename std::vector<FT>::const_iterator itr = v.begin();
1853
1854 while (itr != v.end())
1855 sum += *itr++;
1856
1857 return sum;
1858 }
1859
1861 template<typename FT>
1862 FT min(const std::vector<FT> &v) {
1863 FT m = v[0];
1864 for (std::size_t i = 1; i < v.size(); ++i)
1865 if (m > v[i])
1866 m = v[i];
1867
1868 return m;
1869 }
1870
1872 template<typename FT>
1873 FT max(const std::vector<FT> &v) {
1874 FT M = v[0];
1875 for (std::size_t i = 1; i < v.size(); ++i)
1876 if (M < v[i])
1877 M = v[i];
1878
1879 return M;
1880 }
1881
1883 template<typename FT>
1884 inline FT mean(const std::vector<FT> &v) {
1885 return sum(v) / FT(v.size());
1886 }
1887
1889 template<typename FT>
1890 inline std::vector<FT> random(int size) {
1891 std::vector<FT> V(size);
1892 for (auto& v : V)
1893 v = random_float();
1894 return V;
1895 }
1896
1898 template<typename FT>
1899 inline FT norm(const std::vector<FT> &v) {
1900 FT sum = 0;
1901 typename std::vector<FT>::const_iterator itr = v.begin();
1902
1903 while (itr != v.end()) {
1904 sum += (*itr) * (*itr);
1905 itr++;
1906 }
1907
1908 return FT(std::sqrt(sum));
1909 }
1910
1912 template<typename FT>
1913 FT norm(const std::vector<std::complex<FT> > &v) {
1914 FT sum = 0;
1915 typename std::vector<std::complex<FT> >::const_iterator itr = v.begin();
1916
1917 while (itr != v.end()) {
1918 sum += std::norm(*itr++);
1919 }
1920
1921 return FT(std::sqrt(sum));
1922 }
1923
1925 template<typename FT>
1926 void swap(std::vector<FT> &lhs, std::vector<FT> &rhs) {
1927 typename std::vector<FT>::iterator itrL = lhs.begin(),
1928 itrR = rhs.begin();
1929
1930 while (itrL != lhs.end())
1931 std::swap(*itrL++, *itrR++);
1932 }
1933
1935 template<typename FT>
1936 std::vector<FT> linspace(FT a, FT b, int n) {
1937 if (n < 1)
1938 return std::vector<FT>();
1939 else if (n == 1)
1940 return std::vector<FT>(1, a);
1941 else {
1942 FT dx = (b - a) / (n - 1);
1943
1944 std::vector<FT> tmp(n);
1945 for (int i = 0; i < n; ++i)
1946 tmp[i] = a + i * dx;
1947
1948 return tmp;
1949 }
1950 }
1951
1953 template<typename FT>
1954 std::vector<FT> abs(const std::vector<std::complex<FT> > &v) {
1955 std::vector<FT> tmp(v.size());
1956 typename std::vector<FT>::iterator itrL = tmp.begin();
1957 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1958
1959 while (itrL != tmp.end())
1960 *itrL++ = std::abs(*itrR++);
1961
1962 return tmp;
1963 }
1964
1966 template<typename FT>
1967 std::vector<FT> arg(const std::vector<std::complex<FT> > &v) {
1968 std::vector<FT> tmp(v.size());
1969 typename std::vector<FT>::iterator itrL = tmp.begin();
1970 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1971
1972 while (itrL != tmp.end())
1973 *itrL++ = std::arg(*itrR++);
1974
1975 return tmp;
1976 }
1977
1979 template<typename FT>
1980 std::vector<FT> real(const std::vector<std::complex<FT> > &v) {
1981 std::vector<FT> tmp(v.size());
1982 typename std::vector<FT>::iterator itrL = tmp.begin();
1983 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1984
1985 while (itrL != tmp.end())
1986 *itrL++ = (*itrR++).real();
1987
1988 return tmp;
1989 }
1990
1992 template<typename FT>
1993 std::vector<FT> imag(const std::vector<std::complex<FT> > &v) {
1994 std::vector<FT> tmp(v.size());
1995 typename std::vector<FT>::iterator itrL = tmp.begin();
1996 typename std::vector<std::complex<FT> >::const_iterator itrR = v.begin();
1997
1998 while (itrL != tmp.end())
1999 *itrL++ = (*itrR++).imag();
2000
2001 return tmp;
2002 }
2003
2005 template<typename FT>
2006 std::vector<std::complex<FT> > complex_vector(const std::vector<FT> &rv) {
2007 int N = rv.size();
2008
2009 std::vector<std::complex<FT> > cv(N);
2010 typename std::vector<std::complex<FT> >::iterator itrL = cv.begin();
2011 typename std::vector<FT>::const_iterator itrR = rv.begin();
2012
2013 while (itrR != rv.end())
2014 *itrL++ = *itrR++;
2015
2016 return cv;
2017 }
2018
2020 template<typename FT>
2021 std::vector<std::complex<FT> > complex_vector(const std::vector<FT> &vR, const std::vector<FT> &vI) {
2022 int N = static_cast<int>(vR.size());
2023
2024 assert(N == vI.size());
2025
2026 std::vector<std::complex<FT> > cv(N);
2027 typename std::vector<std::complex<FT> >::iterator itrC = cv.begin();
2028 typename std::vector<FT>::const_iterator itrR = vR.begin(),
2029 itrI = vI.begin();
2030
2031 while (itrC != cv.end())
2032 *itrC++ = std::complex<FT>(*itrR++, *itrI++);
2033
2034 return cv;
2035 }
2036
2037}
2038
2039#endif // EASY3D_CORE_MATRIX_H
A matrix representation, which supports dynamic sizes.
Definition matrix.h:48
const FT * operator[](int row) const
Return the row_th row as a 1D array (const version).
Definition matrix.h:613
FT * data()
Definition matrix.h:124
Matrix< FT > & operator*=(const FT2 &v)
computed assignment. Multiply each element by v
Definition matrix.h:917
Matrix< FT > & operator/=(const FT2 &v)
computed assignment. Divide each element by v
Definition matrix.h:936
FT & operator()(int row, int col)
Return the element at (row, col).
Definition matrix.h:620
Matrix(int rows, int cols, const FT &x=FT(0))
Definition matrix.h:548
Matrix()
Definition matrix.h:537
Matrix< FT > & operator+=(const FT &v)
computed assignment. Add each element by v
Definition matrix.h:840
Matrix< FT > & operator=(const Matrix< FT > &A)
Assign A to this matrix.
Definition matrix.h:576
Matrix(const Matrix< FT > &A)
Definition matrix.h:542
Matrix< FT > & operator-=(const Matrix< FT > &)
computed assignment. Subtract A from this matrix.
Definition matrix.h:892
const FT & get(int row, int col) const
Get the value of the element at (row, col).
Definition matrix.h:650
void load_identity(FT v=FT(1))
Definition matrix.h:676
Matrix(int rows, int cols, const std::vector< FT > &array)
Definition matrix.h:554
std::vector< FT > get_column(int col) const
Get the matrix's column vector as a 1D array.
Definition matrix.h:739
Matrix< FT > & operator+=(const Matrix< FT > &A)
computed assignment. Add A to this matrix.
Definition matrix.h:854
const FT * data() const
Definition matrix.h:130
void set_column(const std::vector< FT > &v, int col)
Set the matrix's column vector.
Definition matrix.h:767
void load_zero()
Set all elements to zero.
Definition matrix.h:662
Matrix< FT > & resize(int rows, int cols)
Change the size/dimension of the matrix.
Definition matrix.h:709
FT * operator[](int row)
Return the row_th row as a 1D array.
Definition matrix.h:606
std::vector< FT > get_row(int row) const
Get the matrix's row vector as a 1D array.
Definition matrix.h:724
Matrix< FT > inverse() const
Return the inverse of the matrix (for positive square matrices only)
Definition matrix.h:809
const FT & operator()(int row, int col) const
Return the element at (row, col) (const version).
Definition matrix.h:629
void set_row(const std::vector< FT > &v, int row)
Set the matrix's row vector.
Definition matrix.h:754
void set(int row, int col, FT v)
Set the value of the element at (row, col).
Definition matrix.h:640
Matrix< FT > transpose() const
Return the transposed matrix.
Definition matrix.h:777
Matrix< FT > & operator-=(const FT &v)
computed assignment. Subtract each element by v
Definition matrix.h:878
FT trace() const
Definition matrix.h:827
Matrix(int rows, int cols, const FT *array)
Definition matrix.h:561
Matrix< FT > & operator=(const FT &x)
Assign x to every entry of this matrix.
Definition matrix.h:596
FT determinant() const
Return the determinant of the matrix (for square matrices only)
Definition matrix.h:789
void load_random()
Set all elements to a random value (in the range [0.0, 1.0])
Definition matrix.h:686
Definition collider.cpp:182
Matrix< FT > operator+(const Matrix< FT > &, const FT &)
Definition matrix.h:1010
T trace(const Mat< N, N, T > &m)
Returns the trace (sum of elements on the main diagonal) of an N x N (square) matrix.
Mat< M, N, T > transpose(const Mat< N, M, T > &m)
Transposes a matrix.
Definition mat.h:1120
Matrix< FT > operator-(const Matrix< FT > &)
arithmetic operators
Definition matrix.h:995
Matrix< FT > & elem_divd_eq(Matrix< FT > &, const Matrix< FT > &)
Definition matrix.h:1283
Matrix< FT > elem_divd(const Matrix< FT > &, const Matrix< FT > &)
Definition matrix.h:1276
std::vector< FT > mean(const Matrix< FT > &)
Definition matrix.h:1537
Matrix< FT > transpose_mult(const Matrix< FT > &, const Matrix< FT > &)
transpose multiplication
Definition matrix.h:1320
Matrix< FT > diagonal(const std::vector< FT > &)
diagonal matrix
Definition matrix.h:1427
Matrix< FT > elem_mult(const Matrix< FT > &, const Matrix< FT > &)
element-wise multiplication / division
Definition matrix.h:1262
Matrix< FT1 > operator/(const Matrix< FT1 > &, const FT2 &)
matrix-scalar division
Definition matrix.h:1114
Matrix< FT > mult_transpose(const Matrix< FT > &, const Matrix< FT > &)
Definition matrix.h:1356
FT min()
Function returning minimum representable value for a given type.
void swap(Matrix< FT > &, Matrix< FT > &)
Definition matrix.h:1470
Matrix< FT > random(int row, int col)
Generate a matrix with all its elements randomly initialized in the range [0.0, 1....
Definition matrix.h:1390
Matrix< FT > identity(int N, const FT &v=FT(1))
Definition matrix.h:1401
Matrix< std::complex< FT > > complex_matrix(const Matrix< FT > &)
Convert real matrix to complex matrix.
Definition matrix.h:1602
float random_float()
Random real in [0, 1].
Definition random.h:39
Matrix< FT > real(const Matrix< std::complex< FT > > &A)
Get real part of a std::complex matrix.
Definition matrix.h:1572
std::vector< std::complex< FT > > complex_vector(const std::vector< FT > &)
Get imaginary part of a complex vector.
Definition matrix.h:2006
std::vector< FT > linspace(FT, FT, int)
Swap two vectors.
Definition matrix.h:1936
Matrix< FT > imag(const Matrix< std::complex< FT > > &A)
Get imaginary part of a std::complex matrix.
Definition matrix.h:1587
T determinant(const Mat< N, N, T > &m)
Computes the determinant of a square matrix.
Definition mat.h:1143
void mult(const Matrix< FT > &, const Matrix< FT > &, Matrix< FT > &)
multiplication
Definition matrix.h:1139
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Output stream support for Graph::Vertex.
Definition graph.h:1300
FT max()
Function returning maximum representable value for a given type.
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Input stream support for GenericLine.
Definition line.h:183
Matrix< FT > arg(const Matrix< std::complex< FT > > &A)
Get angle of a std::complex matrix.
Definition matrix.h:1558
Matrix< FT > abs(const Matrix< std::complex< FT > > &A)
Get magnitude of a std::complex matrix.
Definition matrix.h:1544
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition matrix.h:1834
std::vector< FT > sum(const Matrix< FT > &)
Definition matrix.h:1485
Matrix< FT > conjugate_transpose(const Matrix< FT > &)
Definition matrix.h:1305
FT norm(const Matrix< FT > &)
utilities
Definition matrix.h:1455
Matrix< FT > & elem_mult_eq(Matrix< FT > &, const Matrix< FT > &)
Definition matrix.h:1269
Mat< N, M, T > operator*(T lhs, const Mat< N, M, T > &rhs)
Multiplies a scalar by a matrix.
Definition mat.h:1000