OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
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 "gsl/gsl_linalg.h"
29#include "gsl/gsl_eigen.h"
30
32
34
35//template class MMatrix<double>;
36
38namespace interpolation {
39
40template <class Tmplt>
41MMatrix<Tmplt>::MMatrix() : _matrix(nullptr)
42{}
45
46template MMatrix<double> MMatrix<double> ::Diagonal(size_t i, double diag, double off_diag);
48
49template std::istream& operator>>(std::istream& in, MMatrix<double>& mat);
50template std::istream& operator>>(std::istream& in, MMatrix<m_complex>& mat);
51
52template MMatrix<double> ::MMatrix(size_t i, size_t j, double* data_beg );
53template MMatrix<m_complex>::MMatrix(size_t i, size_t j, m_complex* data_beg );
54template MMatrix<double> ::MMatrix(size_t i, size_t j, double value);
55template MMatrix<m_complex>::MMatrix(size_t i, size_t j, m_complex value);
56template MMatrix<double> ::MMatrix(size_t i, size_t j );
57template MMatrix<m_complex>::MMatrix(size_t i, size_t j );
58
61
62template <>
64{
65 if(_matrix != nullptr) gsl_matrix_free( (gsl_matrix*)_matrix );
66 _matrix = nullptr;
68
69template <>
71{
72 if(_matrix != nullptr) gsl_matrix_complex_free( (gsl_matrix_complex*)_matrix );
73 _matrix = nullptr;
74}
75
76
77template <>
79{
80 if (&mm == this) return *this;
81 delete_matrix();
82 if(!mm._matrix) { _matrix = nullptr; return *this; }
83 _matrix = gsl_matrix_alloc( mm.num_row(), mm.num_col() );
84 gsl_matrix_memcpy((gsl_matrix*)_matrix, (const gsl_matrix*)mm._matrix);
85 return *this;
86}
87
88template <>
90{
91 if (&mm == this) return *this;
92 delete_matrix();
93 if(!mm._matrix) { _matrix = nullptr; return *this; }
94 _matrix = gsl_matrix_complex_alloc( mm.num_row(), mm.num_col() );
95 gsl_matrix_complex_memcpy((gsl_matrix_complex*)_matrix, (const gsl_matrix_complex*)mm._matrix);
96 return *this;
97}
98
99template <>
100MMatrix<double>::MMatrix( const MMatrix<double>& mm ) : _matrix(nullptr)
101{
102 if(mm._matrix)
103 {
104 _matrix = gsl_matrix_alloc(mm.num_row(), mm.num_col() );
105 gsl_matrix_memcpy( (gsl_matrix*)_matrix, (gsl_matrix*)mm._matrix );
107}
108
109template <>
110MMatrix<m_complex>::MMatrix( const MMatrix<m_complex>& mm ) : _matrix(nullptr)
111{
112 if(mm._matrix)
113 {
114 _matrix = gsl_matrix_complex_alloc( mm.num_row(), mm.num_col() );
115 gsl_matrix_complex_memcpy( (gsl_matrix_complex*)_matrix, (gsl_matrix_complex*)mm._matrix );
116 }
117}
118
119template <class Tmplt>
120MMatrix<Tmplt>::MMatrix(size_t i, size_t j, Tmplt* data_beg ) : _matrix(nullptr)
121{
122 build_matrix(i, j, data_beg);
124
125template <class Tmplt>
126MMatrix<Tmplt>::MMatrix(size_t i, size_t j, Tmplt value )
127{
128 build_matrix(i, j);
129 for(size_t a=1; a<=i; a++)
130 for(size_t b=1; b<=j; b++)
131 operator()(a,b) = value;
133
134template <class Tmplt>
135MMatrix<Tmplt>::MMatrix(size_t i, size_t j )
136{
137 build_matrix(i, j);
138}
139
140template <class Tmplt>
141MMatrix<Tmplt> MMatrix<Tmplt>::Diagonal(size_t i, Tmplt diag_value, Tmplt off_diag_value)
142{
143 MMatrix<Tmplt> mm(i,i);
144 for(size_t a=1; a<=i; a++)
145 {
146 for(size_t b=1; b< a; b++) mm(a, b) = off_diag_value;
147 for(size_t b=a+1; b<=i; b++) mm(a, b) = off_diag_value;
148 mm(a,a) = diag_value;
149 }
150 return mm;
152
154template <class Tmplt>
156{
157 delete_matrix();
158}
161
162template <>
163void MMatrix<double>::build_matrix(size_t i, size_t j)
164{
165 _matrix = gsl_matrix_alloc(i, j);
166}
167
168template <>
169void MMatrix<m_complex>::build_matrix(size_t i, size_t j)
170{
171 _matrix = gsl_matrix_complex_alloc(i, j);
172}
173
174template <>
175void MMatrix<double>::build_matrix(size_t i, size_t j, double* data)
176{
177 _matrix = gsl_matrix_alloc(i, j);
178 for(size_t a=0; a<i; a++)
179 for(size_t b=0; b<j; b++)
180 operator()(a+1,b+1) = data[b*i + a];
181}
182
183template <>
184void MMatrix<m_complex>::build_matrix(size_t i, size_t j, m_complex* data)
185{
186 _matrix = gsl_matrix_complex_alloc(i, j);
187 for(size_t a=0; a<i; a++)
188 for(size_t b=0; b<j; b++)
189 operator()(a+1,b+1) = data[b*i + a];
190}
191
192
194
195template <>
197{
198 int signum = 1;
199
200 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix::determinant()", "Attempt to get determinant of non-square matrix"));
201 gsl_permutation * p = gsl_permutation_alloc (num_row());
202 MMatrix<m_complex> copy(*this);
203 gsl_linalg_complex_LU_decomp ((gsl_matrix_complex*)copy._matrix, p, &signum);
204 gsl_permutation_free(p);
205 return gsl_linalg_complex_LU_det((gsl_matrix_complex*)copy._matrix, signum);
206}
207
208template <>
210{
211 int signum = 1;
212 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix::determinant()", "Attempt to get determinant of non-square matrix"));
213 gsl_permutation * p = gsl_permutation_alloc (num_row());
214 MMatrix<double> copy(*this);
215 gsl_linalg_LU_decomp ((gsl_matrix*)copy._matrix, p, &signum);
216 double d = gsl_linalg_LU_det((gsl_matrix*)copy._matrix, signum);
217 gsl_permutation_free(p);
218 return d;
219}
220
221template <class Tmplt>
223{
224 MMatrix<Tmplt> copy(*this);
225 copy.invert();
226 return copy;
227}
228
229
230template <>
232{
233 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix::invert()", "Attempt to get inverse of non-square matrix"));
234 gsl_permutation* perm = gsl_permutation_alloc(num_row());
235 MMatrix<m_complex> lu(*this); //hold LU decomposition
236 int s=0;
237 gsl_linalg_complex_LU_decomp ( (gsl_matrix_complex*)lu._matrix, perm, &s);
238 gsl_linalg_complex_LU_invert ( (gsl_matrix_complex*)lu._matrix, perm, (gsl_matrix_complex*)_matrix);
239 gsl_permutation_free( perm );
240 for(size_t i=1; i<=num_row(); i++)
241 for(size_t j=1; j<=num_row(); j++)
242 if(operator()(i,j) != operator()(i,j)) throw(GeneralClassicException("MMatrix::invert()", "Failed to invert matrix - singular?"));
243}
244
245template <>
247{
248 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix::invert()", "Attempt to get inverse of non-square matrix"));
249 gsl_permutation* perm = gsl_permutation_alloc(num_row());
250 MMatrix<double> lu(*this); //hold LU decomposition
251 int s=0;
252 gsl_linalg_LU_decomp ( (gsl_matrix*)lu._matrix, perm, &s);
253 gsl_linalg_LU_invert ( (gsl_matrix*)lu._matrix, perm, (gsl_matrix*)_matrix);
254 gsl_permutation_free( perm );
255 for(size_t i=1; i<=num_row(); i++)
256 for(size_t j=1; j<=num_row(); j++)
257 if(operator()(i,j) != operator()(i,j)) throw(GeneralClassicException("MMatrix::invert()", "Failed to invert matrix - singular?"));
258}
259
260template <>
262{
263 MMatrix<double> in(num_col(), num_row());
264 gsl_matrix_transpose_memcpy ((gsl_matrix*)in._matrix, (gsl_matrix*)_matrix);
265 return in;
266}
267
268template <>
270{
271 MMatrix<m_complex> in(num_col(), num_row());
272 gsl_matrix_complex_transpose_memcpy ((gsl_matrix_complex*)in._matrix, (gsl_matrix_complex*)_matrix);
273 return in;
274}
275
276template <class Tmplt>
277MMatrix<Tmplt> MMatrix<Tmplt>::sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const
278{
279 MMatrix<Tmplt> sub_matrix(max_row-min_row+1, max_col-min_col+1);
280 for(size_t i=min_row; i<=max_row; i++)
281 for(size_t j=min_col; j<=max_col; j++)
282 sub_matrix(i-min_row+1, j-min_col+1) = operator()(i,j);
283 return sub_matrix;
284}
285template MMatrix<double> MMatrix<double> ::sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
286template MMatrix<m_complex> MMatrix<m_complex>::sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
287
288
289template <class Tmplt>
291{
292 Tmplt t = operator()(1,1);
293 for(size_t i=2; i<=num_row() && i<=num_col(); i++) t+= operator()(i,i);
294 return t;
295}
296template double MMatrix<double>::trace() const;
297template m_complex MMatrix<m_complex>::trace() const;
298
299
300template <class Tmplt>
302{
303 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix<double>::eigenvalues", "Attempt to get eigenvectors of non-square matrix") );
304 MMatrix<Tmplt> temp = *this;
305 MVector<m_complex> evals(num_row(), m_complex_build(2.,-1.));
306 gsl_eigen_nonsymm_workspace * w = gsl_eigen_nonsymm_alloc(num_row());
307 gsl_eigen_nonsymm_params(0, 1, w);
308 int ierr = gsl_eigen_nonsymm(get_matrix(temp), evals.get_vector(evals), w);
309 gsl_eigen_nonsymm_free(w);
310 if(ierr != 0) throw(GeneralClassicException("MMatrix<Tmplt>::eigenvalues", "Failed to calculate eigenvalue"));
311 return evals;
312}
314
315template <class Tmplt>
316std::pair<MVector<m_complex>, MMatrix<m_complex> > MMatrix<Tmplt>::eigenvectors() const
317{
318 if(num_row() != num_col()) throw(GeneralClassicException("MMatrix<double>::eigenvectors", "Attempt to get eigenvectors of non-square matrix") );
319 MMatrix<Tmplt> temp = *this;
320 MVector<m_complex> evals(num_row());
321 MMatrix<m_complex> evecs(num_row(), num_row());
322 gsl_eigen_nonsymmv_workspace * w = gsl_eigen_nonsymmv_alloc(num_row());
323 int ierr = gsl_eigen_nonsymmv(get_matrix(temp), evals.get_vector(evals), get_matrix(evecs), w);
324 gsl_eigen_nonsymmv_free(w);
325 if(ierr != 0) throw(GeneralClassicException("MMatrix<Tmplt>::eigenvectors", "Failed to calculate eigenvalue"));
326 return std::pair<MVector<m_complex>, MMatrix<m_complex> > (evals, evecs) ;
327}
328template std::pair<MVector<m_complex>, MMatrix<m_complex> > MMatrix<double>::eigenvectors() const;
329
331
333{
334 MMatrix<double> out(m1.num_row(), m2.num_col());
335 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1., (gsl_matrix*)m1._matrix, (gsl_matrix*)m2._matrix, 0., (gsl_matrix*)out._matrix);
336 m1 = out;
337 return m1;
338}
339
341{
342 MMatrix<m_complex> out(m1.num_row(), m2.num_col());
343 gsl_blas_zgemm( CblasNoTrans, CblasNoTrans, m_complex_build(1.), (gsl_matrix_complex*)m1._matrix,
344 (gsl_matrix_complex*)m2._matrix, m_complex_build(0.), (gsl_matrix_complex*)out._matrix);
345 m1 = out;
346 return m1;
347}
348
349template <class Tmplt> std::ostream& operator<<(std::ostream& out, MMatrix<Tmplt> mat)
350{
351 out << mat.num_row() << " " << mat.num_col() << "\n";
352 for(size_t i=1; i<=mat.num_row(); i++)
353 {
354 out << " ";
355 for(size_t j=1; j<mat.num_col(); j++)
356 out << mat(i,j) << " ";
357 out << mat(i,mat.num_col()) << "\n";
358 }
359 return out;
360}
361template std::ostream& operator<<(std::ostream& out, MMatrix<double> mat);
362template std::ostream& operator<<(std::ostream& out, MMatrix<m_complex> mat);
363
364template <class Tmplt> std::istream& operator>>(std::istream& in, MMatrix<Tmplt>& mat)
365{
366 size_t nr, nc;
367 in >> nr >> nc;
368 mat = MMatrix<Tmplt>(nr, nc);
369 for(size_t i=1; i<=nr; i++)
370 for(size_t j=1; j<=nc; j++)
371 in >> mat(i,j);
372 return in;
373}
374
375
377
379{
380 MMatrix<double> md(mc.num_row(), mc.num_col());
381 for(size_t i=1; i<=mc.num_row(); i++)
382 for(size_t j=1; j<=mc.num_col(); j++)
383 md(i,j) = re(mc(i,j));
384 return md;
385}
386
388{
389 MMatrix<double> md(mc.num_row(), mc.num_col());
390 for(size_t i=1; i<=mc.num_row(); i++)
391 for(size_t j=1; j<=mc.num_col(); j++)
392 md(i,j) = im(mc(i,j));
393 return md;
394}
395
397{
398 MMatrix<m_complex> mc(real.num_row(), real.num_col());
399 for(size_t i=1; i<=mc.num_row(); i++)
400 for(size_t j=1; j<=mc.num_col(); j++)
401 mc(i,j) = m_complex_build(real(i,j));
402 return mc;
403}
404
406{
407 if(real.num_row() != imaginary.num_row() || real.num_col() != imaginary.num_col())
408 throw(GeneralClassicException("MMatrix<m_complex>::complex", "Attempt to build complex matrix when real and imaginary matrix don't have the same size"));
409 MMatrix<m_complex> mc(real.num_row(), real.num_col());
410 for(size_t i=1; i<=mc.num_row(); i++)
411 for(size_t j=1; j<=mc.num_col(); j++)
412 mc(i,j) = m_complex_build(real(i,j), imaginary(i,j));
413 return mc;
414}
415
416template <class Tmplt>
418{
419 MVector<Tmplt> temp(num_row());
420 for(size_t i=1; i<=num_row(); i++) temp(i) = operator()(i,column);
421 return temp;
422}
423template MVector<double> MMatrix<double>::get_mvector(size_t column) const;
424template MVector<m_complex> MMatrix<m_complex>::get_mvector(size_t column) const;
425
426}
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
const int nr
Definition: ClassicRandom.h:24
std::complex< double > a
m_complex m_complex_build(double r, double i)
Definition: MVector.h:62
gsl_complex m_complex
Definition: MVector.h:60
template std::ostream & operator<<(std::ostream &out, MMatrix< m_complex > mat)
template std::istream & operator>>(std::istream &in, MMatrix< double > &mat)
MMatrix< double > re(MMatrix< m_complex > mc)
Definition: MMatrix.cpp:378
MMatrix< m_complex > & operator*=(MMatrix< m_complex > &m1, MMatrix< m_complex > m2)
Definition: MMatrix.cpp:340
MMatrix< m_complex > complex(MMatrix< double > real, MMatrix< double > imaginary)
Definition: MMatrix.cpp:405
std::istream & operator>>(std::istream &in, MMatrix< Tmplt > &mat)
Definition: MMatrix.cpp:364
MMatrix< double > im(MMatrix< m_complex > mc)
Definition: MMatrix.cpp:387
BOOST_UBLAS_INLINE V trace(ublas::matrix< V > &e)
Computes the trace of a square matrix.
~MMatrix()
destructor
Definition: MMatrix.cpp:155
void invert()
turns this matrix into its inverse
size_t num_col() const
returns number of columns in the matrix
void build_matrix(size_t i, size_t j)
size_t num_row() const
returns number of rows in the matrix
MMatrix< Tmplt > inverse() const
returns matrix inverse leaving this matrix unchanged
Definition: MMatrix.cpp:222
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:141
MMatrix()
default constructor makes an empty MMatrix of size (0,0)
Definition: MMatrix.cpp:41
static gsl_vector * get_vector(const MVector< double > &m)
Definition: MVector.h:246