00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00061
00062
00063
00065
00066
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;
00353 int _nc;
00354 C* _data;
00355
00356 };
00357
00358
00359
00360 L_HXBASIS typedef HxTMatrix<double> HxMatrix ;
00361
00362
00363
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
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) {
00450
00451 fp = fopen(fileName.c_str(), "rb") ;
00452
00453
00454 fread(&_nr, sizeof(int), 1, fp) ;
00455 fread(&_nc, sizeof(int), 1, fp) ;
00456
00457 _data = new C[_nr * _nc];
00458
00459
00460 fread(_data,sizeof(C),_nr*_nc,fp) ;
00461
00462 }
00463 else {
00464
00465 fp = fopen(fileName.c_str(), "r") ;
00466
00467
00468 fscanf(fp, "%d %d", &_nr, &_nc);
00469
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
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
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
00528
00529
00530
00531
00532
00533 return tmp;
00534
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
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
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 {
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 {
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
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
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
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
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
00951 C* u = _data;
00952 int i = 0;
00953 while (i < _nc)
00954 *u++ = v[i++];
00955 }
00956
00957
00958
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
00969
00970
00971
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)
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
00997
00998
00999
01000
01001 return m;
01002 }
01003
01004 template<class C> HxTMatrix<C>
01005 HxTMatrix<C>::rotate2dDeg(double alpha)
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
01030
01031
01032
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
01046
01047
01048
01049
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)
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
01074
01075
01076
01077
01078
01079 return m;
01080 }
01081
01082 template<class C> HxTMatrix<C>
01083 HxTMatrix<C>::rotateX3dDeg(double alpha)
01084 {
01085 return rotateX3d(M_PI*alpha/180.0);
01086 }
01087
01088 template<class C> HxTMatrix<C>
01089 HxTMatrix<C>::rotateY3d(double alpha)
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
01098
01099
01100
01101
01102
01103 return m;
01104 }
01105
01106 template<class C> HxTMatrix<C>
01107 HxTMatrix<C>::rotateY3dDeg(double alpha)
01108 {
01109 return rotateY3d(M_PI*alpha/180.0);
01110 }
01111
01112 template<class C> HxTMatrix<C>
01113 HxTMatrix<C>::rotateZ3d(double alpha)
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
01121
01122
01123
01124
01125
01126 return m;
01127 }
01128
01129 template<class C> HxTMatrix<C>
01130 HxTMatrix<C>::rotateZ3dDeg(double alpha)
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
01158
01159
01160
01161
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
01174
01175
01176
01177
01178
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
01192
01193
01194
01195
01196
01197 return m;
01198 }
01199
01200
01201
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
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
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
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
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
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) {
01395
01396 fp = fopen(fileName.c_str(), "wb") ;
01397
01398
01399 fwrite(&_nr, sizeof(int), 1, fp) ;
01400 fwrite(&_nc, sizeof(int), 1, fp) ;
01401
01402
01403 fwrite(_data,sizeof(C),_nr*_nc,fp) ;
01404
01405 }
01406 else {
01407
01408 fp = fopen(fileName.c_str(), "w") ;
01409
01410
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
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
01593 }
01594
01595 template<class C> HxTMatrix<C>
01596 HxTMatrix<C>::tan() const
01597 {
01598 return conv<C>(conv<double>(*this).map(::tan));
01599
01600 }
01601
01602 template<class C> HxTMatrix<C>
01603 HxTMatrix<C>::sinh() const
01604 {
01605 return conv<C>(conv<double>(*this).map(::sinh));
01606
01607 }
01608
01609 template<class C> HxTMatrix<C>
01610 HxTMatrix<C>::cosh() const
01611 {
01612 return conv<C>(conv<double>(*this).map(::cosh));
01613
01614 }
01615
01616 template<class C> HxTMatrix<C>
01617 HxTMatrix<C>::tanh() const
01618 {
01619 return conv<C>(conv<double>(*this).map(::tanh));
01620
01621 }
01622
01623 template<class C> HxTMatrix<C>
01624 HxTMatrix<C>::exp() const
01625 {
01626 return conv<C>(conv<double>(*this).map(::exp));
01627
01628 }
01629
01630 template<class C> HxTMatrix<C>
01631 HxTMatrix<C>::log() const
01632 {
01633 return conv<C>(conv<double>(*this).map(::log));
01634
01635 }
01636
01637 template<class C> HxTMatrix<C>
01638 HxTMatrix<C>::sqrt() const
01639 {
01640 return conv<C>(conv<double>(*this).map(::sqrt));
01641
01642 }
01643
01644 template<class C> HxTMatrix<C>
01645 HxTMatrix<C>::abs() const
01646 {
01647 return conv<C>(conv<double>(*this).map(::fabs));
01648
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
01663
01664
01665
01666
01667
01668 #ifndef PI
01669 #define PI M_PI
01670 #endif
01671
01672
01673
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
01692
01693
01694
01695
01696
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
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
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);
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
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
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
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
02074
02075 imap = HxVector(nrVectors) ;
02076 if(!cIsInitialized) {
02077
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
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100 }
02101 }
02102
02103
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
02121
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
02134 mylist[jm].push_back(i);
02135 err += dm;
02136 }
02137
02138 numloop--;
02139
02140
02141
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
02161
02162
02163 if(err != errOld && numloop>0) contin = true;
02164
02165 errOld = err;
02166
02167 }
02168
02169 printf("\n");
02170
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
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
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
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209 template<class C> HxTMatrix<C>
02210 HxTMatrix<C>::covariance(HxVector &mean) const
02211 {
02212
02213 int i,j,k;
02214
02215 HxTMatrix<C> COVxy(_nc,_nc, 0.0) ;
02216
02217 mean = HxVector(_nc) ;
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
02236 return COVxy;
02237 }
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
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;
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;
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
02332
02333
02334
02335
02336
02337
02338
02339
02340
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];
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);
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));
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
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) {
02413 d[k] = d[i];
02414 d[i] = p;
02415
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
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
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