EvtGen 2.2.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
Loading...
Searching...
No Matches
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
28template <class T>
29class EvtMatrix {
30 private:
31 T** m_mat;
33
34 public:
35 EvtMatrix() : m_range( 0 ){};
36 ~EvtMatrix();
37 inline void setRange( int range );
38
39 T& operator()( int row, int col ) { return m_mat[row][col]; }
40 T* operator[]( int row ) { return m_mat[row]; }
41 T det();
42 EvtMatrix* min( int row, int col );
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
51template <class T>
52inline 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 ( m_range != range ) {
57 if ( m_range ) {
58 for ( int row = 0; row < m_range; row++ )
59 delete[] m_mat[row];
60 delete[] m_mat;
61 }
62
63 m_mat = new T*[range];
64 for ( int row = 0; row < range; row++ )
65 m_mat[row] = new T[range];
66
67 // Set the new range.
68 m_range = range;
69 }
70
71 // Since user is willing to change the range, reset the matrix elements.
72 for ( int row = 0; row < m_range; row++ )
73 for ( int col = 0; col < m_range; col++ )
74 m_mat[row][col] = 0.;
75}
76
77template <class T>
79{
80 for ( int row = 0; row < m_range; row++ )
81 delete[] m_mat[row];
82 delete[] m_mat;
83}
84
85template <class T>
86std::string EvtMatrix<T>::dump()
87{
88 std::ostringstream str;
89
90 for ( int row = 0; row < m_range; row++ ) {
91 str << "|";
92 for ( int col = 0; col < m_range; col++ )
93 str << "\t" << m_mat[row][col];
94 str << "\t|" << std::endl;
95 }
96
97 return str.str();
98}
99
100template <class T>
102{
103 if ( m_range == 1 )
104 return m_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 ( m_range == 2 )
109 return m_mat[0][0] * m_mat[1][1] - m_mat[0][1] * m_mat[1][0];
110
111 T sum = 0.;
112
113 for ( int col = 0; col < m_range; col++ ) {
114 EvtMatrix<T>* minor = min( 0, col );
115 sum += std::pow( -1., col ) * m_mat[0][col] * minor->det();
116 delete minor;
117 }
118
119 return sum;
120}
121
122// Returns the minor at (i, j).
123template <class T>
124EvtMatrix<T>* EvtMatrix<T>::min( int row, int col )
125{
126 EvtMatrix<T>* minor = new EvtMatrix<T>();
127 minor->setRange( m_range - 1 );
128
129 int minIndex = 0;
130
131 for ( int r = 0; r < m_range; r++ )
132 for ( int c = 0; c < m_range; c++ )
133 if ( ( r != row ) && ( c != col ) ) {
134 ( *minor )( minIndex / ( m_range - 1 ),
135 minIndex % ( m_range - 1 ) ) = m_mat[r][c];
136 minIndex++;
137 }
138
139 return minor;
140}
141
142template <class T>
144{
145 EvtMatrix<T>* inv = new EvtMatrix<T>();
146 inv->setRange( m_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 < m_range; row++ )
152 for ( int col = 0; col < m_range; col++ )
153 ( *inv )( row, col ) = 0.;
154 return inv;
155 }
156
157 T determinant = det();
158
159 for ( int row = 0; row < m_range; row++ )
160 for ( int col = 0; col < m_range; col++ ) {
161 EvtMatrix<T>* minor = min( row, col );
162 inv->m_mat[col][row] = std::pow( -1., row + col ) * minor->det() /
163 determinant;
164 delete minor;
165 }
166
167 return inv;
168}
169
170template <class T>
171EvtMatrix<T>* operator*( const EvtMatrix<T>& left, const EvtMatrix<T>& right )
172{
173 // Chech that the matrices have the correct range.
174 if ( left.m_range != right.m_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.m_range );
181
182 // Initialize the elements of the matrix.
183 for ( int row = 0; row < left.m_range; row++ )
184 for ( int col = 0; col < right.m_range; col++ )
185 ( *mat )[row][col] = 0;
186
187 for ( int row = 0; row < left.m_range; row++ )
188 for ( int col = 0; col < right.m_range; col++ )
189 for ( int line = 0; line < right.m_range; line++ )
190 ( *mat )[row][col] += left.m_mat[row][line] *
191 right.m_mat[line][col];
192
193 return mat;
194}
195
196#endif
EvtMatrix< T > * operator*(const EvtMatrix< T > &left, const EvtMatrix< T > &right)
Definition EvtMatrix.hh:171
int m_range
Definition EvtMatrix.hh:32
friend EvtMatrix< M > * operator*(const EvtMatrix< M > &left, const EvtMatrix< M > &right)
std::string dump()
Definition EvtMatrix.hh:86
EvtMatrix * min(int row, int col)
Definition EvtMatrix.hh:124
T & operator()(int row, int col)
Definition EvtMatrix.hh:39
void setRange(int range)
Definition EvtMatrix.hh:52
T ** m_mat
Definition EvtMatrix.hh:31
EvtMatrix * inverse()
Definition EvtMatrix.hh:143
T * operator[](int row)
Definition EvtMatrix.hh:40