1 /*****************************************************************************
2 * Project: BaBar detector at the SLAC PEP-II B-factory
4 * File: $Id: EvtMatrix.hh,v 1.5 2008/11/27 16:27:24 jordix Exp $
7 * Class to make simple computations with matrices: assignment, product,
8 * determinant, inverse... Still many functions could be implemented.
10 * Modification history:
11 * Jordi Garra Ticó 2008/07/03 File created
12 *****************************************************************************/
15 #ifndef __EVT_MATRIX_HH__
16 #define __EVT_MATRIX_HH__
23 template <class T> class EvtMatrix
29 EvtMatrix() : _range( 0 ) {};
31 inline void setRange( int range );
33 T& operator()( int row, int col ) { return _mat[ row ][ col ]; }
34 T* operator[]( int row ) { return _mat[ row ]; }
36 EvtMatrix* min( int row, int col );
40 template <class M> friend EvtMatrix< M >* operator*( const EvtMatrix< M >& left, const EvtMatrix< M >& right );
46 template <class T> inline void EvtMatrix< T >::setRange( int range )
48 // If the range is changed, delete any previous matrix stored
49 // and allocate elements with the newly specified range.
50 if ( _range != range )
54 for ( int row = 0; row < _range; row++ )
59 _mat = new T*[ range ];
60 for ( int row = 0; row < range; row++ )
61 _mat[ row ] = new T[ range ];
67 // Since user is willing to change the range, reset the matrix elements.
68 for ( int row = 0; row < _range; row++ )
69 for ( int col = 0; col < _range; col++ )
70 _mat[ row ][ col ] = 0.;
74 template <class T> EvtMatrix< T >::~EvtMatrix()
76 for( int row = 0; row < _range; row++ )
82 template <class T> std::string EvtMatrix< T >::dump()
84 std::ostringstream str;
86 for ( int row = 0; row < _range; row++ )
89 for ( int col = 0; col < _range; col++ )
90 str << "\t" << _mat[ row ][ col ];
91 str << "\t|" << std::endl;
98 template <class T> T EvtMatrix< T >::det()
101 return _mat[ 0 ][ 0 ];
103 // There's no need to define the range 2 determinant manually, but it may
104 // speed up the calculation.
106 return _mat[ 0 ][ 0 ] * _mat[ 1 ][ 1 ] - _mat[ 0 ][ 1 ] * _mat[ 1 ][ 0 ];
110 for ( int col = 0; col < _range; col++ )
112 EvtMatrix< T >* minor = min( 0, col );
113 sum += pow( -1., col ) * _mat[ 0 ][ col ] * minor->det();
121 // Returns the minor at (i, j).
122 template <class T> EvtMatrix< T >* EvtMatrix< T >::min( int row, int col )
124 EvtMatrix< T >* minor = new EvtMatrix< T >();
125 minor->setRange( _range - 1 );
129 for ( int r = 0; r < _range; r++ )
130 for ( int c = 0; c < _range; c++ )
131 if ( ( r != row ) && ( c != col ) )
133 (*minor)( minIndex / ( _range - 1 ), minIndex % ( _range - 1 ) ) = _mat[ r ][ c ];
141 template <class T> EvtMatrix< T >* EvtMatrix< T >::inverse()
143 EvtMatrix< T >* inv = new EvtMatrix< T >();
144 inv->setRange( _range );
148 std::cerr << "This matrix has a null determinant and cannot be inverted. Returning zero matrix." << std::endl;
149 for ( int row = 0; row < _range; row++ )
150 for ( int col = 0; col < _range; col++ )
151 (*inv)( row, col ) = 0.;
155 T determinant = det();
157 for ( int row = 0; row < _range; row++ )
158 for ( int col = 0; col < _range; col++ )
160 EvtMatrix< T >* minor = min( row, col );
161 inv->_mat[col][row] = pow( -1., row + col ) * minor->det() / determinant;
170 EvtMatrix< T >* operator*( const EvtMatrix< T >& left, const EvtMatrix< T >& right )
172 // Chech that the matrices have the correct range.
173 if ( left._range != right._range )
175 std::cerr << "These matrices cannot be multiplied." << std::endl;
176 return new EvtMatrix< T >();
179 EvtMatrix< T >* mat = new EvtMatrix< T >();
180 mat->setRange( left._range );
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;
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 ] * right._mat[ line ][ col ];