OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
MMatrix.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, Chris Rogers
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "Utilities/GSLEigen.h"
29#include "Utilities/GSLLinalg.h"
30
32
34
35// template class MMatrix<double>;
36
38namespace interpolation {
39
40 template <class Tmplt>
41 MMatrix<Tmplt>::MMatrix() : _matrix(nullptr) {}
42 template MMatrix<double>::MMatrix();
44
45 template MMatrix<double> MMatrix<double>::Diagonal(size_t i, double diag, double off_diag);
47 size_t i, m_complex diag, m_complex off_diag);
48
49 template std::istream& operator>>(std::istream& in, MMatrix<double>& mat);
50 template std::istream& operator>>(std::istream& in, MMatrix<m_complex>& mat);
51
52 template MMatrix<double>::MMatrix(size_t i, size_t j, double* data_beg);
53 template MMatrix<m_complex>::MMatrix(size_t i, size_t j, m_complex* data_beg);
54 template MMatrix<double>::MMatrix(size_t i, size_t j, double value);
55 template MMatrix<m_complex>::MMatrix(size_t i, size_t j, m_complex value);
56 template MMatrix<double>::MMatrix(size_t i, size_t j);
57 template MMatrix<m_complex>::MMatrix(size_t i, size_t j);
58
61
62 template <>
64 if (_matrix != nullptr) gsl_matrix_free((gsl_matrix*)_matrix);
65 _matrix = nullptr;
66 }
67
68 template <>
70 if (_matrix != nullptr) gsl_matrix_complex_free((gsl_matrix_complex*)_matrix);
71 _matrix = nullptr;
72 }
73
74 template <>
76 if (&mm == this) return *this;
77 delete_matrix();
78 if (!mm._matrix) {
79 _matrix = nullptr;
80 return *this;
81 }
82 _matrix = gsl_matrix_alloc(mm.num_row(), mm.num_col());
83 gsl_matrix_memcpy((gsl_matrix*)_matrix, (const gsl_matrix*)mm._matrix);
84 return *this;
85 }
86
87 template <>
89 if (&mm == this) return *this;
90 delete_matrix();
91 if (!mm._matrix) {
92 _matrix = nullptr;
93 return *this;
94 }
97 (gsl_matrix_complex*)_matrix, (const gsl_matrix_complex*)mm._matrix);
98 return *this;
99 }
100
101 template <>
102 MMatrix<double>::MMatrix(const MMatrix<double>& mm) : _matrix(nullptr) {
103 if (mm._matrix) {
106 }
107 }
108
109 template <>
117
118 template <class Tmplt>
119 MMatrix<Tmplt>::MMatrix(size_t i, size_t j, Tmplt* data_beg) : _matrix(nullptr) {
120 build_matrix(i, j, data_beg);
121 }
123 template <class Tmplt>
124 MMatrix<Tmplt>::MMatrix(size_t i, size_t j, Tmplt value) {
125 build_matrix(i, j);
126 for (size_t a = 1; a <= i; a++)
127 for (size_t b = 1; b <= j; b++)
128 operator()(a, b) = value;
129 }
130
131 template <class Tmplt>
132 MMatrix<Tmplt>::MMatrix(size_t i, size_t j) {
133 build_matrix(i, j);
134 }
135
136 template <class Tmplt>
137 MMatrix<Tmplt> MMatrix<Tmplt>::Diagonal(size_t i, Tmplt diag_value, Tmplt off_diag_value) {
138 MMatrix<Tmplt> mm(i, i);
139 for (size_t a = 1; a <= i; a++) {
140 for (size_t b = 1; b < a; b++)
141 mm(a, b) = off_diag_value;
142 for (size_t b = a + 1; b <= i; b++)
143 mm(a, b) = off_diag_value;
144 mm(a, a) = diag_value;
146 return mm;
147 }
148
149 template <class Tmplt>
151 delete_matrix();
153 template MMatrix<double>::~MMatrix();
155
156 template <>
157 void MMatrix<double>::build_matrix(size_t i, size_t j) {
158 _matrix = gsl_matrix_alloc(i, j);
159 }
160
161 template <>
162 void MMatrix<m_complex>::build_matrix(size_t i, size_t j) {
163 _matrix = gsl_matrix_complex_alloc(i, j);
164 }
165
166 template <>
167 void MMatrix<double>::build_matrix(size_t i, size_t j, double* data) {
168 _matrix = gsl_matrix_alloc(i, j);
169 for (size_t a = 0; a < i; a++)
170 for (size_t b = 0; b < j; b++)
171 operator()(a + 1, b + 1) = data[b * i + a];
172 }
173
174 template <>
175 void MMatrix<m_complex>::build_matrix(size_t i, size_t j, m_complex* data) {
176 _matrix = gsl_matrix_complex_alloc(i, j);
177 for (size_t a = 0; a < i; a++)
178 for (size_t b = 0; b < j; b++)
179 operator()(a + 1, b + 1) = data[b * i + a];
180 }
181
183
184 template <>
186 int signum = 1;
187
188 if (num_row() != num_col())
190 "MMatrix::determinant()", "Attempt to get determinant of non-square matrix"));
192 MMatrix<m_complex> copy(*this);
196 }
197
198 template <>
200 int signum = 1;
201 if (num_row() != num_col())
203 "MMatrix::determinant()", "Attempt to get determinant of non-square matrix"));
205 MMatrix<double> copy(*this);
206 gsl_linalg_LU_decomp((gsl_matrix*)copy._matrix, p, &signum);
207 double d = gsl_linalg_LU_det((gsl_matrix*)copy._matrix, signum);
209 return d;
210 }
211
212 template <class Tmplt>
214 MMatrix<Tmplt> copy(*this);
215 copy.invert();
216 return copy;
217 }
218
219 template <>
221 if (num_row() != num_col())
223 "MMatrix::invert()", "Attempt to get inverse of non-square matrix"));
224 gsl_permutation* perm = gsl_permutation_alloc(num_row());
225 MMatrix<m_complex> lu(*this); // hold LU decomposition
226 int s = 0;
229 (gsl_matrix_complex*)lu._matrix, perm, (gsl_matrix_complex*)_matrix);
231 for (size_t i = 1; i <= num_row(); i++)
232 for (size_t j = 1; j <= num_row(); j++)
233 if (operator()(i, j) != operator()(i, j))
235 "MMatrix::invert()", "Failed to invert matrix - singular?"));
236 }
237
238 template <>
240 if (num_row() != num_col())
242 "MMatrix::invert()", "Attempt to get inverse of non-square matrix"));
243 gsl_permutation* perm = gsl_permutation_alloc(num_row());
244 MMatrix<double> lu(*this); // hold LU decomposition
245 int s = 0;
247 gsl_linalg_LU_invert((gsl_matrix*)lu._matrix, perm, (gsl_matrix*)_matrix);
249 for (size_t i = 1; i <= num_row(); i++)
250 for (size_t j = 1; j <= num_row(); j++)
251 if (operator()(i, j) != operator()(i, j))
253 "MMatrix::invert()", "Failed to invert matrix - singular?"));
254 }
255
256 template <>
258 MMatrix<double> in(num_col(), num_row());
260 return in;
261 }
262
263 template <>
265 MMatrix<m_complex> in(num_col(), num_row());
268 return in;
269 }
270
271 template <class Tmplt>
273 size_t min_row, size_t max_row, size_t min_col, size_t max_col) const {
274 MMatrix<Tmplt> sub_matrix(max_row - min_row + 1, max_col - min_col + 1);
275 for (size_t i = min_row; i <= max_row; i++)
276 for (size_t j = min_col; j <= max_col; j++)
277 sub_matrix(i - min_row + 1, j - min_col + 1) = operator()(i, j);
278 return sub_matrix;
279 }
281 size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
283 size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
284
285 template <class Tmplt>
286 Tmplt MMatrix<Tmplt>::trace() const {
287 Tmplt t = operator()(1, 1);
288 for (size_t i = 2; i <= num_row() && i <= num_col(); i++)
289 t += operator()(i, i);
290 return t;
291 }
292 template double MMatrix<double>::trace() const;
293 template m_complex MMatrix<m_complex>::trace() const;
294
295 template <class Tmplt>
297 if (num_row() != num_col())
299 "MMatrix<double>::eigenvalues",
300 "Attempt to get eigenvectors of non-square matrix"));
301 MMatrix<Tmplt> temp = *this;
302 MVector<m_complex> evals(num_row(), m_complex_build(2., -1.));
305 int ierr = gsl_eigen_nonsymm(get_matrix(temp), evals.get_vector(evals), w);
307 if (ierr != 0)
309 "MMatrix<Tmplt>::eigenvalues", "Failed to calculate eigenvalue"));
310 return evals;
311 }
313
314 template <class Tmplt>
315 std::pair<MVector<m_complex>, MMatrix<m_complex> > MMatrix<Tmplt>::eigenvectors() const {
316 if (num_row() != num_col())
318 "MMatrix<double>::eigenvectors",
319 "Attempt to get eigenvectors of non-square matrix"));
320 MMatrix<Tmplt> temp = *this;
321 MVector<m_complex> evals(num_row());
322 MMatrix<m_complex> evecs(num_row(), num_row());
324 int ierr =
325 gsl_eigen_nonsymmv(get_matrix(temp), evals.get_vector(evals), get_matrix(evecs), w);
327 if (ierr != 0)
329 "MMatrix<Tmplt>::eigenvectors", "Failed to calculate eigenvalue"));
330 return std::pair<MVector<m_complex>, MMatrix<m_complex> >(evals, evecs);
331 }
332 template std::pair<MVector<m_complex>, MMatrix<m_complex> > MMatrix<double>::eigenvectors()
333 const;
334
336
338 MMatrix<double> out(m1.num_row(), m2.num_col());
341 0., (gsl_matrix*)out._matrix);
342 m1 = out;
343 return m1;
344 }
345
355
356 template <class Tmplt>
357 std::ostream& operator<<(std::ostream& out, MMatrix<Tmplt> mat) {
358 out << mat.num_row() << " " << mat.num_col() << "\n";
359 for (size_t i = 1; i <= mat.num_row(); i++) {
360 out << " ";
361 for (size_t j = 1; j < mat.num_col(); j++)
362 out << mat(i, j) << " ";
363 out << mat(i, mat.num_col()) << "\n";
364 }
365 return out;
366 }
367 template std::ostream& operator<<(std::ostream& out, MMatrix<double> mat);
368 template std::ostream& operator<<(std::ostream& out, MMatrix<m_complex> mat);
369
370 template <class Tmplt>
371 std::istream& operator>>(std::istream& in, MMatrix<Tmplt>& mat) {
372 size_t nr, nc;
373 in >> nr >> nc;
374 mat = MMatrix<Tmplt>(nr, nc);
375 for (size_t i = 1; i <= nr; i++)
376 for (size_t j = 1; j <= nc; j++)
377 in >> mat(i, j);
378 return in;
379 }
380
382
384 MMatrix<double> md(mc.num_row(), mc.num_col());
385 for (size_t i = 1; i <= mc.num_row(); i++)
386 for (size_t j = 1; j <= mc.num_col(); j++)
387 md(i, j) = re(mc(i, j));
388 return md;
389 }
390
392 MMatrix<double> md(mc.num_row(), mc.num_col());
393 for (size_t i = 1; i <= mc.num_row(); i++)
394 for (size_t j = 1; j <= mc.num_col(); j++)
395 md(i, j) = im(mc(i, j));
396 return md;
397 }
398
400 MMatrix<m_complex> mc(real.num_row(), real.num_col());
401 for (size_t i = 1; i <= mc.num_row(); i++)
402 for (size_t j = 1; j <= mc.num_col(); j++)
403 mc(i, j) = m_complex_build(real(i, j));
404 return mc;
405 }
406
408 if (real.num_row() != imaginary.num_row() || real.num_col() != imaginary.num_col())
410 "MMatrix<m_complex>::complex",
411 "Attempt to build complex matrix when real and imaginary matrix don't have the "
412 "same size"));
413 MMatrix<m_complex> mc(real.num_row(), real.num_col());
414 for (size_t i = 1; i <= mc.num_row(); i++)
415 for (size_t j = 1; j <= mc.num_col(); j++)
416 mc(i, j) = m_complex_build(real(i, j), imaginary(i, j));
417 return mc;
418 }
419
420 template <class Tmplt>
422 MVector<Tmplt> temp(num_row());
423 for (size_t i = 1; i <= num_row(); i++)
424 temp(i) = operator()(i, column);
425 return temp;
426 }
427 template MVector<double> MMatrix<double>::get_mvector(size_t column) const;
428 template MVector<m_complex> MMatrix<m_complex>::get_mvector(size_t column) const;
429
430} // namespace interpolation
const int nr
void gsl_blas_zgemm(CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB, gsl_complex alpha, const gsl_matrix_complex *A, const gsl_matrix_complex *B, gsl_complex beta, gsl_matrix_complex *C)
Complex matrix-matrix multiply and accumulate.
Definition GSLBLAS.h:90
@ CblasNoTrans
Definition GSLBLAS.h:32
void gsl_blas_dgemm(CBLAS_TRANSPOSE TransA, CBLAS_TRANSPOSE TransB, double alpha, const gsl_matrix *A, const gsl_matrix *B, double beta, gsl_matrix *C)
Real matrix-matrix multiply and accumulate.
Definition GSLBLAS.h:44
void gsl_eigen_nonsymmv_free(gsl_eigen_nonsymmv_workspace *w)
Free a workspace allocated by gsl_eigen_nonsymmv_alloc.
Definition GSLEigen.h:85
int gsl_eigen_nonsymm(gsl_matrix *A, gsl_vector_complex *eval, gsl_eigen_nonsymm_workspace *)
Compute eigenvalues of a real nonsymmetric matrix.
Definition GSLEigen.h:94
int gsl_eigen_nonsymmv(gsl_matrix *A, gsl_vector_complex *eval, gsl_matrix_complex *evec, gsl_eigen_nonsymmv_workspace *w)
Compute eigenvalues and a simplified set of eigenvectors.
Definition GSLEigen.h:194
void gsl_eigen_nonsymm_params(int, int, gsl_eigen_nonsymm_workspace *)
Accept GSL-style parameters (no-op in this implementation).
Definition GSLEigen.h:61
gsl_eigen_nonsymm_workspace * gsl_eigen_nonsymm_alloc(size_t n)
Allocate a nonsymmetric eigenvalue workspace for matrices.
Definition GSLEigen.h:49
void gsl_eigen_nonsymm_free(gsl_eigen_nonsymm_workspace *w)
Free a workspace allocated by gsl_eigen_nonsymm_alloc.
Definition GSLEigen.h:69
gsl_eigen_nonsymmv_workspace * gsl_eigen_nonsymmv_alloc(size_t n)
Allocate a nonsymmetric eigenvalue/vector workspace for matrices.
Definition GSLEigen.h:75
gsl_complex gsl_linalg_complex_LU_det(const gsl_matrix_complex *LU, int signum)
Determinant from LU decomposition (complex).
Definition GSLLinalg.h:248
void gsl_permutation_free(gsl_permutation *p)
Free a permutation allocated by gsl_permutation_alloc.
Definition GSLLinalg.h:52
int gsl_linalg_LU_invert(const gsl_matrix *LU, const gsl_permutation *p, gsl_matrix *inverse)
Invert a matrix from its LU decomposition (real).
Definition GSLLinalg.h:139
gsl_permutation * gsl_permutation_alloc(size_t n)
Allocate an identity permutation of size .
Definition GSLLinalg.h:40
int gsl_linalg_complex_LU_decomp(gsl_matrix_complex *A, gsl_permutation *p, int *signum)
In-place LU decomposition with partial pivoting (complex).
Definition GSLLinalg.h:187
int gsl_linalg_complex_LU_invert(const gsl_matrix_complex *LU, const gsl_permutation *p, gsl_matrix_complex *inverse)
Invert a matrix from its LU decomposition (complex).
Definition GSLLinalg.h:263
double gsl_linalg_LU_det(const gsl_matrix *LU, int signum)
Determinant from LU decomposition (real).
Definition GSLLinalg.h:124
int gsl_linalg_LU_decomp(gsl_matrix *A, gsl_permutation *p, int *signum)
In-place LU decomposition with partial pivoting (real).
Definition GSLLinalg.h:66
gsl_matrix * gsl_matrix_alloc(size_t n1, size_t n2)
Allocate a zero-initialized real matrix of size .
Definition GSLMatrix.h:94
void gsl_matrix_complex_transpose_memcpy(gsl_matrix_complex *dest, const gsl_matrix_complex *src)
Copy the transpose into dest (complex).
Definition GSLMatrix.h:307
void gsl_matrix_free(gsl_matrix *m)
Free a matrix allocated by gsl_matrix_alloc.
Definition GSLMatrix.h:108
void gsl_matrix_complex_memcpy(gsl_matrix_complex *dest, const gsl_matrix_complex *src)
Copy src into dest (complex matrices).
Definition GSLMatrix.h:279
void gsl_matrix_transpose_memcpy(gsl_matrix *dest, const gsl_matrix *src)
Copy the transpose into dest.
Definition GSLMatrix.h:291
void gsl_matrix_complex_free(gsl_matrix_complex *m)
Free a matrix allocated by gsl_matrix_complex_alloc.
Definition GSLMatrix.h:136
gsl_matrix_complex * gsl_matrix_complex_alloc(size_t n1, size_t n2)
Allocate a zero-initialized complex matrix of size .
Definition GSLMatrix.h:120
void gsl_matrix_memcpy(gsl_matrix *dest, const gsl_matrix *src)
Copy src into dest (real matrices).
Definition GSLMatrix.h:268
void invert()
turns this matrix into its inverse
MVector< Tmplt > get_mvector(size_t column) const
Definition MMatrix.cpp:421
size_t num_col() const
returns number of columns in the matrix
MVector< m_complex > eigenvalues() const
returns a vector of eigenvalues. Throws an exception if either this matrix is not square or the eigen...
Definition MMatrix.cpp:296
void build_matrix(size_t i, size_t j)
MMatrix< Tmplt > & operator=(const MMatrix< Tmplt > &mm)
MMatrix< Tmplt > T() const
returns matrix transpose T (such that M(i,j) = T(j,i))
size_t num_row() const
returns number of rows in the matrix
std::pair< MVector< m_complex >, MMatrix< m_complex > > eigenvectors() const
Definition MMatrix.cpp:315
MMatrix< Tmplt > inverse() const
returns matrix inverse leaving this matrix unchanged
Definition MMatrix.cpp:213
MMatrix< Tmplt > sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const
Definition MMatrix.cpp:272
static MMatrix< Tmplt > Diagonal(size_t i, Tmplt diag_value, Tmplt off_diag_value)
Construct a square matrix filling on and off diagonal values.
Definition MMatrix.cpp:137
Tmplt determinant() const
returns matrix determinant; throws an exception if matrix is not square
MMatrix()
default constructor makes an empty MMatrix of size (0,0)
Definition MMatrix.cpp:41
Tmplt trace() const
returns sum of terms with row == column, even if matrix is not square
Definition MMatrix.cpp:286
static gsl_vector * get_vector(const MVector< double > &m)
Definition MVector.h:336
m_complex m_complex_build(double r, double i)
Definition MVector.h:60
MMatrix< m_complex > complex(MMatrix< double > real)
Definition MMatrix.cpp:399
template std::istream & operator>>(std::istream &in, MMatrix< double > &mat)
MMatrix< double > re(MMatrix< m_complex > mc)
Definition MMatrix.cpp:383
std::ostream & operator<<(std::ostream &out, const Mesh::Iterator &it)
Definition Mesh.cpp:33
MMatrix< double > & operator*=(MMatrix< double > &m1, MMatrix< double > m2)
Definition MMatrix.cpp:337
MMatrix< double > im(MMatrix< m_complex > mc)
Definition MMatrix.cpp:391
Complex number stored as .
Definition GSLComplex.h:27
Workspace for nonsymmetric eigenvalue computation.
Definition GSLEigen.h:30
Workspace for nonsymmetric eigenvalues/eigenvectors.
Definition GSLEigen.h:38
Dense complex matrix in row-major storage.
Definition GSLMatrix.h:45
Dense real matrix in row-major storage.
Definition GSLMatrix.h:29
Permutation vector for LU decomposition.
Definition GSLLinalg.h:30