// @(#)root/smatrix:$Id$
// Author: T. Glebe, L. Moneta, J. Palacios    2005

#ifndef ROOT_Math_SMatrix
#define ROOT_Math_SMatrix

/*********************************************************************************
//
// source:
//
// type:      source code
//
// created:   20. Mar 2001
//
// author:    Thorsten Glebe
//            HERA-B Collaboration
//            Max-Planck-Institut fuer Kernphysik
//            Saupfercheckweg 1
//            69117 Heidelberg
//            Germany
//            E-mail: T.Glebe@mpi-hd.mpg.de
//
// Description: A fixed size two dimensional Matrix class
//
// changes:
// 20 Mar 2001 (TG) creation
// 21 Mar 2001 (TG) added operators +=, -=, *=, /=
// 26 Mar 2001 (TG) place_in_row(), place_in_col() added
// 02 Apr 2001 (TG) non-const Array() added
// 03 Apr 2001 (TG) invert() added
// 07 Apr 2001 (TG) CTOR from SVertex (dyadic product) added
// 09 Apr 2001 (TG) CTOR from array added
// 11 Apr 2001 (TG) rows(), cols(), size() replaced by rows, cols, size
// 25 Mai 2001 (TG) row(), col() added
// 04 Sep 2001 (TG) moved inlined functions to .icc file
// 11 Jan 2002 (TG) added operator==(), operator!=()
// 14 Jan 2002 (TG) added more operator==(), operator!=(), operator>(), operator<()
//
***************************************************************************/
// for platform specific configurations

#ifndef ROOT_Math_MnConfig
#include "Math/MConfig.h"
#endif

#include <iosfwd>




//doxygen tag

/**
   @defgroup SMatrixGroup SMatrix

   \ref SMatrix  for high performance vector and matrix computations.
   Classes representing Matrices and Vectors of arbitrary type and dimension and related functions.
   For a detailed description and usage examples see:
   <ul>
    <li>\ref SMatrix home page
    <li>\ref SVectorDoc
    <li>\ref SMatrixDoc
    <li>\ref MatVecFunctions
   </ul>

*/

/**
   @defgroup SMatrixSVector Matrix and Vector classes

   @ingroup SMatrixGroup

   Classes representing Matrices and Vectors of arbitrary type and dimension.
   For a detailed description and usage examples see:
   <ul>
    <li>\ref SVectorDoc
    <li>\ref SMatrixDoc
    <li>\ref MatVecFunctions
   </ul>

*/


#ifndef ROOT_Math_Expression
#include "Math/Expression.h"
#endif
#ifndef ROOT_Math_MatrixRepresentationsStatic
#include "Math/MatrixRepresentationsStatic.h"
#endif


namespace ROOT {

namespace Math {


template <class T, unsigned int D> class SVector;

struct SMatrixIdentity { };
struct SMatrixNoInit { };

//__________________________________________________________________________
/**
    SMatrix: a generic fixed size D1 x D2 Matrix class.
    The class is template on the scalar type, on the matrix sizes:
    D1 = number of rows and D2 = number of columns
    amd on the representation storage type.
    By default the representation is MatRepStd<T,D1,D2> (standard D1xD2 of type T),
    but it can be of type MatRepSym<T,D> for symmetric matrices DxD, where the storage is only
    D*(D+1)/2.

    See \ref SMatrixDoc.

    Original author is Thorsten Glebe
    HERA-B Collaboration, MPI Heidelberg (Germany)

    @ingroup SMatrixSVector

    @authors T. Glebe, L. Moneta and J. Palacios
*/
//==============================================================================
// SMatrix: column-wise storage
//==============================================================================
template <class T,
          unsigned int D1,
          unsigned int D2 = D1,
          class R=MatRepStd<T, D1, D2> >
class SMatrix {
public:
   /** @name --- Typedefs --- */

   /** contained scalar type */
   typedef T  value_type;

   /** storage representation type */
   typedef R  rep_type;

   /** STL iterator interface. */
   typedef T*  iterator;

   /** STL const_iterator interface. */
   typedef const T*  const_iterator;



   /** @name --- Constructors and Assignment --- */

   /**
      Default constructor:
   */
   SMatrix();
   ///
  /**
       construct from without initialization
   */
   inline SMatrix( SMatrixNoInit ){}

   /**
       construct from an identity matrix
   */
   SMatrix( SMatrixIdentity );
   /**
       copy constructor (from a matrix of the same representation
   */
   SMatrix(const SMatrix<T,D1,D2,R>& rhs);
   /**
      construct from a matrix with different representation.
      Works only from symmetric to general and not viceversa.
   */
   template <class R2>
   SMatrix(const SMatrix<T,D1,D2,R2>& rhs);

   /**
      Construct from an expression.
      In case of symmetric matrices does not work if expression is of type general
      matrices. In case one needs to force the assignment from general to symmetric, one can use the
      ROOT::Math::AssignSym::Evaluate function.
   */
   template <class A, class R2>
   SMatrix(const Expr<A,T,D1,D2,R2>& rhs);


   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin start iterator position
      \param end end iterator position
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
      \param lower if true the lower triangular part is filled

      Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the
      triangular block. In the case of symmetric matrices triang is considered always to be true
      (what-ever the user specifies) and the size of the iterators must be equal to the size of the
      triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2

