MeVisLabToolboxReference
|
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