Image Component Library (ICL)
|
00001 /******************************************************************** 00002 ** Image Component Library (ICL) ** 00003 ** ** 00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** 00005 ** Neuroinformatics Group ** 00006 ** Website: www.iclcv.org and ** 00007 ** http://opensource.cit-ec.de/projects/icl ** 00008 ** ** 00009 ** File : ICLMath/src/ICLMath/FixedMatrix.h ** 00010 ** Module : ICLMath ** 00011 ** Authors: Christof Elbrechter ** 00012 ** ** 00013 ** ** 00014 ** GNU LESSER GENERAL PUBLIC LICENSE ** 00015 ** This file may be used under the terms of the GNU Lesser General ** 00016 ** Public License version 3.0 as published by the ** 00017 ** ** 00018 ** Free Software Foundation and appearing in the file LICENSE.GPL ** 00019 ** included in the packaging of this file. Please review the ** 00020 ** following information to ensure the license requirements will ** 00021 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** 00022 ** ** 00023 ** The development of this software was supported by the ** 00024 ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** 00025 ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** 00026 ** Forschungsgemeinschaft (DFG) in the context of the German ** 00027 ** Excellence Initiative. ** 00028 ** ** 00029 ********************************************************************/ 00030 00031 #pragma once 00032 00033 #include <iterator> 00034 #include <algorithm> 00035 #include <numeric> 00036 #include <functional> 00037 #include <iostream> 00038 #include <vector> 00039 #include <cmath> 00040 00041 #include <ICLUtils/Exception.h> 00042 #include <ICLMath/DynMatrix.h> 00043 #include <ICLUtils/ClippedCast.h> 00044 #include <ICLMath/MatrixSubRectIterator.h> 00045 #include <ICLUtils/FixedArray.h> 00046 00047 #ifdef HAVE_IPP 00048 #include <ippm.h> 00049 #endif 00050 00051 namespace icl{ 00052 namespace math{ 00053 00055 struct FixedMatrixBase{ 00057 template<class SrcIterator, class DstIterator, unsigned int N> 00058 static void optimized_copy(SrcIterator srcBegin, SrcIterator srcEnd, DstIterator dstBegin){ 00059 if(N>30){ 00060 std::copy(srcBegin,srcEnd,dstBegin); 00061 }else{ 00062 while(srcBegin != srcEnd){ 00063 // *dstBegin++ = *srcBegin++; 00064 *dstBegin = 00065 *srcBegin; 00066 00067 dstBegin++; 00068 srcBegin++; 00069 } 00070 } 00071 } 00072 }; 00073 00075 00076 template<class T,unsigned int COLS,unsigned int ROWS> class FixedMatrix; 00080 00081 00090 template<class T,unsigned int N, class Iterator> 00091 class FixedMatrixPart : public FixedMatrixBase{ 00092 00093 public: 00095 Iterator begin; 00096 00098 Iterator end; 00099 00101 FixedMatrixPart(Iterator begin, Iterator end):begin(begin),end(end){} 00102 00104 FixedMatrixPart& operator=(const T &value){ 00105 std::fill(begin,end,value); 00106 return *this; 00107 } 00109 00110 FixedMatrixPart& operator=(const FixedMatrixPart &other){ 00111 FixedMatrixBase::optimized_copy<Iterator,Iterator,N>(other.begin,other.end,begin); 00112 return *this; 00113 } 00114 00116 00118 template<class OtherIterator, class OtherT> 00119 FixedMatrixPart& operator=(const FixedMatrixPart<OtherT,N,OtherIterator> &other){ 00120 std::transform(other.begin,other.end,begin,utils::clipped_cast<OtherT,T>); 00121 return *this; 00122 } 00123 00125 00126 template<unsigned int COLS> 00127 FixedMatrixPart& operator=(const FixedMatrix<T,COLS,N/COLS> &m); 00128 00130 00131 template<class T2, unsigned int COLS> 00132 FixedMatrixPart& operator=(const FixedMatrix<T2,COLS,N/COLS> &m); 00133 00134 }; 00135 00136 00137 00139 00170 template<class T,unsigned int COLS,unsigned int ROWS> 00171 class FixedMatrix : public utils::FixedArray<T,COLS*ROWS>, public FixedMatrixBase{ 00172 public: 00173 00175 00176 DynMatrix<T> dyn() { return DynMatrix<T>(COLS,ROWS,begin(),false); } 00177 00179 const DynMatrix<T> dyn() const { return DynMatrix<T>(COLS,ROWS,const_cast<T*>(begin()),false); } 00180 00182 static const FixedMatrix &null(){ 00183 static FixedMatrix null_matrix(T(0)); 00184 return null_matrix; 00185 } 00186 00188 static const unsigned int DIM = COLS*ROWS; 00189 00190 public: 00191 00193 00194 FixedMatrix(){} 00195 00197 FixedMatrix(const T &initValue){ 00198 std::fill(begin(),end(),initValue); 00199 } 00200 00202 00206 FixedMatrix(const T *srcdata){ 00207 FixedMatrixBase::optimized_copy<const T*,T*,DIM>(srcdata,srcdata+dim(),begin()); 00208 //std::copy(srcdata,srcdata+dim(),begin()); 00209 } 00210 00212 00215 FixedMatrix(const T& v0,const T& v1,const T& v2=0,const T& v3=0, 00216 const T& v4=0,const T& v5=0,const T& v6=0,const T& v7=0, 00217 const T& v8=0,const T& v9=0,const T& v10=0,const T& v11=0, 00218 const T& v12=0,const T& v13=0,const T& v14=0,const T& v15=0){ 00219 #define C1(N) if(DIM>N) utils::FixedArray<T,COLS*ROWS>::m_data[N]=v##N 00220 #define C4(A,B,C,D) C1(A);C1(B);C1(C);C1(D) 00221 C4(0,1,2,3);C4(4,5,6,7);C4(8,9,10,11);C4(12,13,14,15); 00222 #undef C1 00223 #undef C2 00224 } 00225 00227 00228 template<class OtherIterator> 00229 FixedMatrix(OtherIterator begin, OtherIterator end){ 00230 FixedMatrixBase::optimized_copy<OtherIterator,T*,DIM>(begin,end,this->begin()); 00231 // std::copy(begin,end,begin()); 00232 } 00233 00234 // Explicit Copy template based constructor (deep copy) 00235 FixedMatrix(const FixedMatrix &other){ 00236 FixedMatrixBase::optimized_copy<const T*,T*,DIM>(other.begin(),other.end(),begin()); 00237 //std::copy(other.begin(),other.end(),begin()); 00238 } 00239 00240 // Explicit Copy template based constructor (deep copy) 00241 template<class otherT> 00242 FixedMatrix(const FixedMatrix<otherT,COLS,ROWS> &other){ 00243 std::transform(other.begin(),other.end(),begin(),utils::clipped_cast<otherT,T>); 00244 } 00245 00247 template<class Iterator> 00248 FixedMatrix (const FixedMatrixPart<T,DIM,Iterator> &r){ 00249 FixedMatrixBase::optimized_copy<Iterator,T*,DIM>(r.begin,r.end,begin()); 00250 } 00251 00253 template<class otherT, class Iterator> 00254 FixedMatrix(const FixedMatrixPart<otherT,DIM,Iterator> &r){ 00255 std::transform(r.begin,r.end,begin(),utils::clipped_cast<otherT,T>); 00256 } 00257 00259 FixedMatrix &operator=(const FixedMatrix &other){ 00260 if(this == &other) return *this; 00261 FixedMatrixBase::optimized_copy<const T*,T*,DIM>(other.begin(),other.end(),begin()); 00262 //std::copy(other.begin(),other.end(),begin()); 00263 return *this; 00264 } 00265 00267 00268 template<class otherT> 00269 FixedMatrix &operator=(const FixedMatrix<otherT,COLS,ROWS> &other){ 00270 if(this == &other) return *this; 00271 std::transform(other.begin(),other.end(),begin(),utils::clipped_cast<otherT,T>); 00272 return *this; 00273 } 00274 00276 FixedMatrix &operator=(const T &t){ 00277 std::fill(begin(),end(),t); 00278 return *this; 00279 } 00280 00282 template<class Iterator> 00283 FixedMatrix &operator=(const FixedMatrixPart<T,DIM,Iterator> &r){ 00284 // std::copy(r.begin,r.end,begin()); 00285 FixedMatrixBase::optimized_copy<Iterator,T*,DIM>(r.begin,r.end,begin()); 00286 return *this; 00287 } 00288 00290 template<class otherT, class Iterator> 00291 FixedMatrix &operator=(const FixedMatrixPart<otherT,DIM,Iterator> &r){ 00292 std::transform(r.begin,r.end,begin(),utils::clipped_cast<otherT,T>); 00293 return *this; 00294 } 00295 00297 00301 FixedMatrix operator/(const FixedMatrix &m) const 00302 throw (IncompatibleMatrixDimensionException, 00303 InvalidMatrixDimensionException, 00304 SingularMatrixException){ 00305 return this->operator*(m.inv()); 00306 } 00307 00309 FixedMatrix &operator/=(const FixedMatrix &m) const 00310 throw (IncompatibleMatrixDimensionException, 00311 InvalidMatrixDimensionException, 00312 SingularMatrixException){ 00313 return *this = this->operator*(m.inv()); 00314 } 00315 00317 FixedMatrix operator*(T f) const{ 00318 FixedMatrix d; 00319 std::transform(begin(),end(),d.begin(),std::bind2nd(std::multiplies<T>(),f)); 00320 return d; 00321 } 00322 00324 FixedMatrix &operator*=(T f){ 00325 std::transform(begin(),end(),begin(),std::bind2nd(std::multiplies<T>(),f)); 00326 return *this; 00327 } 00328 00330 FixedMatrix operator/(T f) const{ 00331 FixedMatrix d; 00332 std::transform(begin(),end(),d.begin(),std::bind2nd(std::divides<T>(),f)); 00333 return d; 00334 } 00335 00337 FixedMatrix &operator/=(T f){ 00338 std::transform(begin(),end(),begin(),std::bind2nd(std::divides<T>(),f)); 00339 return *this; 00340 } 00341 00343 FixedMatrix operator+(const T &t) const{ 00344 FixedMatrix d; 00345 std::transform(begin(),end(),d.begin(),std::bind2nd(std::plus<T>(),t)); 00346 return d; 00347 } 00348 00350 FixedMatrix &operator+=(const T &t){ 00351 std::transform(begin(),end(),begin(),std::bind2nd(std::plus<T>(),t)); 00352 return *this; 00353 } 00354 00355 00357 FixedMatrix operator-(const T &t) const{ 00358 FixedMatrix d; 00359 std::transform(begin(),end(),d.begin(),std::bind2nd(std::minus<T>(),t)); 00360 return d; 00361 } 00362 00364 FixedMatrix &operator-=(const T &t){ 00365 std::transform(begin(),end(),begin(),std::bind2nd(std::minus<T>(),t)); 00366 return *this; 00367 } 00368 00370 FixedMatrix operator+(const FixedMatrix &m) const{ 00371 FixedMatrix d; 00372 std::transform(begin(),end(),m.begin(),d.begin(),std::plus<T>()); 00373 return d; 00374 } 00375 00377 FixedMatrix &operator+=(const FixedMatrix &m){ 00378 std::transform(begin(),end(),m.begin(),begin(),std::plus<T>()); 00379 return *this; 00380 } 00381 00383 FixedMatrix operator-(const FixedMatrix &m) const{ 00384 FixedMatrix d; 00385 std::transform(begin(),end(),m.begin(),d.begin(),std::minus<T>()); 00386 return d; 00387 } 00389 FixedMatrix &operator-=(const FixedMatrix &m){ 00390 std::transform(begin(),end(),m.begin(),begin(),std::minus<T>()); 00391 return *this; 00392 } 00393 00395 00397 FixedMatrix operator-() const { 00398 FixedMatrix cpy(*this); 00399 std::transform(cpy.begin(),cpy.end(),cpy.begin(),std::negate<T>()); 00400 return cpy; 00401 } 00402 00403 00405 T &operator()(unsigned int col,unsigned int row){ 00406 return begin()[col+cols()*row]; 00407 } 00408 00410 const T &operator() (unsigned int col,unsigned int row) const{ 00411 return begin()[col+cols()*row]; 00412 } 00413 00415 T &at(unsigned int col,unsigned int row) throw (InvalidIndexException){ 00416 if(col>=cols() || row >= rows()) throw InvalidIndexException("row or col index too large"); 00417 return begin()[col+cols()*row]; 00418 } 00419 00421 const T &at(unsigned int col,unsigned int row) const throw (InvalidIndexException){ 00422 return const_cast<FixedMatrix*>(this)->at(col,row); 00423 } 00424 00426 00428 T &operator[](unsigned int idx){ 00429 return begin()[idx]; 00430 } 00432 00434 const T &operator[](unsigned int idx) const{ 00435 return begin()[idx]; 00436 } 00437 00438 00440 typedef T* iterator; 00441 00443 typedef const T* const_iterator; 00444 00446 typedef T* row_iterator; 00447 00449 typedef const T* const_row_iterator; 00450 00452 static unsigned int rows(){ return ROWS; } 00453 00455 static unsigned int cols(){ return COLS; } 00456 00458 T *data() { return utils::FixedArray<T,COLS*ROWS>::m_data; } 00459 00461 const T *data() const { return utils::FixedArray<T,COLS*ROWS>::m_data; } 00462 00464 static unsigned int dim() { return DIM; } 00465 00467 struct col_iterator : public std::iterator<std::random_access_iterator_tag,T>{ 00468 00470 typedef unsigned int difference_type; 00471 00473 mutable T *p; 00474 00476 static const unsigned int STRIDE = COLS; 00477 00479 col_iterator(T *col_begin):p(col_begin){} 00480 00482 col_iterator &operator++(){ 00483 p+=STRIDE; 00484 return *this; 00485 } 00487 const col_iterator &operator++() const{ 00488 p+=STRIDE; 00489 return *this; 00490 } 00492 col_iterator operator++(int){ 00493 col_iterator tmp = *this; 00494 ++(*this); 00495 return tmp; 00496 } 00498 const col_iterator operator++(int) const{ 00499 col_iterator tmp = *this; 00500 ++(*this); 00501 return tmp; 00502 } 00503 00505 col_iterator &operator--(){ 00506 p-=STRIDE; 00507 return *this; 00508 } 00509 00511 const col_iterator &operator--() const{ 00512 p-=STRIDE; 00513 return *this; 00514 } 00515 00517 col_iterator operator--(int){ 00518 col_iterator tmp = *this; 00519 --(*this); 00520 return tmp; 00521 } 00522 00524 const col_iterator operator--(int) const{ 00525 col_iterator tmp = *this; 00526 --(*this); 00527 return tmp; 00528 } 00529 00531 col_iterator &operator+=(difference_type n){ 00532 p += n * STRIDE; 00533 return *this; 00534 } 00535 00537 const col_iterator &operator+=(difference_type n) const{ 00538 p += n * STRIDE; 00539 return *this; 00540 } 00541 00542 00544 col_iterator &operator-=(difference_type n){ 00545 p -= n * STRIDE; 00546 return *this; 00547 } 00548 00550 const col_iterator &operator-=(difference_type n) const{ 00551 p -= n * STRIDE; 00552 return *this; 00553 } 00554 00555 00557 col_iterator operator+(difference_type n) { 00558 col_iterator tmp = *this; 00559 tmp+=n; 00560 return tmp; 00561 } 00562 00564 const col_iterator operator+(difference_type n) const{ 00565 col_iterator tmp = *this; 00566 tmp+=n; 00567 return tmp; 00568 } 00569 00571 col_iterator operator-(difference_type n) { 00572 col_iterator tmp = *this; 00573 tmp-=n; 00574 return tmp; 00575 } 00576 00578 const col_iterator operator-(difference_type n) const { 00579 col_iterator tmp = *this; 00580 tmp-=n; 00581 return tmp; 00582 } 00583 00585 difference_type operator-(const col_iterator &i) const{ 00586 return (p-i.p)/STRIDE; 00587 } 00588 00590 T &operator*(){ 00591 return *p; 00592 } 00593 00595 const T &operator*() const{ 00596 return *p; 00597 } 00598 00600 bool operator==(const col_iterator &i) const{ return p == i.p; } 00601 00603 bool operator!=(const col_iterator &i) const{ return p != i.p; } 00604 00606 bool operator<(const col_iterator &i) const{ return p < i.p; } 00607 00609 bool operator<=(const col_iterator &i) const{ return p <= i.p; } 00610 00612 bool operator>=(const col_iterator &i) const{ return p >= i.p; } 00613 00615 bool operator>(const col_iterator &i) const{ return p > i.p; } 00616 00617 }; 00618 00619 // const column operator typedef 00620 typedef const col_iterator const_col_iterator; 00621 00623 iterator begin() { return utils::FixedArray<T,COLS*ROWS>::m_data; } 00624 00626 iterator end() { return utils::FixedArray<T,COLS*ROWS>::m_data+dim(); } 00627 00629 const_iterator begin() const { return utils::FixedArray<T,COLS*ROWS>::m_data; } 00630 00632 const_iterator end() const { return utils::FixedArray<T,COLS*ROWS>::m_data+dim(); } 00633 00635 col_iterator col_begin(unsigned int col) { return col_iterator(begin()+col); } 00636 00638 col_iterator col_end(unsigned int col) { return col_iterator(begin()+col+dim()); } 00639 00641 const_col_iterator col_begin(unsigned int col) const { return col_iterator(const_cast<T*>(begin())+col); } 00642 00644 const_col_iterator col_end(unsigned int col) const { return col_iterator(const_cast<T*>(begin())+col+dim()); } 00645 00647 row_iterator row_begin(unsigned int row) { return begin()+row*cols(); } 00648 00650 row_iterator row_end(unsigned int row) { return begin()+(row+1)*cols(); } 00651 00653 const_row_iterator row_begin(unsigned int row) const { return begin()+row*cols(); } 00654 00656 const_row_iterator row_end(unsigned int row) const { return begin()+(row+1)*cols(); } 00657 00659 00671 template<unsigned int MCOLS> 00672 void mult(const FixedMatrix<T,MCOLS,COLS> &m, FixedMatrix<T,MCOLS,ROWS> &dst) const{ 00673 for(unsigned int c=0;c<MCOLS;++c){ 00674 for(unsigned int r=0;r<ROWS;++r){ 00675 // std::cout << "calling inner_product" << std::endl; 00676 dst(c,r) = std::inner_product(m.col_begin(c),m.col_end(c),row_begin(r),T(0)); 00677 } 00678 } 00679 } 00681 00704 template<unsigned int MCOLS> 00705 FixedMatrix<T,MCOLS,ROWS> operator*(const FixedMatrix<T,MCOLS,COLS> &m) const{ 00706 FixedMatrix<T,MCOLS,ROWS> d; 00707 mult(m,d); 00708 return d; 00709 } 00710 00711 00712 00714 00720 FixedMatrix inv() const throw (InvalidMatrixDimensionException,SingularMatrixException){ 00721 return FixedMatrix(dyn().inv().data()); 00722 } 00723 00725 00728 T det() const throw(InvalidMatrixDimensionException){ 00729 return dyn().det(); 00730 } 00731 00733 FixedMatrix<T,ROWS,COLS> transp() const{ 00734 FixedMatrix<T,ROWS,COLS> d; 00735 for(unsigned int i=0;i<cols();++i){ 00736 FixedMatrixBase::optimized_copy<const_col_iterator, typename FixedMatrix<T,ROWS,COLS>::row_iterator,DIM>(col_begin(i),col_end(i),d.row_begin(i)); 00737 // std::copy(col_begin(i),col_end(i),d.row_begin(i)); 00738 } 00739 return d; 00740 } 00741 00743 00744 template<unsigned int OTHER_COLS> 00745 T element_wise_inner_product(const FixedMatrix<T,OTHER_COLS,DIM/OTHER_COLS> &other) const { 00746 return std::inner_product(begin(),end(),other.begin(),T(0)); 00747 } 00748 00749 00751 00754 template<unsigned int OTHER_COLS> 00755 FixedMatrix<T,OTHER_COLS,COLS> dot(const FixedMatrix<T,OTHER_COLS,ROWS> &M) const{ 00756 return this->transp() * M; 00757 } 00758 00760 double cond(const double p=2) const { 00761 DynMatrix<T> mat = this->dyn(); 00762 return mat.cond(); 00763 } 00764 00766 T trace() const{ 00767 ICLASSERT_RETURN_VAL(COLS==ROWS,0); 00768 double accu = 0; 00769 for(int i=0;i<DIM;i+=COLS+1){ 00770 accu += begin()[i]; 00771 } 00772 return accu; 00773 } 00774 00776 FixedMatrixPart<T,COLS,row_iterator> row(unsigned int idx){ 00777 return FixedMatrixPart<T,COLS,row_iterator>(row_begin(idx),row_end(idx)); 00778 } 00779 00781 FixedMatrixPart<T,COLS,const_row_iterator> row(unsigned int idx) const{ 00782 return FixedMatrixPart<T,COLS,const_row_iterator>(row_begin(idx),row_end(idx)); 00783 } 00784 00786 FixedMatrixPart<T,ROWS,col_iterator> col(unsigned int idx){ 00787 return FixedMatrixPart<T,ROWS,col_iterator>(col_begin(idx),col_end(idx)); 00788 } 00789 00791 FixedMatrixPart<T,ROWS,const_col_iterator> col(unsigned int idx) const{ 00792 return FixedMatrixPart<T,ROWS,const_col_iterator>(col_begin(idx),col_end(idx)); 00793 } 00794 00796 template<unsigned int X,unsigned int Y,unsigned int WIDTH,unsigned int HEIGHT> 00797 FixedMatrixPart<T,WIDTH*HEIGHT,MatrixSubRectIterator<T> > part(){ 00798 return FixedMatrixPart<T,WIDTH*HEIGHT,MatrixSubRectIterator<T> >( 00799 MatrixSubRectIterator<T>(begin(),COLS,X,Y,WIDTH,HEIGHT), 00800 MatrixSubRectIterator<T>::create_end_iterator(begin(),COLS,X,Y,WIDTH,HEIGHT)); 00801 } 00802 00804 template<unsigned int X,unsigned int Y,unsigned int WIDTH,unsigned int HEIGHT> 00805 const FixedMatrixPart<T,WIDTH*HEIGHT,MatrixSubRectIterator<T> > part() const{ 00806 return const_cast<FixedMatrix<T,COLS,ROWS>*>(this)->part<X,Y,WIDTH,HEIGHT>(); 00807 } 00808 00810 00815 template<unsigned int NEW_WIDTH,unsigned int NEW_HEIGHT> 00816 inline FixedMatrix<T,NEW_WIDTH,NEW_HEIGHT> resize(const T &init=T(0)) const { 00817 FixedMatrix<T,NEW_WIDTH,NEW_HEIGHT> M(init); 00818 for(unsigned int x=0;x<COLS && x < NEW_WIDTH; ++x){ 00819 for(unsigned int y=0;y<ROWS && y < NEW_HEIGHT; ++y){ 00820 M(x,y) = (*this)(x,y); 00821 } 00822 } 00823 return M; 00824 } 00825 00827 00831 static FixedMatrix<T,ROWS,COLS> id(){ 00832 FixedMatrix<T,ROWS,COLS> m(T(0)); 00833 for(unsigned int i=0;i<ROWS && i<COLS;++i){ 00834 m(i,i) = 1; 00835 } 00836 return m; 00837 } 00838 00840 inline double length(T norm=2) const{ 00841 double sumSquares = 0; 00842 for(unsigned int i=0;i<DIM;++i){ 00843 sumSquares += ::pow((*this)[i],(double)norm); 00844 } 00845 return ::pow( sumSquares, 1.0/norm); 00846 } 00847 00849 inline void normalize(T norm=2){ 00850 T l = (T)length(norm); 00851 if(l) (*this) /= l; 00852 } 00853 00855 inline FixedMatrix<T,COLS,ROWS> normalized(T norm=2) const{ 00856 T l = (T)length(norm); 00857 return l ? (*this)/l : *this; 00858 } 00859 00861 template<class otherT> 00862 bool operator==(const FixedMatrix<otherT,COLS,ROWS> &m) const{ 00863 for(unsigned int i=0;i<DIM;++i){ 00864 if(begin()[i] != m[i]) return false; 00865 } 00866 return true; 00867 } 00869 template<class otherT> 00870 bool operator!=(const FixedMatrix<otherT,COLS,ROWS> &m) const{ 00871 return !this->operator==(m); 00872 } 00873 00874 00876 FixedMatrix<T,1,ROWS> diag() const throw (InvalidMatrixDimensionException){ 00877 if(ROWS != COLS) throw InvalidMatrixDimensionException("trace is only possible for sqaure matrices"); 00878 FixedMatrix<T,1,ROWS> t; 00879 for(unsigned int i=0;i<ROWS;++i){ 00880 t[i] = (*this)(i,i); 00881 } 00882 return t; 00883 } 00884 00886 00887 void decompose_QR(FixedMatrix<T,COLS,ROWS> &Q, FixedMatrix<T,COLS,COLS> &R) const{ 00888 DynMatrix<T> Qd = Q.dyn(), Rd = R.dyn(); 00889 dyn().decompose_QR(Qd,Rd); 00890 } 00891 00893 00894 void decompose_RQ(FixedMatrix<T,ROWS,ROWS> &R, FixedMatrix<T,ROWS,ROWS> &Q) const{ 00895 DynMatrix<T> Rd = R.dyn(), Qd = Q.dyn(); 00896 dyn().decompose_RQ(Rd,Qd); 00897 } 00898 00900 00901 void svd(FixedMatrix<T,COLS,ROWS> &U, FixedMatrix<T,1,COLS> &s, FixedMatrix<T,COLS,COLS> &V) const{ 00902 DynMatrix<T> Ud = U.dyn(), sd = s.dyn(), Vd = V.dyn(); 00903 return dyn().svd(Ud,sd,Vd); 00904 } 00905 00907 00908 FixedMatrix<T,ROWS,COLS> pinv(bool useSVD=0, float zeroThreshold=0.00000000000000001) const { 00909 return FixedMatrix<T,ROWS,COLS>(dyn().pinv(useSVD,zeroThreshold).begin()); 00910 } 00911 00913 00926 void eigen(FixedMatrix &eigenvectors, FixedMatrix<T,1,COLS> &eigenvalues) const{ 00927 if(ROWS != COLS) throw InvalidMatrixDimensionException("eigenvalue decomposition is only possible for sqaure matrices (use svd instead!)"); 00928 DynMatrix<T> evecs = eigenvectors.dyn(), evals = eigenvalues.dyn(); 00929 return dyn().eigen(evecs,evals); 00930 } 00931 00932 00933 }; 00934 00936 00937 template<class T,unsigned int WIDTH,unsigned int HEIGHT, unsigned int HEIGHT2> 00938 inline FixedMatrix<T,WIDTH,HEIGHT+HEIGHT2> operator%(const FixedMatrix<T,WIDTH,HEIGHT> &a, 00939 const FixedMatrix<T,WIDTH,HEIGHT2> &b){ 00940 FixedMatrix<T,WIDTH,HEIGHT+HEIGHT2> M; 00941 for(unsigned int i=0;i<HEIGHT;++i) M.row(i) = a.row(i); 00942 for(unsigned int i=0;i<HEIGHT2;++i) M.row(i+HEIGHT) = b.row(i); 00943 return M; 00944 } 00945 00947 00948 template<class T,unsigned int WIDTH,unsigned int HEIGHT, unsigned int WIDTH2> 00949 inline FixedMatrix<T,WIDTH+WIDTH2,HEIGHT> operator,(const FixedMatrix<T,WIDTH,HEIGHT> &a, 00950 const FixedMatrix<T,WIDTH2,HEIGHT> &b){ 00951 FixedMatrix<T,WIDTH+WIDTH2,HEIGHT> M; 00952 for(unsigned int i=0;i<WIDTH;++i) M.col(i) = a.col(i); 00953 for(unsigned int i=0;i<WIDTH2;++i) M.col(i+WIDTH) = b.col(i); 00954 return M; 00955 } 00956 00957 00958 00959 00961 00963 template<class T, unsigned int M_ROWS_AND_COLS,unsigned int V_COLS> 00964 inline FixedMatrix<T,V_COLS,M_ROWS_AND_COLS> &operator*=(FixedMatrix<T,V_COLS,M_ROWS_AND_COLS> &v, 00965 const FixedMatrix<T,M_ROWS_AND_COLS,M_ROWS_AND_COLS> &m){ 00966 return v = (m*v); 00967 } 00968 00970 00971 template<class T, unsigned int COLS, unsigned int ROWS> 00972 inline std::ostream &operator<<(std::ostream &s,const FixedMatrix<T,COLS,ROWS> &m){ 00973 return s << m.dyn(); 00974 } 00975 00977 00978 template<class T, unsigned int COLS, unsigned int ROWS> 00979 inline std::istream &operator>>(std::istream &s,FixedMatrix<T,COLS,ROWS> &m){ 00980 DynMatrix<T> dyn = m.dyn(); 00981 return s >> dyn; 00982 } 00983 00984 00986 template<class T> 00987 FixedMatrix<T,2,2> create_rot_2D(T angle); 00988 00990 template<class T> 00991 FixedMatrix<T,3,3> create_hom_3x3(T angle, T dx=0, T dy=0, T v0=0, T v1=0); 00992 00994 template<class T> 00995 inline FixedMatrix<T,3,3> create_hom_3x3_trans(T dx, T dy){ 00996 FixedMatrix<T,3,3> m = FixedMatrix<T,3,3>::id(); 00997 m(2,0)=dx; 00998 m(2,1)=dy; 00999 return m; 01000 } 01001 01002 01004 template<class T> 01005 FixedMatrix<T,3,3> create_rot_3D(T axisX, T axisY, T axisZ, T angle); 01006 01008 template<class T> 01009 FixedMatrix<T,3,3> create_rot_3D(T rx,T ry,T rz); 01010 01012 template<class T> 01013 FixedMatrix<T,4,4> create_hom_4x4(T rx, T ry, T rz, T dx=0, T dy=0, T dz=0, T v0=0, T v1=0, T v2=0); 01014 01016 template<class T> 01017 FixedMatrix<T,4,4> create_rot_4x4(T axisX, T axisY, T axisZ, T angle); 01018 01019 01021 template<class T> 01022 inline FixedMatrix<T,4,4> create_hom_4x4_trans(T dx, T dy, T dz){ 01023 FixedMatrix<T,4,4> m = FixedMatrix<T,4,4>::id(); 01024 m(3,0)=dx; 01025 m(3,1)=dy; 01026 m(3,2)=dy; 01027 return m; 01028 } 01029 01031 01035 template<class T,unsigned int COLS, unsigned int ROWS> 01036 FixedMatrix<T,1,3> extract_euler_angles(const FixedMatrix<T,COLS,ROWS> &m) throw (InvalidMatrixDimensionException){ 01037 ICLASSERT_THROW(COLS>2 && ROWS>2,InvalidMatrixDimensionException("extract_euler_angles needs a matrix that has at least 3 rows and columns")); 01038 if( m(1,2) > -0.999999 && m(1,2) < 0.999999){ //avoid Gimbal lock 01039 return FixedMatrix<T,1,3>(asin(m(1,2)),atan2(m(0,2),m(2,2)),atan2(m(1,0),m(1,1))); 01040 }else{ 01041 return FixedMatrix<T,1,3>(-M_PI/2,0,-atan2(m(0,1),m(0,0))); 01042 } 01043 } 01044 01045 01047 template<class T,unsigned int N, class Iterator> template<unsigned int COLS> 01048 inline FixedMatrixPart<T,N,Iterator>& FixedMatrixPart<T,N,Iterator>::operator=(const FixedMatrix<T,COLS,N/COLS> &m){ 01049 FixedMatrixBase::optimized_copy<const T*,Iterator,N>(m.begin(),m.end(),begin); 01050 //std::copy(m.begin(),m.end(),begin); 01051 return *this; 01052 } 01053 template<class T,unsigned int N, class Iterator> template<class T2, unsigned int COLS> 01054 inline FixedMatrixPart<T,N,Iterator>& FixedMatrixPart<T,N,Iterator>::operator=(const FixedMatrix<T2,COLS,N/COLS> &m){ 01055 std::transform(m.begin(),m.end(),begin,utils::clipped_cast<T2,T>); 01056 return *this; 01057 } 01060 #ifdef HAVE_IPP 01061 #define OPTIMIZED_MATRIX_MULTIPLICATION(LEFT_COLS,LEFT_ROWS,RIGHT_COLS,TYPE,IPPSUFFIX) \ 01062 template<> template<> \ 01063 inline void \ 01064 FixedMatrix<TYPE,RIGHT_COLS,LEFT_ROWS>::mult \ 01065 ( \ 01066 const FixedMatrix<TYPE,RIGHT_COLS,LEFT_COLS> &m, \ 01067 FixedMatrix<TYPE,RIGHT_COLS,LEFT_ROWS> &dst \ 01068 ) const { \ 01069 static const unsigned int ST=sizeof(TYPE); \ 01070 ippmMul_mm_##IPPSUFFIX(data(),LEFT_COLS*ST,ST,LEFT_COLS,LEFT_ROWS, \ 01071 m.data(),RIGHT_COLS*ST,ST,RIGHT_COLS,LEFT_COLS, \ 01072 dst.data(),RIGHT_COLS*ST,ST); \ 01073 } 01074 01075 OPTIMIZED_MATRIX_MULTIPLICATION(2,2,2,float,32f); 01076 OPTIMIZED_MATRIX_MULTIPLICATION(3,3,3,float,32f); 01077 OPTIMIZED_MATRIX_MULTIPLICATION(4,4,4,float,32f); 01078 01079 OPTIMIZED_MATRIX_MULTIPLICATION(2,2,2,double,64f); 01080 OPTIMIZED_MATRIX_MULTIPLICATION(3,3,3,double,64f); 01081 OPTIMIZED_MATRIX_MULTIPLICATION(4,4,4,double,64f); 01082 #undef OPTIMIZED_MATRIX_MULTIPLICATION 01083 01084 01085 #endif 01086 01087 #define USE_OPTIMIZED_INV_AND_DET_FOR_2X2_3X3_AND_4X4_MATRICES 01088 01089 #ifdef USE_OPTIMIZED_INV_AND_DET_FOR_2X2_3X3_AND_4X4_MATRICES 01090 01092 // this functions are implemented in iclFixedMatrix.cpp. All templates are 01093 // instantiated for float and double 01094 01095 template<class T> 01096 void icl_util_get_fixed_4x4_matrix_inv(const T *src, T*dst); 01097 template<class T> 01098 void icl_util_get_fixed_3x3_matrix_inv(const T *src, T*dst); 01099 template<class T> 01100 void icl_util_get_fixed_2x2_matrix_inv(const T *src, T*dst); 01101 01102 template<class T> 01103 T icl_util_get_fixed_4x4_matrix_det(const T *src); 01104 template<class T> 01105 T icl_util_get_fixed_3x3_matrix_det(const T *src); 01106 template<class T> 01107 T icl_util_get_fixed_2x2_matrix_det(const T *src); 01108 01109 #define SPECIALISED_MATRIX_INV_AND_DET(D,T) \ 01110 template<> \ 01111 inline FixedMatrix<T,D,D> FixedMatrix<T,D,D>::inv() const \ 01112 throw (InvalidMatrixDimensionException,SingularMatrixException){ \ 01113 FixedMatrix<T,D,D> r; \ 01114 icl_util_get_fixed_##D##x##D##_matrix_inv<T>(begin(),r.begin()); \ 01115 return r; \ 01116 } \ 01117 template<> \ 01118 inline T FixedMatrix<T,D,D>::det() const \ 01119 throw(InvalidMatrixDimensionException){ \ 01120 return icl_util_get_fixed_##D##x##D##_matrix_det<T>(begin()); \ 01121 } 01122 01123 01124 SPECIALISED_MATRIX_INV_AND_DET(2,float); 01125 SPECIALISED_MATRIX_INV_AND_DET(3,float); 01126 SPECIALISED_MATRIX_INV_AND_DET(4,float); 01127 SPECIALISED_MATRIX_INV_AND_DET(2,double); 01128 SPECIALISED_MATRIX_INV_AND_DET(3,double); 01129 SPECIALISED_MATRIX_INV_AND_DET(4,double); 01130 01131 01132 #undef SPECIALISED_MATRIX_INV_AND_DET 01133 01135 #endif 01136 01137 01138 } // namespace math 01139 } 01140