evtgen is hosted by Hepforge, IPPP Durham
EvtGen  2.0.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
EvtMatrix.hh
Go to the documentation of this file.
1 
2 /***********************************************************************
3 * Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4 * *
5 * This file is part of EvtGen. *
6 * *
7 * EvtGen is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * EvtGen is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19 ***********************************************************************/
20 
21 #ifndef __EVT_MATRIX_HH__
22 #define __EVT_MATRIX_HH__
23 
24 #include <cmath>
25 #include <sstream>
26 #include <vector>
27 
28 template <class T>
29 class EvtMatrix {
30  private:
31  T** _mat;
32  int _range;
33 
34  public:
35  EvtMatrix() : _range( 0 ){};
36  ~EvtMatrix();
37  inline void setRange( int range );
38 
39  T& operator()( int row, int col ) { return _mat[row][col]; }
40  T* operator[]( int row ) { return _mat[row]; }
41  T det();
42  EvtMatrix* min( int row, int col );
43  EvtMatrix* inverse();
44  std::string dump();
45 
46  template <class M>
47  friend EvtMatrix<M>* operator*( const EvtMatrix<M>& left,
48  const EvtMatrix<M>& right );
49 };
50 
51 template <class T>
52 inline void EvtMatrix<T>::setRange( int range )
53 {
54  // If the range is changed, delete any previous matrix stored
55  // and allocate elements with the newly specified range.
56  if ( _range != range ) {
57  if ( _range ) {
58  for ( int row = 0; row < _range; row++ )
59  delete[] _mat[row];
60  delete[] _mat;
61  }
62 
63  _mat = new T*[range];
64  for ( int row = 0; row < range; row++ )
65  _mat[row] = new T[range];
66 
67  // Set the new range.
68  _range = range;
69  }
70 
71  // Since user is willing to change the range, reset the matrix elements.
72  for ( int row = 0; row < _range; row++ )
73  for ( int col = 0; col < _range; col++ )
74  _mat[row][col] = 0.;
75 }
76 
77 template <class T>
79 {
80  for ( int row = 0; row < _range; row++ )
81  delete[] _mat[row];
82  delete[] _mat;
83 }
84 
85 template <class T>
86 std::string EvtMatrix<T>::dump()
87 {
88  std::ostringstream str;
89 
90  for ( int row = 0; row < _range; row++ ) {
91  str << "|";
92  for ( int col = 0; col < _range; col++ )
93  str << "\t" << _mat[row][col];
94  str << "\t|" << std::endl;
95  }
96 
97  return str.str();
98 }
99 
100 template <class T>
102 {
103  if ( _range == 1 )
104  return _mat[0][0];
105 
106  // There's no need to define the range 2 determinant manually, but it may
107  // speed up the calculation.
108  if ( _range == 2 )
109  return _mat[0][0] * _mat[1][1] - _mat[0][1] * _mat[1][0];
110 
111  T sum = 0.;
112 
113  for ( int col = 0; col < _range; col++ ) {
114  EvtMatrix<T>* minor = min( 0, col );
115  sum += std::pow( -1., col ) * _mat[0][col] * minor->det();
116  delete minor;
117  }
118 
119  return sum;
120 }
121 
122 // Returns the minor at (i, j).
123 template <class T>
124 EvtMatrix<T>* EvtMatrix<T>::min( int row, int col )
125 {
126  EvtMatrix<T>* minor = new EvtMatrix<T>();
127  minor->setRange( _range - 1 );
128 
129  int minIndex = 0;
130 
131  for ( int r = 0; r < _range; r++ )
132  for ( int c = 0; c < _range; c++ )
133  if ( ( r != row ) && ( c != col ) ) {
134  ( *minor )( minIndex / ( _range - 1 ),
135  minIndex % ( _range - 1 ) ) = _mat[r][c];
136  minIndex++;
137  }
138 
139  return minor;
140 }
141 
142 template <class T>
144 {
145  EvtMatrix<T>* inv = new EvtMatrix<T>();
146  inv->setRange( _range );
147 
148  if ( det() == 0 ) {
149  std::cerr << "This matrix has a null determinant and cannot be inverted. Returning zero matrix."
150  << std::endl;
151  for ( int row = 0; row < _range; row++ )
152  for ( int col = 0; col < _range; col++ )
153  ( *inv )( row, col ) = 0.;
154  return inv;
155  }
156 
157  T determinant = det();
158 
159  for ( int row = 0; row < _range; row++ )
160  for ( int col = 0; col < _range; col++ ) {
161  EvtMatrix<T>* minor = min( row, col );
162  inv->_mat[col][row] = std::pow( -1., row + col ) * minor->det() /
163  determinant;
164  delete minor;
165  }
166 
167  return inv;
168 }
169 
170 template <class T>
171 EvtMatrix<T>* operator*( const EvtMatrix<T>& left, const EvtMatrix<T>& right )
172 {
173  // Chech that the matrices have the correct range.
174  if ( left._range != right._range ) {
175  std::cerr << "These matrices cannot be multiplied." << std::endl;
176  return new EvtMatrix<T>();
177  }
178 
179  EvtMatrix<T>* mat = new EvtMatrix<T>();
180  mat->setRange( left._range );
181 
182  // Initialize the elements of the matrix.
183  for ( int row = 0; row < left._range; row++ )
184  for ( int col = 0; col < right._range; col++ )
185  ( *mat )[row][col] = 0;
186 
187  for ( int row = 0; row < left._range; row++ )
188  for ( int col = 0; col < right._range; col++ )
189  for ( int line = 0; line < right._range; line++ )
190  ( *mat )[row][col] += left._mat[row][line] *
191  right._mat[line][col];
192 
193  return mat;
194 }
195 
196 #endif
T ** _mat
Definition: EvtMatrix.hh:31
EvtMatrix< T > * operator *(const EvtMatrix< T > &left, const EvtMatrix< T > &right)
Definition: EvtMatrix.hh:171
T * operator[](int row)
Definition: EvtMatrix.hh:40
std::string dump()
Definition: EvtMatrix.hh:86
int _range
Definition: EvtMatrix.hh:32
EvtMatrix * min(int row, int col)
Definition: EvtMatrix.hh:124
~EvtMatrix()
Definition: EvtMatrix.hh:78
friend EvtMatrix< M > * operator *(const EvtMatrix< M > &left, const EvtMatrix< M > &right)
T & operator()(int row, int col)
Definition: EvtMatrix.hh:39
EvtMatrix * inverse()
Definition: EvtMatrix.hh:143
void setRange(int range)
Definition: EvtMatrix.hh:52