   */
   template<class InputIterator>
   SMatrix(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);

   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin  start iterator position
      \param size   iterator size
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
      \param lower if true the lower triangular part is filled

      Size of the iterators must not be larger than the size of the matrix representation.
      In the case of symmetric matrices the size is N*(N+1)/2.

   */
   template<class InputIterator>
   SMatrix(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);

   /**
      constructor of a symmetrix a matrix from a SVector containing the lower (upper)
      triangular part.
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SMatrix(const SVector<T, D1*(D2+1)/2> & v, bool lower = true );
#else
   template<unsigned int N>
   SMatrix(const SVector<T,N> & v, bool lower = true );
#endif


   /**
       Construct from a scalar value (only for size 1 matrices)
   */
   explicit SMatrix(const T& rhs);

   /**
       Assign from another compatible matrix.
       Possible Symmetirc to general but NOT vice-versa
   */
   template <class M>
   SMatrix<T,D1,D2,R>& operator=(const M& rhs);

   /**
       Assign from a matrix expression
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      Assign from an identity matrix
   */
   SMatrix<T,D1,D2,R> & operator=(SMatrixIdentity );

   /**
       Assign from a scalar value (only for size 1 matrices)
   */
   SMatrix<T,D1,D2,R>& operator=(const T& rhs);

   /** @name --- Matrix dimension --- */

   /**
      Enumeration defining the matrix dimension,
      number of rows, columns and size = rows*columns)
   */
   enum {
      /// return no. of matrix rows
      kRows = D1,
      /// return no. of matrix columns
      kCols = D2,
      /// return no of elements: rows*columns
      kSize = D1*D2
   };

   /** @name --- Access functions --- */

   /** access the parse tree with the index starting from zero and
       following the C convention for the order in accessing
       the matrix elements.
       Same convention for general and symmetric matrices.
   */
   T apply(unsigned int i) const;

   /// return read-only pointer to internal array
   const T* Array() const;
   /// return pointer to internal array
   T* Array();

   /** @name --- STL-like interface ---
       The iterators access the matrix element in the order how they are
       stored in memory. The C (row-major) convention is used, and in the
       case of symmetric matrices the iterator spans only the lower diagonal
       block. For example for a symmetric 3x3 matrices the order of the 6
       elements \f${a_0,...a_5}\f$ is:
       \f[
       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)
       \f]
   */

   /** STL iterator interface. */
   iterator begin();

   /** STL iterator interface. */
   iterator end();

   /** STL const_iterator interface. */
   const_iterator begin() const;

   /** STL const_iterator interface. */
   const_iterator end() const;

   /**
      Set matrix elements with STL iterator interface. The data will be copied into the matrix
      \param begin start iterator position
      \param end end iterator position
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
      \param lower if true the lower triangular part is filled

      Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the
      triangular block. In the case of symmetric matrices triang is considered always to be true
      (what-ever the user specifies) and the size of the iterators must be equal to the size of the
      triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2

   */
   template<class InputIterator>
   void SetElements(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);

   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin  start iterator position
      \param size   iterator size
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators
      \param lower if true the lower triangular part is filled

      Size of the iterators must not be larger than the size of the matrix representation.
      In the case of symmetric matrices the size is N*(N+1)/2.

   */
   template<class InputIterator>
   void SetElements(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);


