Horus Doc || C++ Reference || Class Overview   Pixels   Images   Detector   Geometry   Registry || Doxygen's quick Index  

HxMatrix.h

00001 /*
00002  *  Copyright (c) 1998, University of Amsterdam, The Netherlands.
00003  *  All rights reserved.
00004  *
00005  *
00006  *  Author(s):
00007  *  Dennis Koelma (koelma@wins.uva.nl)
00008  *  Edo Poll (poll@wins.uva.nl)
00009  *  Jan-Mark Geusebroek (poll@wins.uva.nl)
00010  *  Jan van Gemert (jvgemert@science.uva.nl)
00011  */
00012 
00013 
00014 // Template code in the header file.
00015 // because this yields the most generic patterns, and avoids dead code.
00016 
00017 #ifndef HxTMatrix_h
00018 #define HxTMatrix_h
00019 
00020 #include "HxIo.h"
00021 #include "HxStd.h"
00022 
00023 #include "HxVec3Double.h"
00024 
00025 //declare the HxVector class.
00026 class L_HXBASIS HxVector;
00027 
00028 
00033 template<class C> class L_HXBASIS HxTMatrix {
00034 public:
00035 
00039     HxTMatrix<C>() ;
00040 
00042     HxTMatrix<C>(int nrow, int ncol);
00043 
00045     HxTMatrix<C>(int nrow, int ncol, C a);
00046 
00048     HxTMatrix<C>(int nrow, int ncol, C* data);
00049 
00051     HxTMatrix<C>(const HxString fileName, bool bin=true);
00052 
00054     HxTMatrix<C>(const HxTMatrix &m) ;
00055 
00057     HxTMatrix<C>(const HxVector& v);
00058 
00060 //  template<class C, class U>
00061 //  friend HxTMatrix<C> conv(const HxTMatrix<U> &m) ;
00062 // if I unComment this, I get an internal compilor error.. what to do ?
00063 
00065 
00066     // Destructor
00067     ~HxTMatrix<C>() ;
00068 
00074     static HxTMatrix<C>     translate2d(C x, C y);
00075 
00077     static HxTMatrix<C>     scale2d(double sx, double sy);
00078 
00080     static HxTMatrix<C>     rotate2d(double alpha);
00081 
00083     static HxTMatrix<C>     rotate2dDeg(double alpha);
00084 
00086     static HxTMatrix<C>     reflect2d(int doX, int doY);
00087 
00089     static HxTMatrix<C>     shear2d(double sx, double sy);
00090 
00092     static HxTMatrix<C>     translate3d(double x, double y, double z);
00093 
00095     static HxTMatrix<C>     scale3d(double sx, double sy, double sz);
00096 
00098     static HxTMatrix<C>     rotateX3d(double alpha);
00099 
00101     static HxTMatrix<C>     rotateX3dDeg(double alpha);
00102 
00104     static HxTMatrix<C>     rotateY3d(double alpha);
00105 
00107     static HxTMatrix<C>     rotateY3dDeg(double alpha);
00108 
00110     static HxTMatrix<C>     rotateZ3d(double alpha);
00111 
00113     static HxTMatrix<C>     rotateZ3dDeg(double alpha);
00114 
00116     static HxTMatrix<C>     reflect3d(int doX, int doY, int doZ);
00117 
00119     static HxTMatrix<C>     projection(double f);
00120 
00122     static HxTMatrix<C>     camera(double f);
00123 
00125     static HxTMatrix<C>     lift2dTo3dXY();
00126 
00128 
00132     int             nRow()  const;
00133 
00135     int             nCol()  const;
00136 
00138     int             nElem() const;
00139 
00141     int             valid() const;
00142 
00144     HxVector        getRow(long r) const;
00145 
00147     HxVector        getCol(long c) const;
00148 
00149 
00151 
00154 
00156     HxTMatrix<C>        setRow(long r, HxVector v, bool makeCopy=false) ;
00157 
00159     HxTMatrix<C>        setCol(long c, HxVector v, bool makeCopy=false) ;
00160 
00162     HxTMatrix<C>&       operator=(C a);
00163 
00165     HxTMatrix<C>&       operator=(const HxTMatrix<C>& m);
00166 
00168     C*                  operator[](int i) const;
00169 
00170 
00172     HxTMatrix<C>        operator-() const;
00173 
00175     HxTMatrix<C>        operator*(double          val) const ;
00176 
00178     HxTMatrix<C>        operator*(const HxTMatrix<C>& a) const ;
00179 
00181     friend HxVector     operator*(const HxVector& , const HxTMatrix<C>& );
00182 
00184     friend HxVector     operator*(const HxTMatrix<C>& , const HxVector& );
00185 
00187     HxTMatrix<C>        operator/(double val) const ;
00188 
00190     friend HxTMatrix<C> operator/(double a, const HxTMatrix<C>& b);
00191 
00193     HxTMatrix<C>        operator+(const HxTMatrix<C>& a) const ;
00194 
00196     HxTMatrix<C>        operator+(double          val) const ;
00197 
00199     HxTMatrix<C>        operator-(const HxTMatrix<C>& a) const ;
00200 
00202     HxTMatrix<C>        operator-(double          val) const ;
00203 
00205     int                 operator==(const HxTMatrix<C>& a) const ;
00206 
00208     int                 operator!=(const HxTMatrix<C>& a) const ;
00209 
00213     HxVec3Double        operator*(const HxVec3Double& b) const;
00214 
00215 
00217 
00221     HxTMatrix<C>        delRow(long r) const;
00222 
00224     HxTMatrix<C>        delCol(long c) const;
00225 
00227     void                write2disk(const HxString fileName, bool bin=true) const ;
00228 
00229 
00231     HxTMatrix<C>        i() const;
00232 
00234     HxTMatrix<C>        t() const;
00235 
00237     HxTMatrix<C>        covariance(HxVector &mean=HxVector()) const ;
00238 
00242     HxTMatrix<C>        svd(HxVector& W, HxTMatrix<C>& V) const;
00243 
00247     HxTMatrix<C>        klm(int newDim) const;
00248 
00260     void                kmeans(HxTMatrix<C> &c, HxVector &imap, int numloop, bool cIsInitialized) const ;
00261 
00262 
00266     HxTMatrix<C>        add(const HxTMatrix<C>& b) const;
00267 
00268 
00272     HxTMatrix<C>        add(const double val) const;
00273 
00274 
00278     HxTMatrix<C>        sub(const HxTMatrix<C>& b) const;
00279 
00283     HxTMatrix<C>        sub(const double val) const;
00284 
00288     HxTMatrix<C>        mul(const HxTMatrix<C>& b) const;
00289 
00293     HxTMatrix<C>        mul(const HxVector& v) const;
00294 
00298     HxTMatrix<C>        mul(const double val) const;
00299 
00303     HxTMatrix<C>        div(const double val) const;
00304 
00306     HxTMatrix<C>        sin() const;
00307 
00309     HxTMatrix<C>        cos() const;
00310 
00312     HxTMatrix<C>        tan() const;
00313 
00315     HxTMatrix<C>        sinh() const;
00316 
00318     HxTMatrix<C>        cosh() const;
00319 
00321     HxTMatrix<C>        tanh() const;
00322 
00324     HxTMatrix<C>        exp() const;
00325 
00327     HxTMatrix<C>        log() const;
00328 
00330     HxTMatrix<C>        sqrt() const;
00331 
00333     HxTMatrix<C>        abs() const;
00334 
00336     HxTMatrix<C>        sgn() const;
00337 
00339     HxTMatrix<C>        map(C (*f)(C)) const;
00340 
00342     HxTMatrix<C>        app(const HxTMatrix<C>& b) const;
00343 
00345 
00346     STD_OSTREAM&    put(STD_OSTREAM& os) const;
00347 
00348 
00349 private:
00350 
00351     friend class HxVector ;
00352     int     _nr;    // number of rows
00353     int     _nc;    // number of columns
00354     C*      _data;  // data pointer
00355 
00356 };
00357 
00358 
00359 // declare HxMatrix
00360 L_HXBASIS typedef HxTMatrix<double>  HxMatrix ;
00361 
00362 
00363 //#include <cmath>
00364 #include "HxEnvironment.h"
00365 
00366 template<class C> 
00367 static void svdcmp(C* a, HxVector &w, C* v, int n, int m);
00368 
00369 template<class C> 
00370 static int ludcmp(C* a, int n, short *indx, double *d);
00371 
00372 template<class C> 
00373 static void lubksb(C* a, int n, short *indx, double *b);
00374 
00375 #ifndef HxMatrix_EPS_DEF 
00376 #define HxMatrix_EPS_DEF
00377 const double HxMatrix_EPS = 1e-12;
00378 #endif
00379 
00380 #ifndef M_PI
00381 #define M_PI 3.14159265358979323846
00382 #endif
00383 
00384 #ifndef HxMatrix_Error 
00385 #define HxMatrix_Error
00386 static void
00387 error(HxString msg)
00388 {
00389     HxEnvironment::instance()->errorStream() << "error: " << msg << STD_ENDL;
00390     HxEnvironment::instance()->flush();
00391 }
00392 #endif
00393 
00394 
00395 //---------------------------------------------------
00396 //      Construction:
00397 //---------------------------------------------------
00398 
00399 template<class C> inline
00400 HxTMatrix<C>::HxTMatrix<C>()
00401 {
00402     _nr = 0;
00403     _nc = 0;
00404     _data = 0;
00405 }
00406 
00407 
00408 
00409 template<class C> inline
00410 HxTMatrix<C>::HxTMatrix<C>(int nRow, int nCol)
00411 {
00412     _nr = nRow;
00413     _nc = nCol;
00414     _data = new C[_nr * _nc];
00415 }
00416 
00417 
00418 
00419 template<class C> inline
00420 HxTMatrix<C>::HxTMatrix<C>(int nRow, int nCol, C a)
00421 {
00422     _nr = nRow;
00423     _nc = nCol;
00424     _data = new C[_nr * _nc];
00425 
00426     C* t = _data;
00427     int i = nElem();
00428     while (--i >= 0)
00429         *t++ = a;
00430 
00431 }
00432 
00433 
00434 template<class C> inline
00435 HxTMatrix<C>::HxTMatrix<C>(int nRow, int nCol, C* data)
00436 {
00437     _nr = nRow;
00438     _nc = nCol;
00439     _data = data;
00440 }
00441 
00442 template<class C> inline
00443 HxTMatrix<C>::HxTMatrix<C>(HxString fileName, bool bin)
00444 {
00445 
00446     
00447     FILE *fp;
00448 
00449     if(bin) {   // read binary file
00450 
00451         fp = fopen(fileName.c_str(), "rb") ;
00452 
00453         // read the header of the matrix
00454         fread(&_nr, sizeof(int), 1, fp) ;
00455         fread(&_nc, sizeof(int), 1, fp) ;
00456 
00457         _data = new C[_nr * _nc];
00458 
00459         // read data
00460         fread(_data,sizeof(C),_nr*_nc,fp) ;
00461 
00462     } 
00463     else {  // read text file
00464 
00465         fp = fopen(fileName.c_str(), "r") ;
00466 
00467         //read the header of the matrix
00468         fscanf(fp, "%d %d", &_nr, &_nc);
00469     //  printf("nr=%d, nc=%d\n",_nr,_nc) ;
00470 
00471         _data = new C[_nr * _nc];
00472 
00473         double d ;
00474         for(int i=0; i<_nr;i++) {
00475             for(int j=0; j<_nc;j++) {
00476                 fscanf(fp, "%lf ", &d) ;
00477                 (*this)[i][j] = (C) d ;
00478             }
00479         }
00480 
00481     }
00482     fclose(fp) ;
00483 
00484 }
00485 
00486 
00487 
00488 template<class C> inline
00489 HxTMatrix<C>::HxTMatrix<C>(const HxTMatrix& m)
00490 {
00491     _nr = m.nRow();
00492     _nc = m.nCol();
00493     _data = new C[_nr * _nc];
00494 
00495     C* t = m._data;
00496     C* u = _data;
00497     int i = m.nElem();
00498     while (--i >= 0)
00499         *u++ = *t++;
00500 }
00501 
00502 /*
00503 template<class C> inline
00504 HxTMatrix<C>::HxTMatrix<C>(const HxMatrix& m)
00505 {
00506 
00507     _nr = m.nRow();
00508     _nc = m.nCol();
00509     _data = new C[_nr * _nc];
00510 
00511     for(int r=0; r<m.nRow(); r++)
00512         for(int c=0; c<m.nCol(); c++)
00513             (*this)[r][c] = m[r][c] ;
00514 }
00515 */
00516 
00517 
00518 template<class C, class U> inline
00519 HxTMatrix<C> conv(const HxTMatrix<U> &m)
00520 {
00521     HxTMatrix<C> tmp(m.nRow(), m.nCol()) ;
00522 
00523     for(int r=0; r<m.nRow(); r++)
00524         for(int c=0; c<m.nCol(); c++)
00525             tmp[r][c] = m[r][c] ;
00526 /*
00527     C* t = m._data;
00528     C* u = tmp._data;
00529     int i = m.nElem();
00530     while (--i >= 0)
00531         *u++ = *t++;
00532 */
00533     return tmp;
00534 
00535 }
00536 
00537 /*
00538 template<class C, class U>
00539 HxTMatrix<C>::HxTMatrix(const HxTMatrix<U>& m )
00540 {
00541     HxTMatrix<C> tmp(m.nRow(), m.nCol(), (C) 0) ;
00542 
00543     for(int r=0; r<m.nRow(); r++)
00544         for(int c=0; c<m.nCol(); c++)
00545             tmp[r][c] = m[r][c] ;
00546     return tmp;
00547 
00548     return conv<C>(m) ;
00549 }
00550 */
00551 
00552 template<class C> inline
00553 HxTMatrix<C>::~HxTMatrix<C>()
00554 {
00555     delete[] _data ;
00556 }
00557 
00558 template<class C> STD_OSTREAM&
00559 HxTMatrix<C>::put(STD_OSTREAM& os) const
00560 {
00561     C* t = _data;
00562     int i = nRow();
00563     while (--i >= 0) {
00564         int j = nCol();
00565         os << "| ";
00566         while (--j >= 0)
00567             os << (double) *t++ << " ";
00568         os << "|" << STD_ENDL;
00569     }
00570     return os;
00571 }
00572 
00573 
00574 //---------------------------------------------------
00575 //      Inquiry:
00576 //---------------------------------------------------
00577 
00578 #include "HxVector.h"
00579 
00580 template<class C> inline int
00581 HxTMatrix<C>::nRow() const
00582 {
00583     return _nr;
00584 }
00585 
00586 template<class C> inline int
00587 HxTMatrix<C>::nCol() const
00588 {
00589     return _nc;
00590 }
00591 
00592 template<class C> inline int
00593 HxTMatrix<C>::nElem() const
00594 {
00595     return _nr * _nc;
00596 }
00597 
00598 template<class C> inline int
00599 HxTMatrix<C>::valid() const
00600 {
00601     return ((_nc != 0) && (_nr != 0));
00602 }
00603 
00604 template<class C> inline HxVector
00605 HxTMatrix<C>::getRow(long r) const
00606 {
00607 
00608     if(r>= _nr || r<0){
00609         error("getRow: rownr exceeded the number of rows in HxTMatrix<C>.");
00610         return HxVector(0);
00611     }
00612 
00613     HxVector tmp(_nc);
00614 
00615     for(int i = 0; i<_nc; i++)
00616         tmp[i] = (*this)[r][i] ;
00617 
00618     return tmp ;
00619 }
00620 
00621 template<class C> inline HxVector
00622 HxTMatrix<C>::getCol(long c) const
00623 {
00624 
00625     if(c>= _nc || c<0){
00626         error("getCol: Colnr exceeded number of columns in HxTMatrix<C>.");
00627         return HxVector(0);
00628     }
00629 
00630     HxVector tmp(_nr);
00631     for(int i = 0; i<_nr; i++)
00632     {
00633         tmp[i] = (*this)[i][c] ;
00634     }
00635     return tmp;
00636 
00637 }
00638 
00639 
00640 template<class C> inline HxTMatrix<C> 
00641 HxTMatrix<C>::setRow(long r, HxVector v, bool makeCopy) 
00642 {
00643 
00644     if(r>= _nr || r<0){
00645         error("setRow: rownr exceeded the number of rows in HxTMatrix<C>.");
00646         return HxTMatrix<C>(0,0) ;
00647     }
00648     if(_nc != v.nElem()){
00649         error("setRow: v.nElem not equal to matrix dimension");
00650         return HxTMatrix<C>(0,0) ;
00651     }
00652 
00653     HxTMatrix<C> tmp(0,0);
00654 
00655     if(makeCopy) {
00656 
00657         tmp = HxTMatrix<C>(_nr,_nc);
00658 
00659         for(int row = 0; row<_nr; row++)
00660             for(int col = 0; col<_nc; col++)
00661                 if(row!=r) tmp[row][col] = (*this)[row][col] ;
00662                 else tmp[row][col] = v[col] ;
00663     } 
00664     else { // only change the original, faster
00665 
00666         for(int col = 0; col<_nc; col++)
00667             (*this)[r][col] = v[col] ;
00668     }
00669 
00670 
00671     return tmp;
00672 
00673 }
00674 
00675 template<class C> inline HxTMatrix<C> 
00676 HxTMatrix<C>::setCol(long c, HxVector v, bool makeCopy) 
00677 {
00678 
00679     if(c>= _nc || c<0){
00680         error("setCol: Colnr exceeded number of columns in HxTMatrix<C>.");
00681         return HxTMatrix<C>(0,0) ;
00682     }
00683     if(_nr != v.nElem()){
00684         error("setCol: v.nElem not equal to matrix dimension");
00685         return HxTMatrix<C>(0,0) ;
00686     }
00687 
00688     HxTMatrix<C> tmp(0,0);
00689 
00690     if(makeCopy) {
00691 
00692         tmp = HxTMatrix<C>(_nr,_nc);
00693 
00694         for(int row = 0; row<_nr; row++)
00695             for(int col = 0; col<_nc; col++)
00696                 if(col!=c) tmp[row][col] = (*this)[row][col] ;
00697                 else tmp[row][col] = v[row] ;
00698     }
00699     else { // only change the original, faster
00700 
00701         for(int row = 0; row<_nr; row++)
00702             (*this)[row][c] = v[row] ;
00703     }
00704 
00705     return tmp;
00706 
00707 }
00708 template<class C> inline HxTMatrix<C> 
00709 HxTMatrix<C>::delRow(long r) const
00710 {
00711 
00712     if(r>= _nr || r <0){
00713         error("delRow: rownr exceeded the number of rows in HxTMatrix<C>.");
00714         return HxTMatrix<C>(0,0) ;
00715     }
00716 
00717     HxTMatrix<C> tmp(_nr-1,_nc);
00718 
00719     for(int row = 0; row<_nr; row++)
00720         for(int col = 0; col<_nc; col++)
00721             if(row < r) tmp[row][col] = (*this)[row][col] ;
00722             else if(row > r) tmp[row-1][col] = (*this)[row][col] ;
00723 
00724     return tmp ;
00725 
00726 }
00727 
00728 
00729 template<class C> inline HxTMatrix<C> 
00730 HxTMatrix<C>::delCol(long c) const
00731 {
00732 
00733     if(c>= _nc || c<0){
00734         error("delCol: colnr exceeded the number of cols in HxTMatrix<C>.");
00735         return HxTMatrix<C>(0,0) ;
00736     }
00737 
00738     HxTMatrix<C> tmp(_nr,_nc-1);
00739 
00740     for(int row = 0; row<_nr; row++)
00741         for(int col = 0; col<_nc; col++)
00742             if(col < c) tmp[row][col] = (*this)[row][col] ;
00743             else if(col > c) tmp[row][col-1] = (*this)[row][col] ;
00744 
00745     return tmp ;
00746 
00747 }
00748 
00749 
00750 //---------------------------------------------------
00751 //      Operators:
00752 //---------------------------------------------------
00753 
00754 template<class C> inline HxTMatrix<C>&
00755 HxTMatrix<C>::operator=(C a)
00756 {
00757     int i = nElem();
00758     C *t = _data;
00759     while (--i >= 0)
00760         *t++ = a;
00761     return *this;
00762 }
00763 
00764 
00765 
00766 template<class C> inline HxTMatrix<C>&
00767 HxTMatrix<C>::operator=(const HxTMatrix<C>& m)
00768 {
00769     if (this != &m) {
00770         delete [] _data;
00771         _nr = m.nRow();
00772         _nc = m.nCol();
00773         _data = new C [_nr * _nc];
00774         C *t = _data;
00775         C *u = m._data;
00776         int i = m.nElem();
00777         while (--i >= 0)
00778             *t++ = *u++;
00779     }
00780     return *this;
00781 }
00782 
00783 
00784 template<class C> inline C*
00785 HxTMatrix<C>::operator[](int i) const
00786 {
00787     return &_data[i*_nc];
00788 }
00789 
00790 
00791 template<class C> inline HxTMatrix<C>
00792 HxTMatrix<C>::operator-() const
00793 {
00794     HxTMatrix<C> m(*this);
00795     C* t = m._data;
00796     C* u = _data;
00797     int i = nElem();
00798     while (--i >= 0)
00799         *t++ = -(*u++);
00800     return m;
00801 }
00802 
00803 template<class C> inline HxTMatrix<C>
00804 HxTMatrix<C>::operator*(double val) const
00805 {
00806     HxTMatrix<C> m(*this);
00807     C* t = m._data;
00808     int i = nElem();
00809     while (--i >= 0)
00810         *t++ = *t * val ;
00811     return m;
00812 }
00813 
00814 template<class C> inline HxTMatrix<C>
00815 operator*(double a, const HxTMatrix<C> &b)
00816 {
00817     return b * a ;
00818 }
00819 
00820 
00821 template<class C> inline HxTMatrix<C>
00822 HxTMatrix<C>::operator/(double val) const
00823 {
00824     HxTMatrix<C> m(*this);
00825     C* t = m._data;
00826     int i = nElem();
00827     while (--i >= 0)
00828         *t++ = *t / val ;
00829     return m;}
00830 
00831 template<class C> inline HxTMatrix<C>
00832 operator/(double a, const HxTMatrix<C> &b)
00833 {
00834     HxTMatrix<C> m(b);
00835     C* t = m._data;
00836     C* u = b._data;
00837     int i = b.nElem();
00838     while (--i >= 0)
00839         *t++ = a / *u++;
00840     return m;
00841 }
00842 
00843 
00844 template<class C> inline HxTMatrix<C>
00845 HxTMatrix<C>::operator+(double val) const
00846 {
00847 
00848     HxTMatrix<C> m(*this);
00849     C* t = m._data;
00850     int i = nElem();
00851     while (--i >= 0)
00852         *t++ = val + *t;
00853     return m;
00854 }
00855 
00856 
00857 template<class C> inline HxTMatrix<C>
00858 operator+(double a, const HxTMatrix<C> &b)
00859 {
00860     return b + a ;
00861 }
00862 
00863 
00864 template<class C> inline HxTMatrix<C>
00865 HxTMatrix<C>::operator-(double val) const
00866 {
00867 
00868     HxTMatrix<C> m(*this);
00869     C* t = m._data;
00870     int i = nElem();
00871     while (--i >= 0)
00872         *t++ = *t - val ;
00873     return m;
00874 }
00875 
00876 template<class C> inline HxTMatrix<C>
00877 operator-(double val, const HxTMatrix<C> &b)
00878 {
00879     return -b + val;
00880 }
00881 
00882 
00883 template<class C> inline int
00884 HxTMatrix<C>::operator!=(const HxTMatrix<C> &a) const
00885 {
00886     return !(a == *this);
00887 }
00888 
00889 
00890 template<class C> inline STD_OSTREAM&
00891 operator<<(STD_OSTREAM& os, const HxTMatrix<C> v)
00892 {
00893     return v.put(os);
00894 }
00895 
00896 //---------------------------------------------------
00897 //      Operations:
00898 //---------------------------------------------------
00899 
00900 template<class C> inline HxTMatrix<C>
00901 HxTMatrix<C>::t() const
00902 {
00903     HxTMatrix<C> m(nCol(), nRow());
00904     int i, j;
00905     for (i=0 ; i<nRow() ; i++)
00906         for (j=0 ; j<nCol() ; j++)
00907             m[j][i] = (*this)[i][j];
00908     return m;
00909 }
00910 
00911 
00912 template<class C> inline HxTMatrix<C>
00913 HxTMatrix<C>::map(C (*f)(C)) const
00914 {
00915     HxTMatrix<C> m(*this);
00916     C* t = m._data;
00917     C* u = _data;
00918     int i = nElem();
00919     while (--i >= 0)
00920             *t++ = (C) f(*u++);
00921     return m;
00922 }
00923 
00924 
00925 //L_HXBASIS HxMatrix     operator*(const HxMatrix& a, const HxMatrix& b);
00926 //template<class C> L_HXBASIS HxVector
00927 //operator*(const HxVector& a, const HxTMatrix<C>& b);
00928 //template<class C>
00929 //L_HXBASIS HxVector     operator*(const HxTMatrix<C> &b, const HxVector& a);
00930 //L_HXBASIS HxMatrix     operator+(const HxMatrix& a, const HxMatrix& b);
00931 //L_HXBASIS HxMatrix     operator-(const HxMatrix& a, const HxMatrix& b);
00932 //L_HXBASIS int          operator==(const HxMatrix& a, const HxMatrix& b);
00933 //L_HXBASIS HxVec3Double operator*(const HxVec3Double& a, const HxMatrix& b);
00934 //L_HXBASIS HxVec3Double operator*(const HxMatrix& a, const HxVec3Double& b);
00935 
00936 
00937 
00938 
00939 //---------------------------------------------------
00940 //      Construction:
00941 //---------------------------------------------------
00942 
00943 template<class C> 
00944 HxTMatrix<C>::HxTMatrix<C>(const HxVector& v)
00945 {
00946     _nc = v.nElem();
00947     _nr = 1;
00948     _data = new C[_nr * _nc];
00949 
00950     //int t = _nc;
00951     C* u = _data;
00952     int i = 0;
00953     while (i < _nc)
00954         *u++ = v[i++];
00955 }
00956 
00957 //---------------------------------------------------
00958 //      HxTMatrix generation:
00959 //---------------------------------------------------
00960 
00961 template<class C> HxTMatrix<C> 
00962 HxTMatrix<C>::translate2d(C x, C y)
00963 {
00964     HxTMatrix<C> m(3,3);
00965     m[0][0] = 1; m[0][1] = 0; m[0][2] = x;
00966     m[1][0] = 0; m[1][1] = 1; m[1][2] = y;
00967     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1;
00968     /* prefix:
00969     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;
00970     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;
00971     m[2][0] = x; m[2][1] = y; m[2][2] = 1;
00972     */
00973     return m;
00974 }
00975 
00976 
00977 
00978 template<class C> HxTMatrix<C>
00979 HxTMatrix<C>::scale2d(double sx, double sy)
00980 {
00981     HxTMatrix<C> m(3,3);
00982     m[0][0] = sx; m[0][1] =  0; m[0][2] = 0;
00983     m[1][0] =  0; m[1][1] = sy; m[1][2] = 0;
00984     m[2][0] =  0; m[2][1] =  0; m[2][2] = 1;
00985     return m;
00986 }
00987 
00988 
00989 template<class C> HxTMatrix<C> 
00990 HxTMatrix<C>::rotate2d(double alpha) // alpha in rad
00991 {
00992     HxTMatrix<C> m(3,3);
00993     m[0][0] = ::cos(alpha); m[0][1] = -::sin(alpha); m[0][2] = 0;
00994     m[1][0] = ::sin(alpha); m[1][1] = ::cos(alpha);  m[1][2] = 0;
00995     m[2][0] = 0;            m[2][1] = 0;             m[2][2] = 1;
00996     /* prefix:
00997     m[0][0] =  ::cos(alpha); m[0][1] = ::sin(alpha); m[0][2] = 0;
00998     m[1][0] = -::sin(alpha); m[1][1] = ::cos(alpha); m[1][2] = 0;
00999     m[2][0] = 0;             m[2][1] = 0;            m[2][2] = 1;
01000     */
01001     return m;
01002 }
01003 
01004 template<class C> HxTMatrix<C>
01005 HxTMatrix<C>::rotate2dDeg(double alpha) // alpha in deg
01006 {
01007     return rotate2d(M_PI*alpha/180.0);
01008 }
01009 
01010 template<class C> HxTMatrix<C>
01011 HxTMatrix<C>::reflect2d(int doX, int doY)
01012 {
01013     double rx = (doX) ? -1 : 1;
01014     double ry = (doY) ? -1 : 1;
01015     HxTMatrix<C> m(3,3);
01016     m[0][0] = rx; m[0][1] =  0; m[0][2] = 0;
01017     m[1][0] =  0; m[1][1] = ry; m[1][2] = 0;
01018     m[2][0] =  0; m[2][1] =  0; m[2][2] = 1;
01019     return m;
01020 }
01021 
01022 template<class C> HxTMatrix<C>
01023 HxTMatrix<C>::shear2d(double sx, double sy)
01024 {
01025     HxTMatrix<C> m(3,3);
01026     m[0][0] =  1; m[0][1] = sx; m[0][2] = 0;
01027     m[1][0] = sy; m[1][1] =  1; m[1][2] = 0;
01028     m[2][0] =  0; m[2][1] =  0; m[2][2] = 1;
01029     /* prefix:
01030     m[0][0] =  1; m[0][1] = sy; m[0][2] = 0;
01031     m[1][0] = sx; m[1][1] =  1; m[1][2] = 0;
01032     m[2][0] =  0; m[2][1] =  0; m[2][2] = 1;
01033     */
01034     return m;
01035 }
01036 
01037 template<class C> HxTMatrix<C>
01038 HxTMatrix<C>::translate3d(double x, double y, double z)
01039 {
01040     HxTMatrix<C> m(4,4);
01041     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = x;
01042     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = y;
01043     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = z;
01044     m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
01045     /* prefix:
01046     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
01047     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
01048     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0;
01049     m[3][0] = x; m[3][1] = y; m[3][2] = z; m[3][3] = 1;
01050     */
01051     return m;
01052 }
01053 
01054 template<class C> HxTMatrix<C>
01055 HxTMatrix<C>::scale3d(double sx, double sy, double sz)
01056 {
01057     HxTMatrix<C> m(4,4);
01058     m[0][0] = sx; m[0][1] =  0; m[0][2] =  0; m[0][3] = 0;
01059     m[1][0] =  0; m[1][1] = sy; m[1][2] =  0; m[1][3] = 0;
01060     m[2][0] =  0; m[2][1] =  0; m[2][2] = sz; m[2][3] = 0;
01061     m[3][0] =  0; m[3][1] =  0; m[3][2] =  0; m[3][3] = 1;
01062     return m;
01063 }
01064 
01065 template<class C> HxTMatrix<C>
01066 HxTMatrix<C>::rotateX3d(double alpha) // alpha in rad
01067 {
01068     HxTMatrix<C> m(4,4);
01069     m[0][0] = 1; m[0][1] = 0;            m[0][2] = 0;             m[0][3] = 0;
01070     m[1][0] = 0; m[1][1] = ::cos(alpha); m[1][2] = -::sin(alpha); m[1][3] = 0;
01071     m[2][0] = 0; m[2][1] = ::sin(alpha); m[2][2] = ::cos(alpha);  m[2][3] = 0;
01072     m[3][0] = 0; m[3][1] = 0;            m[3][2] = 0;             m[3][3] = 1;
01073     /* prefix
01074     m[0][0] = 1; m[0][1] = 0;             m[0][2] = 0;            m[0][3] = 0;
01075     m[1][0] = 0; m[1][1] = ::cos(alpha);  m[1][2] = ::sin(alpha); m[1][3] = 0;
01076     m[2][0] = 0; m[2][1] = -::sin(alpha); m[2][2] = ::cos(alpha); m[2][3] = 0;
01077     m[3][0] = 0; m[3][1] = 0;             m[3][2] = 0;            m[3][3] = 1;
01078     */
01079     return m;
01080 }
01081 
01082 template<class C> HxTMatrix<C>
01083 HxTMatrix<C>::rotateX3dDeg(double alpha) // alpha in deg
01084 {
01085     return rotateX3d(M_PI*alpha/180.0);
01086 }
01087 
01088 template<class C> HxTMatrix<C>
01089 HxTMatrix<C>::rotateY3d(double alpha) // alpha in rad
01090 {
01091     HxTMatrix<C> m(4,4);
01092     alpha = M_PI*alpha/180.0;
01093     m[0][0] = ::cos(alpha);  m[0][1] = 0; m[0][2] = ::sin(alpha); m[0][3] = 0;
01094     m[1][0] = 0;             m[1][1] = 1; m[1][2] = 0;            m[1][3] = 0;
01095     m[2][0] = -::sin(alpha); m[2][1] = 0; m[2][2] = ::cos(alpha); m[2][3] = 0;
01096     m[3][0] = 0;             m[3][1] = 0; m[3][2] = 0;            m[3][3] = 1;
01097     /* prefix:
01098     m[0][0] = ::cos(alpha); m[0][1] = 0; m[0][2] = -::sin(alpha); m[0][3] = 0;
01099     m[1][0] = 0;            m[1][1] = 1; m[1][2] = 0;             m[1][3] = 0;
01100     m[2][0] = ::sin(alpha); m[2][1] = 0; m[2][2] = ::cos(alpha);  m[2][3] = 0;
01101     m[3][0] = 0;            m[3][1] = 0; m[3][2] = 0;             m[3][3] = 1;
01102     */
01103     return m;
01104 }
01105 
01106 template<class C> HxTMatrix<C>
01107 HxTMatrix<C>::rotateY3dDeg(double alpha) // alpha in deg
01108 {
01109     return rotateY3d(M_PI*alpha/180.0);
01110 }
01111 
01112 template<class C> HxTMatrix<C>
01113 HxTMatrix<C>::rotateZ3d(double alpha) // alpha in rad
01114 {
01115     HxTMatrix<C> m(4,4);
01116     m[0][0] = ::cos(alpha); m[0][1] = -::sin(alpha); m[0][2] = 0; m[0][3] = 0;
01117     m[1][0] = ::sin(alpha); m[1][1] = ::cos(alpha);  m[1][2] = 0; m[1][3] = 0;
01118     m[2][0] = 0;            m[2][1] = 0;             m[2][2] = 1; m[2][3] = 0;
01119     m[3][0] = 0;            m[3][1] = 0;             m[3][2] = 0; m[3][3] = 1;
01120     /* prefix:
01121     m[0][0] = ::cos(alpha);  m[0][1] = ::sin(alpha); m[0][2] = 0; m[0][3] = 0;
01122     m[1][0] = -::sin(alpha); m[1][1] = ::cos(alpha); m[1][2] = 0; m[1][3] = 0;
01123     m[2][0] = 0;             m[2][1] = 0;            m[2][2] = 1; m[2][3] = 0;
01124     m[3][0] = 0;             m[3][1] = 0;            m[3][2] = 0; m[3][3] = 1;
01125     */
01126     return m;
01127 }
01128 
01129 template<class C> HxTMatrix<C>
01130 HxTMatrix<C>::rotateZ3dDeg(double alpha) // alpha in deg
01131 {
01132     return rotateZ3d(M_PI*alpha/180.0);
01133 }
01134 
01135 template<class C> HxTMatrix<C>
01136 HxTMatrix<C>::reflect3d(int doX, int doY, int doZ)
01137 {
01138     double rx = (doX) ? -1 : 1;
01139     double ry = (doY) ? -1 : 1;
01140     double rz = (doZ) ? -1 : 1;
01141     HxTMatrix<C> m(4,4);
01142     m[0][0] = rx; m[0][1] =  0; m[0][2] =  0; m[0][3] = 0;
01143     m[1][0] =  0; m[1][1] = ry; m[1][2] =  0; m[1][3] = 0;
01144     m[2][0] =  0; m[2][1] =  0; m[2][2] = rz; m[2][3] = 0;
01145     m[3][0] =  0; m[3][1] =  0; m[3][2] =  0; m[3][3] = 1;
01146     return m;
01147 }
01148 
01149 template<class C> HxTMatrix<C>
01150 HxTMatrix<C>::projection(double f)
01151 {
01152     HxTMatrix<C> m(4,4);
01153     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
01154     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
01155     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 1/f;
01156     m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
01157     /* prefix:
01158     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;   m[0][3] = 0;
01159     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;   m[1][3] = 0;
01160     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1;   m[2][3] = 0;
01161     m[3][0] = 0; m[3][1] = 0; m[3][2] = 1/f; m[3][3] = 1;
01162     */
01163     return m;
01164 }
01165 
01166 template<class C> HxTMatrix<C>
01167 HxTMatrix<C>::camera(double f)
01168 {
01169     HxTMatrix<C> m(3,4);
01170     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;   m[0][3] = 0;
01171     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;   m[1][3] = 0;
01172     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1/f; m[2][3] = 1;
01173     /* prefix:
01174     HxTMatrix<C> m(4,3);
01175     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;
01176     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;
01177     m[2][0] = 0; m[2][1] = 0; m[2][2] = 1/f;
01178     m[3][0] = 0; m[3][1] = 0; m[3][2] = 1;
01179     */
01180     return m;
01181 }
01182 
01183 template<class C> HxTMatrix<C>
01184 HxTMatrix<C>::lift2dTo3dXY()
01185 {
01186     HxTMatrix<C> m(4,3);
01187     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0;
01188     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0;
01189     m[2][0] = 0; m[2][1] = 0; m[2][2] = 0;
01190     m[3][0] = 0; m[3][1] = 0; m[3][2] = 1;
01191     /* prefix:
01192     HxTMatrix<C> m(3,4);
01193     m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0;
01194     m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0;
01195     m[2][0] = 0; m[2][1] = 0; m[2][2] = 0; m[2][3] = 1;
01196     */
01197     return m;
01198 }
01199 
01200 //---------------------------------------------------
01201 //      Operators:
01202 //---------------------------------------------------
01203 
01204 template<class C> inline int 
01205 HxTMatrix<C>::operator==(const HxTMatrix<C>& a) const 
01206 {
01207     if ((a.nCol() != nCol()) || (a.nRow() != nRow()))
01208         return 0;
01209 
01210     C* t = _data;
01211     C* u = a._data;
01212     int i = a.nElem();
01213     while (--i >= 0) {
01214         if (fabs(*t++ - *u++) > HxMatrix_EPS)
01215             return 0;
01216     }
01217     return 1;
01218 
01219 }
01220 
01221 
01222 template<class C> HxTMatrix<C> 
01223 HxTMatrix<C>::operator+(const HxTMatrix<C> &a) const 
01224 {
01225     if ((a.nCol() != nCol()) || (a.nRow() != nRow()) ) {
01226         error("nonconformant HxTMatrix<C> + HxTMatrix<C> operands.");
01227         return HxTMatrix<C>(0,0);
01228     }
01229     HxTMatrix<C> m(nRow(), nCol());
01230     int i, j;
01231     for (i=0 ; i<nRow() ; i++) {
01232         for (j=0 ; j<nCol() ; j++)
01233             m[i][j] = a[i][j] + (*this)[i][j];
01234     }
01235     return m;
01236 }
01237 
01238 
01239 template<class C> HxTMatrix<C> 
01240 HxTMatrix<C>::operator-(const HxTMatrix<C> &a) const 
01241 {
01242     if ((a.nCol() != nCol()) || (a.nRow() != nRow()) ) {
01243         error("nonconformant HxTMatrix<C> + HxTMatrix<C> operands.");
01244         return HxTMatrix<C>(0,0);
01245     }
01246     HxTMatrix<C> m(nRow(), nCol());
01247     int i, j;
01248     for (i=0 ; i<nRow() ; i++) {
01249         for (j=0 ; j<nCol() ; j++)
01250             m[i][j] = (*this)[i][j] - a[i][j] ;
01251     }
01252     return m;
01253 }
01254 
01255 
01256 template<class C> HxTMatrix<C>
01257 HxTMatrix<C>::operator*(const HxTMatrix<C> &a) const 
01258 {
01259     if (nCol() != a.nRow()) {
01260         error("nonconformant HxTMatrix<C> * HxTMatrix<C> operands.");
01261         return HxTMatrix<C>(0,0);
01262     }
01263     HxTMatrix<C> m((*this).nRow(), a.nCol(), 0.0);
01264     double sum;
01265     int i, j, k;
01266     for (i=0 ; i<nRow() ; i++) {
01267         for (j=0 ; j<a.nCol() ; j++) {
01268             sum = 0;
01269             for (k=0 ; k<nCol() ; k++)
01270                 sum += (*this)[i][k] * a[k][j];
01271             m[i][j] = sum;
01272         }
01273     }
01274     return m;
01275 }
01276 /*
01277 template<class C> HxVector 
01278 operator*(const HxVector &a, const HxTMatrix<C> &b)
01279 {
01280     if (a.nElem() != b.nRow()) {
01281         error("nonconformant HxVector * HxTMatrix<C> operands.");
01282         return HxVector(0);
01283     }
01284     HxVector v(b.nCol());
01285     double sum;
01286     int i, j;
01287     for (i=0 ; i<b.nCol() ; i++) {
01288         sum = 0;
01289         for (j=0 ; j<b.nRow() ; j++)
01290             sum += a[j] * b[j][i];
01291         v[i] = sum;
01292     }
01293     return v;
01294 }
01295 
01296 
01297 */
01298 template<class C> HxVector 
01299 operator*(const HxVector &a, const HxTMatrix<C> &b)
01300 {
01301     if (a.nElem() != b.nRow()) {
01302         error("nonconformant HxVector * HxTMatrix<C> operands.");
01303         return HxVector(0);
01304     }
01305     HxVector v(b.nCol());
01306     double sum;
01307     int i, j;
01308     for (i=0 ; i<b.nCol() ; i++) {
01309         sum = 0;
01310         for (j=0 ; j<b.nRow() ; j++)
01311             sum += a[j] * b[j][i];
01312         v[i] = sum;
01313     }
01314     return v;
01315 }
01316 
01317 
01318 template<class C> HxVector 
01319 operator*(const HxTMatrix<C> &a, const HxVector &b)
01320 {
01321     if (b.nElem() != a.nCol()) {
01322         error("nonconformant HxTMatrix<C> * HxVector operands.");
01323         return HxVector(0);
01324     }
01325     HxVector v(a.nRow());
01326     double sum;
01327     int i, j;
01328     for (i=0 ; i<a.nRow() ; i++) {
01329         sum = 0;
01330         for (j=0 ; j<a.nCol() ; j++)
01331             sum += a[i][j] * b[j];
01332         v[i] = sum;
01333     }
01334     return v;
01335 }
01336 
01337 
01338 /*
01339 
01340 template<class C> HxVector 
01341 operator*(const HxTMatrix<C> &b, const HxVector &a)  
01342 {
01343     if (a.nElem() != b.nCol()) {
01344         error("nonconformant HxTMatrix<C> * HxVector operands.");
01345         return HxVector(0);
01346     }
01347     HxVector v(b.nRow());
01348     double sum;
01349     int i, j;
01350     for (i=0 ; i<b.nRow() ; i++) {
01351         sum = 0;
01352         for (j=0 ; j<b.nCol() ; j++)
01353             sum += b[i][j] * a[j];
01354         v[i] = sum;
01355     }
01356     return v;
01357 }
01358 
01359 */
01360 
01361 template<class C> HxVec3Double 
01362 operator*(const HxVec3Double &a, const HxTMatrix<C> &b)
01363 {
01364     return b*a;
01365 }
01366 
01367 
01368 
01369 template<class C> HxVec3Double 
01370 HxTMatrix<C>::operator*(const HxVec3Double &b) const
01371 {
01372     if ((nRow() != 3) || (nCol() != 3)) {
01373         error("nonconformant HxTMatrix<C> * HxVec3Double operands.");
01374         return HxVec3Double();
01375     }
01376     double v[3];
01377     for (int i=0 ; i<nRow() ; i++) {
01378         v[i] = (*this)[i][0]*b.x() + (*this)[i][1]*b.y() + (*this)[i][2]*b.z();
01379     }
01380     return HxVec3Double(v[0], v[1], v[2]);
01381 }
01382 
01383 //*/
01384 
01385 //---------------------------------------------------
01386 //      Operations:
01387 //---------------------------------------------------
01388 
01389 template<class C>  void  
01390 HxTMatrix<C>::write2disk(const HxString fileName, bool bin) const 
01391 {
01392     FILE *fp;
01393 
01394     if(bin) {   // write to binary file
01395     
01396         fp = fopen(fileName.c_str(), "wb") ;
01397 
01398         //write the header of the matrix
01399         fwrite(&_nr, sizeof(int), 1, fp) ;
01400         fwrite(&_nc, sizeof(int), 1, fp) ;
01401 
01402         // write data
01403         fwrite(_data,sizeof(C),_nr*_nc,fp) ;
01404 
01405     }
01406     else {      // write to text file
01407 
01408         fp = fopen(fileName.c_str(), "w") ;
01409 
01410         //write the header of the matrix
01411         fprintf(fp,"%d \t %d \n", _nr, _nc) ;
01412         for(int i=0; i<_nr;i++) {
01413             for(int j=0; j<_nc;j++)
01414                 fprintf(fp," %f",(double)(*this)[i][j] );
01415                 fprintf(fp,"\n");
01416         }
01417 
01418     }
01419 
01420     fclose(fp) ;
01421 }
01422 
01423 template<class C> HxTMatrix<C> 
01424 HxTMatrix<C>::i() const
01425 {
01426     if (nRow() != nCol()) {
01427         error("Inverse: matrix is not square!.");
01428         return HxTMatrix<C>(0, 0);
01429     }
01430 
01431     int size = nRow();
01432     HxTMatrix<C> m(size,size), tmp(*this);
01433     short* idx = new short [size];
01434     double d;
01435 
01436     if (!ludcmp(tmp._data, size, idx, &d)) {
01437         error( "Inverse: singular matrix can't be inverted." );
01438         delete [] idx;
01439         return HxTMatrix<C>(0,0);
01440     }
01441     
01442     double * res = new double [size];
01443 
01444     for (int j = 0; j < size; j++) {
01445         for (int i = 0; i < size; i++)
01446             res[i] = 0.0;
01447         res[j] = 1.0;
01448         lubksb(tmp._data, size, idx, res);
01449         for (i = 0; i < size; i++)
01450             m[i][j] = res[i];
01451     }
01452 
01453      delete [] res;
01454      delete [] idx;
01455 
01456      return m;
01457 }
01458 
01459 
01460 
01461 template<class C> HxTMatrix<C> 
01462 HxTMatrix<C>::svd(HxVector& W, HxTMatrix<C>& V) const
01463 {
01464     int row = nRow();
01465     int col = nCol();
01466 
01467     if (col > row) {
01468         error( "Svd: HxTMatrix must be augmented with extra rows of zeros." );
01469         W = HxVector(0);
01470         V = HxTMatrix<C>(0,0);
01471         return HxTMatrix<C>(0,0);
01472     }
01473 
01474     HxTMatrix<C> U(*this);
01475     W = HxVector(col);
01476     V = HxTMatrix<C>(col,col);
01477 
01478     svdcmp(U._data, W, V._data, col, row);
01479 
01480     /* sort on eigenvalue */
01481     for (int i = 0; i < col; i++) {
01482         int idx = i;
01483         double val = W[idx];
01484 
01485         for (int j = i+1; j < col; j++)
01486             if( W[j] > val ) {
01487                 idx = j;
01488                 val = W[idx];
01489             }
01490 
01491         if (idx != i) {
01492             val = W[idx]; W[idx] = W[i]; W[i] = val;
01493             for (int j = 0; j < col; j++) {
01494                 val = V[j][idx];
01495                 V[j][idx] = V[j][i];
01496                 V[j][i] = val;
01497             }
01498             for (j = 0; j < row; j++) {
01499                 val = U[j][idx];
01500                 U[j][idx] = U[j][i];
01501                 U[j][i] = val;
01502             }
01503         }
01504     }
01505 
01506     return U;
01507 }
01508 
01509 
01510 template<class C> HxTMatrix<C>  
01511 HxTMatrix<C>::app(const HxTMatrix<C>& b) const
01512 {
01513        int newRows = b.nRow() + nRow() ;
01514        int newCols = b.nCol()>nCol() ? b.nCol() : nCol() ;
01515        int i,j ;
01516 
01517        HxTMatrix<C> m( newRows, newCols, (C) 0.0) ;
01518 
01519        for (i=0; i<nRow(); i++)
01520         for (j=0; j<nCol(); j++)
01521           m[i][j] = (*this)[i][j] ;
01522 
01523         for (i=nRow(); i<newRows; i++)
01524          for (j=0; j<b.nCol(); j++)
01525           m[i][j] = b[i-nRow()][j] ;
01526 
01527         return m;
01528 }
01529 
01530 
01531 
01532 template<class C> HxTMatrix<C> 
01533 HxTMatrix<C>::add(const HxTMatrix<C>& b) const
01534 {
01535     return *this+b;
01536 }
01537 
01538 template<class C> HxTMatrix<C> 
01539 HxTMatrix<C>::add(const double val) const
01540 {
01541     return *this+val;
01542 }
01543 
01544 template<class C> HxTMatrix<C> 
01545 HxTMatrix<C>::sub(const HxTMatrix<C>& b) const
01546 {
01547     return *this-b;
01548 }
01549 
01550 template<class C> HxTMatrix<C> 
01551 HxTMatrix<C>::sub(const double val) const
01552 {
01553     return *this-val;
01554 }
01555 
01556 template<class C> HxTMatrix<C> 
01557 HxTMatrix<C>::mul(const HxTMatrix<C>& b) const
01558 {
01559     return *this*b;
01560 }
01561 
01562 template<class C> HxTMatrix<C> 
01563 HxTMatrix<C>::mul(const double val) const
01564 {
01565     return *this*val;
01566 }
01567 
01568 
01569 template<class C> HxTMatrix<C> 
01570 HxTMatrix<C>::mul(const HxVector& v) const
01571 {
01572     return *this*v;
01573 }
01574 
01575 
01576 template<class C> HxTMatrix<C> 
01577 HxTMatrix<C>::div(const double val) const
01578 {
01579     return *this/val;
01580 }
01581 
01582 template<class C> HxTMatrix<C> 
01583 HxTMatrix<C>::sin() const
01584 {
01585     return conv<C>(conv<double>(*this).map(::sin));
01586 }
01587 
01588 template<class C> HxTMatrix<C> 
01589 HxTMatrix<C>::cos() const
01590 {
01591     return conv<C>(conv<double>(*this).map(::cos));
01592     //return map(::cos);
01593 }
01594 
01595 template<class C> HxTMatrix<C> 
01596 HxTMatrix<C>::tan() const
01597 {
01598     return conv<C>(conv<double>(*this).map(::tan));
01599     //    return map(::tan);
01600 }
01601 
01602 template<class C> HxTMatrix<C> 
01603 HxTMatrix<C>::sinh() const
01604 {
01605     return conv<C>(conv<double>(*this).map(::sinh));
01606 //    return map(::sinh);
01607 }
01608 
01609 template<class C> HxTMatrix<C> 
01610 HxTMatrix<C>::cosh() const
01611 {
01612     return conv<C>(conv<double>(*this).map(::cosh));
01613 //    return map(::cosh);
01614 }
01615 
01616 template<class C> HxTMatrix<C> 
01617 HxTMatrix<C>::tanh() const
01618 {
01619     return conv<C>(conv<double>(*this).map(::tanh));
01620 //    return map(::tanh);
01621 }
01622 
01623 template<class C> HxTMatrix<C> 
01624 HxTMatrix<C>::exp() const
01625 {
01626     return conv<C>(conv<double>(*this).map(::exp));
01627 //    return map(::exp);
01628 }
01629 
01630 template<class C> HxTMatrix<C> 
01631 HxTMatrix<C>::log() const
01632 {
01633     return conv<C>(conv<double>(*this).map(::log));
01634 //  return map(::log);
01635 }
01636 
01637 template<class C> HxTMatrix<C> 
01638 HxTMatrix<C>::sqrt() const
01639 {
01640     return conv<C>(conv<double>(*this).map(::sqrt));
01641 //    return map(::sqrt);
01642 }
01643 
01644 template<class C> HxTMatrix<C> 
01645 HxTMatrix<C>::abs() const
01646 {
01647     return conv<C>(conv<double>(*this).map(::fabs));
01648 //    return map(::fabs);
01649 }
01650 
01651 template<class C> 
01652 inline C sgn(C a) { return a < 0.0 ? -1.0 : +1.0; }
01653 
01654 template<class C> HxTMatrix<C> 
01655 HxTMatrix<C>::sgn() const
01656 {
01657     return map(::sgn);
01658 }
01659 
01660 
01661 //---------------------------------------------------
01662 //      Larger Operations:
01663 //---------------------------------------------------
01664 
01665 
01666 // ===================== singular value decomposition =====================
01667 
01668 #ifndef PI
01669 #define PI M_PI
01670 #endif
01671 
01672 /*
01673 PYTHAG computes sqrt(a^{2} + b^{2}) without destructive overflow or underflow.
01674 */
01675 static double at, bt, ct;
01676 #define PYTHAG(a, b) ((at = fabs(a)) > (bt = fabs(b)) ? \
01677 (ct = bt/at, at*sqrt(1.0+ct*ct)): (bt ? (ct = at/bt, bt*sqrt(1.0+ct*ct)): 0.0))
01678 
01679 static double maxarg1, maxarg2;
01680 #define MAX(a, b) (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? \
01681 (maxarg1) : (maxarg2))
01682 
01683 static int imaxarg1, imaxarg2;
01684 #define IMIN(a,b)    (imaxarg1=(a),imaxarg2=(b),imaxarg1 > imaxarg2 ? \
01685     imaxarg2 : imaxarg1)
01686 
01687 #define SIGN(a, b) ((b) < 0.0 ? -fabs(a): fabs(a))
01688 
01689 
01690 /*
01691 Given a matrix a[m][n], this routine computes its singular value
01692 decomposition, A = U*W*V^{T}.  The matrix U replaces a on output.
01693 The diagonal matrix of singular values W is output as a vector w[n].
01694 The matrix V (not the transpose V^{T}) is output as v[n][n].
01695 m must be greater or equal to n;  if it is smaller, then a should be
01696 filled up to square with zero rows.
01697 */
01698 
01699 template<class C> 
01700 static void svdcmp(C* a, HxVector &w, C* v, int n, int m)
01701 {
01702     double *rv1 = new double [n];
01703     double g = 0.0;
01704     double scale = 0.0;
01705     double anorm = 0.0;
01706     int l = 0;
01707 
01708     for (int i=0;i<n;i++) {
01709 //      cout << "Don't KILL me yet.. still doing something, " << i << " till " << n << endl;
01710         l=i+1;
01711         rv1[i]=scale*g;
01712         g = 0.0;
01713         scale = 0.0;
01714 
01715         if (i < m) {
01716             for (int k=i;k<m;k++)
01717                 scale += fabs(a[k*n+i]);
01718             if (scale) {
01719                 double s = 0.0;
01720                 for (int k=i;k<m;k++) {
01721                     a[k*n+i] /= scale;
01722                     s += a[k*n+i]*a[k*n+i];
01723                 }
01724 
01725                 double f=a[i*n+i];
01726                 g = -SIGN(sqrt(s),f);
01727 
01728                 double h=f*g-s;
01729                 a[i*n+i]=f-g;
01730 
01731                 for (int j=l;j<n;j++) {
01732                     s = 0.0;
01733                     for (int k=i;k<m;k++)
01734                         s += a[k*n+i]*a[k*n+j];
01735                     f=s/h;
01736                     for (k=i;k<m;k++)
01737                         a[k*n+j] += f*a[k*n+i];
01738                 }
01739                 for (k=i;k<m;k++)
01740                     a[k*n+i] *= scale;
01741             }
01742         }
01743         w[i]=scale*g;
01744         g = 0.0;
01745         scale = 0.0;
01746         if (i < m && i != n-1) {
01747             for (int k=l;k<n;k++)
01748                 scale += fabs(a[i*n+k]);
01749             if (scale) {
01750                 double s = 0.0;
01751 
01752                 for (int k=l;k<n;k++) {
01753                     a[i*n+k] /= scale;
01754                     s += a[i*n+k]*a[i*n+k];
01755                 }
01756 
01757                 double f=a[i*n+l];
01758                 g = -SIGN(sqrt(s),f);
01759 
01760                 double h=f*g-s;
01761                 a[i*n+l]=f-g;
01762 
01763                 for (k=l;k<n;k++)
01764                     rv1[k]=a[i*n+k]/h;
01765                 for (int j=l;j<m;j++) {
01766                     s = 0.0;
01767                     for (int k=l;k<n;k++)
01768                         s += a[j*n+k]*a[i*n+k];
01769                     for (k=l;k<n;k++)
01770                         a[j*n+k] += s*rv1[k];
01771                 }
01772                 for (k=l;k<n;k++)
01773                     a[i*n+k] *= scale;
01774             }
01775         }
01776         anorm=MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
01777     }
01778     for (i=n-1;i>=0;i--) {
01779         if (i < n-1) {
01780             if (g) {
01781                 for (int j=l;j<n;j++)
01782                     v[j*n+i]=(a[i*n+j]/a[i*n+l])/g;
01783 
01784                 for (j=l;j<n;j++) {
01785                     double s = 0.0;
01786                     for (int k=l;k<n;k++)
01787                         s += a[i*n+k]*v[k*n+j];
01788                     for (k=l;k<n;k++)
01789                         v[k*n+j] += s*v[k*n+i];
01790                 }
01791             }
01792             for (int j=l;j<n;j++)
01793                 v[i*n+j]=v[j*n+i]=0.0;
01794         }
01795         v[i*n+i]=1.0;
01796         g=rv1[i];
01797         l=i;
01798     }
01799     for (i=IMIN(m,n)-1;i>=0;i--) {
01800         l=i+1;
01801         g=w[i];
01802         for (int j=l;j<n;j++)
01803             a[i*n+j]=0.0;
01804         if (g) {
01805             g=1.0/g;
01806             for (int j=l;j<n;j++) {
01807                 double s = 0.0;
01808                 for (int k=l;k<m;k++)
01809                     s += a[k*n+i]*a[k*n+j];
01810 
01811                 double f=(s/a[i*n+i])*g;
01812                 for (k=i;k<m;k++)
01813                     a[k*n+j] += f*a[k*n+i];
01814             }
01815             for (j=i;j<m;j++)
01816                 a[j*n+i] *= g;
01817         }
01818         else
01819             for (int j=i;j<m;j++)
01820                 a[j*n+i]=0.0;
01821         a[i*n+i]++;
01822     }
01823 
01824     for (int k=n-1;k>=0;k--) {
01825         for (int its=1;its<=30;its++) {
01826             int flag=1;
01827             int nm;
01828             double f, h, x, y, z;
01829 
01830             for (l=k;l>=0;l--) {
01831                 nm=l-1;
01832                 if ((double)(fabs(rv1[l])+anorm) == anorm) {
01833                     flag=0;
01834                     break;
01835                 }
01836                 if ((double)(fabs(w[nm])+anorm) == anorm) break;
01837             }
01838 
01839             if (flag) {
01840                 double c = 0.0;
01841                 double s = 1.0;
01842 
01843                 for (int i=l;i<=k;i++) {
01844                     f=s*rv1[i];
01845                     rv1[i]=c*rv1[i];
01846                     if ((double)(fabs(f)+anorm) == anorm) break;
01847                     g=w[i];
01848                     h=PYTHAG(f,g);
01849                     w[i]=h;
01850                     h=1.0/h;
01851                     c=g*h;
01852                     s = -f*h;
01853                     for (int j=0;j<m;j++) {
01854                         y=a[j*n+nm];
01855                         z=a[j*n+i];
01856                         a[j*n+nm]=y*c+z*s;
01857                         a[j*n+i]=z*c-y*s;
01858                     }
01859                 }
01860             }
01861 
01862             z=w[k];
01863             if (l == k) {
01864                 if (z < 0.0) {
01865                     w[k] = -z;
01866                     for (int j=0;j<n;j++) v[j*n+k] = -v[j*n+k];
01867                 }
01868                 break;
01869             }
01870             if (its == 30) {
01871                 delete [] rv1;
01872                 error( "HxMatrix: no convergence in 30 svdcmp iterations");
01873             }
01874             x=w[l];
01875             nm=k-1;
01876             y=w[nm];
01877             g=rv1[nm];
01878             h=rv1[k];
01879             f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
01880             g=PYTHAG(f,1.0);
01881             f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
01882 
01883             double c = 1.0;
01884             double s = 1.0;
01885             for (int j=l;j<=nm;j++) {
01886                 int i=j+1;
01887                 g=rv1[i];
01888                 y=w[i];
01889                 h=s*g;
01890                 g=c*g;
01891                 z=PYTHAG(f,h);
01892                 rv1[j]=z;
01893                 c=f/z;
01894                 s=h/z;
01895                 f=x*c+g*s;
01896                 g=g*c-x*s;
01897                 h=y*s;
01898                 y *= c;
01899                 for (int jj=0;jj<n;jj++) {
01900                     x=v[jj*n+j];
01901                     z=v[jj*n+i];
01902                     v[jj*n+j]=x*c+z*s;
01903                     v[jj*n+i]=z*c-x*s;
01904                 }
01905                 z=PYTHAG(f,h);
01906                 w[j]=z;
01907                 if (z) {
01908                     z=1.0/z;
01909                     c=f*z;
01910                     s=h*z;
01911                 }
01912                 f=c*g+s*y;
01913                 x=c*y-s*g;
01914                 for (jj=0;jj<m;jj++) {
01915                     y=a[jj*n+j];
01916                     z=a[jj*n+i];
01917                     a[jj*n+j]=y*c+z*s;
01918                     a[jj*n+i]=z*c-y*s;
01919                 }
01920             }
01921             rv1[l]=0.0;
01922             rv1[k]=f;
01923             w[k]=x;
01924         }
01925     }
01926 
01927     delete [] rv1;
01928 }
01929 
01930 
01931 
01932 // ===================== matrix inverse =====================
01933 
01934 template<class C> 
01935 static int ludcmp(C* a, int n, short *indx, double *d)
01936 {
01937     double *vv = new double [n];
01938 
01939     *d=1.0;
01940     for (int i=0;i<n;i++) {
01941         double big=0.0;
01942         for (int j=0;j<n;j++) {
01943             double temp = fabs(a[i*n+j]);
01944             if (temp > big)
01945                 big=temp;
01946         }
01947         if (big == 0.0)
01948             return(0); // Singular matrix 
01949         vv[i]=1.0/big;
01950     }
01951     for (int j=0;j<n;j++) {
01952         for (int i=0;i<j;i++) {
01953             double sum=a[i*n+j];
01954             for (int k=0;k<i;k++)
01955                 sum -= a[i*n+k]*a[k*n+j];
01956             a[i*n+j]=sum;
01957         }
01958         double big=0.0;
01959         int imax = 0;
01960         for (i=j;i<n;i++) {
01961             double sum=a[i*n+j];
01962             for (int k=0;k<j;k++)
01963                 sum -= a[i*n+k]*a[k*n+j];
01964             a[i*n+j]=sum;
01965 
01966             double dum = vv[i]*fabs(sum);
01967             if ( dum >= big) {
01968                 big=dum;
01969                 imax=i;
01970             }
01971         }
01972         if (j != imax) {
01973             for (int k=0;k<n;k++) {
01974                 double dum=a[imax*n+k];
01975                 a[imax*n+k]=a[j*n+k];
01976                 a[j*n+k]=dum;
01977             }
01978             *d = -(*d);
01979             vv[imax]=vv[j];
01980         }
01981         indx[j]=imax;
01982         if (a[j*n+j] == 0.0)
01983             a[j*n+j]=HxMatrix_EPS;
01984         if (j != n-1) {
01985             double dum=1.0/a[j*n+j];
01986             for (int i=j+1;i<n;i++)
01987                 a[i*n+j] *= dum;
01988         }
01989     }
01990     delete [] vv;
01991 
01992     return(1);
01993 }
01994 
01995 template<class C> 
01996 static void lubksb(C* a, int n, short *indx, double *b)
01997 {
01998     int ii = -1;
01999 
02000     for (int i=0;i<n;i++) {
02001         int ip=indx[i];
02002         double sum=b[ip];
02003         b[ip]=b[i];
02004         if (ii>=0)
02005             for (int j=ii;j<=i-1;j++)
02006                 sum -= a[i*n+j]*b[j];
02007         else if (sum) ii=i;
02008         b[i]=sum;
02009     }
02010     for (i=n-1;i>=0;i--) {
02011         double sum=b[i];
02012         for (int j=i+1;j<n;j++)
02013             sum -= a[i*n+j]*b[j];
02014         b[i]=sum/a[i*n+i];
02015     }
02016 }
02017 
02018 
02019 // ===================== K-means clustering =====================
02020 
02021 /*
02022  *  K-means clustering algorithm
02023  *  Author(s):
02024  *  Jan van Gemert (jvgemert@science.uva.nl)
02025  *  Hieu T. Nguyen (tat@science.uva.nl)
02026  */
02027 
02028 /*==============================================================================*/
02029 
02030 // calculate vec distance
02031 template<class C>
02032 inline double vec_distance(C* v1, C* v2, int nElem) 
02033 {
02034     double s=0,tmp ;
02035     for(int i=0;i<nElem;i++) 
02036         s += (tmp = v1[i] - v2[i],tmp*tmp);
02037     return sqrt(s);
02038 }
02039 
02040 
02041 // calculate vec distance, given a current minimum
02042 template<class C>
02043 inline double vec_distance(C* v1, C* v2, int nElem, C currentMin) 
02044 {
02045     if(currentMin>0) {
02046         C currentMinSquared = currentMin*currentMin ;
02047         double s=0,tmp ;
02048         int i=0 ;
02049         while(s<currentMinSquared && i<nElem) {
02050                 s += (tmp = v1[i] - v2[i],tmp*tmp);
02051                 i++;
02052         }
02053         return i==nElem?sqrt(s):currentMin ;
02054     }
02055     return currentMin ;
02056 
02057     
02058 }
02059 
02060 
02061 /*==============================================================================*/
02062 
02063 #include<list>
02064 
02065 template<class C> void
02066 HxTMatrix<C>::kmeans(HxTMatrix<C> &c, HxVector &imap, int numloop, bool cIsInitialized) const 
02067 {
02068     int i,j;
02069 
02070     int nrVectors = _nr ; 
02071     int nrDimensions = _nc ;
02072     int nrClusters = c.nRow() ;
02073     //printf("K-means, nrClusters= %d, nr=%d, nc=%d\n", nrClusters, _nr, _nc );
02074 
02075     imap = HxVector(nrVectors) ;
02076     if(!cIsInitialized) {
02077             // the cluster matrix is not initialized, initialize it with some vectors.
02078         c = HxTMatrix<C>(nrClusters,nrDimensions) ;
02079         int steps = nrVectors / nrClusters ;
02080         for(i=0;i<nrClusters;i++) {
02081             for(j=0;j<nrDimensions;j++) {
02082                     c[i][j] = (*this)[i*steps][j] ;
02083             }
02084 
02085 //          printf("cluster %d in data %d \n", i, i*steps);
02086 
02087                 /* start of code to check if this vector did not occur already
02088             int k=0; 
02089             bool occurs = false ;
02090             int index = i * _nc ;
02091             while(k<i && !occurs) {
02092 
02093                 double d = vec_distance(&c._data[k*_nc], &c._data[index], _nc, 0.01); 
02094                 if(d < 0.01) occurs = true ;
02095                 else k++ ;
02096             }
02097 
02098             if(occurs) printf("dist between %d and %d Small !\n",i,k) ;
02099             //*/
02100         }
02101     } 
02102 
02103     // check c matrix dimensions
02104     if(c.nCol() != nrDimensions) {
02105         error( "error kmeans: c matrix does not have similar dimensionality." );
02106         exit(1);
02107     }
02108     
02109     std::list<int> *mylist;
02110     std::list<int>::const_iterator listIter;
02111     bool contin = true;
02112     double err = 0, errOld=0;
02113 
02114     int emptyclust =0 ;
02115     while(contin)
02116     {
02117         emptyclust =0 ;
02118         err=0 ;
02119         contin = false;
02120         // create a list for each cluster vector, and keep the data vectors who 
02121         // belong to a cluster in their corresponding list.
02122         mylist = new std::list<int>[nrClusters];
02123         for(i=0;i<nrVectors;i++)
02124         {
02125             int jm=0;
02126             double d = 0;
02127             int indexI = i*_nc ;
02128             double dm = vec_distance(&_data[indexI],c._data, _nc);
02129             for(j=1;j<nrClusters;j++) {
02130                 d = vec_distance(&_data[indexI], &c._data[j*_nc], _nc, dm); 
02131                 if( d<dm ) { dm = d;jm=j; }
02132             }
02133 //          std::cout << i << " in " << jm << std::endl ;           
02134             mylist[jm].push_back(i);
02135             err += dm;
02136         }
02137         
02138         numloop--;
02139 //      printf("recalculate\n");
02140         // recalculate the position of the cluster vectors, 
02141         // based on the datavectors who belong to the cluster
02142         for(i=0;i<nrClusters;i++) {
02143             if( (mylist[i].size()) > 0 )
02144             {
02145                 for(j=0;j<nrDimensions;j++) c[i][j] = 0;
02146 
02147                 std::list<int>::const_iterator myListEnd = mylist[i].end() ;
02148                 for(listIter = mylist[i].begin(); listIter!=myListEnd;listIter++)
02149                     for(j=0;j<nrDimensions;j++) 
02150                         c[i][j] += (*this)[*listIter][j];
02151 
02152                 for(j=0;j<nrDimensions;j++) c[i][j] /= mylist[i].size();
02153             }
02154             else { 
02155                 emptyclust++ ;
02156                 printf("empty cluster: %d\n",i);
02157             }
02158         }
02159 
02160         //printf("loop %d dist=%f, distOld=%f, emptyClusters: %d\n",numloop, err, errOld, emptyclust);
02161 //      printf("%d, ",numloop);
02162         // quit if the numLoops is reached or if the error stays constant
02163         if(err != errOld && numloop>0) contin = true;
02164 
02165         errOld = err;
02166 
02167     } // end while(contin)
02168 
02169     printf("\n");
02170     // for each data vector, store the cluster it belongs to in vector imap
02171     int filledClusters = 0 ;
02172     for(i=0;i<nrClusters;i++) 
02173         if(!mylist[i].empty())  {
02174             for(listIter= mylist[i].begin();listIter!=mylist[i].end();listIter++)
02175                 imap[*listIter] = filledClusters; 
02176             filledClusters++ ;
02177         }
02178 
02179     // if there are empty clusters, remove them.
02180     if(emptyclust > 0 ) {
02181         printf("removing empty clusters: new clustersize = %d = %d",nrClusters-emptyclust,filledClusters);  
02182         int counter=0 ;
02183         HxTMatrix<C> tmpC(nrClusters-emptyclust, nrDimensions) ;
02184     
02185         // copy filled clusters to a temp. matrix
02186         for(i=0;i<nrClusters;i++) 
02187             if(!mylist[i].empty()) { 
02188                 for(j=0;j<nrDimensions;j++) tmpC[counter][j] = c[i][j];
02189                 counter++ ;
02190             }
02191         c = tmpC ;
02192     }
02193 
02194     delete[] mylist;
02195 
02196 }
02197 
02198 
02199 // ===================== covariance matrix =====================
02200 /*
02201  *  covariance matrix
02202  *  Author(s):
02203  *  Minh A. Hoang (minh@science.uva.nl)
02204  *  Jan van Gemert (jvgemert@science.uva.nl)
02205  * Compute the covariance matrix of the observed data
02206  * Output: [nc x nc] covariance matrix and a vector of mean-values for each dimension.
02207  */
02208 
02209 template<class C> HxTMatrix<C> 
02210 HxTMatrix<C>::covariance(HxVector &mean) const 
02211 {
02212 //  printf("Calculating the covariance matrix...");
02213     int i,j,k;
02214 
02215     HxTMatrix<C> COVxy(_nc,_nc, 0.0) ;
02216 
02217     mean = HxVector(_nc) ; //means
02218     for (i=0; i<_nc; i++) mean[i] = 0;
02219 
02220     for (k=0; k<_nr; k++)
02221         for (i=0; i<_nc; i++) {
02222             mean[i] += (*this)[k][i];
02223             for (j=i; j<_nc; j++)
02224                 COVxy[i][j] += ((*this)[k][i] * (*this)[k][j]) ;
02225         }
02226 
02227     for (i=0; i<_nc; i++) mean[i] /= _nr;
02228 
02229     for (i=0; i<_nc; i++)
02230         for (j=i; j<_nc; j++) {
02231             COVxy[i][j] = COVxy[i][j]/_nr - mean[i]*mean[j];
02232             COVxy[j][i] = COVxy[i][j];
02233         }
02234 
02235 //  printf("...done\n");
02236     return COVxy;
02237 }
02238 
02239 
02240 // ===================== Karhunen Loeve mapping (PCA) =====================
02241 /*
02242  *  Karhunen Loeve mapping (PCA)
02243  *  Author(s):
02244  *  Minh A. Hoang (minh@science.uva.nl)
02245  *  Jan van Gemert (jvgemert@science.uva.nl)
02246  *  Principal Componant Analysis to reduce matrix to newDim dimensions
02247  */
02248 
02249 // KLM helping functions
02250 
02251 /*
02252  Householder reduction of a real, symmetric matrix a[0..n-1][0..n-1]
02253  Output: a is replaced by the orthogonal matrix Q effecting the
02254  transformation. d[0..n-1] returns the diagonal elements of the
02255  tridiagonal matrix, and e[0..n-1] the off-diagonal elements, with e[0]=0;
02256  */
02257 template<class C> 
02258 void tred2(HxTMatrix<C> &a, HxVector &d, HxVector &e)
02259 {
02260     int i,j,k,l;
02261     double scale,hh,h,g,f;
02262 
02263     int n = d.nElem() ;
02264 
02265     for (i=n-1; i>0; i--)
02266     {
02267         l = i-1;
02268         h = scale = 0.0;
02269         if (l>0)
02270         {
02271             for (k=0; k<=l; k++) scale += fabs(a[i][k]);
02272             if (scale == 0.0) e[i] = a[i][l];
02273             else
02274             {
02275                 for (k=0; k<=l; k++)
02276                 {
02277                     a[i][k] /= scale; //use scale a's for transformation
02278                     h += a[i][k]*a[i][k];
02279                 }
02280                 f = a[i][l];
02281                 g = (f >=0.0 ? -sqrt(h) : sqrt(h));
02282                 e[i] = scale*g;
02283                 h -= f*g;
02284                 a[i][l] = f-g;
02285                 f = 0.0;
02286                 for (j=0; j<=l; j++)
02287                 {
02288                     a[j][i] = a[i][j]/h;
02289                     g = 0.0;
02290                     for (k=0; k<=j; k++) g += a[j][k]*a[i][k];
02291                     for (k=j+1; k<=l; k++) g += a[k][j]*a[i][k];
02292                     e[j] = g/h; //form element of p in temporarily unused element of e
02293                     f += e[j]*a[i][j];
02294                 }
02295                 hh = f/(h+h);
02296                 for (j=0; j<=l; j++)
02297                 {
02298                     f = a[i][j];
02299                     e[j] = g = e[j]-hh*f;
02300                     for (k=0; k<=j; k++) a[j][k] -= (f*e[k]+g*a[i][k]);
02301                 }
02302             }
02303         }
02304         else e[i] = a[i][l];
02305         d[i] = h;
02306     }
02307 
02308     d[0] = 0.0;
02309     e[0] = 0.0;
02310 
02311     for (i=0; i<n; i++)
02312     {
02313         l = i-1;
02314         if (d[i])
02315         {
02316             for (j=0; j<=l; j++)
02317             {
02318                 g = 0.0;
02319                 for (k=0; k<=l; k++) g += a[i][k]*a[k][j];
02320                 for (k=0; k<=l; k++) a[k][j] -= g*a[k][i];
02321             }
02322         }
02323         d[i] = a[i][i];
02324         a[i][i] = 1.0;
02325         for (j=0; j<=l; j++) a[j][i] = a[i][j] = 0.0;
02326     }
02327 
02328 }
02329 
02330 /*
02331  QL algorithm with implicit shifts, to determin the eigenvalues and eigenvectors
02332  of a real, symetric, tridiagonal matrix, of of a real, symmetric matrix previously
02333  reduced by tred2
02334  Input: d[0..n-1] contains the diagonal elements of the tridiagonal matrix
02335  e[0..n-1] inputs the subdiagonal elements of the tridiagonal matrix with e[0] arbitrary
02336  Output: d returns the eigenvalues, e is destroyed.
02337  If the eigenvectors of a tridiagonal matrix are desired, the matrix z[0..n-1][0..n-1]
02338  is input as the identity matrix. If the eigenvectors of a matrix that has been reduced
02339  by tred2 are required, then z is input as the matrix output by tred2.
02340  In either case, the kth column of z returns the normalized eigenvector corresponding to d[k]
02341  */
02342 template<class C> 
02343 void tqli(HxVector &d, HxVector &e, HxTMatrix<C> &z)
02344 {
02345 
02346     int m,l,iter,i,k;
02347     double s,r,p,g,f,dd,c,b;
02348 
02349     int n = e.nElem() ;
02350 
02351     for (i=1; i<n; i++) e[i-1]=e[i]; //renumber
02352     e[n-1] = 0.0;
02353 
02354 
02355     for (l=0; l<n; l++)
02356     {
02357         iter=0;
02358         do
02359         {
02360             for (m=l; m<n-1; m++)
02361             {
02362                 dd = fabs(d[m]) + fabs(d[m+1]);
02363                 if ( (fabs(e[m]) + dd) == dd) break;
02364             }
02365             if (m != l)
02366             {
02367                 if (iter++ == 30) printf("Too many iterations in tqli\n");
02368                 g = (d[l+1]-d[l])/(2.0*e[l]);
02369                 r = sqrt(g*g + 1.0);//=pythag(g,1.0);
02370                 g = d[m] - d[l] + e[l]/(g+SIGN(r,g));
02371                 s = c = 1.0;
02372                 p = 0.0;
02373                 for (i=m-1; i>=l; i--)
02374                 {
02375                     f = s*e[i];
02376                     b = c*e[i];
02377                     e[i+1] = (r=sqrt(f*f+g*g));//=(r=pythag(f,g));
02378                     if (r == 0.0)
02379                     {
02380                         d[i+1] -= p;
02381                         e[m] = 0.0;
02382                         break;
02383                     }
02384                     s = f/r;
02385                     c = g/r;
02386                     g = d[i+1]-p;
02387                     r = (d[i]-g)*s + 2.0*c*b;
02388                     d[i+1] = g+(p=s*r);
02389                     g = c*r-b;
02390 
02391                     for (k=0; k<n; k++)
02392                     {
02393                         f = z[k][i+1];
02394                         z[k][i+1] = s*z[k][i] + c*f;
02395                         z[k][i] = c*z[k][i] - s*f;
02396                     }
02397                 }
02398                 if (r==0.0 && i>=l) continue;
02399                 d[l] -= p;
02400                 e[l] = g;
02401                 e[m] = 0.0;
02402             }
02403         } while (m != l);
02404     }
02405 
02406     //eigenvalues d[0..n-1], eigenvectors z[0..n-1][0..n-1], sort them now
02407     int j;
02408     for (i=0; i<n-1; i++)
02409     {
02410         p = d[k=i];
02411         for (j=i+1; j<n; j++) if (d[j]>=p) p = d[k=j];
02412         if (k!=i) { //insert
02413             d[k] = d[i];
02414             d[i] = p;
02415             //exchange corresponding eigenvectors
02416             for (j=0; j<n; j++)
02417             {
02418                 p = z[j][i];
02419                 z[j][i] = z[j][k];
02420                 z[j][k] = p;
02421             }
02422         }
02423     }
02424 }
02425 
02426 
02427 //  Karhunen Loeve mapping (PCA)
02428 
02429 
02430 template<class C> HxTMatrix<C> 
02431 HxTMatrix<C>::klm(int newDim) const
02432 {
02433     if (newDim<1 || newDim>_nc)
02434     {
02435         printf("klm: new dimensionality is invalid, dimsize is set as 1...\n");
02436         newDim = 1;
02437     }
02438 
02439     HxTMatrix<C> newfvec(_nr,newDim);
02440 
02441     HxTMatrix<C> a = this->covariance() ;
02442 
02443     HxVector d(_nc) ;
02444 
02445     HxVector e(_nc) ;
02446 
02447     tred2(a,d,e);
02448 
02449     tqli(d,e,a);
02450 
02451     // d[k] is an eigenvalue and a[][k] is a corresponding eigenvector
02452 
02453     for (int k=0; k<_nr; k++)
02454         for (int i=0; i<newDim; i++) {
02455             double vl = 0.0;
02456             for (int j=0; j<_nc; j++) vl += ((*this)[k][j]*a[j][i]);
02457             newfvec[k][i] = vl;
02458         }
02459 
02460     return newfvec;
02461 }
02462 
02463 
02464 
02465 #endif

Generated on Tue Feb 3 14:18:39 2004 for C++Reference by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001