Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:37

0001 // -*- C++ -*-
0002 // CLASSDOC OFF
0003 // ---------------------------------------------------------------------------
0004 // CLASSDOC ON
0005 // 
0006 // This file is a part of the CLHEP - a Class Library for High Energy Physics.
0007 // 
0008 // This is the definition of the HepSymMatrix class.
0009 // 
0010 // This software written by Nobu Katayama and Mike Smyth, Cornell University.
0011 //
0012 // .SS Usage
0013 //
0014 //   This is very much like the Matrix, except of course it is restricted to
0015 //   Symmetric Matrix.  All the operations for Matrix can also be done here
0016 //   (except for the +=,-=,*= that don't yield a symmetric matrix.  e.g.
0017 //    +=(const Matrix &) is not defined)
0018    
0019 //   The matrix is stored as a lower triangular matrix.
0020 //   In addition to the (row, col) method of finding element, fast(row, col)
0021 //   returns an element with checking to see if row and col need to be 
0022 //   interchanged so that row >= col.
0023 
0024 //   New operations are:
0025 //
0026 // .ft B
0027 //  sym = s.similarity(m);
0028 //
0029 //  This returns m*s*m.T(). This is a similarity
0030 //  transform when m is orthogonal, but nothing
0031 //  restricts m to be orthogonal.  It is just
0032 //  a more efficient way to calculate m*s*m.T,
0033 //  and it realizes that this should be a 
0034 //  HepSymMatrix (the explicit operation m*s*m.T
0035 //  will return a Matrix, not realizing that 
0036 //  it is symmetric).
0037 //
0038 // .ft B
0039 //  sym =  similarityT(m);
0040 //
0041 // This returns m.T()*s*m.
0042 //
0043 // .ft B
0044 // s << m;
0045 //
0046 // This takes the matrix m, and treats it
0047 // as symmetric matrix that is copied to s.
0048 // This is useful for operations that yield
0049 // symmetric matrix, but which the computer
0050 // is too dumb to realize.
0051 //
0052 // .ft B
0053 // s = vT_times_v(const HepVector v);
0054 //
0055 //  calculates v.T()*v.
0056 //
0057 // ./"This code has been written by Mike Smyth, and the algorithms used are
0058 // ./"described in the thesis "A Tracking Library for a Silicon Vertex Detector"
0059 // ./"(Mike Smyth, Cornell University, June 1993).
0060 // ./"This is file contains C++ stuff for doing things with Matrixes.
0061 // ./"To turn on bound checking, define MATRIX_BOUND_CHECK before including
0062 // ./"this file.
0063 //
0064 
0065 #ifndef _SYMMatrix_H_
0066 #define _SYMMatrix_H_
0067 
0068 #include <vector>
0069 
0070 #include "CLHEP/Matrix/defs.h"
0071 #include "CLHEP/Matrix/GenMatrix.h"
0072 #include "CLHEP/Utility/thread_local.h"
0073 
0074 namespace CLHEP {
0075 
0076 class HepRandom;
0077 
0078 class HepMatrix;
0079 class HepDiagMatrix;
0080 class HepVector;
0081 
0082 /**
0083  * @author
0084  * @ingroup matrix
0085  */
0086 class HepSymMatrix : public HepGenMatrix {
0087 public:
0088    inline HepSymMatrix();
0089    // Default constructor. Gives 0x0 symmetric matrix.
0090    // Another SymMatrix can be assigned to it.
0091 
0092    explicit HepSymMatrix(int p);
0093    HepSymMatrix(int p, int);
0094    // Constructor. Gives p x p symmetric matrix.
0095    // With a second argument, the matrix is initialized. 0 means a zero
0096    // matrix, 1 means the identity matrix.
0097 
0098    HepSymMatrix(int p, HepRandom &r);
0099 
0100    HepSymMatrix(const HepSymMatrix &hm1);
0101    // Copy constructor.
0102 
0103    HepSymMatrix(const HepDiagMatrix &hm1);
0104    // Constructor from DiagMatrix
0105 
0106    virtual ~HepSymMatrix();
0107    // Destructor.
0108 
0109    inline int num_row() const;
0110    inline int num_col() const;
0111    // Returns number of rows/columns.
0112 
0113    const double & operator()(int row, int col) const; 
0114    double & operator()(int row, int col);
0115    // Read and write a SymMatrix element.
0116    // ** Note that indexing starts from (1,1). **
0117 
0118    const double & fast(int row, int col) const;
0119    double & fast(int row, int col);
0120    // fast element access.
0121    // Must be row>=col;
0122    // ** Note that indexing starts from (1,1). **
0123 
0124    void assign(const HepMatrix &hm2);
0125    // Assigns hm2 to s, assuming hm2 is a symmetric matrix.
0126 
0127    void assign(const HepSymMatrix &hm2);
0128    // Another form of assignment. For consistency.
0129 
0130    HepSymMatrix & operator*=(double t);
0131    // Multiply a SymMatrix by a floating number.
0132 
0133    HepSymMatrix & operator/=(double t); 
0134    // Divide a SymMatrix by a floating number.
0135 
0136    HepSymMatrix & operator+=( const HepSymMatrix &hm2);
0137    HepSymMatrix & operator+=( const HepDiagMatrix &hm2);
0138    HepSymMatrix & operator-=( const HepSymMatrix &hm2);
0139    HepSymMatrix & operator-=( const HepDiagMatrix &hm2);
0140    // Add or subtract a SymMatrix.
0141 
0142    HepSymMatrix & operator=( const HepSymMatrix &hm2);
0143    HepSymMatrix & operator=( const HepDiagMatrix &hm2);
0144    // Assignment operators. Notice that there is no SymMatrix = Matrix.
0145 
0146    HepSymMatrix operator- () const;
0147    // unary minus, ie. flip the sign of each element.
0148 
0149    HepSymMatrix T() const;
0150    // Returns the transpose of a SymMatrix (which is itself).
0151 
0152    HepSymMatrix apply(double (*f)(double, int, int)) const;
0153    // Apply a function to all elements of the matrix.
0154 
0155    HepSymMatrix similarity(const HepMatrix &hm1) const;
0156    HepSymMatrix similarity(const HepSymMatrix &hm1) const;
0157    // Returns hm1*s*hm1.T().
0158 
0159    HepSymMatrix similarityT(const HepMatrix &hm1) const;
0160    // temporary. test of new similarity.
0161    // Returns hm1.T()*s*hm1.
0162 
0163    double similarity(const HepVector &v) const;
0164    // Returns v.T()*s*v (This is a scaler).
0165 
0166    HepSymMatrix sub(int min_row, int max_row) const;
0167    // Returns a sub matrix of a SymMatrix.
0168    void sub(int row, const HepSymMatrix &hm1);
0169    // Sub matrix of this SymMatrix is replaced with hm1.
0170    HepSymMatrix sub(int min_row, int max_row);
0171    // SGI CC bug. I have to have both with/without const. I should not need
0172    // one without const.
0173 
0174    inline HepSymMatrix inverse(int &ifail) const;
0175    // Invert a Matrix. The matrix is not changed
0176    // Returns 0 when successful, otherwise non-zero.
0177 
0178    void invert(int &ifail);
0179    // Invert a Matrix.
0180    // N.B. the contents of the matrix are replaced by the inverse.
0181    // Returns ierr = 0 when successful, otherwise non-zero. 
0182    // This method has less overhead then inverse().
0183 
0184    inline void invert();
0185    // Invert a matrix. Throw std::runtime_error on failure.
0186 
0187    inline HepSymMatrix inverse() const;
0188    // Invert a matrix. Throw std::runtime_error on failure. 
0189 
0190    double determinant() const;
0191    // calculate the determinant of the matrix.
0192 
0193    double trace() const;
0194    // calculate the trace of the matrix (sum of diagonal elements).
0195 
0196    class HepSymMatrix_row {
0197    public:
0198       inline HepSymMatrix_row(HepSymMatrix&,int);
0199       inline double & operator[](int);
0200    private:
0201       HepSymMatrix& _a;
0202       int _r;
0203    };
0204    class HepSymMatrix_row_const {
0205    public:
0206       inline HepSymMatrix_row_const(const HepSymMatrix&,int);
0207       inline const double & operator[](int) const;
0208    private:
0209       const HepSymMatrix& _a;
0210       int _r;
0211    };
0212    // helper class to implement m[i][j]
0213 
0214    inline HepSymMatrix_row operator[] (int);
0215    inline HepSymMatrix_row_const operator[] (int) const;
0216    // Read or write a matrix element.
0217    // While it may not look like it, you simply do m[i][j] to get an
0218    // element. 
0219    // ** Note that the indexing starts from [0][0]. **
0220 
0221    // Special-case inversions for 5x5 and 6x6 symmetric positive definite:
0222    // These set ifail=0 and invert if the matrix was positive definite;
0223    // otherwise ifail=1 and the matrix is left unaltered.
0224    void invertCholesky5 (int &ifail);  
0225    void invertCholesky6 (int &ifail);
0226 
0227    // Inversions for 5x5 and 6x6 forcing use of specific methods:  The
0228    // behavior (though not the speed) will be identical to invert(ifail).
0229    void invertHaywood4 (int & ifail);  
0230    void invertHaywood5 (int &ifail);  
0231    void invertHaywood6 (int &ifail);
0232    void invertBunchKaufman (int &ifail);  
0233 
0234 protected:
0235    inline int num_size() const;
0236   
0237 private:
0238    friend class HepSymMatrix_row;
0239    friend class HepSymMatrix_row_const;
0240    friend class HepMatrix;
0241    friend class HepDiagMatrix;
0242 
0243    friend void tridiagonal(HepSymMatrix *a,HepMatrix *hsm);
0244    friend double condition(const HepSymMatrix &m);
0245    friend void diag_step(HepSymMatrix *t,int begin,int end);
0246    friend void diag_step(HepSymMatrix *t,HepMatrix *u,int begin,int end);
0247    friend HepMatrix diagonalize(HepSymMatrix *s);
0248    friend HepVector house(const HepSymMatrix &a,int row,int col);
0249    friend void house_with_update2(HepSymMatrix *a,HepMatrix *v,int row,int col);
0250 
0251    friend HepSymMatrix operator+(const HepSymMatrix &hm1, 
0252                   const HepSymMatrix &hm2);
0253    friend HepSymMatrix operator-(const HepSymMatrix &hm1, 
0254                   const HepSymMatrix &hm2);
0255    friend HepMatrix operator*(const HepSymMatrix &hm1, const HepSymMatrix &hm2);
0256    friend HepMatrix operator*(const HepSymMatrix &hm1, const HepMatrix &hm2);
0257    friend HepMatrix operator*(const HepMatrix &hm1, const HepSymMatrix &hm2);
0258    friend HepVector operator*(const HepSymMatrix &hm1, const HepVector &hm2);
0259    // Multiply a Matrix by a Matrix or Vector.
0260    
0261    friend HepSymMatrix vT_times_v(const HepVector &v);
0262    // Returns v * v.T();
0263 
0264 #ifdef DISABLE_ALLOC
0265    std::vector<double > m;
0266 #else
0267    std::vector<double,Alloc<double,25> > m;
0268 #endif
0269    int nrow;
0270    int size_;                    // total number of elements
0271 
0272    static CLHEP_THREAD_LOCAL double posDefFraction5x5;
0273    static CLHEP_THREAD_LOCAL double adjustment5x5;
0274    static const  double CHOLESKY_THRESHOLD_5x5;
0275    static const  double CHOLESKY_CREEP_5x5;
0276 
0277    static CLHEP_THREAD_LOCAL double posDefFraction6x6;
0278    static CLHEP_THREAD_LOCAL double adjustment6x6;
0279    static const double CHOLESKY_THRESHOLD_6x6;
0280    static const double CHOLESKY_CREEP_6x6;
0281 
0282    void invert4  (int & ifail);
0283    void invert5  (int & ifail);
0284    void invert6  (int & ifail);
0285 
0286 };
0287 
0288 //
0289 // Operations other than member functions for Matrix, SymMatrix, DiagMatrix
0290 // and Vectors implemented in Matrix.cc and Matrix.icc (inline).
0291 //
0292 
0293 std::ostream& operator<<(std::ostream &s, const HepSymMatrix &q);
0294 // Write out Matrix, SymMatrix, DiagMatrix and Vector into ostream.
0295 
0296 HepMatrix operator*(const HepMatrix &hm1, const HepSymMatrix &hm2);
0297 HepMatrix operator*(const HepSymMatrix &hm1, const HepMatrix &hm2);
0298 HepMatrix operator*(const HepSymMatrix &hm1, const HepSymMatrix &hm2);
0299 HepSymMatrix operator*(double t, const HepSymMatrix &s1);
0300 HepSymMatrix operator*(const HepSymMatrix &s1, double t);
0301 // Multiplication operators.
0302 // Note that m *= hm1 is always faster than m = m * hm1
0303 
0304 HepSymMatrix operator/(const HepSymMatrix &hm1, double t);
0305 // s = s1 / t. (s /= t is faster if you can use it.)
0306 
0307 HepMatrix operator+(const HepMatrix &hm1, const HepSymMatrix &s2);
0308 HepMatrix operator+(const HepSymMatrix &s1, const HepMatrix &hm2);
0309 HepSymMatrix operator+(const HepSymMatrix &s1, const HepSymMatrix &s2);
0310 // Addition operators
0311 
0312 HepMatrix operator-(const HepMatrix &hm1, const HepSymMatrix &s2);
0313 HepMatrix operator-(const HepSymMatrix &hm1, const HepMatrix &hm2);
0314 HepSymMatrix operator-(const HepSymMatrix &s1, const HepSymMatrix &s2);
0315 // subtraction operators
0316 
0317 HepSymMatrix dsum(const HepSymMatrix &s1, const HepSymMatrix &s2);
0318 // Direct sum of two symmetric matrices;
0319 
0320 double condition(const HepSymMatrix &m);
0321 // Find the conditon number of a symmetric matrix.
0322 
0323 void diag_step(HepSymMatrix *t, int begin, int end);
0324 void diag_step(HepSymMatrix *t, HepMatrix *u, int begin, int end);
0325 // Implicit symmetric QR step with Wilkinson Shift
0326 
0327 HepMatrix diagonalize(HepSymMatrix *s);
0328 // Diagonalize a symmetric matrix.
0329 // It returns the matrix U so that s_old = U * s_diag * U.T()
0330 
0331 HepVector house(const HepSymMatrix &a, int row=1, int col=1);
0332 void house_with_update2(HepSymMatrix *a, HepMatrix *v, int row=1, int col=1);
0333 // Finds and does Householder reflection on matrix.
0334 
0335 void tridiagonal(HepSymMatrix *a, HepMatrix *hsm);
0336 HepMatrix tridiagonal(HepSymMatrix *a);
0337 // Does a Householder tridiagonalization of a symmetric matrix.
0338 
0339 }  // namespace CLHEP
0340 
0341 #ifdef ENABLE_BACKWARDS_COMPATIBILITY
0342 //  backwards compatibility will be enabled ONLY in CLHEP 1.9
0343 using namespace CLHEP;
0344 #endif
0345 
0346 #ifndef HEP_DEBUG_INLINE
0347 #include "CLHEP/Matrix/SymMatrix.icc"
0348 #endif
0349 
0350 #endif /*!_SYMMatrix_H*/