Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

Matrix.h

Go to the documentation of this file.
00001 /* WARANTY NOTICE AND COPYRIGHT
00002 This program is free software; you can redistribute it and/or
00003 modify it under the terms of the GNU General Public License
00004 as published by the Free Software Foundation; either version 2
00005 of the License, or (at your option) any later version.
00006 
00007 This program is distributed in the hope that it will be useful,
00008 but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 GNU General Public License for more details.
00011 
00012 You should have received a copy of the GNU General Public License
00013 along with this program; if not, write to the Free Software
00014 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00015 
00016 Copyright (C) Michael J. Meyer
00017 
00018 matmjm@mindspring.com
00019 spyqqqdia@yahoo.com
00020 
00021 */
00022 
00023 #ifndef martingale_matrix_h
00024 #define martingale_matrix_h
00025 
00026 
00027 #include <string>
00028 #include <sstream>
00029 #include <iostream>
00030 #include <algorithm>                      // min,max
00031 #include <cmath>
00032 #include "TypedefsMacros.h"
00033 //#include "tnt/tnt_array1d.h"
00034 //#include "tnt/tnt_array2d.h"
00035 #include "jama/jama_eig.h"
00036 //#include "tnt_array1d_utils.h"
00037 //#include "tnt_array2d_utils.h"
00038 #include "Array.h"
00039 //#include "Utils.h"                 
00040 
00041 /*
00042  * DataStructures.h
00043  *
00044  * Created on February 19, 2003, 6:00 PM
00045  */
00046 
00047 MTGL_BEGIN_NAMESPACE(Martingale)
00048 
00049 
00050 
00051 
00079 /***************************************************************************************
00080 
00081                       Useful global functions
00082 
00083 ***************************************************************************************/
00084 
00085 
00086 
00087 
00096 template<typename S>
00097 S relativeError(S exact, S approx, S epsilon)
00098 {
00099         S d=exact;
00100         if((-epsilon<d)&&(d<epsilon)) d=epsilon;
00101  
00102         return 100*(approx-exact)/d;
00103 } 
00104 
00105 
00106 
00107 
00108 /***************************************************************************************
00109 
00110                       C-Style vectors
00111 
00112 ***************************************************************************************/
00113 
00114 // forward declarations
00115 template<typename S,typename MatrixType> class Matrix;
00116 
00117 
00127 template<class S>
00128 class Vector {
00129 
00130 protected:
00131 
00132     int dim;         // dimension
00133         int b;           // index base: indices i=b,b+1,...,b+dim-1
00134     S* dptr;         // pointer to data
00135 
00136 public:
00137         
00138 // ACCESSORS
00139         
00141    int getDimension() const { return dim; }
00143    void setDimension(int d) { dim=d; }
00145    int getIndexBase() const { return b; }
00147    void setIndexBase(int base) { b=base; }
00148    S* getData() const { return dptr; }
00149  
00150       
00152    S& operator[](int i)
00153    {
00154            #ifdef SUBSCRIPT_CHECK
00155               SubscriptCheck::checkSubscript(i,b,dim,"Vector");
00156            #endif          
00157            return dptr[i-b]; 
00158     }
00159    
00161    const S& operator[](int i) const 
00162    { 
00163            #ifdef SUBSCRIPT_CHECK
00164               SubscriptCheck::checkSubscript(i,b,dim,"Vector");
00165            #endif         
00166            return dptr[i-b]; 
00167    }
00168    
00169    
00170    // CONSTRUCTION - DESTRUCTION
00171    ~Vector(){ delete[] dptr; }
00172    
00175    explicit Vector(int d, int base=0) : 
00176    dim(d), b(base), dptr(new S[d]) 
00177    { 
00178            for(int i=0;i<dim;i++) dptr[i]=0; 
00179    }
00180 
00181    
00182    // shallow copy not good enough if we return from function
00183    Vector(const Vector& v) : 
00184    dim(v.getDimension()), b(v.getIndexBase()), dptr(new S[dim])
00185    {
00186            S* vdptr=v.getData(); 
00187            for(int i=0;i<dim;i++) dptr[i]=vdptr[i];
00188    }
00189    
00190    
00197    Vector(int n, S& v) : 
00198    dim(n), b(0), dptr(new S[n])
00199    {
00200             for(int i=0;i<dim;i++) dptr[i]=v;
00201    }
00202 
00203    
00209    Vector(int n, S* a) : dim(n), b(0), dptr(new S[n])
00210    {
00211             for(int i=0;i<dim;i++) dptr[i]=a[i];
00212    }
00213    
00214    
00218    template<int n>
00219    Vector(S a[n]) : dim(n), dptr(new S[n])
00220    {
00221             for(int i=0;i<dim;i++) dptr[i]=a[i];
00222    }
00223 
00224    
00228    Vector& operator=(const Vector& x)
00229    {
00230        dim=x.getDimension(); 
00231            b=x.getIndexBase();
00232            S* xdptr=x.getData();
00233            for(int i=0;i<dim;i++) dptr[i]=xdptr[i];
00234            return *this;
00235    } 
00236    
00237    
00238    
00239 // ALGEBRAIC OPERATIONS NEEDED BY RANDOMOBJECT
00240    
00244    Vector& switchComponents(int i, int j)
00245    { 
00246        S tmp=dptr[i-b]; dptr[i-b]=dptr[j-b]; dptr[j-b]=tmp; 
00247    }
00248    
00249    
00253    Vector& operator +=(const Vector& x)
00254    { 
00255            S* xdptr=x.getData();
00256            for(int i=0;i<dim;i++) dptr[i]+=xdptr[i];
00257            return *this;
00258    }
00259    
00263    Vector& operator -=(const Vector& x)
00264    { 
00265            S* xdptr=x.getData();
00266            for(int i=0;i<dim;i++) dptr[i]-=xdptr[i];
00267            return *this;
00268    }
00269    
00272    Vector& operator /=(int N)
00273    { 
00274            Real f=1.0/N;
00275            for(int i=0;i<dim;i++) dptr[i]*=f;
00276            return *this;
00277    }
00278    
00279    
00282    Vector& operator *=(const S& lambda)
00283    { 
00284            for(int i=0;i<dim;i++) dptr[i]*=lambda;
00285            return *this;
00286    }
00287 
00288    
00291    template<typename MatrixBaseType>
00292    Vector& operator *=(const Matrix<S,MatrixBaseType>& A)
00293    { 
00294            int d=A.rows();        // new dimension
00295            S* Ax=new Real[d];         // new memory
00296            for(int i=0;i<d;i++){
00297                    
00298                    S sum=0.0;
00299                    for(int j=A.rowBegin(i);j<A.rowEnd(i);j++) sum+=A.entry(i,j)*dptr[j];
00300                    Ax[i]=sum;
00301            }
00302 
00303        // free the old memory and reset
00304            delete[] dptr; dptr=Ax; dim=d;
00305            return *this;
00306    }   
00307    
00308    
00309 // MEAN, EUCLIDEAN NORM
00310    
00312    S mean() const
00313    {  
00314            S sum=0; 
00315            for(int i=0;i<dim;i++) sum+=dptr[i];
00316            return sum/dim;
00317    }
00318    
00322    Real norm() const
00323    {  
00324            Real sum=0, absx_i; 
00325            for(int i=0;i<dim;i++){ absx_i=fabs(dptr[i]); sum+=absx_i*absx_i; }
00326            return sqrt(sum);
00327    }
00328    
00329    
00330 
00331 // TEST FOR EQUALITY
00332 
00333 
00345 void testEquals(const Vector<S>& v, S precision, S epsilon, string test) const
00346 {
00347         int vdim=v.getDimension(), vbase=v.getIndexBase(); 
00348         if((vdim!=dim)||(vbase!=b)){
00349                 
00350                 std::cout << "\n"+test+": failed, dimensions or index range not equal.";
00351                 return;
00352         }
00353                 
00354         for(int i=0;i<dim;i++)
00355         { 
00356                 S err=relativeError(dptr[i],v[i+b],epsilon);
00357                 if(err>precision){
00358                         
00359                      std::cout << "\n"+test+": failed, "
00360                                << "component v["<<i<<"], relative error " << err;
00361                      return;
00362                 }
00363         } // end for i
00364         
00365     std::cout << "\n"+test+": passed.";
00366 } // end testEquals
00367 
00368 
00369 // PRINTING
00370 
00371 std::ostream&  printSelf(std::ostream& os) const
00372 {
00373         os << "\n\nVector of dimension " << dim << ":" << endl;
00374     for(int i=0;i<dim-1;i++) os << dptr[i] << ", ";
00375     os << dptr[dim-1];
00376     return os << endl;
00377 } // end operator <<
00378         
00379               
00380 }; // end Vector
00381 
00382 
00385 template<class S>
00386 std::ostream& operator << (std::ostream& os, const Vector<S>& v)
00387 {
00388         return v.printSelf(os);
00389 } 
00390 
00391 
00392 typedef Vector<Real> RealVector;
00393         
00394 
00395 
00396 /***************************************************************************************
00397  *
00398  *                             MATRIX CLASSES
00399  *
00400 ***************************************************************************************/
00401 
00437 // IMPLEMENTATION NOTES: we use the Barton-Nachman trick.
00438 // The type of matrix (triangular,symmetric,...) is determined by the base class
00439 // from which the matrix class derives and this base class is a template parameter
00440 // for the derived class template.
00441 //
00442 // Matrices are stored in row major order and usually traversed row by row.
00443 // For each i we need to know where nonzero entries begin and end in this row.
00444 // The functions rowBegin(i) and rowEnd(i) provide this information.
00445 // The function rowEnd(i) returns the index one past the last nonzero entry
00446 // in row i. The functions colBegin(i) and colEnd(i) do the same for
00447 // the columns. The information returned by these functions is type specific
00448 // (upper triangular, lower triangular,...) and not specific to each matrix 
00449 // object and allows optimizations depending on the matrix type (matrix
00450 // products).
00451 
00452 
00453 
00454 /***************************************************************************************
00455  *
00456  *                      MATRIX BASE TYPES
00457  *
00458 ***************************************************************************************/
00459 
00460 // forward declaration
00461 template<typename S> class LowerTriangular;
00462 
00463 
00464 // IMPLEMENTATION NOTES: the matrix base classes define the behaviour for the 
00465 // various special matrix classes. They are put at the base of the derived class
00466 // Matrix using the Barton-Nachman trick (base class is a template parameter for
00467 // the derived template class). 
00468 // 
00469 // Consequently many functions will seem to have unnecessary general parameter
00470 // signatures (the most general applying to any matrix type). This is necessary
00471 // as the derived class Matrix has to be written in the most general case and
00472 // has to call functions without any assumptions of the type of the base class.
00473 
00474 
00478 template<typename S>
00479 class UpperTriangular {
00480         
00481 protected:
00482         
00483         int dim;      // number of rows = number of cols            
00484         S** dptr;     // pointer to data
00485         
00486 public:
00487         
00488         typedef LowerTriangular<S> TransposeType;
00489         
00491 int rows() const { return dim; }
00493 int cols() const { return dim; }
00495 void setCols(int) {   }
00496 
00501 S** allocate(int nRows, int nCols)
00502 {
00503         if(nRows!=nCols)
00504         { cout<<"\n\nUpper triangular matrix must be square. Terminating."; exit(1); }
00505         S** data=new S*[nRows];
00506         for(int i=0;i<nRows;i++){
00507                 
00508         data[i]=new S[nRows-i];
00509         for(int j=i;j<nRows;j++)data[i][j-i]=0;
00510     }
00511         return data;
00512 }
00513 
00514 
00519 UpperTriangular(int nRows, int nCols) : dim(nRows), dptr(allocate(nRows,nCols)) {  } 
00520         
00521 ~UpperTriangular(){  for(int i=0;i<dim;i++) delete[] dptr[i]; delete[] dptr; }
00522         
00523         
00524 
00526 S& entry(int i, int j){ return dptr[i][j-i]; }
00528 const S& entry(int i, int j) const { return dptr[i][j-i]; }
00529 
00530                 
00532 int rowBegin(int i) const { return i; }
00533 
00535 int rowEnd(int i) const { return dim; }
00536 
00538 int colBegin(int j) const { return 0; }
00539 
00541 int colEnd(int j) const { return j+1; }
00542 
00543         
00544 }; // end UpperTriangular
00545 
00546 
00547 
00548 
00552 template<typename S>
00553 class LowerTriangular{
00554                 
00555 protected:
00556         
00557         int dim;      // number of rows = number of cols            
00558         S** dptr;     // pointer to data
00559         
00560 public:
00561         
00562         typedef UpperTriangular<S> TransposeType;
00563         
00565 int rows() const { return dim; }
00567 int cols() const { return dim; }
00569 void setCols(int) {   }
00570 
00571 
00576 S** allocate(int nRows, int nCols)
00577 {
00578         if(nRows!=nCols)
00579         { cout<<"\n\nLower triangular matrix must be square. Terminating."; exit(1); }
00580         S** data=new S*[nRows];
00581         for(int i=0;i<nRows;i++){
00582                 
00583         data[i]=new S[i+1];
00584         for(int j=0;j<=i;j++)data[i][j]=0;
00585    }
00586    return data;
00587 }
00588 
00589                 
00594 LowerTriangular(int nRows, int nCols) : dim(nRows), dptr(allocate(nRows,nCols)) {  } 
00595 
00596 ~LowerTriangular(){  for(int i=0;i<dim;i++) delete[] dptr[i]; delete[] dptr; }
00597         
00598         
00600 S& entry(int i, int j){ return dptr[i][j]; }
00602 const S& entry(int i, int j) const { return dptr[i][j]; }
00603         
00604                 
00606 int rowBegin(int i) const { return 0; }
00607 
00609 int rowEnd(int i) const { return i+1; }
00610 
00612 int colBegin(int j) const { return j; }
00613 
00615 int colEnd(int j) const { return dim; }
00616 
00617                 
00618 }; // end LowerTriangular
00619 
00620 
00621 
00622 
00626 template<typename S>
00627 class Rectangular {
00628         
00629 protected:
00630         
00631         int rows_,        // number of rows 
00632             cols_;        // number of columns
00633         S** dptr;         // pointer to data
00634 
00635         
00636 public:
00637         
00638         typedef Rectangular<S> TransposeType;
00639         
00641 int rows() const { return rows_; }
00643 int cols() const { return cols_; }
00645 void setCols(int nCols) { cols_=nCols;  }
00646 
00647 
00652 S** allocate(int nRows, int nCols)
00653 {
00654         S** data=new S*[nRows];
00655         for(int i=0;i<nRows;i++){
00656                 
00657         data[i]=new S[nCols];
00658         for(int j=0;j<nCols;j++)data[i][j]=0;
00659    }
00660    return data;
00661 }
00662         
00663                 
00668 Rectangular(int nRows, int nCols) : 
00669 rows_(nRows), cols_(nCols), dptr(allocate(nRows,nCols))
00670 {    } 
00671 
00672 ~Rectangular(){  for(int i=0;i<rows_;i++) delete[] dptr[i]; delete[] dptr; }
00673         
00674         
00676 S& entry(int i, int j){ return dptr[i][j]; }
00678 const S& entry(int i, int j) const { return dptr[i][j]; }
00679 
00680         
00682 int rowBegin(int i) const { return 0; }
00683 
00685 int rowEnd(int i) const { return cols_; }
00686 
00688 int colBegin(int j) const { return 0; }
00689 
00691 int colEnd(int j) const { return rows_; }
00692 
00693         
00694 }; // end Rectangular
00695 
00696 
00697 
00698 /***************************************************************************************
00699  *
00700  *                      MATRIX PRODUCT RETURN TYPE
00701  *
00702 ***************************************************************************************/
00703 
00704 
00706 template<typename S, typename MatrixType1, typename MatrixType2>
00707 struct ProductType { typedef Rectangular<S> type; };
00708 
00712 template<typename S, typename MatrixType>
00713 struct ProductType<S,MatrixType,MatrixType> { typedef MatrixType type; };
00714         
00715 
00716 
00717 
00718 /***************************************************************************************
00719  *
00720  *                             MATRIX
00721  *
00722 ***************************************************************************************/
00723 
00724 
00734 template<typename S, typename MatrixBaseType>
00735 class Matrix : public MatrixBaseType {
00736 
00737 protected:
00738 
00739         int a;           // row index base
00740         int b;           // column index base
00741         
00742         static S cache[SMALL][SMALL];          // workspace for small matrix optimization.
00743 
00744 
00745 public:
00746          
00748         typedef typename MatrixBaseType::TransposeType TransposeType;
00749 
00750 
00751 // FREE MEMORY
00752         
00753 void deallocate(){ for(int i=0;i<rows();i++) delete[] dptr[i]; delete[] dptr; }
00754                 
00755 // ACCESSORS
00756 
00758 S** getData() const { return dptr; }
00759 
00761 int getRowIndexBase() const { return a; }
00763 void setRowIndexBase(int r){ a=r; }
00764 
00766 int getColIndexBase() const { return b; }
00768 void setColIndexBase(int c){ b=c; }
00769 
00770 
00774 S& operator()(int i, int j)
00775 { 
00776         #ifdef SUBSCRIPT_CHECK
00777           SubscriptCheck::checkSubscript(i,j,a,b,rows(),cols(),"Matrix");
00778         #endif          
00779         return entry(i-a,j-b);
00780 }
00781 
00782 
00786 const S& operator()(int i, int j) const 
00787 { 
00788         #ifdef SUBSCRIPT_CHECK
00789           SubscriptCheck::checkSubscript(i,j,a,b,rows(),cols(),"Matrix");
00790         #endif          
00791         return entry(i-a,j-b);
00792 }       
00793         
00794 
00795 // EQUALITY CHECK
00796 
00807 void testEquals(const Matrix& B, S precision, S epsilon, string test) const
00808 {
00809         int a_B=B.getRowIndexBase(), b_B=B.getColIndexBase();
00810         if((B.rows()!=rows())||(B.cols()!=cols())){
00811                 
00812                 std::cout << "\nMatrix::testEquals(): "+test+": failed, dimensions not equal.";
00813                 return;
00814         }
00815         
00816         if((a_B!=a)||(b_B!=b)){
00817                 
00818                 std::cout << "\nMatrix::testEquals(): "+test+": failed, index bases not equal.";
00819                 return;
00820         }
00821         
00822         for(int i=0;i<rows();i++)
00823         for(int j=rowBegin(i);j<rowEnd(i);j++) { 
00824                 
00825                     S err=relativeError(entry(i,j),B.entry(i,j),epsilon);
00826                     if((err>precision)||(-err>precision)){
00827                         
00828                             std::cout << "\n"+test+": failed, "
00829                                       << "component B["<<i<<"]["<<j<<"], relative error " << err;
00830                         return;
00831                     } // endif
00832         } // end for i
00833 
00834     std::cout << "\n"+test+": passed.";
00835 } // end testEquals
00836 
00837 
00838 // CONSTRUCTION - DESTRUCTION
00839 
00840 
00846 Matrix(int dim, int c=0) : MatrixBaseType(dim,dim), a(c), b(c) {    }
00847 
00848 
00855 Matrix(int nRows, int nCols, int row_base, int col_base) : 
00856 MatrixBaseType(nRows,nCols),
00857 a(row_base), b(col_base) 
00858 {    }
00859 
00860 
00861 
00864 Matrix(const Matrix& A) : MatrixBaseType(A.rows(),A.cols()),
00865 a(A.getRowIndexBase()), b(A.getColIndexBase()) 
00866 {
00867         for(int i=0;i<rows();i++)
00868         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)=A.entry(i,j);
00869 }
00870 
00871 
00880 template<int dim>
00881 Matrix(S A[dim][dim], int row_base=0, int col_base=0) : 
00882 MatrixBaseType(dim,dim),
00883 a(row_base), b(col_base) 
00884 {
00885         for(int i=0;i<rows();i++)
00886         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)=A[i][j]; 
00887 }
00888 
00889 
00892 Matrix& operator =(const Matrix& B)
00893 {
00894     if(this=&B) return *this;
00895         if((rows()!=B.rows())||(cols()!=B.cols())){
00896                 
00897                 cout << "\n\nMatrix assignement: matrix sizes different. Terminating.";
00898                 exit(1);
00899         }
00900 
00901         a=B.getRowIndexBase(); b=B.getColIndexBase();
00902         for(int i=0;i<rows();i++)
00903         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)=B.entry(i,j);
00904         
00905         return *this;
00906 }
00907 
00908 
00909 
00910 // NORMS
00911 
00915 Real norm() const
00916 {
00917         Real sum=0.0, absij;
00918         for(int i=0;i<rows();i++)
00919         for(int j=rowBegin(i);j<rowEnd(i);j++) { absij=std::abs(entry(i,j)); sum+=absij*absij; }
00920         
00921         return sqrt(sum);
00922 } // end norm
00923 
00924 
00925 
00929 Real rowNorm(int i) const
00930 {
00931         Real sum=0, absij;
00932         for(int j=rowBegin(i);j<rowEnd(i);j++) { absij=std::abs(entry(i,j)); sum+=absij*absij; }
00933         
00934         return sqrt(sum);
00935 } // end norm
00936 
00937 
00938 
00942 Real colNorm(int j)
00943 {
00944         Real sum=0, absij;
00945         for(int i=colBegin(j);i<colEnd(j);i++) { absij=std::abs(entry(i,j)); sum+=absij*absij; }
00946         
00947         return sqrt(sum);
00948 } // end norm
00949         
00950 
00951 
00955 Matrix& scaleRow(int i, Real f)
00956 {
00957         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i-a,j)*=f; 
00958         return *this;
00959 } // end scaleRow
00960 
00961 
00965 Matrix& scaleCol(int j, Real f)
00966 {
00967         for(int i=colBegin(j);i<colEnd(j);i++) entry(i,j-b)*=f;         
00968         return *this;
00969 } // end scaleRow
00970 
00971 
00972         
00973 
00974 // ALGEBRAIC OPERATIONS
00975 
00979 S quadraticForm(const Vector<S>& x) const
00980 {
00981         int dim_x=x.getDimension(), 
00982             b_x=x.getIndexBase();
00983         if((rows()!=dim_x)||(cols()!=dim_x)){
00984                 
00985                 cout << "\n\nMatrix::quadraticForm(): dimensional mismatch. Terminating.";
00986                 exit(1);
00987         }
00988         S d=0, u=0, x_i,x_j;
00989         // diagonal
00990         for(int i=0;i<rows();i++) { x_i=x[i+b_x]; d+=x_i*x_i*entry(i,i); }
00991         // above the diagonal
00992         for(int i=0;i<rows();i++)
00993         for(int j=i+1;j<cols();j++) { x_i=x[i+b_x]; x_j=x[j+b_x]; u+=x_i*x_j*entry(i,j); }
00994 
00995         return d+2*u;
00996 }
00997 
00998 
00999 
01002 Matrix<S,TransposeType>& transpose() const
01003 {
01004         Matrix<S,TransposeType>* 
01005         trnsps=new Matrix<S,TransposeType>(cols(),rows(),b,a);
01006     for(int i=0;i<rows();i++)
01007         for(int j=rowBegin(i);j<rowEnd(i);j++) trnsps->entry(j,i)=entry(i,j);
01008         
01009         return *trnsps;
01010 }
01011         
01012 
01016 Matrix& operator += (const Matrix& B)
01017 {
01018         if((rows()!=B.rows())||(cols()!=B.cols())){
01019                 
01020                 cout << "\n\nMatrix +=: matrix sizes different. Terminating.";
01021                 exit(1);
01022         }
01023         for(int i=0;i<rows();i++)
01024         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)+=B.entry(i,j);
01025                 
01026         return *this;
01027 } // end operator +=
01028 
01029 
01032 Matrix& operator *= (Real f)
01033 {
01034         for(int i=0;i<rows();i++)
01035         for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)*=f;
01036                 
01037         return *this;
01038 } // end operator +=
01039 
01040 
01044 // product will have the same type as this.
01045 Matrix& operator *= (const Matrix& B)
01046 {
01047         if(cols()!=B.rows()) {
01048                 
01049                 cout << "\n\nMatrix *=: matrix sizes not compatible. Terminating.";
01050                 exit(1);
01051         }
01052         
01053         // if both matrices are small and square use the workspace, no memory allocation.
01054         // matrix size does not change and so the product matrix can use the old memory.
01055         if((rows()<SMALL)&&(rows()==cols())&&(cols()==B.cols())){
01056         
01057             for(int i=0;i<rows();i++)
01058             for(int j=rowBegin(i);j<rowEnd(i);j++){
01059                 
01060             S sum=0.0;
01061                     int u=std::max(rowBegin(i),B.colBegin(j)),
01062                         v=std::min(rowEnd(i),B.colEnd(j));
01063                     for(int k=u;k<v;k++) sum+=entry(i,k)*B.entry(k,j);
01064                     cache[i][j]=sum;            
01065             }
01066             // copy the entries from the workspace
01067             for(int i=0;i<rows();i++)
01068             for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)=cache[i][j];
01069                 return *this;
01070         } // end if
01071         
01072         // otherwise allocate new memory for the product
01073         Matrix<S,MatrixBaseType>* product = new Matrix<S,MatrixBaseType>(rows(),B.cols(),a,b);
01074     for(int i=0;i<rows();i++)
01075         for(int j=product->rowBegin(i);j<product->rowEnd(i);j++){
01076                 
01077         S sum=0.0;
01078                 int u=std::max(rowBegin(i),B.colBegin(j)),
01079                     v=std::min(rowEnd(i),B.colEnd(j));
01080                 for(int k=u;k<v;k++) sum+=entry(i,k)*B.entry(k,j);
01081                 product->entry(i,j)=sum;
01082         }
01083         deallocate();                // free old memory
01084         dptr=product->getData();
01085         setCols(B.cols());
01086         return *this;
01087                 
01088 } // end operator *=
01089 
01090 
01091 
01097 // product will have the same type as this.
01098 Matrix& operator ^= (const Matrix<S,TransposeType>& B)
01099 {
01100          if(cols()!=B.cols()){
01101                    
01102                    cout << "\n\nMatrix ^=: dimensions not compatible. Terminating.";
01103                exit(1);
01104          }
01105 
01106         // if both matrices are small and square use the workspace, no memory allocation.
01107         // matrix size does not change and so the product matrix can use the memory of dptr
01108         if((rows()<SMALL)&&(rows()==cols())&&(rows()==B.rows())){
01109         
01110             for(int i=0;i<rows();i++)
01111             for(int j=rowBegin(i);j<rowEnd(i);j++){
01112                 
01113             Real sum=0.0;
01114                     int u=std::max(rowBegin(i),B.rowBegin(j)),
01115                         v=std::min(rowEnd(i),B.rowEnd(j));
01116                     for(int k=u;k<v;k++) sum+=entry(i,k)*B.entry(j,k);
01117                     cache[i][j]=sum;            
01118             }
01119             // copy the entries from the workspace
01120             for(int i=0;i<rows();i++)
01121             for(int j=rowBegin(i);j<rowEnd(i);j++) entry(i,j)=cache[i][j];
01122                 return *this;
01123         } // end if
01124         
01125         // otherwise allocate new memory for the product,
01126         Matrix<S,MatrixBaseType>* product = new Matrix<S,MatrixBaseType>(rows(),B.rows(),a,b);
01127     for(int i=0;i<rows();i++)
01128         for(int j=product->rowBegin(i);j<product->rowEnd(i);j++){
01129                 
01130         S sum=0.0;
01131                 int u=std::max(rowBegin(i),B.rowBegin(j)),
01132                     v=std::min(rowEnd(i),B.rowEnd(j));
01133                 for(int k=u;k<v;k++) sum+=entry(i,k)*B.entry(j,k);
01134                 product->entry(i,j)=sum;
01135         }
01136         deallocate();                     // free the old memory
01137         dptr=product->getData();
01138         setCols(B.rows());
01139         return *this;
01140                 
01141 } // end operator ^=
01142 
01143 
01144 
01145 
01146 // MATRIX FUNCTIONS: some analytic functions f(A), where A=this.
01147 
01148 
01152 Matrix< S,UpperTriangular<S> >& aat() const
01153 {
01154     Matrix< S,UpperTriangular<S> >* 
01155         c = new Matrix< S,UpperTriangular<S> >(rows(),rows(),0,0); // aat
01156         for(int i=0;i<rows();i++)
01157         for(int j=i;j<rows();j++){
01158                 
01159                 S sum=0.0;                                      // row_i\cdot row_j
01160         int u=std::max(rowBegin(i),rowBegin(j)),
01161                     v=std::min(rowEnd(i),rowEnd(j));
01162                 for(int k=u;k<v;k++) sum+=entry(i,k)*entry(j,k);
01163                 c->entry(i,j)=sum;
01164         }
01165         return *c;
01166 } // end aat
01167 
01168 
01169 
01172 Matrix& exp() const
01173 {
01174     if(rows()!=cols()){
01175                 
01176                 cout << "\n\nMatrix::exp(): matrix not square. Terminating.";
01177                 exit(1);
01178         }
01179         
01180         int n=2;
01181         Real fn=norm(), f=4.0, g=1.0;
01182         while((f<fn)){ f*=2.0; n++; }                   // f=2^n
01183         g=1.0/f; g/=64.0;                               // g=1/2^{n+6}
01184 
01185         // temporary matrices
01186         Matrix<S,MatrixBaseType> U(rows());             // U=(A/2^{n+6})=g*A 
01187         Matrix<S,TransposeType>  Ut(rows());            // U', we use ^=U ie. *=U'
01188         Matrix<S,MatrixBaseType> SUk(rows());           // sum of U^k/k!, k=0,1,..,6
01189 
01190         for(int i=0;i<rows();i++)
01191         for(int j=rowBegin(i);j<rowEnd(i);j++){ 
01192                 
01193                 U(i,j)=Ut(j,i)=SUk(i,j)=g*entry(i,j);       // U=A/2^{n+6}
01194                 if(i==j) SUk(i,j)+=1.0;                     // I+U
01195         }
01196         
01197         // Suk=I+U+U^2/2!+...+U^8/8! 
01198         for(int k=2;k<=8;k++){ U^=Ut; g=1.0/k; U*=g; SUk+=U; }
01199         
01200         // exp(A)=Suk^m, m=2^{n+6};
01201     Matrix<S,MatrixBaseType>& F=*(new Matrix<S,MatrixBaseType>(SUk));    
01202         for(int k=0;k<n+6;k++) F*=F;
01203         F.setRowIndexBase(a);   
01204         F.setColIndexBase(b);   
01205         return F;
01206 
01207 } // end exp
01208 
01209 
01210 // PRINTING
01211 
01212 std::ostream& printSelf(std::ostream& os) const
01213 {
01214         os << "\n\nMatrix, rows: " << rows() << endl << endl;
01215         for(int i=0;i<rows();i++){
01216                 
01217                 int u=rowBegin(i), v=rowEnd(i); 
01218                 for(int j=0;j<u;j++) os << 0.0 << ", ";
01219                 for(int j=u;j<v-1;j++) os << entry(i,j) << ", ";
01220                 os << entry(i,v-1) << endl;
01221         }
01222     return os << endl << endl;
01223 } 
01224 
01225 
01226 }; // end Matrix
01227 
01228 
01229 
01230 
01231 // cache must be initialized outside the class:
01232 template<typename S,typename MatrixBaseType>
01233 S Matrix<S,MatrixBaseType>::cache[SMALL][SMALL] = { };
01234 
01235 
01238 template<typename S, typename MatrixBaseType>
01239 std::ostream& operator << (std::ostream& os, const Matrix<S,MatrixBaseType>& A) 
01240 {
01241     return A.printSelf(os);
01242 } // end operator <<
01243 
01244 
01245 
01246 
01247 
01248 // SOME  MATRIX TYPES
01249 
01250 // since there are no templated typedefs:
01251 template<typename S>
01252 class UTRMatrix : public Matrix< S,UpperTriangular<S> >{
01253         
01254 public:
01255 
01260 UTRMatrix(int dim, int a=0) : Matrix< S,UpperTriangular<S> >(dim,dim,a,a) {  }
01261         
01262 };
01263         
01264         
01265 // upper triangular and symmetric real types are more elaborate below.
01266 typedef Matrix< Real,Rectangular<Real> > RealMatrix;
01267 typedef Matrix< Real,LowerTriangular<Real> > LTRRealMatrix;
01268 
01269 
01270 
01271 /***************************************************************************************
01272  *
01273  *                             UPPER TRIANGULAR MATRICES
01274  *
01275 ***************************************************************************************/
01276 
01277 
01278 
01279 // DIAGONALIZATION, RANK REDUCED FACTORIZATION, EIGEN ANALYSIS
01280 
01281 // forward declarations
01282 class UTRRealMatrix;
01283 
01284 
01288 JAMA::Eigenvalue<Real>* eigenDecomposition(const UTRRealMatrix& C);
01289 
01290 
01300 RealMatrix& rank_Reduced_Root(const UTRRealMatrix& C, int r);
01301                 
01302 
01303 
01308 void factorAnalysis(const UTRRealMatrix& C, int r);
01309         
01310 
01311 
01319 void factorizationTest(const UTRRealMatrix& C, int r, string message="");
01320 
01321 
01322 
01335 class UTRRealMatrix : public Matrix< Real,UpperTriangular<Real> > {
01336 
01337 public:
01338         
01343 UTRRealMatrix(int d, int b=0) : Matrix< Real,UpperTriangular<Real> >(d,d,b,b) {  }
01344 
01345         
01350 template<int n>
01351 UTRRealMatrix(Real A[n][n], int b=0) : Matrix< Real,UpperTriangular<Real> >(A,b) {   }
01352         
01353         
01357 RealMatrix& symmetricCompletion() const;
01358 
01359 
01362 UTRRealMatrix& inverse() const;
01363         
01364 
01369 LTRRealMatrix& ltrRoot() const;
01370 
01371 
01377 UTRRealMatrix& utrRoot() const;
01378 
01379 
01388 RealMatrix& rankReducedRoot(int r) const;
01389 
01390 
01393 UTRRealMatrix& exp() const;
01394 
01395 
01404 RealMatrix& matrixFunction(Real (*f)(Real));
01405 
01406 
01411 void analyseFactors(int r) const;
01412 
01413 
01422 void testFactorization(int r, string message="") const;
01423 
01424 
01425 }; // end UTRRealMatrix
01426 
01427 
01428 
01429 
01430 /***************************************************************************************
01431  *
01432  *            MATRIX ARRAYS
01433  *
01434 ***************************************************************************************/
01435 
01436 
01442 class UTRMatrixSequence {
01443         
01444         int n;                         // number of matrices
01445         // array of pointers to const UTRMatrix: *matrix[t] is read only
01446         Array1D<const UTRRealMatrix*> matrices;    
01447         
01448 public:
01449         
01454         UTRMatrixSequence(int m) : 
01455         n(m), matrices(m) 
01456     {  }  
01457         
01459         ~UTRMatrixSequence(){ for(int t=0;t<n;t++) delete matrices[t]; }
01460 
01461         
01464     const UTRRealMatrix& getMatrix(int t) const { return *(matrices[t]); }
01465         
01468     void setMatrix(int t, const UTRRealMatrix& matrix) { matrices[t]=&matrix; }
01469         
01470 }; // end UTRMatrixSequence
01471 
01472 
01473 
01474 
01479 class MatrixSequence {
01480         
01481         int n;                                    // number of matrices
01482         Array1D<const RealMatrix*> matrices;      // matrices[t]: pointer to matrix(t)
01483         
01484 public:
01485         
01490         MatrixSequence(int m) : 
01491         n(m), matrices(m) 
01492     {  }  
01493         
01495         ~MatrixSequence(){ for(int t=0;t<n;t++) delete matrices[t]; }
01496 
01497         
01500     const RealMatrix& getMatrix(int t) const { return *(matrices[t]); }
01501         
01504     void setMatrix(int t, const RealMatrix& matrix) { matrices[t]=&matrix; }
01505         
01506 }; // endMatrixSequence
01507 
01508 
01509 
01510 
01511 MTGL_END_NAMESPACE(Martingale)
01512 
01513 #endif
01514 

Generated on Mon Sep 22 02:16:32 2003 for Libor-Library by doxygen1.3-rc3