MeVisLabToolboxReference
MeVisLab/Standard/Sources/ML/MLVesselGraph/mlMatrixTemplate.h
Go to the documentation of this file.
00001 
00002 
00003 /*
00004  * Copyright 2002, MeVis gGmbH
00005  * ALL RIGHTS RESERVED
00006  *
00007  * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
00008  * INFORMATION OF MEVIS GGMBH. ANY DUPLICATION, MODIFICATION,
00009  * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
00010  * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF MEVIS GGMBH
00011  *
00012  */
00013 
00014 //======================================================
00020 
00025 //======================================================
00026 #ifndef __MatrixTemplate_h__
00027 #define __MatrixTemplate_h__
00028 
00029 #include "mlInitSystemML.h"
00030 #ifdef UNIX
00031 #include "mlDebug.h"
00032 #endif
00033 
00034 #include "mlSystemWarningsDisable.h"
00035 #include <iostream>
00036 #include <valarray>
00037 #include <numeric>
00038 #include <functional>
00039 #include <algorithm>
00040 #include <iterator>
00041 #include "mlSystemWarningsRestore.h"
00042 
00043 //======================================================================
00044 // namespaces
00045 //======================================================================
00046 ML_START_NAMESPACE
00047 //======================================================================
00048 // declaration of class *Slice_iter*
00049 //======================================================================
00054 template<class T>
00055 class Slice_iter {
00056   std::valarray<T>* v;                            
00057   std::slice s;                                   
00058   size_t curr;                                    
00059 
00061   T& ref(size_t i) const { return (*v)[s.start()+i*s.stride()]; }
00062 public:
00064   Slice_iter(std::valarray<T>* vv, std::slice ss) :v(vv), s(ss), curr(0) { }
00065 
00067   Slice_iter<T> end() const
00068   {
00069     Slice_iter<T> t = *this;
00070     t.curr = s.size();                            // index of one plus last element
00071     return t;
00072   }
00073 
00075 
00076   Slice_iter<T>& operator++() { curr++; return *this; }                         
00077   Slice_iter<T> operator++(int) { Slice_iter<T> t = *this; curr++; return t; }  
00078 
00079 
00081 
00082   T& operator[](size_t i) { return ref(i); }      
00083   T& operator()(size_t i) { return ref(i); }      
00084   T& operator*() { return ref(curr); }            
00085 
00086 
00088 
00089   // caution: friend function has to be implemented here inplace to support
00090   // explicit template specification according to ansi standart in gcc, i.e to
00091   // let the compiler know, that the friend functions are realy templated overloads
00092   // (note: the gcc conform syntax (friend bool operator== <> (...)) is not supported
00093   // on other compiler)
00095   friend bool operator== (const Slice_iter<T>& p, const Slice_iter<T>& q)   
00096   {
00097     return p.curr==q.curr
00098       && p.s.stride()==q.s.stride()
00099       && p.s.start()==q.s.start();
00100   }
00101 
00103   friend bool operator!= (const Slice_iter<T>& p, const Slice_iter<T>& q)   
00104   {
00105     return !(p==q);
00106   }
00107 
00109   friend bool operator< (const Slice_iter<T>& p, const Slice_iter<T>& q)   
00110   {
00111     return p.curr<q.curr
00112       && p.s.stride()==q.s.stride()
00113       && p.s.start()==q.s.start();
00114   }
00116 };
00117 
00118 
00119 //======================================================================
00120 // declaration of class *Cslice_iter*
00121 //======================================================================
00126 template<class T>
00127 class Cslice_iter
00128 {
00129   std::valarray<T>* v;                            
00130   std::slice s;                                   
00131   size_t curr;                                    
00132 
00134   const T& ref(size_t i) const { return (*v)[s.start()+i*s.stride()]; }
00135 public:
00137   Cslice_iter(std::valarray<T>* vv, std::slice ss): v(vv), s(ss), curr(0){}
00138 
00140   Cslice_iter<T> end() const
00141   {
00142     Cslice_iter<T> t = *this;
00143     t.curr = s.size();                            // index of one plus last element
00144     return t;
00145   }
00146 
00148 
00149   Cslice_iter<T>& operator++() { curr++; return *this; }                          
00150   Cslice_iter<T> operator++(int) { Cslice_iter<T> t = *this; curr++; return t; }  
00151 
00152 
00154 
00155   const T& operator[](size_t i) const { return ref(i); }  
00156   const T& operator()(size_t i) const { return ref(i); }  
00157   const T& operator*() const { return ref(curr); }        
00158 
00159 
00161 
00162   // caution: friend function has to be implemented here inplace to support
00163   // explicit template specification according to ansi standart in gcc, i.e to
00164   // let the compiler know, that the friend functions are realy templated overloads
00165   // (note: the gcc conform syntax (friend bool operator== <> (...)) is not supported
00166   // on other compiler)
00168   friend bool operator==(const Cslice_iter<T>& p, const Cslice_iter<T>& q) 
00169   {
00170     return p.curr==q.curr
00171       && p.s.stride()==q.s.stride()
00172       && p.s.start()==q.s.start();
00173   }
00174 
00176   friend bool operator!=(const Cslice_iter<T>& p, const Cslice_iter<T>& q) 
00177   {
00178     return !(p==q);
00179   }
00180 
00182   friend bool operator< (const Cslice_iter<T>& p, const Cslice_iter<T>& q) 
00183   {
00184     return p.curr<q.curr
00185       && p.s.stride()==q.s.stride()
00186       && p.s.start()==q.s.start();
00187   }
00189 
00190 };
00191 
00192 //======================================================================
00193 // declaration of class *MatrixTemplate*
00194 //======================================================================
00198 template <class T>
00199 class MatrixTemplate {
00200   std::valarray<T>* v;                            
00201   size_t size_x;                                  
00202   size_t size_y;                                  
00203 public:
00204   MatrixTemplate(size_t x, size_t y);             
00205   MatrixTemplate(const MatrixTemplate<T>&);       
00206   MatrixTemplate<T>& operator=(const MatrixTemplate<T>&);   
00207   ~MatrixTemplate();                              
00208 
00209   void freeMatrix();                                   
00210   void resizeMatrix(size_t x, size_t y, const T& c = T());     
00211   void overrideMatrix(size_t x, size_t y, const T& c = T());   
00212 
00213   size_t size() const { return size_x*size_y; }   
00214   size_t sizeX() const { return size_x; }         
00215   size_t sizeY() const { return size_y; }         
00216 
00217   Slice_iter<T> row(size_t i);                    
00218   Cslice_iter<T> row(size_t i) const;             
00219 
00220   Slice_iter<T> column(size_t i);                 
00221   Cslice_iter<T> column(size_t i) const;          
00222 
00224 
00225   T& operator()(size_t x, size_t y);              
00226   T operator()(size_t x, size_t y) const;         
00227 
00228   Slice_iter<T> operator()(size_t i) { return column(i); }          
00229   Cslice_iter<T> operator()(size_t i) const { return column(i); }   
00230 
00231 
00233 
00234   Slice_iter<T> operator[](size_t i) { return column(i); }          
00235   Cslice_iter<T> operator[](size_t i) const { return column(i); }   
00236 
00237 
00238   MatrixTemplate<T>& operator*=(T);               
00239 
00240   std::valarray<T>& array() { return *v; }        
00241 
00242   operator T * () { return (T*) (&v); }           
00243 };
00244 
00245 
00246 //======================================================================
00247 // declaration of class *MatrixSizedTemplate*
00248 //======================================================================
00254 template <class T, size_t SIZE_X, size_t SIZE_Y>
00255 class MatrixSizedTemplate : public MatrixTemplate<T>
00256 {
00257   public:
00259     MatrixSizedTemplate () : MatrixTemplate<T>(SIZE_X, SIZE_Y) {;}
00260 };
00261 
00262 
00263 
00264 
00265 
00266 
00267 //=======================================================================
00268 // Implementation of MatrixTemplate - functions
00269 //=======================================================================
00270 
00272 template <class T>
00273 inline Slice_iter<T> MatrixTemplate<T>::row(size_t i)
00274 {
00275   return Slice_iter<T>(v,std::slice(i,size_x,size_y));
00276 }
00277 
00279 template <class T>
00280 inline Cslice_iter<T> MatrixTemplate<T>::row(size_t i) const
00281 {
00282   return Cslice_iter<T>(v,std::slice(i,size_x,size_y));
00283 }
00284 
00286 template <class T>
00287 inline Slice_iter<T> MatrixTemplate<T>::column(size_t i)
00288 {
00289   return Slice_iter<T>(v,std::slice(i*size_y,size_y,1));
00290 }
00291 
00293 template <class T>
00294 inline Cslice_iter<T> MatrixTemplate<T>::column(size_t i) const
00295 {
00296   return Cslice_iter<T>(v,std::slice(i*size_y,size_y,1));
00297 }
00298 
00300 template <class T>
00301 MatrixTemplate<T>::MatrixTemplate(size_t x, size_t y)
00302 {
00303   size_x = x;
00304   size_y = y;
00305   v = new std::valarray<T>(size_x*size_y);
00306 }
00307 
00309 template <class T>
00310 MatrixTemplate<T>::MatrixTemplate(const MatrixTemplate<T>&mt)
00311 {
00312   // set size according to transfered object
00313   size_x = mt.size_x;
00314   size_y = mt.size_y;
00315   // assign new valarray of appropriate size
00316   v = new std::valarray<T>(size_x*size_y);
00317 
00318   // copy memory content
00319   *v = *(mt.v);
00320 }
00321 
00323 template <class T>
00324 MatrixTemplate<T>& MatrixTemplate<T>::operator=(const MatrixTemplate<T>&mt)
00325 {
00326   if(this != &mt){
00327     // resize matrixTemplate
00328     this->resizeMatrix(mt.size_x, mt.size_y);
00329     // copy memory content
00330     *v = *(mt.v);
00331   }
00332   return *this;
00333 }
00334 
00336 template <class T>
00337 MatrixTemplate<T>::~MatrixTemplate()
00338 {
00339   delete v;
00340 }
00341 
00345 template <class T>
00346 void MatrixTemplate<T>::resizeMatrix(size_t x, size_t y, const T& c)
00347 {
00348   size_x = x;
00349   size_y = y;
00350   v->resize(size_x*size_y, c);
00351 }
00352 
00356 template <class T>
00357 void MatrixTemplate<T>::overrideMatrix(size_t x, size_t y, const T& c)
00358 {
00359   size_x = x;
00360   size_y = y;
00361   *v = c;
00362   v->resize(size_x*size_y, c);
00363 }
00364 
00365 
00367 template <class T>
00368 void MatrixTemplate<T>::freeMatrix()
00369 {
00370   size_x = 0;
00371   size_y = 0;
00372   v->free();
00373 }
00374 
00376 template <class T>
00377 T& MatrixTemplate<T>::operator()(size_t x, size_t y)
00378 {
00379   return column(x)[y];
00380 }
00381 
00382 
00383 
00384 //---------------------------------------------------------------------------------
00386 //---------------------------------------------------------------------------------
00389 template <class T>
00390 T mul(const Cslice_iter<T>& v1, const std::valarray<T>& v2)
00391 {
00392   T res = 0;
00393   for (size_t i = 0; i<v2.size(); i++) res+= v1[i]*v2[i];
00394   return res;
00395 }
00396 
00397 
00399 template <class T>
00400 std::valarray<T> operator*(const MatrixTemplate<T>& m, const std::valarray<T>& v)
00401 {
00402   if (m.sizeX()!=v.size()){
00403     ML_PRINT_ERROR("mlMatrixTemplate.h, operator*() # 1",
00404                    ML_BAD_PARAMETER,
00405                    "Wrong number of elements in m*v\n, ignoring problem");
00406   }
00407 
00408   std::valarray<T> res(m.sizeY());
00409   for (size_t i = 0; i<m.sizeY(); i++) res[i] = mul(m.row(i),v);
00410   return res;
00411 }
00412 
00413 
00415 //std::valarray<T> operator*(const MatrixTemplate<T>& m, std::valarray<T>& v)
00416 template <class T>
00417 std::valarray<T> mul_mv(const MatrixTemplate<T>& m, std::valarray<T>& v)
00418 {
00419   if (m.sizeX()!=v.size()){
00420     ML_PRINT_ERROR("mlMatrixTemplate.h, mul_mv()",
00421                    ML_BAD_PARAMETER,
00422                    "Wrong number of elements in m*v\n, ignoring problem");
00423   }
00424 
00425   std::valarray<T> res(m.sizeY());
00426 
00427   for (size_t i = 0; i<m.sizeY(); i++) {
00428     const Cslice_iter<T>& ri = m.row(i);
00429     res[i] = inner_product(ri,ri.end(),&v[0],T(0));
00430   }
00431   return res;
00432 }
00433 
00434 
00435 
00437 template <class T>
00438 std::valarray<T> operator*(std::valarray<T>& v, const MatrixTemplate<T>& m)
00439 {
00440   if (v.size()!=m.sizeY()){
00441     ML_PRINT_ERROR("mlMatrixTemplate.h, operator*() # 2",
00442                    ML_BAD_PARAMETER,
00443                    "Wrong number of elements in v*m\n, ignoring problem");
00444   }
00445 
00446   std::valarray<T> res(m.sizeX());
00447 
00448   for (size_t i = 0; i<m.sizeX(); i++) {
00449     const Cslice_iter<T>& ci = m.column(i);
00450     res[i] = inner_product(ci,ci.end(),&v[0],T(0));
00451   }
00452   return res;
00453 }
00454 
00456 template <class T>
00457 MatrixTemplate<T>& MatrixTemplate<T>::operator*=(T d)
00458 {
00459   (*v) *= d;
00460   return *this;
00461 }
00462 
00464 template <class T>
00465 std::ostream& operator<<(std::ostream& os, MatrixTemplate<T>& m)
00466 {
00467   for(int y=0; y<m.sizeY(); y++)
00468   {
00469     for(int x=0; x<m.sizeX(); x++)
00470       os<<m[x][y]<<"\t";
00471     os << "\n";
00472   }
00473   return os;
00474 }
00475 
00477 
00478 
00479 
00480 
00481 } // namespace ml
00482 
00483 #endif //__MatrixTemplate_h__
00484 
00485