OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 
38 namespace interpolation {
39 
40 template <class Tmplt>
41 MMatrix<Tmplt>::MMatrix() : _matrix(NULL)
42 {}
43 template MMatrix<double> ::MMatrix();
45 
46 template MMatrix<double> MMatrix<double> ::Diagonal(size_t i, double diag, double off_diag);
47 template MMatrix<m_complex> MMatrix<m_complex>::Diagonal(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 {
65  if(_matrix != NULL) gsl_matrix_free( (gsl_matrix*)_matrix );
66  _matrix = NULL;
67 }
68 
69 template <>
71 {
72  if(_matrix != NULL) gsl_matrix_complex_free( (gsl_matrix_complex*)_matrix );
73  _matrix = NULL;
74 }
75 
76 
77 template <>
79 {
80  if (&mm == this) return *this;
81  delete_matrix();
82  if(!mm._matrix) { _matrix = NULL; 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 
88 template <>
90 {
91  if (&mm == this) return *this;
92  delete_matrix();
93  if(!mm._matrix) { _matrix = NULL; 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 
99 template <>
100 MMatrix<double>::MMatrix( const MMatrix<double>& mm ) : _matrix(NULL)
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 );
106  }
107 }
108 
109 template <>
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 
119 template <class Tmplt>
120 MMatrix<Tmplt>::MMatrix(size_t i, size_t j, Tmplt* data_beg ) : _matrix(NULL)
121 {
122  build_matrix(i, j, data_beg);
123 }
124 
125 template <class Tmplt>
126 MMatrix<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;
132 }
133 
134 template <class Tmplt>
135 MMatrix<Tmplt>::MMatrix(size_t i, size_t j )
136 {
137  build_matrix(i, j);
138 }
139 
140 template <class Tmplt>
141 MMatrix<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;
151 }
152 
153 
154 template <class Tmplt>
156 {
157  delete_matrix();
158 }
159 template MMatrix<double>::~MMatrix();
161 
162 template <>
163 void MMatrix<double>::build_matrix(size_t i, size_t j)
164 {
165  _matrix = gsl_matrix_alloc(i, j);
166 }
167 
168 template <>
169 void MMatrix<m_complex>::build_matrix(size_t i, size_t j)
170 {
171  _matrix = gsl_matrix_complex_alloc(i, j);
172 }
173 
174 template <>
175 void 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 
183 template <>
184 void 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 
195 template <>
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 
208 template <>
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 
221 template <class Tmplt>
223 {
224  MMatrix<Tmplt> copy(*this);
225  copy.invert();
226  return copy;
227 }
228 
229 
230 template <>
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 
245 template <>
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 
260 template <>
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 
268 template <>
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 
276 template <class Tmplt>
277 MMatrix<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 }
285 template MMatrix<double> MMatrix<double> ::sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
286 template 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 
289 template <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 }
296 template double MMatrix<double>::trace() const;
297 template m_complex MMatrix<m_complex>::trace() const;
298 
299 
300 template <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 
315 template <class Tmplt>
316 std::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 }
328 template 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 
349 template <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 }
361 template std::ostream& operator<<(std::ostream& out, MMatrix<double> mat);
362 template std::ostream& operator<<(std::ostream& out, MMatrix<m_complex> mat);
363 
364 template <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 const gsl_matrix* MMatrix_to_gsl(const MMatrix<double>& m)
378 {
379  if(m._matrix == NULL) throw(GeneralClassicException("MMatrix_to_gsl", "Attempt to reference uninitialised matrix"));
380  return (gsl_matrix*)m._matrix;
381 }
382 
383 const gsl_matrix_complex* MMatrix_to_gsl(const MMatrix<m_complex>& m)
384 {
385  if(m._matrix == NULL) throw(GeneralClassicException("MMatrix_to_gsl", "Attempt to reference uninitialised matrix"));
386  return (gsl_matrix_complex*)m._matrix;
387 }
388 
390 {
391  MMatrix<double> md(mc.num_row(), mc.num_col());
392  for(size_t i=1; i<=mc.num_row(); i++)
393  for(size_t j=1; j<=mc.num_col(); j++)
394  md(i,j) = re(mc(i,j));
395  return md;
396 }
397 
399 {
400  MMatrix<double> md(mc.num_row(), mc.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  md(i,j) = im(mc(i,j));
404  return md;
405 }
406 
408 {
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));
413  return mc;
414 }
415 
417 {
418  if(real.num_row() != imaginary.num_row() || real.num_col() != imaginary.num_col())
419  throw(GeneralClassicException("MMatrix<m_complex>::complex", "Attempt to build complex matrix when real and imaginary matrix don't have the same size"));
420  MMatrix<m_complex> mc(real.num_row(), real.num_col());
421  for(size_t i=1; i<=mc.num_row(); i++)
422  for(size_t j=1; j<=mc.num_col(); j++)
423  mc(i,j) = m_complex_build(real(i,j), imaginary(i,j));
424  return mc;
425 }
426 
427 template <class Tmplt>
429 {
430  MVector<Tmplt> temp(num_row());
431  for(size_t i=1; i<=num_row(); i++) temp(i) = operator()(i,column);
432  return temp;
433 }
434 template MVector<double> MMatrix<double>::get_mvector(size_t column) const;
435 template MVector<m_complex> MMatrix<m_complex>::get_mvector(size_t column) const;
436 
437 }
MMatrix< Tmplt > inverse() const
returns matrix inverse leaving this matrix unchanged
Definition: MMatrix.cpp:222
void build_matrix(size_t i, size_t j)
gsl_complex m_complex
Definition: MVector.h:60
~MMatrix()
destructor
Definition: MMatrix.cpp:155
MMatrix< m_complex > complex(MMatrix< double > real)
Definition: MMatrix.cpp:407
Definition: rbendmap.h:8
const int nr
Definition: ClassicRandom.h:24
static gsl_vector * get_vector(const MVector< double > &m)
Definition: MVector.h:255
m_complex m_complex_build(double r, double i)
Definition: MVector.h:62
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
template std::istream & operator>>(std::istream &in, MMatrix< double > &mat)
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
size_t num_col() const
returns number of columns in the matrix
const gsl_matrix * MMatrix_to_gsl(const MMatrix< double > &m)
Definition: MMatrix.cpp:377
MMatrix< double > im(MMatrix< m_complex > mc)
Definition: MMatrix.cpp:398
MMatrix< double > & operator*=(MMatrix< double > &m1, MMatrix< double > m2)
Definition: MMatrix.cpp:332
MMatrix< double > re(MMatrix< m_complex > mc)
Definition: MMatrix.cpp:389
MMatrix()
default constructor makes an empty MMatrix of size (0,0)
Definition: MMatrix.cpp:41
BOOST_UBLAS_INLINE V trace(ublas::matrix< V > &e)
Computes the trace of a square matrix.
void invert()
turns this matrix into its inverse
std::istream & operator>>(std::istream &, LieMap< T > &x)
Extract LieMap&lt;T&gt; from stream.
Definition: LieMap.h:231
size_t num_row() const
returns number of rows in the matrix