1
// MAUS WARNING: THIS IS LEGACY CODE.
2
//This file is a part of MAUS
4
//MAUS is free software: you can redistribute it and/or modify
5
//it under the terms of the GNU General Public License as published by
6
//the Free Software Foundation, either version 3 of the License, or
7
//(at your option) any later version.
9
//MAUS is distributed in the hope that it will be useful,
10
//but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
//GNU General Public License for more details.
14
//You should have received a copy of the GNU General Public License
15
//along with MAUS in the doc folder. If not, see
16
//<http://www.gnu.org/licenses/>.
18
#ifndef _SRC_COMMON_CPP_MATHS_MMATRIX_HH_
19
#define _SRC_COMMON_CPP_MATHS_MMATRIX_HH_
24
#include "gsl/gsl_matrix.h"
25
#include "gsl/gsl_blas.h"
27
#include "Utils/Exception.hh"
28
typedef MAUS::Exception Squeal;
30
#include "math/MVector.hh"
33
///////////////// MMatrix /////////////////
35
/** @class MMatrix C++ wrapper for GSL matrix
36
* MMatrix class handles matrix algebra, maths operators and some
37
* higher level calculation like matrix inversion, eigenvector
40
* Use template to define two types:\n
41
* (i) MMatrix<double> is a matrix of doubles\n
42
* (ii) MMatrix<m_complex> is a matrix of m_complex\n
44
* Maths operators and a few others are defined, but maths operators
45
* don't allow operations between types - i.e. you can't multiply
46
* a complex matrix by a double matrix. Instead use interface methods
47
* like real() and complex() to convert between types first
49
* Nb: CLHEP::HepMatrix can also be used but doesn't have any eigenvalue
50
* analysis. Conversion functions are provided in MMatrixToCLHEP
52
template <class Tmplt>
56
/** @brief default constructor makes an empty MMatrix of size (0,0)
60
/** @brief Copy constructor makes a deep copy of mv
62
MMatrix(const MMatrix<Tmplt>& mv );
64
/** @brief Construct a matrix and fill with data from memory data_beginning
66
* @params nrows number of rows
67
* @params ncols number of columns
68
* @params data_beginning pointer to the start of a memory block of size
69
* nrows*ncols with data laid out <row> <row> <row>. Note MMatrix
70
* does not take ownership of memory in data_beginning.
72
MMatrix(size_t nrows, size_t ncols, Tmplt* data_beginning );
74
/** @brief Construct a matrix and fill with identical data
76
* @params nrows number of rows
77
* @params ncols number of columns
78
* @params data variable to be copied into all items in the matrix
80
MMatrix(size_t nrows, size_t ncols, Tmplt value);
82
/** @brief Construct a matrix and fill all fields with 0
84
* @params nrows number of rows
85
* @params ncols number of columns
87
MMatrix(size_t nrows, size_t ncols);
89
/** @brief Construct a square matrix filling on and off diagonal values
91
* @params i number of rows and number of columns
92
* @params diag_value fill values with row == column (i.e. on the diagonal)
94
* @params off_diag_value fill values with row != column (i.e. off the
95
* diagonal) with this value
97
static MMatrix<Tmplt> Diagonal(size_t i, Tmplt diag_value, Tmplt off_diag_value);
103
/** @brief returns number of rows in the matrix
105
size_t num_row() const;
107
/** @brief returns number of columns in the matrix
109
size_t num_col() const;
111
/** @brief returns sum of terms with row == column, even if matrix is not
116
/** @brief returns matrix determinant; throws an exception if matrix is not
119
Tmplt determinant() const;
121
/** @brief returns matrix inverse leaving this matrix unchanged
123
MMatrix<Tmplt> inverse() const;
125
/** @brief turns this matrix into its inverse
129
/** @brief returns matrix transpose T (such that M(i,j) = T(j,i))
131
MMatrix<Tmplt> T() const;
133
/** @brief returns a vector of eigenvalues. Throws an exception if either this
134
* matrix is not square or the eigenvalues could not be found (e.g.
135
* singular matrix or whatever).
137
MVector<m_complex> eigenvalues() const; //return vector of eigenvalues
138
std::pair<MVector<m_complex>, MMatrix<m_complex> >
139
eigenvectors() const; //return pair of eigenvalues, eigenvectors (access using my_pair.first or my_pair.second)
141
//return a submatrix, with data from min_row to max_row and min_row to max_row inclusive; indexing starts at 1
142
MMatrix<Tmplt> sub(size_t min_row, size_t max_row, size_t min_col, size_t max_col) const;
143
//create a column vector from the column^th column
144
MVector<Tmplt> get_mvector(size_t column) const;
145
//return a reference to the datum; indexing starts at 1, goes to num_row (inclusive)
146
const Tmplt& operator()(size_t row, size_t column) const;
147
Tmplt& operator()(size_t row, size_t column);
149
MMatrix<Tmplt>& operator= (const MMatrix<Tmplt>& mm);
151
//TODO - implement iterator
157
friend MMatrix<m_complex>& operator *=(MMatrix<m_complex>& m, m_complex c);
158
friend MMatrix<double>& operator *=(MMatrix<double>& m, double d);
159
friend MMatrix<m_complex>& operator *=(MMatrix<m_complex>& m1, MMatrix<m_complex> m2);
160
friend MMatrix<double>& operator *=(MMatrix<double>& m1, MMatrix<double> m2);
161
friend MVector<m_complex> operator * (MMatrix<m_complex> m, MVector<m_complex> v);
162
friend MVector<double> operator * (MMatrix<double> m, MVector<double> v);
163
friend MMatrix<m_complex>& operator +=(MMatrix<m_complex>& m1, const MMatrix<m_complex>& m2);
164
friend MMatrix<double>& operator +=(MMatrix<double>& m1, const MMatrix<double>& m2);
165
template <class Tmplt2> friend MMatrix<Tmplt2> operator + (MMatrix<Tmplt2> m1, const MMatrix<Tmplt2> m2);
167
friend const gsl_matrix* MMatrix_to_gsl(const MMatrix<double>& m);
168
friend const gsl_matrix_complex* MMatrix_to_gsl(const MMatrix<gsl_complex>& m);
170
friend class MMatrix<double>; //To do the eigenvector problem, MMatrix<double> needs to see MMatrix<complex>'s _matrix
174
//build the matrix with size i,j, data not initialised
175
void build_matrix(size_t i, size_t j);
176
//build the matrix with size i,j, data initialised to data in temp
177
void build_matrix(size_t i, size_t j, Tmplt* temp);
178
//delete the matrix and set it to null
179
void delete_matrix();
180
//return the matrix overloaded to the correct type or throw
182
static gsl_matrix* get_matrix(const MMatrix<double>& m);
183
static gsl_matrix_complex* get_matrix(const MMatrix<m_complex>& m);
188
//Operators do what you would expect - i.e. normal mathematical functions
189
MMatrix<m_complex>& operator *=(MMatrix<m_complex>& m, m_complex c);
190
MMatrix<double>& operator *=(MMatrix<double>& m, double d);
191
MMatrix<m_complex>& operator *=(MMatrix<m_complex>& m1, MMatrix<m_complex> m2); //M1 *= M2 returns M1 = M1*M2
192
MMatrix<double>& operator *=(MMatrix<double>& m1, MMatrix<double> m2); //M1 *= M2 returns M1 = M1*M2
193
MVector<m_complex> operator * (MMatrix<m_complex> m, MVector<m_complex> v);
194
MVector<double> operator * (MMatrix<double> m, MVector<double> v);
195
MMatrix<m_complex>& operator +=(MMatrix<m_complex>& m1, const MMatrix<m_complex>& m2);
196
MMatrix<double>& operator +=(MMatrix<double>& m1, const MMatrix<double>& m2);
198
template <class Tmplt> MMatrix<Tmplt>& operator -=(MMatrix<double>& m1, MMatrix<double> m2);
200
template <class Tmplt> MMatrix<Tmplt> operator*(MMatrix<Tmplt>, MMatrix<Tmplt>);
201
template <class Tmplt> MMatrix<Tmplt> operator*(MMatrix<Tmplt>, MVector<Tmplt>);
202
template <class Tmplt> MMatrix<Tmplt> operator*(MMatrix<Tmplt>, Tmplt);
203
template <class Tmplt> MMatrix<Tmplt> operator/(MMatrix<Tmplt>, Tmplt);
205
template <class Tmplt> MMatrix<Tmplt> operator+(MMatrix<Tmplt>, MMatrix<Tmplt>);
206
template <class Tmplt> MMatrix<Tmplt> operator-(MMatrix<Tmplt>, MMatrix<Tmplt>);
207
template <class Tmplt> MMatrix<Tmplt> operator-(MMatrix<Tmplt>); //unary minus returns matrix*(-1)
209
template <class Tmplt> bool operator==(const MMatrix<Tmplt>& c1, const MMatrix<Tmplt>& c2);
210
template <class Tmplt> bool operator!=(const MMatrix<Tmplt>& c1, const MMatrix<Tmplt>& c2);
217
template <class Tmplt> std::ostream& operator<<(std::ostream& out, MMatrix<Tmplt> mat);
218
template <class Tmplt> std::istream& operator>>(std::istream& in, MMatrix<Tmplt>& mat);
220
//return matrix of doubles filled with either real or imaginary part of m
221
MMatrix<double> re(MMatrix<m_complex> m);
222
MMatrix<double> im(MMatrix<m_complex> m);
223
//return matrix of m_complex filled with real and imaginary parts
224
MMatrix<m_complex> complex(MMatrix<double> real);
225
MMatrix<m_complex> complex(MMatrix<double> real, MMatrix<double> imaginary);
227
//return pointer to gsl_matrix objects that store matrix data in m
228
const gsl_matrix* MMatrix_to_gsl(const MMatrix<double>& m);
229
const gsl_matrix_complex* MMatrix_to_gsl(const MMatrix<gsl_complex>& m);
231
//////////////////////////// MMatrix declaration end ///////////////
235
//////////////////////////// MMatrix Inlined Functions //////////////
238
inline size_t MMatrix<double>::num_row() const
240
if(_matrix) return ((gsl_matrix*)_matrix)->size1;
244
inline size_t MMatrix<m_complex>::num_row() const
246
if(_matrix) return ((gsl_matrix_complex*)_matrix)->size1;
250
inline size_t MMatrix<double>::num_col() const
252
if(_matrix) return ((gsl_matrix*)_matrix)->size2;
257
inline size_t MMatrix<m_complex>::num_col() const
259
if(_matrix) return ((gsl_matrix_complex*)_matrix)->size2;
263
MMatrix<m_complex> inline & operator *=(MMatrix<m_complex>& m, m_complex c)
264
{gsl_matrix_complex_scale((gsl_matrix_complex*)m._matrix, c); return m;}
266
MMatrix<double> inline & operator *=(MMatrix<double>& m, double d)
267
{gsl_matrix_scale((gsl_matrix*)m._matrix, d); return m;}
269
MVector<m_complex> inline operator * (MMatrix<m_complex> m, MVector<m_complex> v)
271
MVector<m_complex> v0(m.num_row());
272
gsl_blas_zgemv(CblasNoTrans, m_complex_build(1.), (gsl_matrix_complex*)m._matrix, (gsl_vector_complex*)v._vector, m_complex_build(0.), (gsl_vector_complex*)v0._vector);
276
MVector<double> inline operator * (MMatrix<double> m, MVector<double> v)
278
MVector<double> v0(m.num_row());
279
gsl_blas_dgemv(CblasNoTrans, 1., (gsl_matrix*)m._matrix, (gsl_vector*)v._vector, 0., (gsl_vector*)v0._vector);
283
MMatrix<m_complex> inline & operator +=(MMatrix<m_complex>& m1, const MMatrix<m_complex>& m2)
284
{gsl_matrix_complex_add((gsl_matrix_complex*)m1._matrix, (gsl_matrix_complex*)m2._matrix); return m1;}
286
MMatrix<double> inline & operator +=(MMatrix<double>& m1, const MMatrix<double>& m2)
287
{gsl_matrix_add((gsl_matrix*)m1._matrix, (gsl_matrix*)m2._matrix); return m1;}
289
template <class Tmplt> MMatrix<Tmplt> inline operator - (MMatrix<Tmplt> m1)
290
{for(size_t i=1; i<=m1.num_row(); i++) for(size_t j=1; j<=m1.num_col(); j++) m1(i,j) = -1.*m1(i,j); return m1; }
292
template <class Tmplt> MMatrix<Tmplt> inline operator*(MMatrix<Tmplt> m1, MMatrix<Tmplt> m2)
295
template <class Tmplt> MMatrix<Tmplt> inline operator*(MMatrix<Tmplt> m, MVector<Tmplt> v)
298
template <class Tmplt> MMatrix<Tmplt> inline operator*(MMatrix<Tmplt> m, Tmplt t)
301
template <class Tmplt> MMatrix<Tmplt> inline & operator/=(MMatrix<Tmplt>& m, Tmplt t)
303
template <class Tmplt> MMatrix<Tmplt> inline operator/(MMatrix<Tmplt> m, Tmplt t)
306
template <class Tmplt> MMatrix<Tmplt> inline operator+(MMatrix<Tmplt> m1, MMatrix<Tmplt> m2)
307
{ MMatrix<Tmplt> m3 = m1+=m2; return m3; }
309
template <class Tmplt> MMatrix<Tmplt> inline & operator-=(MMatrix<Tmplt>& m1, MMatrix<Tmplt> m2)
311
template <class Tmplt> MMatrix<Tmplt> inline operator-(MMatrix<Tmplt> m1, MMatrix<Tmplt> m2)
317
const double inline & MMatrix<double>::operator()(size_t i, size_t j) const
318
{ return *gsl_matrix_ptr((gsl_matrix*)_matrix, i-1, j-1); }
320
const m_complex inline & MMatrix<m_complex>::operator()(size_t i, size_t j) const
321
{ return *gsl_matrix_complex_ptr((gsl_matrix_complex*)_matrix, i-1, j-1); }
324
double inline & MMatrix<double>::operator()(size_t i, size_t j)
325
{ return *gsl_matrix_ptr((gsl_matrix*)_matrix, i-1, j-1); }
327
m_complex inline & MMatrix<m_complex>::operator()(size_t i, size_t j)
328
{ return *gsl_matrix_complex_ptr((gsl_matrix_complex*)_matrix, i-1, j-1); }
330
template <class Tmplt>
331
bool operator==(const MMatrix<Tmplt>& lhs, const MMatrix<Tmplt>& rhs)
333
if( lhs.num_row() != rhs.num_row() || lhs.num_col() != rhs.num_col() ) return false;
334
for(size_t i=1; i<=lhs.num_row(); i++)
335
for(size_t j=1; j<=lhs.num_col(); j++)
336
if(lhs(i,j) != rhs(i,j)) return false;
340
template <class Tmplt>
341
bool inline operator!=(const MMatrix<Tmplt>& lhs, const MMatrix<Tmplt>& rhs) {return ! (lhs == rhs);}
344
template <class Tmplt> std::ostream& operator<<(std::ostream& out, MMatrix<Tmplt>);
345
//template <class Tmplt> std::istream& operator>>(std::istream& in, MMatrix<Tmplt>);
347
template <class Tmplt>
348
gsl_matrix inline* MMatrix<Tmplt>::get_matrix(const MMatrix<double>& m)
350
if(m._matrix == NULL)
351
throw(Squeal(Squeal::recoverable, "Attempt to access uninitialised matrix", "MMatrix::get_matrix"));
352
return (gsl_matrix*)m._matrix;
355
template <class Tmplt>
356
gsl_matrix_complex inline* MMatrix<Tmplt>::get_matrix(const MMatrix<m_complex>& m)
358
if(m._matrix == NULL)
359
throw(Squeal(Squeal::recoverable, "Attempt to access uninitialised matrix", "MMatrix::get_matrix"));
360
return (gsl_matrix_complex*)m._matrix;
364
////////////////////////// MMatrix inlined functions end //////////////////////