Mantid
Loading...
Searching...
No Matches
Matrix.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
12#include "MantidKernel/V3D.h"
13
14#include <algorithm>
15#include <climits>
16#include <cmath>
17#include <memory>
18#include <sstream>
19
20namespace Mantid::Kernel {
21//
22#define fabs(x) std::fabs((x)*1.0)
23
24namespace {
25//-------------------------------------------------------------------------
26// Utility methods and function objects in anonymous namespace
27//-------------------------------------------------------------------------
35template <typename T> struct PIndex {
36private:
37 int count;
38public:
40 PIndex() : count(0) {}
42 std::pair<T, int> operator()(const T &A) { return std::pair<T, int>(A, count++); }
43};
44
52template <typename T> struct PSep {
54 int operator()(const std::pair<T, int> &A) { return A.second; }
55};
56
63template <typename T> void indexSort(const std::vector<T> &pVec, std::vector<int> &Index) {
64 Index.resize(pVec.size());
65 std::vector<typename std::pair<T, int>> PartList;
66 PartList.resize(pVec.size());
67
68 transform(pVec.begin(), pVec.end(), PartList.begin(), PIndex<T>());
69 sort(PartList.begin(), PartList.end());
70 transform(PartList.begin(), PartList.end(), Index.begin(), PSep<T>());
71}
72template void indexSort(const std::vector<double> &, std::vector<int> &);
73template void indexSort(const std::vector<float> &, std::vector<int> &);
74template void indexSort(const std::vector<int> &, std::vector<int> &);
75} // namespace
77template <typename T> std::vector<T> Matrix<T>::getVector() const {
78 std::vector<T> rez(m_numRows * m_numColumns);
79 size_t ic(0);
80 for (size_t i = 0; i < m_numRows; i++) {
81 for (size_t j = 0; j < m_numColumns; j++) {
82 rez[ic] = m_rawData[i][j];
83 ic++;
84 }
85 }
86 return rez;
87}
88//
89template <typename T>
90Matrix<T>::Matrix(const size_t nrow, const size_t ncol, const bool makeIdentity)
91 : m_numRows(0), m_numColumns(0)
98{
99 // Note:: m_numRows, m_numColumns zeroed so setMem always works
100 setMem(nrow, ncol);
101 zeroMatrix();
102 if (makeIdentity)
105
106template <typename T>
107Matrix<T>::Matrix(const std::vector<T> &A, const std::vector<T> &B)
108 : m_numRows(0), m_numColumns(0)
116{
117 // Note:: m_numRows,m_numColumns zeroed so setMem always works
118 setMem(A.size(), B.size());
119 for (size_t i = 0; i < m_numRows; i++) {
120 for (size_t j = 0; j < m_numColumns; j++) {
121 m_rawData[i][j] = A[i] * B[j];
122 }
123 }
124}
126template <typename T> Matrix<T>::Matrix(const std::vector<T> &data) : m_numRows(0), m_numColumns(0) {
127 size_t numElements = data.size();
128 auto numRows = static_cast<size_t>(sqrt(double(numElements)));
129 size_t numRowsSquare = numRows * numRows;
130 if (numElements != numRowsSquare) {
131 throw(std::invalid_argument("number of elements in input vector have to be square of some value"));
133
136 size_t ic(0);
137 for (size_t i = 0; i < m_numRows; i++) {
138 for (size_t j = 0; j < m_numColumns; j++) {
139 m_rawData[i][j] = data[ic];
140 ic++;
141 }
142 }
143}
144
145template <typename T>
146Matrix<T>::Matrix(const std::vector<T> &data, const size_t nrow, const size_t ncol) : m_numRows(0), m_numColumns(0) {
147 size_t numel = data.size();
148 size_t test = nrow * ncol;
149 if (test != numel) {
150 throw(std::invalid_argument("number of elements in input vector have is "
151 "incompatible with the number of rows and "
152 "columns"));
154
155 setMem(nrow, ncol);
156
157 size_t ic(0);
158 for (size_t i = 0; i < m_numRows; i++) {
159 for (size_t j = 0; j < m_numColumns; j++) {
160 m_rawData[i][j] = data[ic];
161 ic++;
163 }
166template <typename T>
167Matrix<T>::Matrix(const Matrix<T> &A, const size_t nrow, const size_t ncol)
168 : m_numRows(A.m_numRows - 1), m_numColumns(A.m_numColumns - 1)
176 if (nrow > m_numRows)
177 throw Kernel::Exception::IndexError(nrow, A.m_numRows, "Matrix::Constructor without row");
178 if (ncol > m_numColumns)
179 throw Kernel::Exception::IndexError(ncol, A.m_numColumns, "Matrix::Constructor without col");
180 setMem(m_numRows, m_numColumns);
181 size_t iR(0);
182 for (size_t i = 0; i <= m_numRows; i++) {
183 if (i != nrow) {
184 size_t jR(0);
185 for (size_t j = 0; j <= m_numColumns; j++) {
186 if (j != ncol) {
187 m_rawData[iR][jR] = A.m_rawData[i][j];
188 jR++;
189 }
190 }
191 iR++;
192 }
193 }
194}
195
196template <typename T>
198 : m_numRows(0), m_numColumns(0)
203{
204 // Note:: m_numRows,m_numColumns zeroed so setMem always works
206 if ((m_numRows * m_numColumns) > 0) {
207 for (size_t i = 0; i < m_numRows; i++) {
208 for (size_t j = 0; j < m_numColumns; j++) {
209 m_rawData[i][j] = A.m_rawData[i][j];
210 }
211 }
212 }
213}
214
215template <typename T>
222{
223 if (&A != this) {
224 setMem(A.m_numRows, A.m_numColumns);
225 if ((m_numRows * m_numColumns) > 0) {
226 for (size_t i = 0; i < m_numRows; i++) {
227 for (size_t j = 0; j < m_numColumns; j++) {
228 m_rawData[i][j] = A.m_rawData[i][j];
229 }
230 }
231 }
232 }
233 return *this;
234}
235
236template <typename T>
238 : m_numRows(other.m_numRows), m_numColumns(other.m_numColumns), m_rawDataAlloc(std::move(other.m_rawDataAlloc)),
239 m_rawData(std::move(other.m_rawData)) {
240 other.m_numRows = 0;
241 other.m_numColumns = 0;
242}
243
244template <typename T> Matrix<T> &Matrix<T>::operator=(Matrix<T> &&other) noexcept {
245 m_numRows = other.m_numRows;
246 m_numColumns = other.m_numColumns;
247 m_rawData = std::move(other.m_rawData);
248 m_rawDataAlloc = std::move(other.m_rawDataAlloc);
249
250 other.m_numRows = 0;
251 other.m_numColumns = 0;
252
253 return *this;
254}
255
256template <typename T>
265{
266 const size_t Xpt((m_numRows > A.m_numRows) ? A.m_numRows : m_numRows);
267 const size_t Ypt((m_numColumns > A.m_numColumns) ? A.m_numColumns : m_numColumns);
268 for (size_t i = 0; i < Xpt; i++) {
269 for (size_t j = 0; j < Ypt; j++) {
270 m_rawData[i][j] += A.m_rawData[i][j];
271 }
272 }
273
274 return *this;
275}
276
277template <typename T>
286{
287 const size_t Xpt((m_numRows > A.m_numRows) ? A.m_numRows : m_numRows);
288 const size_t Ypt((m_numColumns > A.m_numColumns) ? A.m_numColumns : m_numColumns);
289 for (size_t i = 0; i < Xpt; i++) {
290 for (size_t j = 0; j < Ypt; j++) {
291 m_rawData[i][j] -= A.m_rawData[i][j];
292 }
293 }
294
295 return *this;
296}
297
298template <typename T>
307{
308 Matrix<T> X(*this);
309 return X += A;
310}
311
312template <typename T>
321{
322 Matrix<T> X(*this);
323 return X -= A;
324}
325
326template <typename T>
334{
335 if (m_numColumns != A.m_numRows)
336 throw Kernel::Exception::MisMatch<size_t>(m_numColumns, A.m_numRows, "Matrix::operator*(Matrix)");
337 Matrix<T> X(m_numRows, A.m_numColumns);
338 for (size_t i = 0; i < m_numRows; i++) {
339 for (size_t j = 0; j < A.m_numColumns; j++) {
340 for (size_t kk = 0; kk < m_numColumns; kk++) {
341 X.m_rawData[i][j] += m_rawData[i][kk] * A.m_rawData[kk][j];
342 }
343 }
344 }
345 return X;
346}
347
348template <typename T>
349std::vector<T> Matrix<T>::operator*(const std::vector<T> &Vec) const
356{
357 if (m_numColumns > Vec.size())
358 throw Kernel::Exception::MisMatch<size_t>(m_numColumns, Vec.size(), "Matrix::operator*(m_rawDataec)");
359
360 std::vector<T> Out(m_numRows);
361 for (size_t i = 0; i < m_numRows; i++) {
362 for (size_t j = 0; j < m_numColumns; j++) {
363 Out[i] += m_rawData[i][j] * Vec[j];
364 }
365 }
366 return Out;
367}
368
375template <typename T> void Matrix<T>::multiplyPoint(const std::vector<T> &in, std::vector<T> &out) const {
376 out.resize(m_numRows);
377 std::fill(std::begin(out), std::end(out), static_cast<T>(0.0));
378 if (m_numColumns > in.size())
379 throw Kernel::Exception::MisMatch<size_t>(m_numColumns, in.size(), "Matrix::multiplyPoint(in,out)");
380 for (size_t i = 0; i < m_numRows; i++) {
381 for (size_t j = 0; j < m_numColumns; j++) {
382 out[i] += m_rawData[i][j] * in[j];
383 }
384 }
385}
386
387template <typename T>
395{
396 if (m_numColumns != 3 || m_numRows > 3)
397 throw Kernel::Exception::MisMatch<size_t>(m_numColumns, 3, "Matrix::operator*(m_rawData3D)");
398
399 V3D v;
400 for (size_t i = 0; i < m_numRows; ++i) {
401 v[i] = m_rawData[i][0] * Vx.X() + m_rawData[i][1] * Vx.Y() + m_rawData[i][2] * Vx.Z();
402 }
403
404 return v;
405}
406
407template <typename T>
408Matrix<T> Matrix<T>::operator*(const T &Value) const
414{
415 Matrix<T> X(*this);
416 for (size_t i = 0; i < m_numRows; i++) {
417 for (size_t j = 0; j < m_numColumns; j++) {
418 X.m_rawData[i][j] *= Value;
419 }
420 }
421 return X;
422}
423
431template <typename T> Matrix<T> &Matrix<T>::operator*=(const Matrix<T> &A) {
432 if (m_numColumns != A.m_numRows)
433 throw Kernel::Exception::MisMatch<size_t>(m_numColumns, A.m_numRows, "Matrix*=(Matrix<T>)");
434 // This construct to avoid the problem of changing size
435 *this = this->operator*(A);
436 return *this;
437}
438
439template <typename T>
446{
447 for (size_t i = 0; i < m_numRows; i++) {
448 for (size_t j = 0; j < m_numColumns; j++) {
449 m_rawData[i][j] *= Value;
450 }
451 }
452 return *this;
453}
454
455template <typename T>
462{
463 for (size_t i = 0; i < m_numRows; i++) {
464 for (size_t j = 0; j < m_numColumns; j++) {
465 m_rawData[i][j] /= Value;
466 }
467 }
468 return *this;
469}
470
471template <typename T>
479{
480 return !(this->operator==(A));
481}
482
483template <typename T>
493{
494 return this->equals(A, 1e-8);
495}
496
497//---------------------------------------------------------------------------------------
498template <typename T>
499bool Matrix<T>::equals(const Matrix<T> &A, const double Tolerance) const
509{
510 if (&A != this) // this == A == always true
511 {
512 if (A.m_numRows != m_numRows || A.m_numColumns != m_numColumns)
513 return false;
514
515 double maxS(0.0);
516 double maxDiff(0.0); // max di
517 for (size_t i = 0; i < m_numRows; i++)
518 for (size_t j = 0; j < m_numColumns; j++) {
519 const T diff = (m_rawData[i][j] - A.m_rawData[i][j]);
520 if (std::isnan(static_cast<double>(diff))) {
521 maxDiff = std::numeric_limits<T>::max();
522 } else {
523 if (fabs(diff) > maxDiff)
524 maxDiff = fabs(diff);
525 }
526 if (fabs(m_rawData[i][j]) > maxS)
527 maxS = fabs(m_rawData[i][j]);
528 }
529 if (maxDiff < Tolerance)
530 return true;
531 if (maxS > 1.0 && (maxDiff / maxS) < Tolerance)
532 return true;
533 return false;
534 }
535 // this == this is true
536 return true;
537}
538
539//---------------------------------------------------------------------------------------
545template <typename T> bool Matrix<T>::operator<(const Matrix<T> &A) const {
546 if (&A == this) // this < A == always false
547 return false;
548
549 if (A.m_numRows != m_numRows || A.m_numColumns != m_numColumns)
550 return false;
551
552 for (size_t i = 0; i < m_numRows; i++)
553 for (size_t j = 0; j < m_numColumns; j++) {
554 if (m_rawData[i][j] >= A.m_rawData[i][j])
555 return false;
556 }
557 return true;
558}
559
560//---------------------------------------------------------------------------------------
566template <typename T> bool Matrix<T>::operator>=(const Matrix<T> &A) const {
567 if (&A == this)
568 return true;
569
570 if (A.m_numRows != m_numRows || A.m_numColumns != m_numColumns)
571 return false;
572
573 for (size_t i = 0; i < m_numRows; i++)
574 for (size_t j = 0; j < m_numColumns; j++) {
575 if (m_rawData[i][j] < A.m_rawData[i][j])
576 return false;
577 }
578 return true;
579}
580
586template <typename T> void Matrix<T>::setMem(const size_t a, const size_t b) {
587 if (a == m_numRows && b == m_numColumns && m_rawData != nullptr)
588 return;
589
590 if (a == 0 || b == 0)
591 return;
592
593 m_numRows = a;
594 m_numColumns = b;
595
596 // Allocate memory first - this has to be a flat 1d array masquerading as a 2d
597 // array so we can expose the memory to Python APIs via numpy which expects
598 // this
599 // style of memory layout.
600 auto allocatedMemory = std::make_unique<T[]>((m_numRows * m_numColumns));
601
602 // Next allocate an array of pointers for the rows (X). This partitions
603 // the 1D array into a 2D array for callers.
604 auto rowPtrs = std::make_unique<T *[]>(m_numRows);
605
606 for (size_t i = 0; i < m_numRows; i++) {
607 // Calculate offsets into the allocated memory array (Y)
608 rowPtrs[i] = &allocatedMemory[i * m_numColumns];
609 }
610
611 m_rawDataAlloc = std::move(allocatedMemory);
612 m_rawData = std::move(rowPtrs);
613}
614
620template <typename T> void Matrix<T>::swapRows(const size_t RowI, const size_t RowJ) {
621 if ((m_numRows * m_numColumns > 0) && RowI < m_numRows && RowJ < m_numRows && RowI != RowJ) {
622 for (size_t k = 0; k < m_numColumns; k++) {
623 T tmp = m_rawData[RowI][k];
624 m_rawData[RowI][k] = m_rawData[RowJ][k];
625 m_rawData[RowJ][k] = tmp;
626 }
627 }
628}
629
635template <typename T> void Matrix<T>::swapCols(const size_t colI, const size_t colJ) {
636 if ((m_numRows * m_numColumns) > 0 && colI < m_numColumns && colJ < m_numColumns && colI != colJ) {
637 for (size_t k = 0; k < m_numRows; k++) {
638 T tmp = m_rawData[k][colI];
639 m_rawData[k][colI] = m_rawData[k][colJ];
640 m_rawData[k][colJ] = tmp;
641 }
642 }
643}
644
645template <typename T>
650{
651 if ((m_numRows * m_numColumns) > 0) {
652 for (size_t i = 0; i < m_numRows; i++) {
653 for (size_t j = 0; j < m_numColumns; j++) {
654 m_rawData[i][j] = static_cast<T>(0);
655 }
656 }
657 }
658}
659
660template <typename T>
666{
667 if ((m_numRows * m_numColumns) > 0) {
668 for (size_t i = 0; i < m_numRows; i++) {
669 for (size_t j = 0; j < m_numColumns; j++) {
670 m_rawData[i][j] = static_cast<T>(j == i);
671 }
672 }
673 }
674}
675template <typename T> void Matrix<T>::setColumn(const size_t nCol, const std::vector<T> &newCol) {
676 if (nCol >= this->m_numColumns) {
677 throw(std::invalid_argument("nCol requested> nCol availible"));
678 }
679 size_t m_numRowsM = newCol.size();
680 if (m_numRows < m_numRowsM)
681 m_numRowsM = m_numRows;
682 for (size_t i = 0; i < m_numRowsM; i++) {
683 m_rawData[i][nCol] = newCol[i];
684 }
685}
686template <typename T> void Matrix<T>::setRow(const size_t nRow, const std::vector<T> &newRow) {
687 if (nRow >= this->m_numRows) {
688 throw(std::invalid_argument("nRow requested> nRow availible"));
689 }
690 size_t m_numColumnsM = newRow.size();
691 if (m_numColumns < m_numColumnsM)
692 m_numColumnsM = m_numColumns;
693 for (size_t j = 0; j < m_numColumnsM; j++) {
694 m_rawData[nRow][j] = newRow[j];
695 }
696}
697
698template <typename T>
699void Matrix<T>::rotate(const double tau, const double s, const int i, const int j, const int k, const int m)
711{
712 const T gg = m_rawData[i][j];
713 const T hh = m_rawData[k][m];
714 m_rawData[i][j] = static_cast<T>(gg - s * (hh + gg * tau));
715 m_rawData[k][m] = static_cast<T>(hh + s * (gg - hh * tau));
716}
717
718template <typename T>
719Matrix<T> Matrix<T>::preMultiplyByDiagonal(const std::vector<T> &Dvec) const
726{
727 if (Dvec.size() != m_numRows) {
728 std::ostringstream cx;
729 cx << "Matrix::preMultiplyByDiagonal Size: " << Dvec.size() << " " << m_numRows << " " << m_numColumns;
730 throw std::runtime_error(cx.str());
731 }
732 Matrix<T> X(Dvec.size(), m_numColumns);
733 for (size_t i = 0; i < Dvec.size(); i++) {
734 for (size_t j = 0; j < m_numColumns; j++) {
735 X.m_rawData[i][j] = Dvec[i] * m_rawData[i][j];
736 }
737 }
738 return X;
739}
740
741template <typename T>
742Matrix<T> Matrix<T>::postMultiplyByDiagonal(const std::vector<T> &Dvec) const
749{
750 if (Dvec.size() != m_numColumns) {
751 std::ostringstream cx;
752 cx << "Error Matrix::bDiaognal size:: " << Dvec.size() << " " << m_numRows << " " << m_numColumns;
753 throw std::runtime_error(cx.str());
754 }
755
756 Matrix<T> X(m_numRows, Dvec.size());
757 for (size_t i = 0; i < m_numRows; i++) {
758 for (size_t j = 0; j < Dvec.size(); j++) {
759 X.m_rawData[i][j] = Dvec[j] * m_rawData[i][j];
760 }
761 }
762 return X;
763}
764
765template <typename T>
772{
773 if ((m_numRows * m_numColumns) == 0)
774 return *this;
775
776 if (m_numRows == m_numColumns) // inplace transpose
777 {
778 Matrix<T> MT(*this);
779 MT.Transpose();
780 return MT;
781 }
782
783 // irregular matrix
784 Matrix<T> MT(m_numColumns, m_numRows);
785 for (size_t i = 0; i < m_numRows; i++)
786 for (size_t j = 0; j < m_numColumns; j++)
787 MT.m_rawData[j][i] = m_rawData[i][j];
788
789 return MT;
790}
791
792template <typename T>
799{
800 if ((m_numRows * m_numColumns) == 0)
801 return *this;
802
803 if (m_numRows == m_numColumns) // in place transpose
804 {
805 for (size_t i = 0; i < m_numRows; i++) {
806 for (size_t j = i + 1; j < m_numColumns; j++) {
807 std::swap(m_rawData[i][j], m_rawData[j][i]);
808 }
809 }
810 return *this;
811 }
812
813 // irregular matrix
814 // get some memory
815
816 auto allocatedMemory = std::make_unique<T[]>((m_numRows * m_numColumns));
817 auto transposePtrs = std::make_unique<T *[]>(m_numRows);
818
819 for (size_t i = 0; i < m_numColumns; i++) {
820 // Notice how this partitions using Rows (X) instead of Cols(Y)
821 transposePtrs[i] = &allocatedMemory[i * m_numRows];
822 }
823
824 for (size_t i = 0; i < m_numRows; i++) {
825 for (size_t j = 0; j < m_numColumns; j++) {
826 transposePtrs[j][i] = m_rawData[i][j];
827 }
828 }
829 // remove old memory
830 std::swap(m_numRows, m_numColumns);
831
832 m_rawDataAlloc = std::move(allocatedMemory);
833 m_rawData = std::move(transposePtrs);
834
835 return *this;
836}
837template <typename T>
847{
848 // check for input errors
849 if (m_numRows != m_numColumns || B.m_numRows != m_numRows) {
850 throw std::invalid_argument("Matrix not square, or sizes do not match");
851 }
852
853 // pivoted rows
854 std::vector<int> pivoted(m_numRows);
855 fill(pivoted.begin(), pivoted.end(), 0);
856
857 std::vector<int> indxcol(m_numRows); // Column index
858 std::vector<int> indxrow(m_numRows); // row index
859
860 size_t irow(0), icol(0);
861 for (size_t i = 0; i < m_numRows; i++) {
862 // Get Biggest non-pivoted item
863 double bigItem = 0.0; // get point to pivot over
864 for (size_t j = 0; j < m_numRows; j++) {
865 if (pivoted[j] != 1) // check only non-pivots
866 {
867 for (size_t k = 0; k < m_numRows; k++) {
868 if (!pivoted[k]) {
869 if (fabs(m_rawData[j][k]) >= bigItem) {
870 bigItem = fabs(m_rawData[j][k]);
871 irow = j;
872 icol = k;
873 }
874 }
875 }
876 }
877 }
878 pivoted[icol]++;
879 // Swap in row/col to make a diagonal item
880 if (irow != icol) {
881 swapRows(irow, icol);
882 B.swapRows(irow, icol);
883 }
884 indxrow[i] = static_cast<int>(irow);
885 indxcol[i] = static_cast<int>(icol);
886
887 if (m_rawData[icol][icol] == 0.0) {
888 throw std::runtime_error("Error doing G-J elem on a singular matrix");
889 }
890 const T pivDiv = T(1.0) / m_rawData[icol][icol];
891 m_rawData[icol][icol] = 1;
892 for (size_t l = 0; l < m_numRows; l++) {
893 m_rawData[icol][l] *= pivDiv;
894 }
895 for (size_t l = 0; l < B.m_numColumns; l++) {
896 B.m_rawData[icol][l] *= pivDiv;
897 }
898
899 for (size_t ll = 0; ll < m_numRows; ll++) {
900 if (ll != icol) {
901 const T div_num = m_rawData[ll][icol];
902 m_rawData[ll][icol] = 0.0;
903 for (size_t l = 0; l < m_numRows; l++) {
904 m_rawData[ll][l] -= m_rawData[icol][l] * div_num;
905 }
906 for (size_t l = 0; l < B.m_numColumns; l++) {
907 B.m_rawData[ll][l] -= B.m_rawData[icol][l] * div_num;
908 }
909 }
910 }
911 }
912
913 // Un-roll interchanges
914 if (m_numRows > 0) {
915 for (int l = static_cast<int>(m_numRows) - 1; l >= 0; l--) {
916 if (indxrow[l] != indxcol[l]) {
917 swapCols(indxrow[l], indxcol[l]);
918 }
919 }
920 }
921}
922
923template <typename T>
930{
931 if (m_numRows != m_numColumns && m_numRows < 1)
932 return 0;
933
934 if (m_numRows == 1) {
935 T det = m_rawData[0][0];
936 if (m_rawData[0][0] != static_cast<T>(0.))
937 m_rawData[0][0] = static_cast<T>(1.) / m_rawData[0][0];
938 return det;
939 }
940 std::vector<int> indx(m_numRows); // Set in lubcmp
941 std::vector<double> col(m_numRows);
942
943 int determinant = 0;
944 Matrix<T> Lcomp(*this);
945 Lcomp.lubcmp(indx.data(), determinant);
946
947 auto det = static_cast<double>(determinant);
948 for (size_t j = 0; j < m_numRows; j++)
949 det *= Lcomp.m_rawData[j][j];
950
951 for (size_t j = 0; j < m_numRows; j++) {
952 for (size_t i = 0; i < m_numRows; i++)
953 col[i] = 0.0;
954 col[j] = 1.0;
955 Lcomp.lubksb(indx.data(), col.data());
956 for (size_t i = 0; i < m_numRows; i++)
957 m_rawData[i][j] = static_cast<T>(col[i]);
958 }
959 return static_cast<T>(det);
960}
961
962template <typename T>
968{
969 bool regular = true;
970 if ((numRows() > 1) && (numCols() > 1)) {
971 if (numRows() == numCols()) {
972 std::vector<T> diagonal = {m_rawData[0][0], m_rawData[1][0]};
973 for (size_t i = 1; i < numRows() && regular; i++) {
974 for (size_t j = 1; i < numCols() && regular; i++) {
975 size_t diff = std::abs(static_cast<int>(i - j));
976 if (diff < 2) {
977 if (std::abs(diagonal[diff] - m_rawData[i][j]) > std::numeric_limits<double>::epsilon()) {
978 regular = false;
979 }
980 } else if (m_rawData[i][j] != 0) {
981 throw std::runtime_error("Matrix is not tridiagonal");
982 }
983 }
984 }
985 } else {
986 regular = false;
987 }
988 }
989 if (regular) {
990 // use analytic expression as described in G Y Hu and R F O'Connell (1996)
991 T scalefactor = numRows() > 1 ? m_rawData[1][0] : 1;
992 *this /= scalefactor;
993 long double D = m_rawData[0][0];
994 long double k = static_cast<long double>(numRows());
995
996 for (size_t i = 0; i < numRows(); i++) {
997 for (size_t j = 0; j < numCols(); j++) {
998 long double lambda;
999 auto iMinusj = std::abs(static_cast<long double>(i) - static_cast<long double>(j));
1000 auto iPlusj = static_cast<long double>(i + j);
1001 if (D >= 2) {
1002 m_rawData[i][j] = static_cast<T>(std::pow(-1.0, iPlusj));
1003 lambda = std::acosh(D / 2.0);
1004 } else if (D > -2.0) {
1005 m_rawData[i][j] = 1; // use +1 here instead of the -1 in the paper
1006 lambda = std::acos(-D / 2.0); // extra minus sign here compared to paper
1007 } else {
1008 m_rawData[i][j] = -1;
1009 lambda = std::acosh(-D / 2.0);
1010 }
1011 if (std::abs(D) > 2.0) {
1012 long double a, b, c;
1013 if (((k + 1) * std::asinh(D / 2.0)) <= std::asinh(std::numeric_limits<long double>::max())) {
1014 a = std::cosh((k + 1 - iMinusj) * lambda);
1015 b = std::cosh((k + 1 - iPlusj - 2) * lambda); // extra -2 because i and j are 1-based in the paper
1016 c = 2 * std::sinh(lambda) * std::sinh((k + 1) * lambda);
1017 } else {
1018 // cosh, sinh overflow for x~>710 so use approximation based on expansion of cosh, sinh into e^x and e^-x
1019 a = std::exp(-iMinusj * lambda);
1020 b = std::exp(-(iPlusj + 2) * lambda) + std::exp(-(2 * k - iPlusj) * lambda);
1021 c = 2 * std::sinh(lambda);
1022 }
1023
1024 long double value = m_rawData[i][j];
1025 value *= (a - b) / c;
1026 m_rawData[i][j] = static_cast<T>(value);
1027 } else if (std::abs(D) == 2.0) {
1028 long double value = m_rawData[i][j];
1029 value *= (2 * k + 2 - iMinusj - iPlusj - 2) * (iPlusj + 2 - iMinusj);
1030 value /= (4 * (k + 1));
1031 m_rawData[i][j] = static_cast<T>(value);
1032 } else {
1033 long double value = m_rawData[i][j];
1034 value *= std::cos((k + 1 - iMinusj) * lambda) -
1035 std::cos((k + 1 - iPlusj - 2) * lambda); // extra -2 because i and j are 1-based in the paper
1036 value /= 2 * std::sin(lambda) * std::sin((k + 1) * lambda);
1037 m_rawData[i][j] = static_cast<T>(value);
1038 }
1039 }
1040 }
1041 *this /= scalefactor;
1042 } else {
1043 Invert();
1044 }
1045}
1046
1047template <typename T>
1053{
1054 if (m_numRows != m_numColumns)
1055 throw Kernel::Exception::MisMatch<size_t>(m_numRows, m_numColumns, "Determinant error :: Matrix is not square");
1056
1057 Matrix<T> Mt(*this); // temp copy
1058 T D = Mt.factor();
1059 return D;
1060}
1061
1062template <typename T>
1070{
1071 if (m_numRows != m_numColumns || m_numRows < 1)
1072 throw std::runtime_error("Matrix::factor Matrix is not square");
1073
1074 double deter = 1.0;
1075 for (int i = 0; i < static_cast<int>(m_numRows) - 1; i++) // loop over each row
1076 {
1077 int jmax = i;
1078 double Pmax = fabs(m_rawData[i][i]);
1079 for (int j = i + 1; j < static_cast<int>(m_numRows); j++) // find max in Row i
1080 {
1081 if (fabs(m_rawData[i][j]) > Pmax) {
1082 Pmax = fabs(m_rawData[i][j]);
1083 jmax = j;
1084 }
1085 }
1086 if (Pmax < 1e-8) // maxtrix signular
1087 {
1088 // std::cerr<<"Matrix Singular"<<'\n';
1089 return 0;
1090 }
1091 // Swap Columns
1092 if (i != jmax) {
1093 swapCols(i, jmax);
1094 deter *= -1; // change sign.
1095 }
1096 // zero all rows below diagonal
1097 Pmax = m_rawData[i][i];
1098 deter *= Pmax;
1099 for (int k = i + 1; k < static_cast<int>(m_numRows); k++) // row index
1100 {
1101 const double scale = m_rawData[k][i] / Pmax;
1102 m_rawData[k][i] = static_cast<T>(0);
1103 for (int q = i + 1; q < static_cast<int>(m_numRows); q++) // column index
1104 m_rawData[k][q] -= static_cast<T>(scale * m_rawData[i][q]);
1105 }
1106 }
1107 deter *= m_rawData[m_numRows - 1][m_numRows - 1];
1108 return static_cast<T>(deter);
1109}
1110
1111template <typename T>
1117{
1118 for (size_t i = 0; i < m_numRows; i++) {
1119 T sum = 0;
1120 for (size_t j = 0; j < m_numColumns; j++) {
1121 sum += m_rawData[i][j] * m_rawData[i][j];
1122 }
1123 sum = static_cast<T>(std::sqrt(static_cast<double>(sum)));
1124 for (size_t j = 0; j < m_numColumns; j++) {
1125 m_rawData[i][j] /= sum;
1126 }
1127 }
1128}
1129
1130template <typename T>
1136{
1137 T sum(0);
1138 for (size_t i = 0; i < m_numRows; i++) {
1139 for (size_t j = 0; j < m_numColumns; j++) {
1140 sum += m_rawData[i][j] * m_rawData[i][j];
1141 }
1142 }
1143 return sum;
1144}
1145
1146template <typename T>
1147void Matrix<T>::lubcmp(int *rowperm, int &interchange)
1154{
1155 double sum, dum, big, temp;
1156
1157 if (m_numRows != m_numColumns || m_numRows < 2) {
1158 std::cerr << "Error with lubcmp\n";
1159 return;
1160 }
1161 std::vector<double> result(m_numRows);
1162 interchange = 1;
1163 for (int i = 0; i < static_cast<int>(m_numRows); i++) {
1164 big = 0.0;
1165 for (int j = 0; j < static_cast<int>(m_numRows); j++)
1166 if ((temp = fabs(m_rawData[i][j])) > big)
1167 big = temp;
1168
1169 if (big == 0.0) {
1170 for (int j = 0; j < static_cast<int>(m_numRows); j++) {
1171 rowperm[j] = j;
1172 }
1173 return;
1174 }
1175 result[i] = 1.0 / big;
1176 }
1177
1178 for (int j = 0; j < static_cast<int>(m_numRows); j++) {
1179 for (int i = 0; i < j; i++) {
1180 sum = m_rawData[i][j];
1181 for (int k = 0; k < i; k++)
1182 sum -= m_rawData[i][k] * m_rawData[k][j];
1183 m_rawData[i][j] = static_cast<T>(sum);
1184 }
1185 big = 0.0;
1186 int imax = j;
1187 for (int i = j; i < static_cast<int>(m_numRows); i++) {
1188 sum = m_rawData[i][j];
1189 for (int k = 0; k < j; k++)
1190 sum -= m_rawData[i][k] * m_rawData[k][j];
1191 m_rawData[i][j] = static_cast<T>(sum);
1192 if ((dum = result[i] * fabs(sum)) >= big) {
1193 big = dum;
1194 imax = i;
1195 }
1196 }
1197
1198 if (j != imax) {
1199 for (int k = 0; k < static_cast<int>(m_numRows); k++) { // Interchange rows
1200 dum = m_rawData[imax][k];
1201 m_rawData[imax][k] = m_rawData[j][k];
1202 m_rawData[j][k] = static_cast<T>(dum);
1203 }
1204 interchange *= -1;
1205 result[imax] = static_cast<T>(result[j]);
1206 }
1207 rowperm[j] = imax;
1208
1209 if (m_rawData[j][j] == 0.0)
1210 m_rawData[j][j] = static_cast<T>(1e-14);
1211 if (j != static_cast<int>(m_numRows) - 1) {
1212 dum = 1.0 / (m_rawData[j][j]);
1213 for (int i = j + 1; i < static_cast<int>(m_numRows); i++)
1214 m_rawData[i][j] *= static_cast<T>(dum);
1215 }
1216 }
1217}
1218
1219template <typename T>
1220void Matrix<T>::lubksb(const int *rowperm, double *b)
1225{
1226 int ii = -1;
1227
1228 for (int i = 0; i < static_cast<int>(m_numRows); i++) {
1229 int ip = rowperm[i];
1230 double sum = b[ip];
1231 b[ip] = b[i];
1232 if (ii != -1)
1233 for (int j = ii; j < i; j++)
1234 sum -= m_rawData[i][j] * b[j];
1235 else if (sum != 0.)
1236 ii = i;
1237 b[i] = sum;
1238 }
1239
1240 for (int i = static_cast<int>(m_numRows) - 1; i >= 0; i--) {
1241 double sum = b[i];
1242 for (int j = i + 1; j < static_cast<int>(m_numRows); j++)
1243 sum -= m_rawData[i][j] * b[j];
1244 b[i] = sum / m_rawData[i][i];
1245 }
1246}
1247
1248template <typename T>
1254{
1255 const size_t minSize = (m_numRows > m_numColumns) ? m_numColumns : m_numRows;
1256 for (size_t i = 0; i < minSize; i++) {
1257 for (size_t j = i + 1; j < minSize; j++) {
1258 m_rawData[i][j] = (m_rawData[i][j] + m_rawData[j][i]) / 2;
1259 m_rawData[j][i] = m_rawData[i][j];
1260 }
1261 }
1262}
1263
1264template <typename T>
1265std::vector<T> Matrix<T>::Diagonal() const
1270{
1271 const size_t Msize = (m_numColumns > m_numRows) ? m_numRows : m_numColumns;
1272 std::vector<T> Diag(Msize);
1273 for (size_t i = 0; i < Msize; i++) {
1274 Diag[i] = m_rawData[i][i];
1275 }
1276 return Diag;
1277}
1278
1279template <typename T>
1285{
1286 const size_t Msize = (m_numColumns > m_numRows) ? m_numRows : m_numColumns;
1287 T Trx = 0;
1288 for (size_t i = 0; i < Msize; i++) {
1289 Trx += m_rawData[i][i];
1290 }
1291 return Trx;
1292}
1293
1294template <typename T>
1301{
1302 if (m_numColumns != m_numRows || m_numRows != DiagMatrix.m_numRows || m_numRows != DiagMatrix.m_numColumns) {
1303 std::cerr << "Matrix not Eigen Form\n";
1304 throw(std::invalid_argument(" Matrix is not in an eigenvalue format"));
1305 }
1306 std::vector<int> index;
1307 std::vector<T> X = DiagMatrix.Diagonal();
1308 indexSort(X, index);
1309 Matrix<T> EigenVec(*this);
1310 for (size_t Icol = 0; Icol < m_numRows; Icol++) {
1311 for (size_t j = 0; j < m_numRows; j++) {
1312 m_rawData[j][Icol] = EigenVec[j][index[Icol]];
1313 }
1314 DiagMatrix[Icol][Icol] = X[index[Icol]];
1315 }
1316}
1317
1318template <typename T>
1319int Matrix<T>::Diagonalise(Matrix<T> &EigenVec, Matrix<T> &DiagMatrix) const
1326{
1327 if (m_numRows != m_numColumns || m_numRows < 1) {
1328 std::cerr << "Matrix not square\n";
1329 return 0;
1330 }
1331 for (size_t i = 0; i < m_numRows; i++)
1332 for (size_t j = i + 1; j < m_numRows; j++)
1333 if (fabs(m_rawData[i][j] - m_rawData[j][i]) > 1e-6) {
1334 std::cerr << "Matrix not symmetric\n";
1335 std::cerr << (*this);
1336 return 0;
1337 }
1338
1339 Matrix<T> A(*this);
1340 // Make V an identity matrix
1341 EigenVec.setMem(m_numRows, m_numRows);
1342 EigenVec.identityMatrix();
1343 DiagMatrix.setMem(m_numRows, m_numRows);
1344 DiagMatrix.zeroMatrix();
1345
1346 std::vector<double> Diag(m_numRows);
1347 std::vector<double> B(m_numRows);
1348 std::vector<double> ZeroComp(m_numRows);
1349 // set b and d to the diagonal elements o A
1350 for (size_t i = 0; i < m_numRows; i++) {
1351 Diag[i] = B[i] = A.m_rawData[i][i];
1352 ZeroComp[i] = 0;
1353 }
1354
1355 int iteration = 0;
1356 for (int i = 0; i < 100; i++) // max 50 iterations
1357 {
1358 double sm = 0.0; // sum of off-diagonal terms
1359 for (size_t ip = 0; ip < m_numRows - 1; ip++)
1360 for (size_t iq = ip + 1; iq < m_numRows; iq++)
1361 sm += fabs(A.m_rawData[ip][iq]);
1362
1363 if (sm == 0.0) // Nothing to do return...
1364 {
1365 // Make OUTPUT -- D + A
1366 // sort Output::
1367 for (size_t ix = 0; ix < m_numRows; ix++)
1368 DiagMatrix.m_rawData[ix][ix] = static_cast<T>(Diag[ix]);
1369 return 1;
1370 }
1371
1372 // Threshold large for first 5 sweeps
1373 double tresh = (i < 6) ? 0.2 * sm / static_cast<int>(m_numRows * m_numRows) : 0.0;
1374
1375 for (int ip = 0; ip < static_cast<int>(m_numRows) - 1; ip++) {
1376 for (int iq = ip + 1; iq < static_cast<int>(m_numRows); iq++) {
1377 double g = 100.0 * fabs(A.m_rawData[ip][iq]);
1378 // After 4 sweeps skip if off diagonal small
1379 if (i > 6 && static_cast<float>(fabs(Diag[ip] + g)) == static_cast<float>(fabs(Diag[ip])) &&
1380 static_cast<float>(fabs(Diag[iq] + g)) == static_cast<float>(fabs(Diag[iq])))
1381 A.m_rawData[ip][iq] = 0;
1382
1383 else if (fabs(A.m_rawData[ip][iq]) > tresh) {
1384 double tanAngle, cosAngle, sinAngle;
1385 double h = Diag[iq] - Diag[ip];
1386 double cot2Theta = 0.5 * h / A.m_rawData[ip][iq];
1387 // tanAngle formula well behaved even if cot2Theta is inf
1388 tanAngle = 1.0 / (fabs(cot2Theta) + sqrt(1.0 + pow(cot2Theta, 2)));
1389 if (cot2Theta < 0.0)
1390 tanAngle = -tanAngle;
1391 cosAngle = 1.0 / sqrt(1 + tanAngle * tanAngle);
1392 sinAngle = tanAngle * cosAngle;
1393 double tau = sinAngle / (1.0 + cosAngle);
1394 h = tanAngle * A.m_rawData[ip][iq];
1395 ZeroComp[ip] -= h;
1396 ZeroComp[iq] += h;
1397 Diag[ip] -= h;
1398 Diag[iq] += h;
1399 A.m_rawData[ip][iq] = 0;
1400 // Rotations 0<j<p
1401 for (int j = 0; j < ip; j++)
1402 A.rotate(tau, sinAngle, j, ip, j, iq);
1403 for (int j = ip + 1; j < iq; j++)
1404 A.rotate(tau, sinAngle, ip, j, j, iq);
1405 for (int j = iq + 1; j < static_cast<int>(m_numRows); j++)
1406 A.rotate(tau, sinAngle, ip, j, iq, j);
1407 for (int j = 0; j < static_cast<int>(m_numRows); j++)
1408 EigenVec.rotate(tau, sinAngle, j, ip, j, iq);
1409 iteration++;
1410 }
1411 }
1412 }
1413 for (size_t j = 0; j < m_numRows; j++) {
1414 B[j] += ZeroComp[j];
1415 Diag[j] = B[j];
1416 ZeroComp[j] = 0.0;
1417 }
1418 }
1419 std::cerr << "Error :: Iterations are a problem\n";
1420 return 0;
1421}
1422
1423template <typename T>
1428{
1429 if (this->m_numRows != this->m_numColumns)
1430 throw(std::invalid_argument("matrix is not square"));
1431 // std::cout << "Matrix determinant-1 is " << (this->determinant()-1) <<
1432 // '\n';
1433 if (fabs(this->determinant() - 1) > 1e-5) {
1434 return false;
1435 } else {
1436 Matrix<T> prod(m_numRows, m_numColumns), ident(m_numRows, m_numColumns, true);
1437 prod = this->operator*(this->Tprime());
1438 // std::cout << "Matrix * Matrix' = " << std::endl << prod << '\n';
1439 return prod.equals(ident, 1e-5);
1440 }
1441}
1442
1443template <typename T>
1449{
1450 if (this->m_numRows != this->m_numColumns)
1451 throw(std::invalid_argument("matrix is not square"));
1452 if (fabs(fabs(this->determinant()) - 1.) > 1e-5) {
1453 return false;
1454 } else {
1455 Matrix<T> prod(m_numRows, m_numColumns), ident(m_numRows, m_numColumns, true);
1456 prod = this->operator*(this->Tprime());
1457 return prod.equals(ident, 1e-7);
1458 }
1459}
1460
1461template <typename T>
1469{
1470 if (this->m_numRows != this->m_numColumns)
1471 throw(std::invalid_argument("matrix is not square"));
1472 if (fabs(this->determinant()) < 1e-10)
1473 throw(std::invalid_argument("Determinant is too small"));
1474 // step 1: orthogonalize the matrix
1475 for (size_t i = 0; i < this->m_numColumns; ++i) {
1476 double spself = 0.;
1477 for (size_t j = 0; j < this->m_numRows; ++j)
1478 spself += (m_rawData[j][i] * m_rawData[j][i]);
1479 for (size_t k = i + 1; k < this->m_numColumns; ++k) {
1480 double spother = 0;
1481 for (size_t j = 0; j < this->m_numRows; ++j)
1482 spother += (m_rawData[j][i] * m_rawData[j][k]);
1483 for (size_t j = 0; j < this->m_numRows; ++j)
1484 m_rawData[j][k] -= static_cast<T>(m_rawData[j][i] * spother / spself);
1485 }
1486 }
1487 // step 2: get scales and rescsale the matrix
1488 std::vector<T> scale(this->m_numRows);
1489 for (size_t i = 0; i < this->m_numColumns; ++i) {
1490 T currentScale{0};
1491 for (size_t j = 0; j < this->m_numRows; ++j)
1492 currentScale += (m_rawData[j][i] * m_rawData[j][i]);
1493 currentScale = static_cast<T>(sqrt(static_cast<double>(currentScale)));
1494 if (currentScale < 1e-10)
1495 throw(std::invalid_argument("Scale is too small"));
1496 scale[i] = currentScale;
1497 }
1498 Matrix<T> scalingMatrix(m_numRows, m_numColumns), change(m_numRows, m_numColumns, true);
1499 for (size_t i = 0; i < this->m_numColumns; ++i)
1500 scalingMatrix[i][i] = static_cast<T>(1.0 / scale[i]);
1501 *this = this->operator*(scalingMatrix);
1502 if (this->determinant() < 0.) {
1503 scale[0] = -scale[0];
1504 change[0][0] = static_cast<T>(-1);
1505 *this = this->operator*(change);
1506 }
1507 return scale;
1508}
1509
1510template <typename T>
1515{
1516 write(std::cout, 10);
1517}
1518
1520template <typename T> void Matrix<T>::setRandom(size_t seed, double rMin, double rMax) {
1521 MersenneTwister rng(seed, rMin, rMax);
1522
1523 for (size_t i = 0; i < m_numRows; i++) {
1524 for (size_t j = 0; j < m_numColumns; j++) {
1525 m_rawData[i][j] = static_cast<T>(rng.nextValue());
1526 }
1527 }
1528}
1529
1530template <typename T>
1531void Matrix<T>::write(std::ostream &Fh, const int blockCnt) const
1537{
1538 std::ios::fmtflags oldFlags = Fh.flags();
1539 Fh.setf(std::ios::floatfield, std::ios::scientific);
1540 const size_t blockNumber((blockCnt > 0) ? blockCnt : m_numColumns);
1541 size_t BCnt(0);
1542 do {
1543 const size_t ACnt = BCnt;
1544 BCnt += blockNumber;
1545 if (BCnt > m_numColumns) {
1546 BCnt = m_numColumns;
1547 }
1548
1549 if (ACnt) {
1550 Fh << " ----- " << ACnt << " " << BCnt << " ------ \n";
1551 }
1552 for (size_t i = 0; i < m_numRows; i++) {
1553 for (size_t j = ACnt; j < BCnt; j++) {
1554 Fh << std::setw(10) << m_rawData[i][j] << " ";
1555 }
1556 Fh << '\n';
1557 }
1558 } while (BCnt < m_numColumns);
1559
1560 Fh.flags(oldFlags);
1561}
1562
1563template <typename T>
1564std::string Matrix<T>::str() const
1569{
1570 std::ostringstream cx;
1571 for (size_t i = 0; i < m_numRows; i++) {
1572 for (size_t j = 0; j < m_numColumns; j++) {
1573 cx << std::setprecision(6) << m_rawData[i][j] << " ";
1574 }
1575 }
1576 return cx.str();
1577}
1578
1586template <typename T> std::ostream &operator<<(std::ostream &os, const Matrix<T> &matrix) {
1587 dumpToStream(os, matrix, ',');
1588 return os;
1589}
1590
1598template <typename T> void dumpToStream(std::ostream &os, const Kernel::Matrix<T> &matrix, const char delimiter) {
1599 size_t nrows(matrix.numRows()), ncols(matrix.numCols());
1600 os << "Matrix(" << nrows << delimiter << ncols << ")";
1601 for (size_t i = 0; i < nrows; ++i) {
1602 for (size_t j = 0; j < ncols; ++j) {
1603 os << matrix[i][j];
1604 if (i < nrows - 1 || j < ncols - 1)
1605 os << delimiter;
1606 }
1607 }
1608}
1609
1617template <typename T> std::istream &operator>>(std::istream &is, Kernel::Matrix<T> &in) {
1618 fillFromStream(is, in, ',');
1619 return is;
1620}
1621
1630template <typename T> void fillFromStream(std::istream &is, Kernel::Matrix<T> &in, const char delimiter) {
1631 // Stream should start with Matrix(
1632 char dump;
1633 std::string start(7, ' ');
1634 for (int i = 0; i < 7; ++i) {
1635 is >> dump;
1636 start[i] = dump;
1637 if (!is)
1638 throw std::invalid_argument("Unexpected character when reading Matrix from stream.");
1639 }
1640 if (start != "Matrix(")
1641 throw std::invalid_argument("Incorrect input format for Matrix stream.");
1642 // Now read a nrows,ncols and )
1643 size_t nrows(0), ncols(0);
1644 is >> nrows;
1645 if (!is)
1646 throw std::invalid_argument("Expected number of rows when reading Matrix "
1647 "from stream, found something else.");
1648 is >> dump;
1649 is >> ncols;
1650 if (!is)
1651 throw std::invalid_argument("Expected number of columns when reading "
1652 "Matrix from stream, found something else.");
1653 is >> dump;
1654 if (dump != ')')
1655 throw std::invalid_argument("Expected closing parenthesis after ncols when "
1656 "reading Matrix from stream, found something "
1657 "else.");
1658
1659 // Resize the matrix
1660 in.setMem(nrows, ncols);
1661
1662 // Use getline with the delimiter set to "," to read
1663 std::string value_str;
1664 size_t row(0), col(0);
1665 while (!is.eof() && std::getline(is, value_str, delimiter)) {
1666 try {
1667 auto value = boost::lexical_cast<T>(value_str);
1668 in.m_rawData[row][col] = value;
1669 } catch (boost::bad_lexical_cast &) {
1670 throw std::invalid_argument("Unexpected type found while reading Matrix from stream: \"" + value_str + "\"");
1671 }
1672 ++col;
1673 if (col == ncols) // New row
1674 {
1675 col = 0;
1676 ++row;
1677 }
1678 }
1679}
1680
1682
1683// Explicit instatiations. Avoid duplicate symbol definitions in
1684// client libraries. This must match the explicit declaration list
1685// in the header. MSVC/gcc differ in whether these symbols need to be
1686// marked as exported
1687#if defined(_MSC_VER)
1688#define KERNEL_MATRIX_SYMBOL_DLL MANTID_KERNEL_DLL
1689#else
1690#define KERNEL_MATRIX_SYMBOL_DLL
1691#endif
1692template class KERNEL_MATRIX_SYMBOL_DLL Matrix<double>;
1693template class KERNEL_MATRIX_SYMBOL_DLL Matrix<int>;
1694template class KERNEL_MATRIX_SYMBOL_DLL Matrix<float>;
1695
1696template MANTID_KERNEL_DLL std::ostream &operator<<(std::ostream &, const DblMatrix &);
1697template MANTID_KERNEL_DLL void dumpToStream(std::ostream &, const DblMatrix &, const char);
1698template MANTID_KERNEL_DLL std::istream &operator>>(std::istream &, DblMatrix &);
1699template MANTID_KERNEL_DLL void fillFromStream(std::istream &, DblMatrix &, const char);
1700
1701template MANTID_KERNEL_DLL std::ostream &operator<<(std::ostream &, const Matrix<float> &);
1702template MANTID_KERNEL_DLL void dumpToStream(std::ostream &, const Matrix<float> &, const char);
1703template MANTID_KERNEL_DLL std::istream &operator>>(std::istream &, Matrix<float> &);
1704template MANTID_KERNEL_DLL void fillFromStream(std::istream &, Matrix<float> &, const char);
1705
1706template MANTID_KERNEL_DLL std::ostream &operator<<(std::ostream &, const IntMatrix &);
1707template MANTID_KERNEL_DLL void dumpToStream(std::ostream &, const IntMatrix &, const char);
1708template MANTID_KERNEL_DLL std::istream &operator>>(std::istream &, IntMatrix &);
1709template MANTID_KERNEL_DLL void fillFromStream(std::istream &, IntMatrix &, const char);
1711
1712} // namespace Mantid::Kernel
const std::vector< double > * lambda
gsl_vector * tmp
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define fabs(x)
Definition: Matrix.cpp:22
int count
counter
Definition: Matrix.cpp:37
Exception for index errors.
Definition: Exception.h:284
Error when two numbers should be identical (or close)
Definition: Exception.h:263
Numerical Matrix class.
Definition: Matrix.h:42
T determinant() const
Calculate the determinant.
Definition: Matrix.cpp:1048
T Invert()
LU inversion routine.
Definition: Matrix.cpp:924
std::vector< T > toRotation()
Transform the matrix to a rotation matrix, by normalizing each column to 1.
Definition: Matrix.cpp:1462
Matrix(const size_t nrow=0, const size_t ncol=0, bool const makeIdentity=false)
Constructor with pre-set sizes.
Definition: Matrix.cpp:90
bool operator<(const Matrix< T > &) const
Element by element comparison of < Always returns false if the Matrix have different sizes.
Definition: Matrix.cpp:545
Matrix< T > operator-(const Matrix< T > &) const
Basic subtraction operator.
Definition: Matrix.cpp:313
void zeroMatrix()
Set the matrix to zero.
Definition: Matrix.cpp:646
void sortEigen(Matrix< T > &)
Sort eigenvectors.
Definition: Matrix.cpp:1295
Matrix< T > & operator+=(const Matrix< T > &)
Basic addition operator.
Definition: Matrix.cpp:257
void multiplyPoint(const std::vector< T > &in, std::vector< T > &out) const
Multiply M*Vec.
Definition: Matrix.cpp:375
void invertTridiagonal()
Check it's a square tridiagonal matrix with all diagonal elements equal and if yes invert the matrix ...
Definition: Matrix.cpp:963
void lubksb(int const *, double *)
Implements a separation of the Matrix into a triangular matrix.
Definition: Matrix.cpp:1220
T Trace() const
Trace of the matrix.
Definition: Matrix.cpp:1280
Matrix< T > & operator/=(const T &)
Divide by constant.
Definition: Matrix.cpp:456
void GaussJordan(Matrix< T > &)
Create a Gauss-Jordan Inversion.
Definition: Matrix.cpp:838
void identityMatrix()
Makes the matrix an idenity matrix.
Definition: Matrix.cpp:661
bool equals(const Matrix< T > &A, const double Tolerance=FLT_EPSILON) const
Element by element comparison within tolerance.
Definition: Matrix.cpp:499
Matrix< T > Tprime() const
Transpose the matrix.
Definition: Matrix.cpp:766
bool operator==(const Matrix< T > &) const
Element by element comparison within tolerance.
Definition: Matrix.cpp:484
bool isRotation() const
Check if a matrix represents a proper rotation @ return :: true/false.
Definition: Matrix.cpp:1424
int Diagonalise(Matrix< T > &, Matrix< T > &) const
(only Symmetric matrix)
Definition: Matrix.cpp:1319
void setRow(const size_t nRow, const std::vector< T > &newRow)
Definition: Matrix.cpp:686
T factor()
Calculate the factor.
Definition: Matrix.cpp:1063
Matrix< T > operator+(const Matrix< T > &) const
Basic addition operator.
Definition: Matrix.cpp:299
T compSum() const
Add up each component sums for the matrix.
Definition: Matrix.cpp:1131
Matrix< T > preMultiplyByDiagonal(const std::vector< T > &) const
pre-multiply D*this
Definition: Matrix.cpp:719
std::vector< T > Diagonal() const
Returns a vector of the diagonal.
Definition: Matrix.cpp:1265
void setRandom(size_t seed=0, double rMin=-1, double rMax=1)
initialize random matrix;
Definition: Matrix.cpp:1520
Matrix< T > operator*(const Matrix< T > &) const
Basic matrix multiply.
Definition: Matrix.cpp:327
std::vector< T > getVector() const
Definition: Matrix.cpp:77
void averSymmetric()
make Matrix symmetric
Definition: Matrix.cpp:1249
void swapCols(const size_t, const size_t)
Swap cols (second V index)
Definition: Matrix.cpp:635
size_t numRows() const
Return the number of rows in the matrix.
Definition: Matrix.h:144
void normVert()
Vertical normalisation.
Definition: Matrix.cpp:1112
void rotate(double const, double const, int const, int const, int const, int const)
Applies a rotation to a particular point of tan(theta)=tau.
Definition: Matrix.cpp:699
size_t m_numRows
Number of rows (x coordinate)
Definition: Matrix.h:48
void setColumn(const size_t nCol, const std::vector< T > &newCol)
Definition: Matrix.cpp:675
void swapRows(const size_t, const size_t)
Swap rows (first V index)
Definition: Matrix.cpp:620
size_t m_numColumns
Number of columns (y coordinate)
Definition: Matrix.h:49
Matrix< T > & operator*=(const Matrix< T > &)
Basic matrix multipy.
Definition: Matrix.cpp:431
size_t numCols() const
Return the number of columns in the matrix.
Definition: Matrix.h:147
Matrix< T > & Transpose()
Transpose the matrix.
Definition: Matrix.cpp:793
void write(std::ostream &, int const =0) const
Write out function for blocks of 10 Columns.
Definition: Matrix.cpp:1531
Matrix< T > & operator-=(const Matrix< T > &)
Basic subtraction operator.
Definition: Matrix.cpp:278
std::string str() const
Convert the matrix into a simple linear string expression.
Definition: Matrix.cpp:1564
bool operator!=(const Matrix< T > &) const
Element by Element comparison.
Definition: Matrix.cpp:472
bool isOrthogonal() const
Check if a matrix is orthogonal.
Definition: Matrix.cpp:1444
void print() const
Simple print out routine.
Definition: Matrix.cpp:1511
bool operator>=(const Matrix< T > &) const
Element by element comparison of >= Always returns false if the Matrix have different sizes.
Definition: Matrix.cpp:566
Matrix< T > & operator=(const Matrix< T > &)
Simple assignment operator.
Definition: Matrix.cpp:216
void lubcmp(int *, int &)
starts inversion process
Definition: Matrix.cpp:1147
void setMem(const size_t, const size_t)
Sets the memory held in matrix.
Definition: Matrix.cpp:586
MatrixMemoryPtrs< T > m_rawData
Representation of 2D data.
Definition: Matrix.h:59
Matrix< T > postMultiplyByDiagonal(const std::vector< T > &) const
post-multiply this*D
Definition: Matrix.cpp:742
This implements the the Mersenne Twister 19937 pseudo-random number generator algorithm as a specialz...
double nextValue() override
Generate the next random number in the sequence within the given range default range.
Class for 3D vectors.
Definition: V3D.h:34
constexpr double X() const noexcept
Get x.
Definition: V3D.h:232
MatrixWorkspace_sptr MANTID_API_DLL operator*(const MatrixWorkspace_sptr &lhs, const MatrixWorkspace_sptr &rhs)
Multiply two workspaces.
MANTID_KERNEL_DLL std::ostream & operator<<(std::ostream &, CPUTimer &)
Convenience function to provide for easier debug printing.
Definition: CPUTimer.cpp:86
MANTID_KERNEL_DLL std::istream & operator>>(std::istream &, Interpolation &)
Reads in parameter value.
MANTID_KERNEL_DLL bool equals(const T x, const T y)
Test for equality of doubles using compiler-defined precision.
MANTID_KERNEL_DLL bool operator==(const Mantid::Kernel::Property &lhs, const Mantid::Kernel::Property &rhs)
Compares this to another property for equality.
Definition: Property.cpp:259
void dumpToStream(std::ostream &, const Kernel::Matrix< T > &, const char)
Write a Matrix to a stream.
Definition: Matrix.cpp:1598
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12
void fillFromStream(std::istream &, Kernel::Matrix< T > &, const char)
Fill a Matrix from a stream using the given separator.
Definition: Matrix.cpp:1630