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

matrix.h

Go to the documentation of this file.
00001 
00008 #ifndef _MATRIX_H_
00009 #define _MATRIX_H_
00010 
00011 /*
00012   Choose at least one matrix package; currently MTL and TNT are
00013   supported.
00014 
00015   Enabling more than one package is legal and can be useful if you
00016   want to support more than one matrix implementation, e.g. for
00017   different source files.  Note that the type generator (by design)
00018   and the MSEQ definitions (due to MTL's broken iterator concept) only
00019   use a single implementation regardless.
00020 */
00021 #define USE_TNT_MATRIX
00022 //#define USE_MTL_MATRIX
00023 
00024 
00025 
00026 #include <numeric>
00027 
00028 
00029 #ifdef USE_TNT_MATRIX
00030 
00031 #define num_cols ncols
00032 #define num_rows nrows
00033 #include "tnt/tnt.h"
00034 #include "tnt/cmat.h"
00035 #include "tnt/vec.h"
00036 #include "tnt/region1d.h"
00037 #include "tnt/region2d.h"
00038 #undef  num_cols
00039 #undef  num_rows
00040 #endif
00041 
00042 
00043 #ifdef USE_MTL_MATRIX
00044 #include "mtl/mtl.h"
00045 #include "mtl/scaled2D.h"
00046 #include "mtl/matrix.h"
00047 #include "mtl/flatten_iterator.h"
00048 #include "mtl/flatten_iterator.h"
00050 #define MSEQ(container)      mtl::flatten_begin(container),mtl::flatten_end(container)
00051 
00052 #define CMSEQ(container)     mtl::const_flatten_begin(container),mtl::const_flatten_end(container)
00053 
00054 #define MTL_MSEQ(container)  mtl::flatten_begin(container),mtl::flatten_end(container)
00055 
00056 #define MTL_CMSEQ(container) mtl:::const_flatten_begin(container),mtl:::const_flatten_end(container)
00057 
00058 #define MBEGIN(container)    mtl::flatten_begin(container)
00059 
00060 #define CMBEGIN(container)   mtl::const_flatten_begin(container)
00061 #endif
00062 
00063 
00064 #ifdef USE_TNT_MATRIX
00065 
00066 #define SubMatrixType const_Region
00067 
00068 #define MatIndex(i) (i+1)
00069 
00070 #define UpperBound(i) (i)
00071 
00072 #else
00073 
00074 #define SubMatrixType submatrix_type
00075 
00076 #define MatIndex(i) (i)
00077 
00078 #define UpperBound(i) (i)
00079 #endif
00080 
00081 
00082 
00083 #ifndef  MSEQ
00084 
00085 #define  MSEQ(container) (container).begin(),(container).end()
00086 
00087 #define CMSEQ(container) (container).begin(),(container).end()
00088 
00089 #define  MBEGIN(container)  (container).begin()
00090 
00091 #define  CMBEGIN(container) (container).begin()
00092 #endif
00093 
00094 
00095 /******************************************************************************/
00096 /* Type generator                                                             */
00097 /******************************************************************************/
00131 template<class T=double>
00132 struct MatrixType {
00133 
00134 
00135   
00136 #ifdef USE_MTL_MATRIX
00137   /* Use MTL if available */
00139   typedef typename mtl::matrix< T, mtl::rectangle<>, mtl::dense<>      >::type rectangular;
00141   typedef typename mtl::matrix< T, mtl::rectangle<>, mtl::dense<>      >::type circular;
00143   typedef typename mtl::matrix< T, mtl::rectangle<>, mtl::compressed<> >::type sparse;
00144 
00145 #else
00146   /* Default to TNT */
00148   typedef TNT::Matrix<T> rectangular;
00150   typedef TNT::Matrix<T> circular;  
00152   typedef TNT::Matrix<T> sparse;  
00153 #endif
00154 
00155 };
00156 
00157 
00158 
00159 /******************************************************************************/
00160 /* Additional routines for namespace mtl                                      */
00161 /******************************************************************************/
00162 
00167 namespace mtl {
00168 
00180 template <class Matrix> inline
00181 Matrix& operator*=(Matrix &A, const typename Matrix::value_type B)
00182 {  mtl::scale(A,B);  return A;  }
00183 
00184  
00185 
00186 template <class Matrix> inline
00187 Matrix& operator+=(Matrix &A, const typename Matrix::value_type B)
00188 {
00189   typedef typename Matrix::size_type Subscript;
00190 
00191   for (Subscript i=0; i<A.nrows(); i++)
00192     for (Subscript j=0; j<A.ncols(); j++)
00193       A[i][j] += B;
00194 
00195   return A;
00196 }
00197 
00198 
00199 template <class Matrix> inline
00200 Matrix& operator-=(Matrix &A, const typename Matrix::value_type B)
00201 {  return A += -1*B;  }
00202 
00203 
00205 } /* namespace mtl */
00206 
00207 
00208 
00209 /******************************************************************************/
00210 /* Additional routines for namespace TNT                                      */
00211 /******************************************************************************/
00212 
00213 #ifdef USE_TNT_MATRIX
00214 
00218 namespace TNT {
00219   
00226 template <class T>
00227 inline Matrix<T>& operator+=(Matrix<T>  &A, const T B)
00228 {
00229   for (Subscript i=0; i<A.nrows(); i++)
00230     for (Subscript j=0; j<A.ncols(); j++)
00231       A[i][j] += B;
00232 
00233   return A;
00234 }
00235 
00236 template <class T>
00237 inline Matrix<T>& operator-=(Matrix<T>  &A, const T B)
00238 {
00239   for (Subscript i=0; i<A.nrows(); i++)
00240     for (Subscript j=0; j<A.ncols(); j++)
00241       A[i][j] -= B;
00242 
00243   return A;
00244 }
00245 
00246 template <class T>
00247 inline Matrix<T>& operator*=(Matrix<T>  &A, const T B)
00248 {
00249   for (Subscript i=0; i<A.nrows(); i++)
00250     for (Subscript j=0; j<A.ncols(); j++)
00251       A[i][j] *= B;
00252 
00253   return A;
00254 }
00255 
00256 template <class T>
00257 inline Matrix<T> operator*(const Matrix<T>  &A, const T B)
00258 {
00259   Subscript M = A.nrows();
00260   Subscript N = A.ncols();
00261   
00262   Matrix<T> tmp(M,N);
00263   
00264   for (Subscript i=0; i<M; i++)
00265     for (Subscript j=0; j<N; j++)
00266       tmp[i][j] = A[i][j]*B; 
00267   
00268   return tmp;
00269 }
00270 
00271 template <class T> inline T sum(const Matrix<T>& A)
00272 {  return std::accumulate(A.begin(),A.end(),T(0));  }
00273  
00274 template <class T> inline T sum(const Vector<T>& A)
00275 {  return std::accumulate(A.begin(),A.end(),T(0));  }
00276  
00277 template <class T> inline T sum(const_Region2D< Matrix<T> >& A)
00278 {
00279   Subscript start = A.lbound();
00280   Subscript Mend  = A.lbound() + A.nrows() - 1;
00281   Subscript Nend  = A.lbound() + A.ncols() - 1;
00282   T partialsum = T(0);
00283   
00284   for (Subscript i=start; i<=Mend; i++)
00285     for (Subscript j=start; j<=Nend; j++)
00286         partialsum += A(i,j);
00287   
00288   return partialsum;
00289 }
00290 
00292 } /* namespace TNT */
00293 #endif
00294 
00295 
00296 
00297 
00298 /******************************************************************************/
00299 /* Routines for namespace mat                                                 */
00300 /******************************************************************************/
00308 namespace mat {
00309 
00310   
00322 template <class Matrix, class InnerC, class OuterC> inline
00323 Matrix matrix_from_nested_containers(const OuterC& n, bool column_major=false)
00324 {
00325   typedef typename Matrix::size_type Subscript;
00326 
00327   /* Find maximum size of a nested container */
00328   Subscript max_minor = 0;
00329   for (typename OuterC::const_iterator i=n.begin(); i!=n.end(); i++) {
00330     const Subscript new_size =  (*i ? ((*i)->size()) : 0);
00331     if (new_size > max_minor) max_minor=new_size;
00332   }
00333 
00334   /* Create and populate new Matrix */
00335   Matrix m((column_major? max_minor  : n.size()  ),
00336            (column_major? n.size()   : max_minor));
00337   int major=0;
00338   for (    typename OuterC::const_iterator i=n.begin();         i!=n.end(); i++,major++) {
00339     int minor=0;
00340     if (*i)
00341       for (typename InnerC::const_iterator j=(*i)->begin(); j!=(*i)->end(); j++,minor++) {
00342         if (column_major) 
00343           m[minor][major] = *j;
00344         else
00345           m[major][minor] = *j;
00346       }
00347   }
00348     
00349   return m;
00350 }
00351 
00352 
00353 
00356 template <class Matrix> inline
00357 typename Matrix::value_type
00358 sum(const Matrix& A)
00359 {  return std::accumulate(CMSEQ(A), typename Matrix::value_type(0) );  }
00360 
00361 
00362 
00364 template <class Matrix> inline
00365 typename Matrix::size_type
00366 size(const Matrix& A)
00367 {  return (A.nrows()*A.ncols());  }
00368 
00369 
00370 
00372 template <class Matrix> inline
00373 Matrix& set(Matrix &A, const typename Matrix::value_type B)
00374 {
00375   typedef typename Matrix::size_type Subscript;
00376 
00377   for (Subscript i=0; i<A.nrows(); i++)
00378     for (Subscript j=0; j<A.ncols(); j++)
00379       A[i][j] = B;
00380 
00381   return A;
00382 }
00383 
00384 
00385 
00387 template <class Matrix> inline
00388 typename Matrix::value_type elem(const Matrix &A, typename Matrix::size_type i, typename Matrix::size_type j)
00389 {
00390   return A(MatIndex(i),MatIndex(j));
00391 }
00392 
00393 
00394 
00402 template <class Matrix> inline
00403 const typename Matrix::SubMatrixType
00404 submatrix(const Matrix &A,
00405           typename Matrix::size_type i1, typename Matrix::size_type i2,
00406           typename Matrix::size_type j1, typename Matrix::size_type j2)
00407 {
00408 #ifdef USE_TNT_MATRIX
00409   TNT::Index1D I(MatIndex(i1),UpperBound(i2));
00410   TNT::Index1D J(MatIndex(j1),UpperBound(j2));  
00411   return A(I,J);
00412 #else
00413   return A.sub_matrix(MatIndex(i1),UpperBound(i2),MatIndex(j1),UpperBound(j2));
00414 #endif
00415 }
00416 
00417 
00418 
00420 #ifdef USE_TNT_MATRIX
00421 template <class T> inline
00422 TNT::Subscript
00423 size(TNT::const_Region2D< TNT::Matrix<T> >& A)
00424 {  return (A.lbound() + A.nrows() - 1)*(A.lbound() + A.ncols() - 1);  }
00425 #endif
00426  
00427 
00428 
00434 template <class Matrix>
00435 typename Matrix::value_type
00436 edge_average(const Matrix& mat)
00437 {
00438   typedef typename Matrix::value_type T;
00439   typedef typename Matrix::size_type  Subscript;
00440   
00441   Subscript X=mat.nrows();
00442   Subscript Y=mat.ncols();
00443 
00444   /* Return zero in case of empty matrix to avoid divide by zero */
00445   if (X<1 || Y<1) return T(0);
00446   
00447   typename Matrix::submatrix_type left   = mat.sub_matrix(0,   1,   0,   Y-1);
00448   typename Matrix::submatrix_type top    = mat.sub_matrix(1,   X,   0,   1  );
00449   typename Matrix::submatrix_type right  = mat.sub_matrix(X-1, X,   1,   Y  );
00450   typename Matrix::submatrix_type bottom = mat.sub_matrix(0,   X-1, Y-1, Y  );
00451 
00452   const T         total =  mat::sum(left)+  mat::sum(top)+  mat::sum(right)+  mat::sum(bottom);
00453   const Subscript count = mat::size(left)+ mat::size(top)+ mat::size(right)+ mat::size(bottom);
00454 
00455   return total/count;
00456 }
00457 
00458 
00463 #ifdef USE_TNT_MATRIX
00464 template <class T>
00465 T edge_average(const TNT::Matrix<T>& mat)
00466 {
00467   using namespace TNT;
00468   
00469   Subscript X=mat.nrows();
00470   Subscript Y=mat.ncols();
00471 
00472   /* Image must be at least 2x2 to have an edge */
00473   if (X<2 || Y<2) return T(0);
00474   
00475   const_Region2D< Matrix<double> > left(   mat, 1, 1,   1, Y-1);
00476   const_Region2D< Matrix<double> > top(    mat, 2, X,   1, 1  );
00477   const_Region2D< Matrix<double> > right(  mat, X, X,   2, Y  );
00478   const_Region2D< Matrix<double> > bottom( mat, 1, X-1, Y, Y  );
00479 
00480   const T         total =  TNT::sum(left)+  TNT::sum(top)+  TNT::sum(right)+  TNT::sum(bottom);  
00481   const Subscript count = mat::size(left)+ mat::size(top)+ mat::size(right)+ mat::size(bottom);
00482 
00483   return total/count;
00484 }
00485 #endif
00486 
00487 
00488 /* Returns the maximum num_rows of any element in the given matrix or region.
00489    
00490   There may be a way to code this using a generic mem_fun() call, but
00491   it wasn't obvious how to specify that call since we don't know the
00492   actual Matrix::value_type, i.e. the type of an element.
00493 
00494   On second thought, if there are iterators available, it should work;
00495   we would just then accept a pair of iterators instead of the
00496   container itself.  However, I'm not sure if one-dimensional
00497   iterators are defined for regions in TNT and MTL.
00498 */
00499 template <class Matrix> inline
00500 typename Matrix::size_type max_nrows(const Matrix &A)
00501 {
00502   typedef typename Matrix::size_type Subscript;
00503   Subscript val=0;
00504   
00505   for (Subscript i=0; i<A.nrows(); i++)
00506     for (Subscript j=0; j<A.ncols(); j++)
00507       if (mat::elem(A,i,j).nrows()>val)
00508         val = mat::elem(A,i,j).nrows();
00509 
00510   return val;
00511 }
00512 
00513 
00514 
00515 /* Returns the maximum num_cols of any element in the given matrix or region.
00516    
00517   As for max_nrows, this routine *should* be unnecessary.
00518 */
00519 template <class Matrix> inline
00520 typename Matrix::size_type max_ncols(const Matrix &A)
00521 {
00522   typedef typename Matrix::size_type Subscript;
00523   Subscript val=0;
00524   
00525   for (Subscript i=0; i<A.nrows(); i++)
00526     for (Subscript j=0; j<A.ncols(); j++)
00527       if (mat::elem(A,i,j).ncols()>val)
00528         val = mat::elem(A,i,j).ncols();
00529 
00530   return val;
00531 }
00532 
00533 
00534 /* Returns the maximum num_rows of any pointed-to element in the given
00535   matrix or region.
00536    
00537   There may be a way to code this using a generic mem_fun() call, but
00538   it wasn't obvious how to specify that call since we don't know the
00539   actual Matrix::value_type, i.e. the type of an element.
00540 */
00541 template <class Matrix> inline
00542 typename Matrix::size_type max_pnrows(const Matrix &A)
00543 {
00544   typedef typename Matrix::size_type Subscript;
00545   Subscript val=0;
00546   
00547   for (Subscript i=0; i<A.nrows(); i++)
00548     for (Subscript j=0; j<A.ncols(); j++) {
00549       typename Matrix::value_type p=mat::elem(A,i,j);
00550       if (p && (p->nrows()>val))
00551         val = p->nrows();
00552     }
00553   
00554   return val;
00555 }
00556 
00557 
00558 
00559 /* Returns the maximum num_cols of any pointed-to element
00560   in the given matrix or region.
00561    
00562   As for max_pnrows, this routine *should* be unnecessary.
00563 */
00564 template <class Matrix> inline
00565 typename Matrix::size_type max_pncols(const Matrix &A)
00566 {
00567   typedef typename Matrix::size_type Subscript;
00568   Subscript val=0;
00569   
00570   for (Subscript i=0; i<A.nrows(); i++)
00571     for (Subscript j=0; j<A.ncols(); j++) {
00572       typename Matrix::value_type p=mat::elem(A,i,j);
00573       if (p && (p->ncols()>val))
00574         val = p->ncols();
00575     }
00576 
00577   return val;
00578 }
00579 
00581 template<class Matrix>
00582 void delete_contents(Matrix& A)
00583 {
00584   typedef typename Matrix::size_type Subscript;
00585   for (Subscript i=0; i<A.nrows(); i++)
00586     for (Subscript j=0; j<A.ncols(); j++)
00587       delete A[i][j];
00588 }
00589 
00590 
00593 template<class Matrix, class OutputStream>
00594 OutputStream& stream_output(const Matrix& A, OutputStream& stream)
00595 {
00596   typedef typename Matrix::size_type Subscript;
00597   for (Subscript i=0; i<A.nrows(); i++) {
00598     for (Subscript j=0; j<A.ncols(); j++)
00599       stream << mat::elem(A,i,j) << " ";
00600     stream << std::endl;
00601   }
00602 
00603   return stream;
00604 }
00605 
00608 template<class Matrix, class InputStream>
00609 InputStream& stream_input(Matrix& A, InputStream& stream)
00610 {
00611   typedef typename Matrix::size_type Subscript;
00612   for (Subscript i=0; i<A.nrows(); i++) {
00613     for (Subscript j=0; j<A.ncols(); j++)
00614       stream >> A[i][j];
00615   }
00616 
00617   return stream;
00618 }
00619 
00620 
00621 /* Avoid namespace pollution */
00622 //#undef MatIndex
00623 #undef UpperBound
00624 
00625 } /* namespace mat */
00626 #endif

Generated on Mon Jan 20 02:35:44 2003 for RF-LISSOM by doxygen1.3-rc2