The template ROOT::Math::SMatrix class has 4 template parameters which define, at compile time, its properties. These are:
- type of the contained elements, T, for example float or double;
- number of rows;
- number of columns;
- representation type (SMatrix Storage Representation). This is a class describing the underlined storage model of the Matrix. Presently exists only two types of this class:
- ROOT::Math::MatRepStd for a general nrows x ncols matrix. This class is itself a template on the contained type T, the number of rows and the number of columns. Its data member is an array T[nrows*ncols] containing the matrix data. The data are stored in the row-major C convention. For example, for a matrix, M, of size 3x3, the data \( \left[a_0,a_1,a_2,.......,a_7,a_8 \right] \) are stored in the following order:
\[ M = \left( \begin{array}{ccc} a_0 & a_1 & a_2 \\ a_3 & a_4 & a_5 \\ a_6 & a_7 & a_8 \end{array} \right) \]
- ROOT::Math::MatRepSym for a symmetric matrix of size NxN. This class is a template on the contained type and on the symmetric matrix size, N. It has as data member an array of type T of size N*(N+1)/2, containing the lower diagonal block of the matrix. The order follows the lower diagonal block, still in a row-major convention. For example for a symmetric 3x3 matrix the order of the 6 elements \( \left[a_0,a_1.....a_5 \right]\) is:
\[ M = \left( \begin{array}{ccc} a_0 & a_1 & a_3 \\ a_1 & a_2 & a_4 \\ a_3 & a_4 & a_5 \end{array} \right) \]
Creating a matrix
The following constructors are available to create a matrix:
- Default constructor for a zero matrix (all elements equal to zero).
- Constructor of an identity matrix.
- Copy constructor (and assignment) for a matrix with the same representation, or from a different one when possible, for example from a symmetric to a general matrix.
- Constructor (and assignment) from a matrix expression, like D = A*B + C. Due to the expression template technique, no temporary objects are created in this operation. In the case of an operation like A = A*B + C, a temporary object is needed and it is created automatically to store the intermediary result in order to preserve the validity of this operation.
- Constructor from a generic STL-like iterator copying the data referred by the iterator, following its order. It is both possible to specify the begin and end of the iterator or the begin and the size. In case of a symmetric matrix, it is required only the triangular block and the user can specify whether giving a block representing the lower (default case) or the upper diagonal part.
- Constructor of a symmetric matrix NxN passing a ROOT::Math::SVector with dimension N*(N+1)/2 containing the lower (or upper) block data elements.
Here are some examples on how to create a matrix. We use typedef's in the following examples to avoid the full C++ names for the matrix classes. Notice that for a general matrix the representation has the default value, ROOT::Math::MatRepStd, and it is not needed to be specified. Furthermore, for a general square matrix, the number of column may be as well omitted.
SMatrix33 m0;
double a[9] = {1,2,3,4,5,6,7,8,9};
SMatrix: a generic fixed size D1 x D2 Matrix class.
SVector: a generic fixed size Vector class.
Example to create a symmetric matrix from an std::vector:
std::vector<double>
v(6);
for (
int i = 0; i<6; ++i)
v[i] =
double(i+1);
SMatrixSym3 s(
v.begin(),
v.end())
SMatrix33 m2 = s;
Example to create a symmetric matrix from a ROOT::Math::SVector containing the lower/upper data block:
Accessing and Setting Methods
The matrix elements can be set using the operator()(irow,icol), where irow and icol are the row and column indexes or by using the iterator interface. Notice that the indexes start from zero and not from one as in FORTRAN. All the matrix elements can be set also by using the ROOT::Math::SetElements function passing a generic iterator. The elements can be accessed by these same methods and also by using the ROOT::Math::SMatrix::apply function. The apply(i) function has exactly the same behavior for general and symmetric matrices, in contrast to the iterator access methods which behave differently (it follows the data order).
double d[9]={1,2,3,4,5,6,7,8,9};
There are methods to place and/or retrieve ROOT::Math::SVector objects as rows or columns in (from) a matrix. In addition one can put (get) a sub-matrix as another ROOT::Math::SMatrix object in a matrix. If the size of the sub-vector or sub-matrix are larger than the matrix size a static assert ( a compilation error) is produced. The non-const
The const methods retrieving contents (getting slices of a matrix) are:
SVector3 irow =
m.Row(0);
SVector3 jcol =
m.Col(1);
SVector2 r2 =
m.SubRow<SVector2> (0,1);
SVector2
c2 =
m.SubCol<SVector2> (1,0);
SMatrix22 subM =
m.Sub<SMatrix22> (1,1);
SVector3 diag =
m.Diagonal();
SVector6 vub =
m.UpperBlock();
SVector6 vlb =
m.LowerBlock();
Linear Algebra Functions
Only limited linear algebra functionality is available for SMatrix. It is possible for squared matrices NxN, to find the inverse or to calculate the determinant. Different inversion algorithms are used if the matrix is smaller than 6x6 or if it is symmetric. In the case of a small matrix, a faster direct inversion is used. For a large (N > 6) symmetric matrix the Bunch-Kaufman diagonal pivoting method is used while for a large (N > 6) general matrix an LU factorization is performed using the same algorithm as in the CERNLIB routine dinv.
The determinant of a square matrix can be obtained as follows:
For additional Matrix functionality see the Matrix and Vector Operators and Functions page