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

DenseMatrix.h

00001 /****************************************************************************
00002  *                                                                          *
00003  *  Program: FDDlib                                                         *
00004  *  Version: 1.1                                                            *
00005  *                                                                          *
00006  *  Copyright (C) 2002 - 2004 by Eric Miller and Dana Brooks                *
00007  *  All rights reserved.                                                    *
00008  *                                                                          *
00009  *  This software is Version 1.1 of the fddlib tomography toolbox.          *
00010  *  It is not to be redistributed or used for any commercial purpose        *
00011  *  without the prior written consent of the authors and Northeastern       *
00012  *  University.                                                             *
00013  *                                                                          *
00014  *  This software is provided as is, and any express or implied warranties, *
00015  *  including but not limited to the implied warranty of merchantability    *
00016  *  and the implied warranty of fitness for a particular purpose, are dis-  *
00017  *  claimed.  In no event shall the authors or Northeastern University be   *
00018  *  liable for any direct, indirect, incidental, special, exemplary, or     *
00019  *  consequential damages (including but not limited to procurement of      * 
00020  *  substitute goods or services; loss of use, data, or profits; or busi-   *
00021  *  ness interruption) however caused and on any theory of liability,       *
00022  *  whether in contract, strict liability, or tort (including negligence or *
00023  *  otherwise) arising in any way from the use of this software, even if    *
00024  *  advised of the possibility of such damage.                              *
00025  *                                                                          *
00026  *  Portions of this code benefit from ideas from Kyle Guilbert, Greg       *
00027  *  Boverman, Derek Uluski, David Kaeli, and Jennifer Black                 *
00028  *                                                                          *
00029  ****************************************************************************/
00030 
00031 #ifndef _DENSE_MATRIX_H_
00032 #define _DENSE_MATRIX_H_
00033 
00034 #include "RealVector.h"
00035 #include "Matrix.h"
00036 #include <string>
00037 
00038 // Minimal tolerance for maintaining linear independence
00039 #define QR_MIN_NORM 1.0e-20
00040 
00041 namespace FDDlib {
00042 
00046 template<class T>
00047 class DenseMatrix : public Matrix<T>
00048 {
00049 protected:
00051   int rows_;
00053   int cols_;
00055   T*  valVec_;
00056   
00057 public:
00062   DenseMatrix(int rows, int cols);
00063   
00065   DenseMatrix();
00066 
00068   DenseMatrix(const DenseMatrix<T>& dm);
00069 
00071   virtual ~DenseMatrix();
00072   
00074   void deallocate();
00075 
00080   void init(int rows, int cols);
00081 
00083   DenseMatrix<T>& operator=(const DenseMatrix<T>& dm);
00084 
00088   DenseMatrix<T>& operator*=(const T v);
00089 
00091   template<class Vector>
00092   Vector operator*(const Vector& m) const;
00093 
00095   int getNumRows() const;
00096 
00098   int getNumCols() const;
00099 
00101   T val(int row, int col) const;
00102 
00104   void set(int row, int col, T v) throw(std::string);
00105 
00111   void QRDecomp(DenseMatrix<T>& Q, DenseMatrix<T>& R) const throw(std::string);
00112 
00118   template<class Vector>
00119   void LSSolve(Vector& x, const Vector& b) const throw(std::string);
00120 
00122   DenseMatrix<T> operator*(const DenseMatrix<T>& a) const;
00123 
00125   DenseMatrix<T> operator+(const DenseMatrix<T>& a) const;
00126 
00128   DenseMatrix<T> operator-(const DenseMatrix<T>& a) const;
00129 
00131   DenseMatrix<T> transpose() const;
00132 
00134   RealVector<T> getRow(int row) const;
00135 
00137   RealVector<T> getColumn(int col) const;
00138 
00140   T& operator()(int row, int col);
00141 
00143   T operator()(int row, int col) const;
00144 
00145 };
00146 
00147 template<class T>
00148 DenseMatrix<T>::DenseMatrix(int rows, int cols)
00149 {
00150   int i;
00151 
00152   rows_ = rows;
00153   cols_ = cols;
00154   valVec_ = new T[rows_*cols_];
00155   for (i = 0; i < rows_*cols_; i++)
00156   {
00157     valVec_[i] = (T) 0;
00158   }
00159 }
00160 
00161 template<class T>
00162 DenseMatrix<T>::DenseMatrix()
00163 {
00164   rows_ = 0;
00165   cols_ = 0;
00166   valVec_ = (T*) NULL;
00167 }
00168 
00169 template<class T>
00170 DenseMatrix<T>::DenseMatrix(const DenseMatrix<T>& dm)
00171 {
00172   int i, j;
00173 
00174   rows_ = dm.getNumRows();
00175   cols_ = dm.getNumCols();
00176   valVec_ = new T[rows_*cols_];
00177   for (i = 0; i <  rows_; i++)
00178   {
00179     for (j = 0; j < cols_; j++)
00180     {
00181       set(i,j, dm.val(i,j));
00182     }
00183   }
00184 }
00185 
00186 template<class T>
00187 void DenseMatrix<T>::deallocate()
00188 {
00189   delete[] valVec_;
00190 }
00191 
00192 
00193 template<class T>
00194 DenseMatrix<T>::~DenseMatrix()
00195 {
00196   delete[] valVec_;
00197 }
00198 
00199 template<class T>
00200 void DenseMatrix<T>::init(int rows, int cols)
00201 {
00202   int i;
00203 
00204   rows_ = rows;
00205   cols_ = cols;
00206   if (valVec_ != (T*) NULL)
00207   {
00208     delete[] valVec_;
00209   }
00210 
00211   valVec_ = new T[rows*cols];
00212   for (i = 0; i < rows_*cols_; i++)
00213   {
00214     valVec_[i] = (T) 0;
00215   }
00216 }
00217 
00218 template<class T>
00219 DenseMatrix<T>& DenseMatrix<T>::operator=(const DenseMatrix<T>& dm)
00220 {
00221   int i, j;
00222 
00223   if (valVec_ != (T*) NULL)
00224     delete[] valVec_;
00225 
00226   rows_ = dm.getNumRows();
00227   cols_ = dm.getNumCols();
00228   valVec_ = new T[rows_*cols_];
00229   for (i = 0; i < rows_; i++)
00230   {
00231     for (j =0; j < cols_; j++)
00232     {
00233       set(i,j,dm.val(i,j));
00234     }
00235   }
00236   return *this;
00237 }
00238 
00239 template<class T>
00240 inline DenseMatrix<T>& DenseMatrix<T>::operator*=(const T v)
00241 {
00242   int i, j;
00243 
00244   for (i = 0; i < rows_; i++)
00245   {
00246     for (j = 0; j < cols_; j++)
00247     {
00248       set(i,j, val(i,j) * v);
00249     }
00250   }
00251 
00252   return *this;
00253 }
00254 
00255 template<class T>
00256 template<class Vector>
00257 inline Vector DenseMatrix<T>::operator*(const Vector& m) const
00258 {
00259   int    i, j;
00260   T      v;
00261   Vector ret(getNumRows());
00262 
00263   for (i = 0; i < getNumRows(); i++)
00264   {
00265     v = (T) 0;
00266     for (j = 0; j < getNumCols(); j++)
00267     {
00268      v += (T) (val(i,j) * m(j));
00269     }
00270     ret(i) = v;
00271   }
00272 
00273   return ret;
00274 }
00275 
00276 template<class T>
00277 inline int DenseMatrix<T>::getNumRows() const
00278 {
00279   return rows_;
00280 }
00281 
00282 template<class T>
00283 inline int DenseMatrix<T>::getNumCols() const
00284 {
00285   return cols_;
00286 }
00287 
00288 template<class T>
00289 inline T DenseMatrix<T>::val(int row, int col) const
00290 {
00291   return valVec_[row*cols_ + col];
00292 }
00293 
00294 template<class T>
00295 inline void DenseMatrix<T>::set(int row, int col, T v) throw(std::string)
00296 {
00297   valVec_[row*cols_ + col] = v;
00298 }
00299 
00300 template<class T>
00301 void DenseMatrix<T>::QRDecomp(DenseMatrix<T>& Q, DenseMatrix<T>& R) const throw(std::string)
00302 {
00303   int        i, j;
00304   T          v;
00305   double     n;
00306   T          proj;
00307 
00308   // What will be an orthonormal basis
00309   // of the columns of A
00310   RealVector<T> * rv = new RealVector<T>[getNumCols()];
00311   for (i = 0; i < getNumCols(); i++)
00312   {
00313     rv[i].init(getNumRows());
00314   }
00315 
00316   for (i = 0; i < getNumRows(); i++)
00317   {
00318     for (j = 0; j < getNumCols(); j++)
00319     {
00320       v = val(i,j);
00321       rv[j].set(i, v);
00322     }
00323   }
00324 
00325   // Now we assume that the columns of the matrix are linearly
00326   // independent
00327 
00328   Q.init(getNumRows(), getNumCols());
00329   R.init(getNumCols(), getNumCols());
00330 
00331   for (i = 0; i < getNumCols(); i++)
00332   {
00333     n = norm(rv[i]);
00334     if (n < QR_MIN_NORM)
00335       throw std::string("DenseMatrix::QRDecomp: norm of basis is too small");
00336     rv[i] *= (T) (1/n);
00337     R(i,i) = (T) n;
00338     for (j = i+1; j < getNumCols(); j++)
00339     {
00340       proj = (T) dot(rv[i], rv[j]);
00341       R(i,j) = proj;
00342       rv[j] -= proj*rv[i];
00343     }
00344   }
00345 
00346   // Now copy the linearly independent
00347   // basis back to Q
00348 
00349   for (i = 0; i < getNumRows(); i++)
00350   {
00351     for (j = 0; j < getNumCols(); j++)
00352     {
00353       v = rv[j].val(i);
00354       Q(i,j) = v;
00355     }
00356   }
00357 
00358 }
00359 
00360 
00361 template<class T>
00362 template<class Vector>
00363 void DenseMatrix<T>::LSSolve(Vector& x, const Vector& b) const throw(std::string)
00364 {
00365   int            i, j;
00366   DenseMatrix<T> Q,R;
00367   Vector         rhs;
00368   T              v;
00369 
00370   try {
00371     QRDecomp(Q,R);
00372   } catch (std::string s) { 
00373     throw std::string("DenseMatrix::LSSolve: QR Decomposition failed.");
00374   }
00375 
00376   // Solution is Rx = Q'*b
00377   rhs = (Q.transpose())*b;
00378 
00379   Vector sol(R.getNumCols());
00380   for (i = 0;  i < R.getNumCols(); i++)
00381   {
00382     sol(i) = 0;
00383   }
00384 
00385   // Now do a backsolve of R, which is upper-triangular
00386   for (i = R.getNumCols()-1; i >= 0; i--)
00387   {
00388     v = rhs(i);
00389     for (j = i+1; j < R.getNumCols(); j++)
00390     {
00391       v -= (T) sol(j)*R(i,j);
00392     }
00393     v = v/( (T) R(i,i));
00394     sol(i) = v;
00395   }
00396 
00397   x = sol;
00398 }
00399 
00400 template<class T>
00401 inline DenseMatrix<T> DenseMatrix<T>::operator*(const DenseMatrix<T>& a) const
00402 {
00403 
00404   int i,j,k;
00405   T   v;
00406   DenseMatrix<T> dm(getNumRows(), a.getNumCols());
00407 
00408   for (i = 0; i < getNumRows(); i++)
00409   {
00410     for (j = 0; j < a.getNumCols(); j++)
00411     {
00412       v = (T) 0;
00413       for (k = 0; k < getNumCols(); k++)
00414       {
00415         v += val(i,k) * a.val(k,j);
00416       }
00417       dm(i,j) = v;
00418     }
00419   }
00420 
00421   return dm;
00422 }
00423 
00424 template<class T>
00425 inline DenseMatrix<T> DenseMatrix<T>::operator+(const DenseMatrix<T>& a) const
00426 {
00427   int i,j;
00428 
00429   DenseMatrix<T> dm(getNumRows(), getNumCols());
00430 
00431   for (i = 0; i < getNumRows(); i++)
00432   {
00433     for (j = 0; j < getNumCols(); i++)
00434     {
00435       dm(i,j) = val(i,j) + b.val(i,j);
00436     }
00437   }
00438 
00439   return dm;
00440 
00441 }
00442 
00443 template<class T>
00444 inline DenseMatrix<T> DenseMatrix<T>::operator-(const DenseMatrix<T>& a) const
00445 {
00446   int i,j;
00447 
00448   DenseMatrix<T> dm(getNumRows(), getNumCols());
00449 
00450   for (i = 0; i < getNumRows(); i++)
00451   {
00452     for (j = 0; j < getNumCols(); i++)
00453     {
00454       dm(i,j) = val(i,j) - a.val(i,j);
00455     }
00456   }
00457 
00458   return dm;
00459 
00460 }
00461 
00462 template<class T>
00463 inline DenseMatrix<T> DenseMatrix<T>::transpose() const
00464 {
00465   int i,j;
00466 
00467   DenseMatrix<T> dm(getNumCols(), getNumRows());
00468 
00469   for (i = 0; i < getNumRows(); i++)
00470   {
00471     for (j = 0; j < getNumCols(); j++)
00472     {
00473       dm(j,i) = val(i,j);
00474     }
00475 
00476   }
00477 
00478   return dm;
00479 
00480 }
00481 
00482 template<class T>
00483 RealVector<T> DenseMatrix<T>::getRow(int row) const
00484 {
00485   RealVector<T> ret(cols_);
00486   int i, j;
00487 
00488   for(i=(row*cols_), j=0; i < ((row+1)*cols_); i++, j++)
00489     ret.set(j, valVec_[i]);
00490 
00491   return ret;
00492 }
00493 
00494 template <class T>
00495 RealVector<T> DenseMatrix<T>::getColumn(int col) const
00496 {
00497   RealVector<T> ret(rows_);
00498   int i, j;
00499 
00500   for(i=col, j=0; i<rows_*cols_; i+=cols_, j++)
00501     ret.set(j, valVec_[i]);
00502 
00503   return ret;
00504 }
00505 
00506 template <class T>
00507 inline T& DenseMatrix<T>::operator()(int row, int col)
00508 {
00509   return valVec_[row*cols_ + col];
00510 }
00511 
00512 template <class T>
00513 inline T DenseMatrix<T>::operator()(int row, int col) const
00514 {
00515   return valVec_[row*cols_ + col];
00516 }
00517 
00518 } // end namespace
00519 #endif

Generated on Mon Aug 30 15:41:06 2004 for FDDLib by doxygen1.2.18