Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:22:09

0001 // @(#)root/smatrix:$Id$
0002 // Author: T. Glebe, L. Moneta, J. Palacios    2005
0003 
0004 #ifndef ROOT_Math_SMatrix
0005 #define ROOT_Math_SMatrix
0006 
0007 /*********************************************************************************
0008 //
0009 // source:
0010 //
0011 // type:      source code
0012 //
0013 // created:   20. Mar 2001
0014 //
0015 // author:    Thorsten Glebe
0016 //            HERA-B Collaboration
0017 //            Max-Planck-Institut fuer Kernphysik
0018 //            Saupfercheckweg 1
0019 //            69117 Heidelberg
0020 //            Germany
0021 //            E-mail: T.Glebe@mpi-hd.mpg.de
0022 //
0023 // Description: A fixed size two dimensional Matrix class
0024 //
0025 // changes:
0026 // 20 Mar 2001 (TG) creation
0027 // 21 Mar 2001 (TG) added operators +=, -=, *=, /=
0028 // 26 Mar 2001 (TG) place_in_row(), place_in_col() added
0029 // 02 Apr 2001 (TG) non-const Array() added
0030 // 03 Apr 2001 (TG) invert() added
0031 // 07 Apr 2001 (TG) CTOR from SVertex (dyadic product) added
0032 // 09 Apr 2001 (TG) CTOR from array added
0033 // 11 Apr 2001 (TG) rows(), cols(), size() replaced by rows, cols, size
0034 // 25 Mai 2001 (TG) row(), col() added
0035 // 04 Sep 2001 (TG) moved inlined functions to .icc file
0036 // 11 Jan 2002 (TG) added operator==(), operator!=()
0037 // 14 Jan 2002 (TG) added more operator==(), operator!=(), operator>(), operator<()
0038 //
0039 ***************************************************************************/
0040 // for platform specific configurations
0041 
0042 #include "Math/MConfig.h"
0043 
0044 #include <iosfwd>
0045 
0046 
0047 /**
0048 \defgroup SMatrixSVector Matrix and Vector classes
0049 \ingroup SMatrixGroup
0050 
0051 Classes representing Matrices and Vectors of arbitrary type and dimension.
0052 For a detailed description and usage examples see:
0053 
0054   - \ref SVectorDoc
0055   - \ref SMatrixDoc
0056   - \ref MatVecFunctions
0057 
0058 */
0059 
0060 
0061 #include "Math/Expression.h"
0062 #include "Math/MatrixRepresentationsStatic.h"
0063 
0064 
0065 namespace ROOT {
0066 
0067 namespace Math {
0068 
0069 
0070 template <class T, unsigned int D> class SVector;
0071 
0072 struct SMatrixIdentity { };
0073 struct SMatrixNoInit { };
0074 
0075 //__________________________________________________________________________
0076 /**
0077     SMatrix: a generic fixed size D1 x D2 Matrix class.
0078     The class is template on the scalar type, on the matrix sizes:
0079     D1 = number of rows and D2 = number of columns
0080     amd on the representation storage type.
0081     By default the representation is MatRepStd<T,D1,D2> (standard D1xD2 of type T),
0082     but it can be of type MatRepSym<T,D> for symmetric matrices DxD, where the storage is only
0083     D*(D+1)/2.
0084 
0085     See \ref SMatrixDoc.
0086 
0087     Original author is Thorsten Glebe
0088     HERA-B Collaboration, MPI Heidelberg (Germany)
0089 
0090     @ingroup SMatrixSVector
0091 
0092     @authors T. Glebe, L. Moneta and J. Palacios
0093 */
0094 //==============================================================================
0095 // SMatrix: column-wise storage
0096 //==============================================================================
0097 template <class T,
0098           unsigned int D1,
0099           unsigned int D2 = D1,
0100           class R=MatRepStd<T, D1, D2> >
0101 class SMatrix {
0102 public:
0103    /** @name --- Typedefs --- */
0104 
0105    /** contained scalar type */
0106    typedef T  value_type;
0107 
0108    /** storage representation type */
0109    typedef R  rep_type;
0110 
0111    /** STL iterator interface. */
0112    typedef T*  iterator;
0113 
0114    /** STL const_iterator interface. */
0115    typedef const T*  const_iterator;
0116 
0117 
0118 
0119    /** @name --- Constructors and Assignment --- */
0120 
0121    /**
0122       Default constructor:
0123    */
0124    SMatrix();
0125    ///
0126   /**
0127        construct from without initialization
0128    */
0129    inline SMatrix( SMatrixNoInit ){}
0130 
0131    /**
0132        construct from an identity matrix
0133    */
0134    SMatrix( SMatrixIdentity );
0135    /**
0136        copy constructor (from a matrix of the same representation
0137    */
0138    SMatrix(const SMatrix<T,D1,D2,R>& rhs);
0139    /**
0140       construct from a matrix with different representation.
0141       Works only from symmetric to general and not viceversa.
0142    */
0143    template <class R2>
0144    SMatrix(const SMatrix<T,D1,D2,R2>& rhs);
0145 
0146    /**
0147       Construct from an expression.
0148       In case of symmetric matrices does not work if expression is of type general
0149       matrices. In case one needs to force the assignment from general to symmetric, one can use the
0150       ROOT::Math::AssignSym::Evaluate function.
0151    */
0152    template <class A, class R2>
0153    SMatrix(const Expr<A,T,D1,D2,R2>& rhs);
0154 
0155 
0156    /**
0157       Constructor with STL iterator interface. The data will be copied into the matrix
0158       \param begin start iterator position
0159       \param end end iterator position
0160       \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
0161       \param lower if true the lower triangular part is filled
0162 
0163       Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the
0164       triangular block. In the case of symmetric matrices triang is considered always to be true
0165       (what-ever the user specifies) and the size of the iterators must be equal to the size of the
0166       triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2
0167 
0168    */
0169    template<class InputIterator>
0170    SMatrix(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);
0171 
0172    /**
0173       Constructor with STL iterator interface. The data will be copied into the matrix
0174       \param begin  start iterator position
0175       \param size   iterator size
0176       \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
0177       \param lower if true the lower triangular part is filled
0178 
0179       Size of the iterators must not be larger than the size of the matrix representation.
0180       In the case of symmetric matrices the size is N*(N+1)/2.
0181 
0182    */
0183    template<class InputIterator>
0184    SMatrix(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);
0185 
0186    /**
0187       constructor of a symmetrix a matrix from a SVector containing the lower (upper)
0188       triangular part.
0189    */
0190 #ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
0191    SMatrix(const SVector<T, D1*(D2+1)/2> & v, bool lower = true );
0192 #else
0193    template<unsigned int N>
0194    SMatrix(const SVector<T,N> & v, bool lower = true );
0195 #endif
0196 
0197 
0198    /**
0199        Construct from a scalar value (only for size 1 matrices)
0200    */
0201    explicit SMatrix(const T& rhs);
0202 
0203    /**
0204        Assign from another compatible matrix.
0205        Possible Symmetirc to general but NOT vice-versa
0206    */
0207    template <class M>
0208    SMatrix<T,D1,D2,R>& operator=(const M& rhs);
0209 
0210    SMatrix<T,D1,D2,R>& operator=(const SMatrix<T,D1,D2,R>& rhs);
0211 
0212    /**
0213        Assign from a matrix expression
0214    */
0215    template <class A, class R2>
0216    SMatrix<T,D1,D2,R>& operator=(const Expr<A,T,D1,D2,R2>& rhs);
0217 
0218    /**
0219       Assign from an identity matrix
0220    */
0221    SMatrix<T,D1,D2,R> & operator=(SMatrixIdentity );
0222 
0223    /**
0224        Assign from a scalar value (only for size 1 matrices)
0225    */
0226    SMatrix<T,D1,D2,R>& operator=(const T& rhs);
0227 
0228    /** @name --- Matrix dimension --- */
0229 
0230    /**
0231       Enumeration defining the matrix dimension,
0232       number of rows, columns and size = rows*columns)
0233    */
0234    enum {
0235       /// return no. of matrix rows
0236       kRows = D1,
0237       /// return no. of matrix columns
0238       kCols = D2,
0239       /// return no of elements: rows*columns
0240       kSize = D1*D2
0241    };
0242 
0243    /** @name --- Access functions --- */
0244 
0245    /** access the parse tree with the index starting from zero and
0246        following the C convention for the order in accessing
0247        the matrix elements.
0248        Same convention for general and symmetric matrices.
0249    */
0250    T apply(unsigned int i) const;
0251 
0252    /// return read-only pointer to internal array
0253    const T* Array() const;
0254    /// return pointer to internal array
0255    T* Array();
0256 
0257    /** @name --- STL-like interface ---
0258        The iterators access the matrix element in the order how they are
0259        stored in memory. The C (row-major) convention is used, and in the
0260        case of symmetric matrices the iterator spans only the lower diagonal
0261        block. For example for a symmetric 3x3 matrices the order of the 6
0262        elements \f${a_0,...a_5}\f$ is:
0263        \f[
0264        M = \left( \begin{array}{ccc}
0265        a_0 & a_1 & a_3  \\
0266        a_1 & a_2  & a_4  \\
0267        a_3 & a_4 & a_5   \end{array} \right)
0268        \f]
0269    */
0270 
0271    /** STL iterator interface. */
0272    iterator begin();
0273 
0274    /** STL iterator interface. */
0275    iterator end();
0276 
0277    /** STL const_iterator interface. */
0278    const_iterator begin() const;
0279 
0280    /** STL const_iterator interface. */
0281    const_iterator end() const;
0282 
0283    /**
0284       Set matrix elements with STL iterator interface. The data will be copied into the matrix
0285       \param begin start iterator position
0286       \param end end iterator position
0287       \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
0288       \param lower if true the lower triangular part is filled
0289 
0290       Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the
0291       triangular block. In the case of symmetric matrices triang is considered always to be true
0292       (what-ever the user specifies) and the size of the iterators must be equal to the size of the
0293       triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2
0294 
0295    */
0296    template<class InputIterator>
0297    void SetElements(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);
0298 
0299    /**
0300       Constructor with STL iterator interface. The data will be copied into the matrix
0301       \param begin  start iterator position
0302       \param size   iterator size
0303       \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
0304       \param lower if true the lower triangular part is filled
0305 
0306       Size of the iterators must not be larger than the size of the matrix representation.
0307       In the case of symmetric matrices the size is N*(N+1)/2.
0308 
0309    */
0310    template<class InputIterator>
0311    void SetElements(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);
0312 
0313 
0314    /** @name --- Operators --- */
0315    /// element wise comparison
0316    bool operator==(const T& rhs) const;
0317    /// element wise comparison
0318    bool operator!=(const T& rhs) const;
0319    /// element wise comparison
0320    template <class R2>
0321    bool operator==(const SMatrix<T,D1,D2,R2>& rhs) const;
0322    /// element wise comparison
0323    bool operator!=(const SMatrix<T,D1,D2,R>& rhs) const;
0324    /// element wise comparison
0325    template <class A, class R2>
0326    bool operator==(const Expr<A,T,D1,D2,R2>& rhs) const;
0327    /// element wise comparison
0328    template <class A, class R2>
0329    bool operator!=(const Expr<A,T,D1,D2,R2>& rhs) const;
0330 
0331    /// element wise comparison
0332    bool operator>(const T& rhs) const;
0333    /// element wise comparison
0334    bool operator<(const T& rhs) const;
0335    /// element wise comparison
0336    template <class R2>
0337    bool operator>(const SMatrix<T,D1,D2,R2>& rhs) const;
0338    /// element wise comparison
0339    template <class R2>
0340    bool operator<(const SMatrix<T,D1,D2,R2>& rhs) const;
0341    /// element wise comparison
0342    template <class A, class R2>
0343    bool operator>(const Expr<A,T,D1,D2,R2>& rhs) const;
0344    /// element wise comparison
0345    template <class A, class R2>
0346    bool operator<(const Expr<A,T,D1,D2,R2>& rhs) const;
0347 
0348    /**
0349       read only access to matrix element, with indices starting from 0
0350    */
0351    const T& operator()(unsigned int i, unsigned int j) const;
0352     /**
0353       read/write access to matrix element with indices starting from 0
0354    */
0355    T& operator()(unsigned int i, unsigned int j);
0356 
0357    /**
0358       read only access to matrix element, with indices starting from 0.
0359       Function will check index values and it will assert if they are wrong
0360    */
0361    const T& At(unsigned int i, unsigned int j) const;
0362    /**
0363       read/write access to matrix element with indices starting from 0.
0364       Function will check index values and it will assert if they are wrong
0365    */
0366    T& At(unsigned int i, unsigned int j);
0367 
0368 
0369   // helper class for implementing the m[i][j] operator
0370 
0371    class SMatrixRow {
0372    public:
0373       SMatrixRow ( SMatrix<T,D1,D2,R> & rhs, unsigned int i ) :
0374          fMat(&rhs), fRow(i)
0375       {}
0376       T & operator[](int j) { return (*fMat)(fRow,j); }
0377    private:
0378       SMatrix<T,D1,D2,R> *  fMat;
0379       unsigned int fRow;
0380    };
0381 
0382    class SMatrixRow_const {
0383    public:
0384       SMatrixRow_const ( const SMatrix<T,D1,D2,R> & rhs, unsigned int i ) :
0385          fMat(&rhs), fRow(i)
0386       {}
0387 
0388       const T & operator[](int j) const { return (*fMat)(fRow, j); }
0389 
0390    private:
0391       const SMatrix<T,D1,D2,R> *  fMat;
0392       unsigned int fRow;
0393    };
0394 
0395   /**
0396       read only access to matrix element, with indices starting from 0 : m[i][j]
0397    */
0398    SMatrixRow_const  operator[](unsigned int i) const { return SMatrixRow_const(*this, i); }
0399    /**
0400       read/write access to matrix element with indices starting from 0 : m[i][j]
0401    */
0402    SMatrixRow operator[](unsigned int i) { return SMatrixRow(*this, i); }
0403 
0404 
0405    /**
0406       addition with a scalar
0407    */
0408    SMatrix<T,D1,D2,R>&operator+=(const T& rhs);
0409 
0410    /**
0411       addition with another matrix of any compatible representation
0412    */
0413    template <class R2>
0414    SMatrix<T,D1,D2,R>&operator+=(const SMatrix<T,D1,D2,R2>& rhs);
0415 
0416    /**
0417       addition with a compatible matrix expression
0418    */
0419    template <class A, class R2>
0420    SMatrix<T,D1,D2,R>& operator+=(const Expr<A,T,D1,D2,R2>& rhs);
0421 
0422    /**
0423       subtraction with a scalar
0424    */
0425    SMatrix<T,D1,D2,R>& operator-=(const T& rhs);
0426 
0427    /**
0428       subtraction with another matrix of any compatible representation
0429    */
0430    template <class R2>
0431    SMatrix<T,D1,D2,R>&operator-=(const SMatrix<T,D1,D2,R2>& rhs);
0432 
0433    /**
0434       subtraction with a compatible matrix expression
0435    */
0436    template <class A, class R2>
0437    SMatrix<T,D1,D2,R>& operator-=(const Expr<A,T,D1,D2,R2>& rhs);
0438 
0439    /**
0440       multiplication with a scalar
0441     */
0442    SMatrix<T,D1,D2,R>& operator*=(const T& rhs);
0443 
0444 
0445    /**
0446       multiplication with another compatible matrix (it is a real matrix multiplication)
0447       Note that this operation does not avid to create a temporary to store intermediate result
0448    */
0449    template <class R2>
0450    SMatrix<T,D1,D2,R>& operator*=(const SMatrix<T,D1,D2,R2>& rhs);
0451 
0452    /**
0453       multiplication with a compatible matrix expression (it is a real matrix multiplication)
0454    */
0455    template <class A, class R2>
0456    SMatrix<T,D1,D2,R>& operator*=(const Expr<A,T,D1,D2,R2>& rhs);
0457 
0458 
0459    /**
0460       division with a scalar
0461    */
0462    SMatrix<T,D1,D2,R>& operator/=(const T& rhs);
0463 
0464 
0465 
0466    /** @name --- Linear Algebra Functions --- */
0467 
0468    /**
0469       Invert a square Matrix ( this method changes the current matrix).
0470       Return true if inversion is successful.
0471       The method used for general square matrices is the LU factorization taken from Dinv routine
0472       from the CERNLIB (written in C++ from CLHEP authors)
0473       In case of symmetric matrices Bunch-Kaufman diagonal pivoting method is used
0474       (The implementation is the one written by the CLHEP authors)
0475    */
0476    bool Invert();
0477 
0478    /**
0479       Invert a square Matrix and  returns a new matrix. In case the inversion fails
0480       the current matrix is returned.
0481       \param ifail . ifail will be set to 0 when inversion is successful.
0482       See ROOT::Math::SMatrix::Invert for the inversion algorithm
0483    */
0484    SMatrix<T,D1,D2,R> Inverse(int & ifail ) const;
0485 
0486    /**
0487       Fast inversion of a square Matrix ( this method changes the current matrix).
0488       Return true if inversion is successful.
0489       The method used is based on direct inversion using the Cramer rule for
0490       matrices upto 5x5. Afterwards the same default algorithm of Invert() is used.
0491       Note that this method is faster but can suffer from much larger numerical accuracy
0492       when the condition of the matrix is large
0493    */
0494    bool InvertFast();
0495 
0496    /**
0497       Invert a square Matrix and  returns a new matrix. In case the inversion fails
0498       the current matrix is returned.
0499       \param ifail . ifail will be set to 0 when inversion is successful.
0500       See ROOT::Math::SMatrix::InvertFast for the inversion algorithm
0501    */
0502    SMatrix<T,D1,D2,R> InverseFast(int & ifail ) const;
0503 
0504    /**
0505       Inversion of a symmetric positive defined Matrix using Choleski decomposition.
0506       ( this method changes the current matrix).
0507       Return true if inversion is successful.
0508       The method used is based on Choleski decomposition
0509       A compile error is given if the matrix is not of type symmetric and a run-time failure if the
0510       matrix is not positive defined.
0511       For solving  a linear system, it is possible to use also the function
0512       ROOT::Math::SolveChol(matrix, vector) which will be faster than performing the inversion
0513    */
0514    bool InvertChol();
0515 
0516    /**
0517       Invert of a symmetric positive defined Matrix using Choleski decomposition.
0518       A compile error is given if the matrix is not of type symmetric and a run-time failure if the
0519       matrix is not positive defined.
0520       In case the inversion fails the current matrix is returned.
0521       \param ifail . ifail will be set to 0 when inversion is successful.
0522       See ROOT::Math::SMatrix::InvertChol for the inversion algorithm
0523    */
0524    SMatrix<T,D1,D2,R> InverseChol(int & ifail ) const;
0525 
0526    /**
0527       determinant of square Matrix via Dfact.
0528       Return true when the calculation is successful.
0529       \param det will contain the calculated determinant value
0530       \b Note: this will destroy the contents of the Matrix!
0531    */
0532    bool Det(T& det);
0533 
0534    /**
0535       determinant of square Matrix via Dfact.
0536       Return true when the calculation is successful.
0537       \param det will contain the calculated determinant value
0538       \b Note: this will preserve the content of the Matrix!
0539    */
0540    bool Det2(T& det) const;
0541 
0542 
0543    /** @name --- Matrix Slice Functions --- */
0544 
0545    /// place a vector in a Matrix row
0546    template <unsigned int D>
0547    SMatrix<T,D1,D2,R>& Place_in_row(const SVector<T,D>& rhs,
0548                                     unsigned int row,
0549                                     unsigned int col);
0550    /// place a vector expression in a Matrix row
0551    template <class A, unsigned int D>
0552    SMatrix<T,D1,D2,R>& Place_in_row(const VecExpr<A,T,D>& rhs,
0553                                     unsigned int row,
0554                                     unsigned int col);
0555    /// place a vector in a Matrix column
0556    template <unsigned int D>
0557    SMatrix<T,D1,D2,R>& Place_in_col(const SVector<T,D>& rhs,
0558                                     unsigned int row,
0559                                     unsigned int col);
0560    /// place a vector expression in a Matrix column
0561    template <class A, unsigned int D>
0562    SMatrix<T,D1,D2,R>& Place_in_col(const VecExpr<A,T,D>& rhs,
0563                                     unsigned int row,
0564                                     unsigned int col);
0565    /// place a matrix in this matrix
0566    template <unsigned int D3, unsigned int D4, class R2>
0567    SMatrix<T,D1,D2,R>& Place_at(const SMatrix<T,D3,D4,R2>& rhs,
0568                                 unsigned int row,
0569                                 unsigned int col);
0570    /// place a matrix expression in this matrix
0571    template <class A, unsigned int D3, unsigned int D4, class R2>
0572    SMatrix<T,D1,D2,R>& Place_at(const Expr<A,T,D3,D4,R2>& rhs,
0573                                 unsigned int row,
0574                                 unsigned int col);
0575 
0576    /**
0577       return a full Matrix row as a vector (copy the content in a new vector)
0578    */
0579    SVector<T,D2> Row(unsigned int therow) const;
0580 
0581    /**
0582       return a full Matrix column as a vector (copy the content in a new vector)
0583    */
0584    SVector<T,D1> Col(unsigned int thecol) const;
0585 
0586    /**
0587       return a slice of therow as a vector starting at the column value col0 until col0+N,
0588       where N is the size of the vector (SVector::kSize )
0589       Condition  col0+N <= D2
0590    */
0591    template <class SubVector>
0592    SubVector SubRow(unsigned int therow, unsigned int col0 = 0 ) const;
0593 
0594    /**
0595       return a slice of the column as a vector starting at the row value row0 until row0+Dsub.
0596       where N is the size of the vector (SVector::kSize )
0597       Condition  row0+N <= D1
0598    */
0599    template <class SubVector>
0600    SubVector SubCol(unsigned int thecol, unsigned int row0 = 0) const;
0601 
0602    /**
0603       return a submatrix with the upper left corner at the values (row0, col0) and with sizes N1, N2
0604       where N1 and N2 are the dimension of the sub-matrix (SubMatrix::kRows and SubMatrix::kCols )
0605       Condition  row0+N1 <= D1 && col0+N2 <=D2
0606    */
0607    template <class SubMatrix >
0608    SubMatrix Sub(unsigned int row0, unsigned int col0) const;
0609 
0610    /**
0611       return diagonal elements of a matrix as a Vector.
0612       It works only for squared matrices D1 == D2, otherwise it will produce a compile error
0613    */
0614    SVector<T,D1> Diagonal() const;
0615 
0616    /**
0617       Set the diagonal elements from a Vector
0618       Require that vector implements SVector::kSize since a check (statically) is done on
0619       diagonal size == vector size
0620    */
0621    template <class Vector>
0622    void SetDiagonal(const Vector & v);
0623 
0624    /**
0625       return the trace of a matrix
0626       Sum of the diagonal elements
0627    */
0628    T Trace() const;
0629 
0630 
0631    /**
0632       return the upper Triangular block of the matrices (including the diagonal) as
0633       a vector of sizes N = D1 * (D1 + 1)/2.
0634       It works only for square matrices with D1==D2, otherwise it will produce a compile error
0635    */
0636 #ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
0637    SVector<T, D1 * (D2 +1)/2> UpperBlock() const;
0638 #else
0639    template<class SubVector>
0640    SubVector UpperBlock() const;
0641 #endif
0642 
0643    /**
0644       return the lower Triangular block of the matrices (including the diagonal) as
0645       a vector of sizes N = D1 * (D1 + 1)/2.
0646       It works only for square matrices with D1==D2, otherwise it will produce a compile error
0647    */
0648 #ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
0649    SVector<T, D1 * (D2 +1)/2> LowerBlock() const;
0650 #else
0651    template<class SubVector>
0652    SubVector LowerBlock() const;
0653 #endif
0654 
0655 
0656    /** @name --- Other Functions --- */
0657 
0658    /**
0659        Function to check if a matrix is sharing same memory location of the passed pointer
0660        This function is used by the expression templates to avoid the alias problem during
0661        expression evaluation. When  the matrix is in use, for example in operations
0662        like A = B * A, a temporary object storing the intermediate result is automatically
0663        created when evaluating the expression.
0664 
0665    */
0666    bool IsInUse(const T* p) const;
0667 
0668    // submatrices
0669 
0670    /// Print: used by operator<<()
0671    std::ostream& Print(std::ostream& os) const;
0672 
0673 
0674 
0675 
0676 public:
0677 
0678    /** @name --- Data Member --- */
0679 
0680    /**
0681       Matrix Storage Object containing matrix data
0682    */
0683    R fRep;
0684 
0685 }; // end of class SMatrix
0686 
0687 
0688 
0689 
0690 //==============================================================================
0691 // operator<<
0692 //==============================================================================
0693 template <class T, unsigned int D1, unsigned int D2, class R>
0694 inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::SMatrix<T,D1,D2,R>& rhs) {
0695   return rhs.Print(os);
0696 }
0697 
0698 
0699   }  // namespace Math
0700 
0701 }  // namespace ROOT
0702 
0703 
0704 
0705 #include "Math/SMatrix.icc"
0706 
0707 #include "Math/MatrixFunctions.h"
0708 
0709 #endif  /* ROOT_Math_SMatrix  */