Diana Software
QMatrix.cc
Go to the documentation of this file.
1 /*
2 *
3 * Class QMatrix
4 *
5 */
6 
7 #include "QMatrix.hh"
8 #include "QVector.hh"
9 #include "QError.hh"
10 #include <cmath>
11 #include <TString.h>
12 #include <sstream>
13 #include <gsl/gsl_blas.h>
14 #include <gsl/gsl_linalg.h>
15 
16 using std::cout;
17 using std::endl;
18 using std::map;
19 using std::ostream;
20 
21 #ifdef _HAVE_FFTW3_
22 #include <fftw3.h>
23 #endif
24 
25 QObjectImp(Diana::QMatrix);
26 
28 void QMatrix::MatrixCopy(const double *orig,const UInt_t Nrow,
29  const UInt_t Ncol,double *dest,
30  UInt_t origTda,UInt_t destTda){
31  if(orig && dest){
32 
33  if(origTda<Ncol) origTda=Ncol;
34  if(destTda<Ncol) destTda=origTda;
35 
36  if(origTda==Ncol && destTda==Ncol)
37  memcpy(dest,orig,Nrow*Ncol*sizeof(double));
38  else
39  for(UInt_t i=0;i<Nrow;i++)
40  memcpy(dest+i*destTda,orig+i*origTda,Ncol*sizeof(double));
41  }
42  else if (!orig && !dest){
43  // If neither of them are allocated, do nothing?
44  }
45  else
46  DianaThrow(QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
47  "Can not copy QMatrix from origin to destination "
48  "before memory allocation!"));
49 }
50 
52  : fDataOwner(true),
53  fSize(0),
54  fNCol(0),
55  fTda(0),
56  fAllocSize(0),
57  fData(0),
58  fMat(0)
59 {}
60 
61 
62 QMatrix::QMatrix(UInt_t nrow,UInt_t ncol)
63  : fDataOwner(true),
64  fSize(0),
65  fNCol(0),
66  fTda(0),
67  fAllocSize(0),
68  fData(0),
69  fMat(0)
70 {
71  Resize(nrow,ncol);
72 }
73 
75  : fDataOwner(true),
76  fSize(0),
77  fNCol(0),
78  fTda(0),
79  fAllocSize(0),
80  fData(0),
81  fMat(0)
82 {
83  Resize(vec.Size(),1);
85 }
86 
88  : fDataOwner(true),
89  fSize(0),
90  fNCol(0),
91  fTda(0),
92  fAllocSize(0),
93  fData(0),
94  fMat(0)
95 {
96  Resize(orig.GetNRow(),orig.GetNCol());
98  MemRowElements());
99 }
100 
101 QMatrix::QMatrix(const gsl_matrix* mat)
102  : fDataOwner(true),
103  fSize(0),
104  fNCol(0),
105  fTda(0),
106  fAllocSize(0),
107  fData(0),
108  fMat(0)
109 {
110  Resize(mat->size1,mat->size2);
111  MatrixCopy(mat->data,GetNRow(),GetNCol(),fData,mat->tda,MemRowElements());
112 }
113 QMatrix::QMatrix(double *data,const UInt_t nrow,const UInt_t ncol,
114  const UInt_t tda)
115  : fDataOwner(false),
116  fSize(nrow*ncol),
117  fNCol(ncol),
118  fTda(tda),
119  fAllocSize(nrow*ncol),
120  fData(data),
121  fMat(0)
122 {
123  if(fTda<fNCol)
124  fTda = fNCol;
125  else
126  fTda = tda;
127  fMat=NULL;
128 }
130  if(fMat) free(fMat);
132  fMat=NULL;
133  fData=NULL;
134  fSize=0;
135  fNCol=0;
136  fTda=0;
137  fAllocSize=0;
138 }
140 {
141  Resize(0,0);
142 }
143 void QMatrix::Resize(UInt_t nrow,UInt_t ncol)
144 {
145  if(GetNRow() == nrow && GetNCol() == ncol) return;
146  if(fDataOwner){
147  if(nrow*ncol > fAllocSize) {
149  fAllocSize=nrow*ncol;
151  }
152  fTda = ncol;
153  fSize = nrow*ncol;
154  fNCol = ncol;
155  if(fMat) free(fMat);
156  fMat = NULL;
157  }
158  else
159  DianaThrow(QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
160  "Attempt to resize a QMatrix which does not own "
161  "the memory."));
162 }
163 void QMatrix::Initialize(double val)
164 {
165  // We must take care here not to overwrite the data in the trailing
166  // dimensions.
167  for(UInt_t i=0;i<(UInt_t) GetNRow(); i++)
168  for(UInt_t j=0;j<(UInt_t) GetNCol(); j++)
169  fData[MemRowElements()*i+j]=val;
170 
171 }
172 
174 {
175  SetMat();
176  gsl_matrix_set_identity(fMat);
177 }
178 
179 void QMatrix::SetCol(UInt_t n,const QVector& vec)
180 {
181  if(vec.Size()==GetNRow()) {
182  SetMat();
183  vec.SetMathVector();
184  gsl_matrix_set_col(fMat,n,vec.fMathVec);
185  }
186  else
187  {
188  DianaThrow (QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,"You are trying to set a column of a QMatrix with a different size QVector"));
189  }
190 }
191 
192 void QMatrix::SetRow(UInt_t n,const QVector& vec)
193 {
194  if(vec.Size()==GetNCol()) {
195  SetMat();
196  // assert(n<=nrow()&&vec.size()==ncol());
197  vec.SetMathVector();
198  gsl_matrix_set_row(fMat,n,vec.fMathVec);
199  }
200  else {
201  DianaThrow( QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,"You are trying to set a row of a QMatrix with a different size QVector"));
202  }
203 }
204 
205 void QMatrix::Set(const map<int,int> & p){
206 
207  map<int,int>::const_iterator iter;
208  int n_ele = p.size();
209 
210  this->Resize(n_ele,2);
211 
212  int i=0;
213 
214  SetMat();
215  for(iter = p.begin(); iter!= p.end(); iter++) {
216  gsl_matrix_set(fMat,i,0,iter->first);
217  gsl_matrix_set(fMat,i,1,iter->second);
218  i++;
219  }
220 }
222 {
223  return QVector(fData+n,GetNRow(),MemRowElements());
224 }
225 QVector QMatrix::GetCol(UInt_t n) const
226 {
227  QVector res(GetNRow());
228  res.SetMathVector();
229  SetMat();
230  gsl_matrix_get_col(res.fMathVec,fMat,n);
231  return res;
232 }
233 
235 {
236  return QVector(fData+n*MemRowElements(),fNCol,1);
237 }
238 QVector QMatrix::GetRow(UInt_t n) const
239 {
240  QVector res(GetNCol());
241  res.SetMathVector();
242  SetMat();
243  gsl_matrix_get_row(res.fMathVec,fMat,n);
244  return res;
245 }
247 {
248  return QVector(fData,GetNRow(),MemRowElements()+1);
249 }
251 {
252  QVector res(GetNCol());
253  for(UInt_t i=0;i<GetNCol();i++)
254  res[i]=(*this)(i,i);
255  return res;
256 }
257 //e che e' sto coso?!??
258 QVector QMatrix::GetRowByColumnIntValue(UInt_t col,int val) const
259 {
260  for(UInt_t i = 0; i < GetNRow(); i++) {
261  if(lround(operator()(i,col)) == val)
262  return GetRow(i);
263  }
264  QVector dummy;
265  return dummy;
266 }
267 
268 double &QMatrix::GetElement(UInt_t i,UInt_t j)
269 {
270  SetMat();
271  if( !(i<GetNRow() && j<GetNCol()) ) {
272  std::stringstream stream;
273  stream<<"N row: "<<GetNRow()<<" Index: "<<i;
274  stream<<"N col: "<<GetNCol()<<" Index: "<<j;
275  DianaThrow( QError(QERR_OUT_OF_RANGE,__FILE__,__LINE__,stream.str()));
276  }
277  return fData[i*MemRowElements()+j];
278 }
279 
280 const double &QMatrix::GetElement(UInt_t i, UInt_t j) const
281 {
282  SetMat();
283  if( !(i<GetNRow() && j<GetNCol()) ) {
284  std::stringstream stream;
285  stream<<"N row: "<<GetNRow()<<" Index: "<<i;
286  stream<<"N col: "<<GetNCol()<<" Index: "<<j;
287  DianaThrow( QError(QERR_OUT_OF_RANGE,__FILE__,__LINE__,stream.str()));
288  }
289  return fData[i*MemRowElements()+j];
290 }
291 
292 
293 const QMatrix& QMatrix::operator=(const QMatrix& orig)
294 {
295  Resize(orig.GetNRow(),orig.GetNCol());
296  if(fSize)
298  orig.MemRowElements(),MemRowElements());
299  if(fMat) free(fMat);
300  fMat=NULL;
301  return *this;
302 }
303 
305 {
306  return operator*=(-1.);
307 }
308 
309 const QMatrix& QMatrix::operator*=(double t)
310 {
311  SetMat();
312  gsl_matrix_scale(fMat,t);
313  return *this;
314 }
315 
316 const QMatrix& QMatrix::operator*=(const QMatrix& other)
317 {
318  // multiply a matrix ths=this*other
319  //gsl does not have matrix multiplications?!?
320  // gsl_matrix* tmpM=gsl_matrix_alloc(other.GetNRow(),other.GetNCol());
321  QMatrix tmp(*this);
322  Resize(GetNRow(),other.GetNCol());
323  SetMat();
324  other.SetMat();
325  tmp.SetMat();
326  gsl_blas_dgemm(CblasNoTrans,CblasNoTrans,1.0,tmp.fMat,other.fMat,0.0,fMat);
327  return *this;
328 }
329 
330 const QMatrix& QMatrix::operator/=(double t)
331 {
332  return operator*=(1/t);
333 }
334 
335 const QMatrix& QMatrix::operator+=(const QMatrix& other)
336 {
337  SetMat();
338  other.SetMat();
339  gsl_matrix_add(fMat,other.fMat);
340  return *this;
341 }
342 
343 const QMatrix& QMatrix::operator-=(const QMatrix& other)
344 {
345  SetMat();
346  other.SetMat();
347  gsl_matrix_sub(fMat,other.fMat);
348  return *this;
349 }
350 
351 const QMatrix& QMatrix::Mult(const QMatrix& other)
352 {
353  SetMat();
354  other.SetMat();
355  gsl_matrix_mul_elements(fMat,other.fMat);
356  return *this;
357 }
358 
359 const QMatrix& QMatrix::Div(const QMatrix& other)
360 {
361  SetMat();
362  other.SetMat();
363  gsl_matrix_div_elements(fMat,other.fMat);
364  return *this;
365 }
366 
368 {
369  QMatrix tmp(*this);
370  tmp*=mat;
371  return tmp;
372 }
373 
375 {
376  QMatrix tmp(*this);
377  tmp*=t;
378  return tmp;
379 }
380 
382 {
383  QMatrix tmp(*this);
384  tmp/=t;
385  return tmp;
386 }
387 
389 {
390  QMatrix tmp(*this);
391  tmp+=mat;
392  return tmp;
393 }
394 
396 {
397  QMatrix tmp(mat);
398  tmp-=mat;
399  return tmp;
400 }
401 
403 {
404  QVector v; // Allocate space for the response, because the matrix m will disappear
405  QMatrix m(vec);
406  v = ((*this)*m).GetCol(0);
407  return v;
408 }
409 
411 {
412  QMatrix tmp(*this);
413  tmp.Transpose();
414  return tmp;
415 }
416 
418 {
419  if(!fDataOwner && GetNRow()!=GetNCol())
420  DianaThrow(QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
421  "Can not transpose matrix if not data owner or square!"));
422  SetMat();
423  gsl_matrix_transpose(fMat);
424  if(GetNRow()!=GetNCol())
425  fTda=fNCol=GetNRow();
426  return *this;
427 }
428 
430 {
431  QMatrix tmp(*this);
432  tmp.Invert();
433  return tmp;
434 }
435 
437 {
438  SetMat();
439  int err=0;
440  int sign=0;
441  gsl_permutation * p = gsl_permutation_calloc(GetNRow());
442  gsl_matrix * LU = gsl_matrix_calloc(GetNRow(), fNCol);
443  int * signum = &sign;
444  gsl_matrix_memcpy(LU, fMat);
445  err=gsl_linalg_LU_decomp(LU, p, signum);
446  if(err)cout<<" ERROR: failed to decompose matrix "<<err<<endl;
447  err=gsl_linalg_LU_invert(LU, p, fMat);
448  if(err)std::cout<<" ERROR: failed to invert LU matrix "<<err<<std::endl;
449  gsl_permutation_free(p);
450  gsl_matrix_free(LU);
451  return *this;
452 }
453 
454 double QMatrix::Det() const
455 {
456  SetMat();
457  int err=0;
458  int sign=0;
459  gsl_permutation * p = gsl_permutation_calloc(GetNRow());
460  gsl_matrix * tmp_ptr = gsl_matrix_calloc(GetNRow(),fNCol);
461  int * signum = &sign;
462  gsl_matrix_memcpy(tmp_ptr, fMat);
463  err=gsl_linalg_LU_decomp(tmp_ptr, p, signum);
464  if(err)cout<<" ERROR: failed to compute matrix determinant "<<err<<endl;
465  double res = gsl_linalg_LU_det(tmp_ptr, *signum);
466  gsl_permutation_free(p);
467  gsl_matrix_free(tmp_ptr);
468  return res;
469 }
471  SetMat();
472  int err=gsl_linalg_cholesky_decomp(fMat);
473  if(err) std::cout << " ERROR: Failed to Cholesky decompose the Matrix "
474  << err << std::endl;
475  return *this;
476 }
478  QMatrix out(*this);
479  out.CholeskyDecompose();
480  return out;
481 }
482 void QMatrix::CholeskySolveX(const QVector &Y,QVector &X) const {
483  if(Y.Size()!=GetNRow())
484  throw QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
485  "Vector and matrix dimensions do not match "
486  "in CholeskySolveX");
487  X.Resize(Y.Size());
488  SetMat();
489  X.SetMathVector();
490  Y.SetMathVector();
491  int err = gsl_linalg_cholesky_solve(fMat,Y.fMathVec,X.fMathVec);
492  if(err) std::cout << " ERROR: Failed to cholesky solve for X!" << err
493  << std::endl;
494 }
495 QMatrix QMatrix::GetSubMatrix(UInt_t nI,UInt_t nJ,UInt_t startI,UInt_t startJ)
496 {
497  if(startI + nI > GetNRow() || startJ + nJ > GetNCol())
498  throw(QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
499  Form("Cannot extract a submatrix of size %ix%i starting from"
500  " element %i,%i from a matrix of size %ix%i",
501  nI,nJ,startI,startJ,GetNRow(),GetNCol())));
502  double *firstElem = fData+startI*MemRowElements()+startJ;
503  QMatrix ret(firstElem,nI,nJ,fTda);
504  return ret;
505 }
506 const QMatrix QMatrix::GetSubMatrix(UInt_t nI,UInt_t nJ,UInt_t startI,
507  UInt_t startJ) const
508 {
509  if(startI + nI > GetNRow() || startJ + nJ > GetNCol())
510  throw(QError(QERR_SIZE_NOT_MATCH,__FILE__,__LINE__,
511  Form("Cannot extract a submatrix of size %ix%i starting from"
512  " element %i,%i from a matrix of size %ix%i",
513  nI,nJ,startI,startJ,GetNRow(),GetNCol())));
514  double *firstElem = fData+startI*MemRowElements()+startJ;
515  QMatrix ret(firstElem,nI,nJ,fTda);
516  return ret;
517 }
518 
520  QMatrix Ret(*this);
521  for(size_t i=0;i<GetNRow();i++) {
522  for(size_t j=0;j<GetNCol();j++) {
523  if(i>0) Ret(i,j) += Ret(i-1,j);
524  if(j>0) Ret(i,j) += Ret(i,j-1);
525  if(i>0 && j>0) Ret(i,j) -= Ret(i-1,j-1);
526  }
527  }
528  return Ret;
529 }
530 
531 void QMatrix::SetMat() const
532 {
533  if(!fMat){
534  fMat = (gsl_matrix*) malloc(sizeof(gsl_matrix));
535  fMat->size1=GetNRow();
536  fMat->size2=fNCol;
537  fMat->owner=1;
538  fMat->data=fData;
539  fMat->block=0;
540  fMat->tda=fTda;//CMT CHECK
541  }
542 }
543 
545 
546 /*************************************
547  * NON MEMBER FUNCTIONS
548  * **********************************/
549 
550 Diana::QMatrix operator*(double t, const Diana::QMatrix&mat){
551  Diana::QMatrix tmp(mat);
552  tmp*=t;
553  return tmp;
554 }
555 
556 ostream& operator<<(ostream&s,const Diana::QMatrix&mat){
557  for (UInt_t i=0;i<mat.GetNRow();i++){
558  for (UInt_t j=0;j<mat.GetNCol();j++) s<<mat(i,j)<<" ";
559  s<<endl;
560  }
561  return s;
562 }
563 
564 
err
Definition: CheckOF.C:114
QVector vec(3)
#define DianaThrow(obj)
Definition: QDianaDebug.hh:26
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
@ QERR_SIZE_NOT_MATCH
Definition: QError.hh:31
@ QERR_OUT_OF_RANGE
Definition: QError.hh:28
Q_END_NAMESPACE Diana::QMatrix operator*(double t, const Diana::QMatrix &mat)
scalar times QMatrix
Definition: QMatrix.cc:550
ostream & operator<<(ostream &s, const Diana::QMatrix &mat)
Definition: QMatrix.cc:556
QObjectImp(Diana::QMatrix)
error class with error type and description
Definition: QError.hh:115
Interface for matrices in Diana analysis.
Definition: QMatrix.hh:24
QMatrix GetSubMatrix(UInt_t nI, UInt_t nJ, UInt_t startI=0, UInt_t startJ=0)
Get a sub matrix of the matrix.
Definition: QMatrix.cc:495
QVector GetDiaganol()
Get the diaganol.
Definition: QMatrix.cc:246
gsl_matrix * fMat
Definition: QMatrix.hh:464
void Initialize(double val=0)
initialize all elements (default to 0)
Definition: QMatrix.cc:163
double & GetElement(UInt_t i, UInt_t j)
Definition: QMatrix.cc:268
UInt_t fNCol
Definition: QMatrix.hh:459
const QMatrix & operator+=(const QMatrix &mat)
add a QMatrix
Definition: QMatrix.cc:335
void Set(const std::map< int, int > &p)
get a QMatrix from a map
Definition: QMatrix.cc:205
const QMatrix & operator=(const QMatrix &orig)
copy the content of another matrix
Definition: QMatrix.cc:293
double Det() const
Determinant.
Definition: QMatrix.cc:454
void Resize(UInt_t nrow, UInt_t ncol)
resize a QMatrix
Definition: QMatrix.cc:143
Double_t * fData
Definition: QMatrix.hh:463
UInt_t fTda
Definition: QMatrix.hh:460
QVector GetCol(UInt_t ncol)
get column
Definition: QMatrix.cc:221
UInt_t fAllocSize
Definition: QMatrix.hh:462
const QMatrix & operator-=(const QMatrix &mat)
subtract a QMatrix
Definition: QMatrix.cc:343
const QMatrix & Mult(const QMatrix &mat)
Multiply element by element.
Definition: QMatrix.cc:351
void CholeskySolveX(const QVector &Y, QVector &X) const
Solve for X using Cholesky decomposition.
Definition: QMatrix.cc:482
UInt_t MemRowElements() const
Definition: QMatrix.hh:451
void Clear()
reset members to default values
Definition: QMatrix.cc:139
QVector GetRowByColumnIntValue(UInt_t col, int val) const
get row matching the integer value val in column col if more than one value is found in column the fi...
Definition: QMatrix.cc:258
const QMatrix & Div(const QMatrix &mat)
Divide element by element.
Definition: QMatrix.cc:359
void SetCol(UInt_t ncol, const QVector &vec)
set column to specific vector
Definition: QMatrix.cc:179
static void MatrixCopy(const double *orig, const UInt_t Nrow, const UInt_t Ncol, double *dest, UInt_t origTda=0, UInt_t destTda=0)
Static method to copy a matrix from one data location to another.
Definition: QMatrix.cc:28
void SetMat() const
Definition: QMatrix.cc:531
QMatrix operator-()
revert sign to all components
Definition: QMatrix.cc:304
friend class QVector
Definition: QMatrix.hh:466
UInt_t fSize
Definition: QMatrix.hh:458
void SetRow(UInt_t nrow, const QVector &vec)
set row to specific vectors
Definition: QMatrix.cc:192
QMatrix operator/(double t) const
Division by scalar.
Definition: QMatrix.cc:381
QMatrix GetSummedAreaMatrix() const
Create a summed area matrix.
Definition: QMatrix.cc:519
QMatrix T() const
transpose returns a different matrix transposed wrt the original
Definition: QMatrix.cc:410
QMatrix operator+(const QMatrix &mat) const
sum matrix
Definition: QMatrix.cc:388
Bool_t fDataOwner
This owns the memory.
Definition: QMatrix.hh:456
QMatrix()
default constructor
Definition: QMatrix.cc:51
UInt_t GetNRow() const
get number rows
Definition: QMatrix.hh:63
QVector GetRow(UInt_t nrow)
get row
Definition: QMatrix.cc:234
const QMatrix & CholeskyDecompose()
Cholesky Decomposition.
Definition: QMatrix.cc:470
const QMatrix & Transpose()
transpose
Definition: QMatrix.cc:417
const QMatrix & operator*=(double t)
multiplication by scalar
Definition: QMatrix.cc:309
const QMatrix & Invert()
inverse inverts the matrix itself
Definition: QMatrix.cc:436
const QMatrix & operator/=(double t)
division by scalar
Definition: QMatrix.cc:330
void SetToIdentity()
initialize to identity
Definition: QMatrix.cc:173
QMatrix operator*(const QMatrix &mat) const
Matrix product.
Definition: QMatrix.cc:367
QMatrix GetCholeskyDecomposition() const
Cholesky Decomposition.
Definition: QMatrix.cc:477
QMatrix Inv() const
inverse returns a different matrix inverted wrt the original
Definition: QMatrix.cc:429
virtual ~QMatrix()
destructor
Definition: QMatrix.cc:129
UInt_t GetNCol() const
get number of columns
Definition: QMatrix.hh:68
Interface for vectors in Diana analysis.
Definition: QVector.hh:30
static void ArrayCopy(const double *orig, const UInt_t origStride, double *dest, const UInt_t destStride, const UInt_t size)
Definition: QVector.cc:60
UInt_t Size() const
size of QVector
Definition: QVector.hh:54
static void ArrayFree(double *array)
Definition: QVector.cc:72
void SetMathVector() const
Definition: QVector.cc:207
UInt_t fStride
data stride
Definition: QVector.hh:441
Double_t * fData
array
Definition: QVector.hh:444
static double * ArrayAlloc(const UInt_t size)
Definition: QVector.cc:32
void Resize(const UInt_t newsize)
resize a QVector
Definition: QVector.cc:170
gsl_vector * fMathVec
temporary gsl_vector to use the gsl library
Definition: QVector.hh:447