   /** @name --- Operators --- */
   /// element wise comparison
   bool operator==(const T& rhs) const;
   /// element wise comparison
   bool operator!=(const T& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator==(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   bool operator!=(const SMatrix<T,D1,D2,R>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator==(const Expr<A,T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator!=(const Expr<A,T,D1,D2,R2>& rhs) const;

   /// element wise comparison
   bool operator>(const T& rhs) const;
   /// element wise comparison
   bool operator<(const T& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator>(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator<(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator>(const Expr<A,T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator<(const Expr<A,T,D1,D2,R2>& rhs) const;

   /**
      read only access to matrix element, with indices starting from 0
   */
   const T& operator()(unsigned int i, unsigned int j) const;
    /**
      read/write access to matrix element with indices starting from 0
   */
   T& operator()(unsigned int i, unsigned int j);

   /**
      read only access to matrix element, with indices starting from 0.
      Function will check index values and it will assert if they are wrong
   */
   const T& At(unsigned int i, unsigned int j) const;
   /**
      read/write access to matrix element with indices starting from 0.
      Function will check index values and it will assert if they are wrong
   */
   T& At(unsigned int i, unsigned int j);


  // helper class for implementing the m[i][j] operator

   class SMatrixRow {
   public:
      SMatrixRow ( SMatrix<T,D1,D2,R> & rhs, unsigned int i ) :
         fMat(&rhs), fRow(i)
      {}
      T & operator[](int j) { return (*fMat)(fRow,j); }
   private:
      SMatrix<T,D1,D2,R> *  fMat;
      unsigned int fRow;
   };

   class SMatrixRow_const {
   public:
      SMatrixRow_const ( const SMatrix<T,D1,D2,R> & rhs, unsigned int i ) :
         fMat(&rhs), fRow(i)
      {}

      const T & operator[](int j) const { return (*fMat)(fRow, j); }

   private:
      const SMatrix<T,D1,D2,R> *  fMat;
      unsigned int fRow;
   };

  /**
      read only access to matrix element, with indices starting from 0 : m[i][j]
   */
   SMatrixRow_const  operator[](unsigned int i) const { return SMatrixRow_const(*this, i); }
   /**
      read/write access to matrix element with indices starting from 0 : m[i][j]
   */
   SMatrixRow operator[](unsigned int i) { return SMatrixRow(*this, i); }


   /**
      addition with a scalar
   */
   SMatrix<T,D1,D2,R>&operator+=(const T& rhs);

   /**
      addition with another matrix of any compatible representation
   */
   template <class R2>
   SMatrix<T,D1,D2,R>&operator+=(const SMatrix<T,D1,D2,R2>& rhs);

   /**
      addition with a compatible matrix expression
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator+=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      subtraction with a scalar
   */
   SMatrix<T,D1,D2,R>& operator-=(const T& rhs);

   /**
      subtraction with another matrix of any compatible representation
   */
   template <class R2>
   SMatrix<T,D1,D2,R>&operator-=(const SMatrix<T,D1,D2,R2>& rhs);

   /**
      subtraction with a compatible matrix expression
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator-=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      multiplication with a scalar
    */
   SMatrix<T,D1,D2,R>& operator*=(const T& rhs);

#ifndef __CINT__


   /**
      multiplication with another compatible matrix (it is a real matrix multiplication)
      Note that this operation does not avid to create a temporary to store intermidiate result
   */
   template <class R2>
   SMatrix<T,D1,D2,R>& operator*=(const SMatrix<T,D1,D2,R2>& rhs);

   /**
      multiplication with a compatible matrix expression (it is a real matrix multiplication)
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator*=(const Expr<A,T,D1,D2,R2>& rhs);

#endif

   /**
      division with a scalar
   */
   SMatrix<T,D1,D2,R>& operator/=(const T& rhs);



   /** @name --- Linear Algebra Functions --- */

   /**
      Invert a square Matrix ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used for general square matrices is the LU factorization taken from Dinv routine
      from the CERNLIB (written in C++ from CLHEP authors)
      In case of symmetric matrices Bunch-Kaufman diagonal pivoting method is used
      (The implementation is the one written by the CLHEP authors)
   */
   bool Invert();

   /**
      Invert a square Matrix and  returns a new matrix. In case the inversion fails
      the current matrix is returned.
      \param ifail . ifail will be set to 0 when inversion is successfull.
      See ROOT::Math::SMatrix::Invert for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> Inverse(int & ifail ) const;

   /**
      Fast Invertion of a square Matrix ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used is based on direct inversion using the Cramer rule for
      matrices upto 5x5. Afterwards the same default algorithm of Invert() is used.
      Note that this method is faster but can suffer from much larger numerical accuracy
      when the condition of the matrix is large
   */
   bool InvertFast();

   /**
      Invert a square Matrix and  returns a new matrix. In case the inversion fails
      the current matrix is returned.
      \param ifail . ifail will be set to 0 when inversion is successfull.
      See ROOT::Math::SMatrix::InvertFast for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> InverseFast(int & ifail ) const;

   /**
      Invertion of a symmetric positive defined Matrix using Choleski decomposition.
      ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used is based on Choleski decomposition
      A compile error is given if the matrix is not of type symmetric and a run-time failure if the
      matrix is not positive defined.
      For solving  a linear system, it is possible to use also the function
      ROOT::Math::SolveChol(matrix, vector) which will be faster than performing the inversion
   */
   bool InvertChol();

   /**
      Invert of a symmetric positive defined Matrix using Choleski decomposition.
      A compile error is given if the matrix is not of type symmetric and a run-time failure if the
      matrix is not positive defined.
      In case the inversion fails the current matrix is returned.
      \param ifail . ifail will be set to 0 when inversion is successfull.
      See ROOT::Math::SMatrix::InvertChol for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> InverseChol(int & ifail ) const;

   /**
      determinant of square Matrix via Dfact.
      Return true when the calculation is successfull.
      \param det will contain the calculated determinant value
      \b Note: this will destroy the contents of the Matrix!
   */
   bool Det(T& det);

   /**
      determinant of square Matrix via Dfact.
      Return true when the calculation is successfull.
      \param det will contain the calculated determinant value
      \b Note: this will preserve the content of the Matrix!
   */
   bool Det2(T& det) const;


   /** @name --- Matrix Slice Functions --- */

   /// place a vector in a Matrix row
   template <unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_row(const SVector<T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector expression in a Matrix row
   template <class A, unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_row(const VecExpr<A,T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector in a Matrix column
   template <unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_col(const SVector<T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector expression in a Matrix column
   template <class A, unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_col(const VecExpr<A,T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a matrix in this matrix
   template <unsigned int D3, unsigned int D4, class R2>
   SMatrix<T,D1,D2,R>& Place_at(const SMatrix<T,D3,D4,R2>& rhs,
                                unsigned int row,
                                unsigned int col);
   /// place a matrix expression in this matrix
   template <class A, unsigned int D3, unsigned int D4, class R2>
   SMatrix<T,D1,D2,R>& Place_at(const Expr<A,T,D3,D4,R2>& rhs,
                                unsigned int row,
                                unsigned int col);

   /**
      return a full Matrix row as a vector (copy the content in a new vector)
   */
   SVector<T,D2> Row(unsigned int therow) const;

   /**
      return a full Matrix column as a vector (copy the content in a new vector)
   */
   SVector<T,D1> Col(unsigned int thecol) const;

   /**
      return a slice of therow as a vector starting at the colum value col0 until col0+N,
      where N is the size of the vector (SubVector::kSize )
      Condition  col0+N <= D2
   */
   template <class SubVector>
   SubVector SubRow(unsigned int therow, unsigned int col0 = 0 ) const;

   /**
      return a slice of the column as a vector starting at the row value row0 until row0+Dsub.
      where N is the size of the vector (SubVector::kSize )
      Condition  row0+N <= D1
   */
   template <class SubVector>
   SubVector SubCol(unsigned int thecol, unsigned int row0 = 0) const;

   /**
      return a submatrix with the upper left corner at the values (row0, col0) and with sizes N1, N2
      where N1 and N2 are the dimension of the sub-matrix (SubMatrix::kRows and SubMatrix::kCols )
      Condition  row0+N1 <= D1 && col0+N2 <=D2
   */
   template <class SubMatrix >
   SubMatrix Sub(unsigned int row0, unsigned int col0) const;

   /**
      return diagonal elements of a matrix as a Vector.
      It works only for squared matrices D1 == D2, otherwise it will produce a compile error
   */
   SVector<T,D1> Diagonal() const;

   /**
      Set the diagonal elements from a Vector
      Require that vector implements ::kSize since a check (statically) is done on
      diagonal size == vector size
   */
   template <class Vector>
   void SetDiagonal(const Vector & v);

   /**
      return the trace of a matrix
      Sum of the diagonal elements
   */
   T Trace() const;


   /**
      return the upper Triangular block of the matrices (including the diagonal) as
      a vector of sizes N = D1 * (D1 + 1)/2.
      It works only for square matrices with D1==D2, otherwise it will produce a compile error
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SVector<T, D1 * (D2 +1)/2> UpperBlock() const;
#else
   template<class SubVector>
   SubVector UpperBlock() const;
#endif

   /**
      return the lower Triangular block of the matrices (including the diagonal) as
      a vector of sizes N = D1 * (D1 + 1)/2.
      It works only for square matrices with D1==D2, otherwise it will produce a compile error
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SVector<T, D1 * (D2 +1)/2> LowerBlock() const;
#else
   template<class SubVector>
   SubVector LowerBlock() const;
#endif


   /** @name --- Other Functions --- */

   /**
       Function to check if a matrix is sharing same memory location of the passed pointer
       This function is used by the expression templates to avoid the alias problem during
       expression evaluation. When  the matrix is in use, for example in operations
       like A = B * A, a temporary object storing the intermediate result is automatically
       created when evaluating the expression.

   */
   bool IsInUse(const T* p) const;

   // submatrices

   /// Print: used by operator<<()
   std::ostream& Print(std::ostream& os) const;




public:

   /** @name --- Data Member --- */

   /**
      Matrix Storage Object containing matrix data
   */
   R fRep;

}; // end of class SMatrix




//==============================================================================
// operator<<
//==============================================================================
template <class T, unsigned int D1, unsigned int D2, class R>
inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::SMatrix<T,D1,D2,R>& rhs) {
  return rhs.Print(os);
}


  }  // namespace Math

}  // namespace ROOT






#ifndef __CINT__

#ifndef ROOT_Math_SMatrix_icc
#include "Math/SMatrix.icc"
#endif

#ifndef ROOT_Math_MatrixFunctions
#include "Math/MatrixFunctions.h"
#endif

#endif //__CINT__

#endif  /* ROOT_Math_SMatrix  */
 SMatrix.h:1
 SMatrix.h:2
 SMatrix.h:3
 SMatrix.h:4
 SMatrix.h:5
 SMatrix.h:6
 SMatrix.h:7
 SMatrix.h:8
 SMatrix.h:9
 SMatrix.h:10
 SMatrix.h:11
 SMatrix.h:12
 SMatrix.h:13
 SMatrix.h:14
 SMatrix.h:15
 SMatrix.h:16
 SMatrix.h:17
 SMatrix.h:18
 SMatrix.h:19
 SMatrix.h:20
 SMatrix.h:21
 SMatrix.h:22
 SMatrix.h:23
 SMatrix.h:24
 SMatrix.h:25
 SMatrix.h:26
 SMatrix.h:27
 SMatrix.h:28
 SMatrix.h:29
 SMatrix.h:30
 SMatrix.h:31
 SMatrix.h:32
 SMatrix.h:33
 SMatrix.h:34
 SMatrix.h:35
 SMatrix.h:36
 SMatrix.h:37
 SMatrix.h:38
 SMatrix.h:39
 SMatrix.h:40
 SMatrix.h:41
 SMatrix.h:42
 SMatrix.h:43
 SMatrix.h:44
 SMatrix.h:45
 SMatrix.h:46
 SMatrix.h:47
 SMatrix.h:48
 SMatrix.h:49
 SMatrix.h:50
 SMatrix.h:51
 SMatrix.h:52
 SMatrix.h:53
 SMatrix.h:54
 SMatrix.h:55
 SMatrix.h:56
 SMatrix.h:57
 SMatrix.h:58
 SMatrix.h:59
 SMatrix.h:60
 SMatrix.h:61
 SMatrix.h:62
 SMatrix.h:63
 SMatrix.h:64
 SMatrix.h:65
 SMatrix.h:66
 SMatrix.h:67
 SMatrix.h:68
 SMatrix.h:69
 SMatrix.h:70
 SMatrix.h:71
 SMatrix.h:72
 SMatrix.h:73
 SMatrix.h:74
 SMatrix.h:75
 SMatrix.h:76
 SMatrix.h:77
 SMatrix.h:78
 SMatrix.h:79
 SMatrix.h:80
 SMatrix.h:81
 SMatrix.h:82
 SMatrix.h:83
 SMatrix.h:84
 SMatrix.h:85
 SMatrix.h:86
 SMatrix.h:87
 SMatrix.h:88
 SMatrix.h:89
 SMatrix.h:90
 SMatrix.h:91
 SMatrix.h:92
 SMatrix.h:93
 SMatrix.h:94
 SMatrix.h:95
 SMatrix.h:96
 SMatrix.h:97
 SMatrix.h:98
 SMatrix.h:99
 SMatrix.h:100
 SMatrix.h:101
 SMatrix.h:102
 SMatrix.h:103
 SMatrix.h:104
 SMatrix.h:105
 SMatrix.h:106
 SMatrix.h:107
 SMatrix.h:108
 SMatrix.h:109
 SMatrix.h:110
 SMatrix.h:111
 SMatrix.h:112
 SMatrix.h:113
 SMatrix.h:114
 SMatrix.h:115
 SMatrix.h:116
 SMatrix.h:117
 SMatrix.h:118
 SMatrix.h:119
 SMatrix.h:120
 SMatrix.h:121
 SMatrix.h:122
 SMatrix.h:123
 SMatrix.h:124
 SMatrix.h:125
 SMatrix.h:126
 SMatrix.h:127
 SMatrix.h:128
 SMatrix.h:129
 SMatrix.h:130
 SMatrix.h:131
 SMatrix.h:132
 SMatrix.h:133
 SMatrix.h:134
 SMatrix.h:135
 SMatrix.h:136
 SMatrix.h:137
 SMatrix.h:138
 SMatrix.h:139
 SMatrix.h:140
 SMatrix.h:141
 SMatrix.h:142
 SMatrix.h:143
 SMatrix.h:144
 SMatrix.h:145
 SMatrix.h:146
 SMatrix.h:147
 SMatrix.h:148
 SMatrix.h:149
 SMatrix.h:150
 SMatrix.h:151
 SMatrix.h:152
 SMatrix.h:153
 SMatrix.h:154
 SMatrix.h:155
 SMatrix.h:156
 SMatrix.h:157
 SMatrix.h:158
 SMatrix.h:159
 SMatrix.h:160
 SMatrix.h:161
 SMatrix.h:162
 SMatrix.h:163
 SMatrix.h:164
 SMatrix.h:165
 SMatrix.h:166
 SMatrix.h:167
 SMatrix.h:168
 SMatrix.h:169
 SMatrix.h:170
 SMatrix.h:171
 SMatrix.h:172
 SMatrix.h:173
 SMatrix.h:174
 SMatrix.h:175
 SMatrix.h:176
 SMatrix.h:177
 SMatrix.h:178
 SMatrix.h:179
 SMatrix.h:180
 SMatrix.h:181
 SMatrix.h:182
 SMatrix.h:183
 SMatrix.h:184
 SMatrix.h:185
 SMatrix.h:186
 SMatrix.h:187
 SMatrix.h:188
 SMatrix.h:189
 SMatrix.h:190
 SMatrix.h:191
 SMatrix.h:192
 SMatrix.h:193
 SMatrix.h:194
 SMatrix.h:195
 SMatrix.h:196
 SMatrix.h:197
 SMatrix.h:198
 SMatrix.h:199
 SMatrix.h:200
 SMatrix.h:201
 SMatrix.h:202
 SMatrix.h:203
 SMatrix.h:204
 SMatrix.h:205
 SMatrix.h:206
 SMatrix.h:207
 SMatrix.h:208
 SMatrix.h:209
 SMatrix.h:210
 SMatrix.h:211
 SMatrix.h:212
 SMatrix.h:213
 SMatrix.h:214
 SMatrix.h:215
 SMatrix.h:216
 SMatrix.h:217
 SMatrix.h:218
 SMatrix.h:219
 SMatrix.h:220
 SMatrix.h:221
 SMatrix.h:222
 SMatrix.h:223
 SMatrix.h:224
 SMatrix.h:225
 SMatrix.h:226
 SMatrix.h:227
 SMatrix.h:228
 SMatrix.h:229
 SMatrix.h:230
 SMatrix.h:231
 SMatrix.h:232
 SMatrix.h:233
 SMatrix.h:234
 SMatrix.h:235
 SMatrix.h:236
 SMatrix.h:237
 SMatrix.h:238
 SMatrix.h:239
 SMatrix.h:240
 SMatrix.h:241
 SMatrix.h:242
 SMatrix.h:243
 SMatrix.h:244
 SMatrix.h:245
 SMatrix.h:246
 SMatrix.h:247
 SMatrix.h:248
 SMatrix.h:249
 SMatrix.h:250
 SMatrix.h:251
 SMatrix.h:252
 SMatrix.h:253
 SMatrix.h:254
 SMatrix.h:255
 SMatrix.h:256
 SMatrix.h:257
 SMatrix.h:258
 SMatrix.h:259
 SMatrix.h:260
 SMatrix.h:261
 SMatrix.h:262
 SMatrix.h:263
 SMatrix.h:264
 SMatrix.h:265
 SMatrix.h:266
 SMatrix.h:267
 SMatrix.h:268
 SMatrix.h:269
 SMatrix.h:270
 SMatrix.h:271
 SMatrix.h:272
 SMatrix.h:273
 SMatrix.h:274
 SMatrix.h:275
 SMatrix.h:276
 SMatrix.h:277
 SMatrix.h:278
 SMatrix.h:279
 SMatrix.h:280
 SMatrix.h:281
 SMatrix.h:282
 SMatrix.h:283
 SMatrix.h:284
 SMatrix.h:285
 SMatrix.h:286
 SMatrix.h:287
 SMatrix.h:288
 SMatrix.h:289
 SMatrix.h:290
 SMatrix.h:291
 SMatrix.h:292
 SMatrix.h:293
 SMatrix.h:294
 SMatrix.h:295
 SMatrix.h:296
 SMatrix.h:297
 SMatrix.h:298
 SMatrix.h:299
 SMatrix.h:300
 SMatrix.h:301
 SMatrix.h:302
 SMatrix.h:303
 SMatrix.h:304
 SMatrix.h:305
 SMatrix.h:306
 SMatrix.h:307
 SMatrix.h:308
 SMatrix.h:309
 SMatrix.h:310
 SMatrix.h:311
 SMatrix.h:312
 SMatrix.h:313
 SMatrix.h:314
 SMatrix.h:315
 SMatrix.h:316
 SMatrix.h:317
 SMatrix.h:318
 SMatrix.h:319
 SMatrix.h:320
 SMatrix.h:321
 SMatrix.h:322
 SMatrix.h:323
 SMatrix.h:324
 SMatrix.h:325
 SMatrix.h:326
 SMatrix.h:327
 SMatrix.h:328
 SMatrix.h:329
 SMatrix.h:330
 SMatrix.h:331
 SMatrix.h:332
 SMatrix.h:333
 SMatrix.h:334
 SMatrix.h:335
 SMatrix.h:336
 SMatrix.h:337
 SMatrix.h:338
 SMatrix.h:339
 SMatrix.h:340
 SMatrix.h:341
 SMatrix.h:342
 SMatrix.h:343
 SMatrix.h:344
 SMatrix.h:345
 SMatrix.h:346
 SMatrix.h:347
 SMatrix.h:348
 SMatrix.h:349
 SMatrix.h:350
 SMatrix.h:351
 SMatrix.h:352
 SMatrix.h:353
 SMatrix.h:354
 SMatrix.h:355
 SMatrix.h:356
 SMatrix.h:357
 SMatrix.h:358
 SMatrix.h:359
 SMatrix.h:360
 SMatrix.h:361
 SMatrix.h:362
 SMatrix.h:363
 SMatrix.h:364
 SMatrix.h:365
 SMatrix.h:366
 SMatrix.h:367
 SMatrix.h:368
 SMatrix.h:369
 SMatrix.h:370
 SMatrix.h:371
 SMatrix.h:372
 SMatrix.h:373
 SMatrix.h:374
 SMatrix.h:375
 SMatrix.h:376
 SMatrix.h:377
 SMatrix.h:378
 SMatrix.h:379
 SMatrix.h:380
 SMatrix.h:381
 SMatrix.h:382
 SMatrix.h:383
 SMatrix.h:384
 SMatrix.h:385
 SMatrix.h:386
 SMatrix.h:387
 SMatrix.h:388
 SMatrix.h:389
 SMatrix.h:390
 SMatrix.h:391
 SMatrix.h:392
 SMatrix.h:393
 SMatrix.h:394
 SMatrix.h:395
 SMatrix.h:396
 SMatrix.h:397
 SMatrix.h:398
 SMatrix.h:399
 SMatrix.h:400
 SMatrix.h:401
 SMatrix.h:402
 SMatrix.h:403
 SMatrix.h:404
 SMatrix.h:405
 SMatrix.h:406
 SMatrix.h:407
 SMatrix.h:408
 SMatrix.h:409
 SMatrix.h:410
 SMatrix.h:411
 SMatrix.h:412
 SMatrix.h:413
 SMatrix.h:414
 SMatrix.h:415
 SMatrix.h:416
 SMatrix.h:417
 SMatrix.h:418
 SMatrix.h:419
 SMatrix.h:420
 SMatrix.h:421
 SMatrix.h:422
 SMatrix.h:423
 SMatrix.h:424
 SMatrix.h:425
 SMatrix.h:426
 SMatrix.h:427
 SMatrix.h:428
 SMatrix.h:429
 SMatrix.h:430
 SMatrix.h:431
 SMatrix.h:432
 SMatrix.h:433
 SMatrix.h:434
 SMatrix.h:435
 SMatrix.h:436
 SMatrix.h:437
 SMatrix.h:438
 SMatrix.h:439
 SMatrix.h:440
 SMatrix.h:441
 SMatrix.h:442
 SMatrix.h:443
 SMatrix.h:444
 SMatrix.h:445
 SMatrix.h:446
 SMatrix.h:447
 SMatrix.h:448
 SMatrix.h:449
 SMatrix.h:450
 SMatrix.h:451
 SMatrix.h:452
 SMatrix.h:453
 SMatrix.h:454
 SMatrix.h:455
 SMatrix.h:456
 SMatrix.h:457
 SMatrix.h:458
 SMatrix.h:459
 SMatrix.h:460
 SMatrix.h:461
 SMatrix.h:462
 SMatrix.h:463
 SMatrix.h:464
 SMatrix.h:465
 SMatrix.h:466
 SMatrix.h:467
 SMatrix.h:468
 SMatrix.h:469
 SMatrix.h:470
 SMatrix.h:471
 SMatrix.h:472
 SMatrix.h:473
 SMatrix.h:474
 SMatrix.h:475
 SMatrix.h:476
 SMatrix.h:477
 SMatrix.h:478
 SMatrix.h:479
 SMatrix.h:480
 SMatrix.h:481
 SMatrix.h:482
 SMatrix.h:483
 SMatrix.h:484
 SMatrix.h:485
 SMatrix.h:486
 SMatrix.h:487
 SMatrix.h:488
 SMatrix.h:489
 SMatrix.h:490
 SMatrix.h:491
 SMatrix.h:492
 SMatrix.h:493
 SMatrix.h:494
 SMatrix.h:495
 SMatrix.h:496
 SMatrix.h:497
 SMatrix.h:498
 SMatrix.h:499
 SMatrix.h:500
 SMatrix.h:501
 SMatrix.h:502
 SMatrix.h:503
 SMatrix.h:504
 SMatrix.h:505
 SMatrix.h:506
 SMatrix.h:507
 SMatrix.h:508
 SMatrix.h:509
 SMatrix.h:510
 SMatrix.h:511
 SMatrix.h:512
 SMatrix.h:513
 SMatrix.h:514
 SMatrix.h:515
 SMatrix.h:516
 SMatrix.h:517
 SMatrix.h:518
 SMatrix.h:519
 SMatrix.h:520
 SMatrix.h:521
 SMatrix.h:522
 SMatrix.h:523
 SMatrix.h:524
 SMatrix.h:525
 SMatrix.h:526
 SMatrix.h:527
 SMatrix.h:528
 SMatrix.h:529
 SMatrix.h:530
 SMatrix.h:531
 SMatrix.h:532
 SMatrix.h:533
 SMatrix.h:534
 SMatrix.h:535
 SMatrix.h:536
 SMatrix.h:537
 SMatrix.h:538
 SMatrix.h:539
 SMatrix.h:540
 SMatrix.h:541
 SMatrix.h:542
 SMatrix.h:543
 SMatrix.h:544
 SMatrix.h:545
 SMatrix.h:546
 SMatrix.h:547
 SMatrix.h:548
 SMatrix.h:549
 SMatrix.h:550
 SMatrix.h:551
 SMatrix.h:552
 SMatrix.h:553
 SMatrix.h:554
 SMatrix.h:555
 SMatrix.h:556
 SMatrix.h:557
 SMatrix.h:558
 SMatrix.h:559
 SMatrix.h:560
 SMatrix.h:561
 SMatrix.h:562
 SMatrix.h:563
 SMatrix.h:564
 SMatrix.h:565
 SMatrix.h:566
 SMatrix.h:567
 SMatrix.h:568
 SMatrix.h:569
 SMatrix.h:570
 SMatrix.h:571
 SMatrix.h:572
 SMatrix.h:573
 SMatrix.h:574
 SMatrix.h:575
 SMatrix.h:576
 SMatrix.h:577
 SMatrix.h:578
 SMatrix.h:579
 SMatrix.h:580
 SMatrix.h:581
 SMatrix.h:582
 SMatrix.h:583
 SMatrix.h:584
 SMatrix.h:585
 SMatrix.h:586
 SMatrix.h:587
 SMatrix.h:588
 SMatrix.h:589
 SMatrix.h:590
 SMatrix.h:591
 SMatrix.h:592
 SMatrix.h:593
 SMatrix.h:594
 SMatrix.h:595
 SMatrix.h:596
 SMatrix.h:597
 SMatrix.h:598
 SMatrix.h:599
 SMatrix.h:600
 SMatrix.h:601
 SMatrix.h:602
 SMatrix.h:603
 SMatrix.h:604
 SMatrix.h:605
 SMatrix.h:606
 SMatrix.h:607
 SMatrix.h:608
 SMatrix.h:609
 SMatrix.h:610
 SMatrix.h:611
 SMatrix.h:612
 SMatrix.h:613
 SMatrix.h:614
 SMatrix.h:615
 SMatrix.h:616
 SMatrix.h:617
 SMatrix.h:618
 SMatrix.h:619
 SMatrix.h:620
 SMatrix.h:621
 SMatrix.h:622
 SMatrix.h:623
 SMatrix.h:624
 SMatrix.h:625
 SMatrix.h:626
 SMatrix.h:627
 SMatrix.h:628
 SMatrix.h:629
 SMatrix.h:630
 SMatrix.h:631
 SMatrix.h:632
 SMatrix.h:633
 SMatrix.h:634
 SMatrix.h:635
 SMatrix.h:636
 SMatrix.h:637
 SMatrix.h:638
 SMatrix.h:639
 SMatrix.h:640
 SMatrix.h:641
 SMatrix.h:642
 SMatrix.h:643
 SMatrix.h:644
 SMatrix.h:645
 SMatrix.h:646
 SMatrix.h:647
 SMatrix.h:648
 SMatrix.h:649
 SMatrix.h:650
 SMatrix.h:651
 SMatrix.h:652
 SMatrix.h:653
 SMatrix.h:654
 SMatrix.h:655
 SMatrix.h:656
 SMatrix.h:657
 SMatrix.h:658
 SMatrix.h:659
 SMatrix.h:660
 SMatrix.h:661
 SMatrix.h:662
 SMatrix.h:663
 SMatrix.h:664
 SMatrix.h:665
 SMatrix.h:666
 SMatrix.h:667
 SMatrix.h:668
 SMatrix.h:669
 SMatrix.h:670
 SMatrix.h:671
 SMatrix.h:672
 SMatrix.h:673
 SMatrix.h:674
 SMatrix.h:675
 SMatrix.h:676
 SMatrix.h:677
 SMatrix.h:678
 SMatrix.h:679
 SMatrix.h:680
 SMatrix.h:681
 SMatrix.h:682
 SMatrix.h:683
 SMatrix.h:684
 SMatrix.h:685
 SMatrix.h:686
 SMatrix.h:687
 SMatrix.h:688
 SMatrix.h:689
 SMatrix.h:690
 SMatrix.h:691
 SMatrix.h:692
 SMatrix.h:693
 SMatrix.h:694
 SMatrix.h:695
 SMatrix.h:696
 SMatrix.h:697
 SMatrix.h:698
 SMatrix.h:699
 SMatrix.h:700
 SMatrix.h:701
 SMatrix.h:702
 SMatrix.h:703
 SMatrix.h:704
 SMatrix.h:705
 SMatrix.h:706
 SMatrix.h:707
 SMatrix.h:708
 SMatrix.h:709
 SMatrix.h:710
 SMatrix.h:711
 SMatrix.h:712
 SMatrix.h:713
 SMatrix.h:714
 SMatrix.h:715
 SMatrix.h:716
 SMatrix.h:717
 SMatrix.h:718
 SMatrix.h:719
 SMatrix.h:720
 SMatrix.h:721
 SMatrix.h:722
 SMatrix.h:723
 SMatrix.h:724
 SMatrix.h:725
 SMatrix.h:726
 SMatrix.h:727
 SMatrix.h:728
 SMatrix.h:729
 SMatrix.h:730
 SMatrix.h:731
 SMatrix.h:732
 SMatrix.h:733
 SMatrix.h:734
 SMatrix.h:735
 SMatrix.h:736
 SMatrix.h:737
 SMatrix.h:738
 SMatrix.h:739
 SMatrix.h:740
 SMatrix.h:741
 SMatrix.h:742
 SMatrix.h:743
 SMatrix.h:744
 SMatrix.h:745
 SMatrix.h:746
 SMatrix.h:747
 SMatrix.h:748