// -*-C++-*- // LAPACK++ (V. 1.1) // (C) 1992-1996 All Rights Reserved. #include "arch.h" #ifndef _LA_TRIDIAG_MAT_DOUBLE_ #define _LA_TRIDIAG_MAT_DOUBLE_ #include "lafnames.h" #include LA_VECTOR_DOUBLE_H /** \brief Tridiagonal square matrix class * * Unlike general banded matrices, this tridiagonal matrix is * stored by diagonals rather than columns. A tridiagonal matrix * of order N is stored in three one-dimensional array, one of * length N containing the diagonal elements and two of length N-1 * containing the subdiagonal and superdiagonal elements with * element index 0 through N-2. * * One such matrix with the element indices looks as follows: * * \f[ A_{n\times n} = * \left(\begin{array}{cccc} * a_{00} & a_{01} & \cdots & 0 \\ * a_{10} & \ddots & & \\ * & & \ddots & a_{(n-2)(n-1)} \\ * 0 & \cdots & a_{(n-1)(n-2)} & a_{(n-1)(n-1)} * \end{array}\right) * \f] * * Multiplication of this matrix should be done by the functions * in blas1pp.h, blas2pp.h and blas3pp.h, * e.g. Blas_Mat_Mat_Mult(), except that currently there isn't any * function available for this class. Please ask on the * lapackpp-devel mailing list for support if you need any * assistance with this. * * \see \ref LaTridiagFactDouble, LaTridiagMatFactorize() */ class DLLIMPORT LaTridiagMatDouble { LaVectorDouble du2_; /* second upper diag, N-2 */ LaVectorDouble du_; /* upper diag, N-1 */ LaVectorDouble d_; /* main diag, N */ LaVectorDouble dl_; /* lower diag, N-1 */ int size_; static double outofbounds_; /* return this address, when addresing out of bounds */ static int debug_; // print debug info. static int *info_; // print matrix info only, not values // originally 0, set to 1, and then // reset to 0 after use. public: /** @name Declaration */ //@{ /** Constructs a null 0x0 matrix. */ LaTridiagMatDouble(); /** Constructs a tridiagonal matrix of size \f$N\times * N\f$. Matrix elements are NOT initialized! */ LaTridiagMatDouble(int N); /** Create a new matrix from an existing one by copying * (deep-copy). */ LaTridiagMatDouble(const LaTridiagMatDouble &); /** Create a new matrix from the given three diagonals. The * dimensions must match: diag must be of length N, * diaglower and diagupper of dimension N-1, otherwise a * failed assertion will terminate the program. */ LaTridiagMatDouble(const LaVectorDouble& diag, const LaVectorDouble& diaglower, const LaVectorDouble& diagupper); /** Destroy matrix and reclaim vector memory space if this * is the only structure using it. */ ~LaTridiagMatDouble(); //@} /** @name Information */ //@{ /** Returns the size \f$N\times N\f$ of this tridiagonal * square matrix. */ int size() const { return size_;} //@} /** @name Access functions */ //@{ /** Returns the \f$(i,j)\f$th element of this matrix, with the * indices i and j starting at zero (zero-based offset). This * means you have * * \f[ A_{n\times n} = * \left(\begin{array}{cccc} * a_{11} & a_{12} & \cdots & 0 \\ * a_{21} & \ddots & & \\ * & & \ddots & a_{(n-1)n} \\ * 0 & \cdots & a_{n(n-1)} & a_{nn} * \end{array}\right) * \f] * * but for accessing the element \f$a_{11}\f$ you have to * write @c A(0,0). * * Optional runtime bounds checking (0<=id_.size()-1) return outofbounds_; else #endif return d_(i); case 1: // lower #ifdef LA_BOUNDS_CHECK if (i>dl_.size()-1) return outofbounds_; else #endif // Before lapackpp-2.4.12 this was dl_(i) but that was WRONG! return dl_(j); case -1: // upper #ifdef LA_BOUNDS_CHECK if (i>du_.size()-1) return outofbounds_; else #endif return du_(i); default: return outofbounds_; } } inline double LaTridiagMatDouble::operator()(int i,int j) const { switch (i-j) { case 0: // main #ifdef LA_BOUNDS_CHECK if (i>d_.size()-1) return outofbounds_; else #endif return d_(i); case 1: // lower #ifdef LA_BOUNDS_CHECK if (i>dl_.size()-1) return outofbounds_; else #endif // Before lapackpp-2.4.12 this was dl_(i) but that was WRONG! return dl_(j); case -1: // upper #ifdef LA_BOUNDS_CHECK if (i>du_.size()-1) return outofbounds_; else #endif return du_(i); default: return outofbounds_; } } inline LaTridiagMatDouble& LaTridiagMatDouble::ref(LaTridiagMatDouble&T) { du2_.ref(T.du2_); du_.ref(T.du_); d_.ref(T.d_); dl_.ref(T.dl_); size_ = T.size_; return *this; } #endif // _LA_TRIDIAG_MAT_DOUBLE_