00001 #ifndef Impala_Core_Matrix_Matrix_h
00002 #define Impala_Core_Matrix_Matrix_h
00003
00004 #include <iostream>
00005 #include "Core/Array/Element/ArithTypes.h"
00006 #include "Core/Vector/VectorTem.h"
00007
00008 namespace Impala
00009 {
00010 namespace Core
00011 {
00012 namespace Matrix
00013 {
00014
00015 using namespace Impala::Core::Vector;
00016
00017
00023 template<class C>
00024 class MatrixTem {
00025 public:
00026
00029
00031 MatrixTem()
00032 {
00033 _nr = 0;
00034 _nc = 0;
00035 _data = 0;
00036 }
00037
00039 MatrixTem(int nRow, int nCol)
00040 {
00041 _nr = nRow;
00042 _nc = nCol;
00043 _data = new C[_nr * _nc];
00044 }
00045
00047 MatrixTem(int nRow, int nCol, C a)
00048 {
00049 _nr = nRow;
00050 _nc = nCol;
00051 _data = new C[_nr * _nc];
00052
00053 C* t = _data;
00054 int i = nElem();
00055 while (--i >= 0)
00056 *t++ = a;
00057 }
00058
00060 MatrixTem(int nRow, int nCol, C* data)
00061 {
00062 _nr = nRow;
00063 _nc = nCol;
00064 _data = data;
00065 }
00066
00068 MatrixTem(const MatrixTem &m)
00069 {
00070 _nr = m.nRow();
00071 _nc = m.nCol();
00072 _data = new C[_nr * _nc];
00073
00074 C* t = m._data;
00075 C* u = _data;
00076 int i = m.nElem();
00077 while (--i >= 0)
00078 *u++ = *t++;
00079 }
00080
00082
00083
00085
00086
00087 ~MatrixTem()
00088 {
00089
00090 }
00091
00094
00096 int
00097 nRow() const
00098 {
00099 return _nr;
00100 }
00101
00103 int
00104 nCol() const
00105 {
00106 return _nc;
00107 }
00108
00110 int
00111 nElem() const
00112 {
00113 return _nr * _nc;
00114 }
00115
00117 int
00118 valid() const
00119 {
00120 return ((_nc != 0) && (_nr != 0));
00121 }
00122
00123
00124 C*
00125 dataPtr() const
00126 {
00127 return _data;
00128 }
00129
00131
00134
00135
00137 MatrixTem<C>&
00138 operator=(const MatrixTem<C>& m)
00139 {
00140 if (this != &m) {
00141 delete [] _data;
00142 _nr = m.nRow();
00143 _nc = m.nCol();
00144 _data = new C [_nr * _nc];
00145 C *t = _data;
00146 C *u = m._data;
00147 int i = m.nElem();
00148 while (--i >= 0)
00149 *t++ = *u++;
00150 }
00151 return *this;
00152 }
00153
00155 C*
00156 operator[](int i) const
00157 {
00158 return &_data[i*_nc];
00159 }
00160
00162 MatrixTem<C>
00163 operator*(double val) const
00164 {
00165 MatrixTem<C> m(*this);
00166 C* t = m._data;
00167 int i = nElem();
00168 while (--i >= 0)
00169 *t++ = *t * val ;
00170 return m;
00171 }
00172
00174 MatrixTem<C>
00175 operator*(const MatrixTem<C>& a) const
00176 {
00177 if (nCol() != a.nRow()) {
00178 std::cerr << "nonconformant MatrixTem * MatrixTem operands."
00179 << std::endl;
00180 return MatrixTem<C>(0,0);
00181 }
00182 MatrixTem<C> m((*this).nRow(), a.nCol(), 0.0);
00183 double sum;
00184 int i, j, k;
00185 for (i=0 ; i<nRow() ; i++) {
00186 for (j=0 ; j<a.nCol() ; j++) {
00187 sum = 0;
00188 for (k=0 ; k<nCol() ; k++)
00189 sum += (*this)[i][k] * a[k][j];
00190 m[i][j] = sum;
00191 }
00192 }
00193 return m;
00194 }
00195
00197 template<class CC>
00198 friend VectorTem<CC>
00199 operator*(const VectorTem<CC>& , const MatrixTem<CC>& );
00200
00202 template<class CC>
00203 friend VectorTem<CC>
00204 operator*(const MatrixTem<CC>& , const VectorTem<CC>& );
00205
00207 MatrixTem<C>
00208 operator+(const MatrixTem<C>& a) const
00209 {
00210 if ((a.nCol() != nCol()) || (a.nRow() != nRow()) ) {
00211 std::cerr << "nonconformant MatrixTem + MatrixTem operands." << std::endl;
00212 return MatrixTem<C>(0,0);
00213 }
00214 MatrixTem<C> m(nRow(), nCol());
00215 int i, j;
00216 for (i=0 ; i<nRow() ; i++) {
00217 for (j=0 ; j<nCol() ; j++)
00218 m[i][j] = a[i][j] + (*this)[i][j];
00219 }
00220 return m;
00221 }
00222
00224 MatrixTem<C> operator+(double val) const
00225 {
00226
00227 MatrixTem<C> m(*this);
00228 C* t = m._data;
00229 int i = nElem();
00230 while (--i >= 0)
00231 *t++ = val + *t;
00232 return m;
00233 }
00234
00236
00239
00240 VectorTem<C>
00241 getRow(long r) const
00242 {
00243
00244 if(r>= _nr || r<0){
00245 std::cerr << "getRow: rownr exceeded the number of rows in MatrixTem."
00246 << std::endl;
00247 return VectorTem<C>(0);
00248 }
00249
00250 VectorTem<C> tmp(_nc);
00251
00252 for(int i = 0; i<_nc; i++)
00253 tmp[i] = (*this)[r][i] ;
00254
00255 return tmp ;
00256 }
00257
00258 VectorTem<C>
00259 getCol(long c) const
00260 {
00261
00262 if(c>= _nc || c<0){
00263 std::cerr << "getCol: Colnr exceeded number of columns in MatrixTem."
00264 << std::endl;
00265 return VectorTem<C>(0);
00266 }
00267
00268 VectorTem<C> tmp(_nr);
00269 for(int i = 0; i<_nr; i++)
00270 {
00271 tmp[i] = (*this)[i][c] ;
00272 }
00273 return tmp;
00274
00275 }
00276
00277
00278 MatrixTem<C>
00279 setRow(long r, VectorTem<C> v, bool makeCopy = false)
00280 {
00281
00282 if(r>= _nr || r<0){
00283 std::cerr << "setRow: rownr exceeded the number of rows in MatrixTem."
00284 << std::endl;
00285 return MatrixTem<C>(0,0) ;
00286 }
00287 if(_nc != v.Size()){
00288 std::cerr << "setRow: v.nElem not equal to matrix dimension" << std::endl;
00289 return MatrixTem<C>(0,0) ;
00290 }
00291
00292 MatrixTem<C> tmp(0,0);
00293
00294 if(makeCopy) {
00295
00296 tmp = MatrixTem<C>(_nr,_nc);
00297
00298 for(int row = 0; row<_nr; row++)
00299 for(int col = 0; col<_nc; col++)
00300 if(row!=r) tmp[row][col] = (*this)[row][col] ;
00301 else tmp[row][col] = v[col] ;
00302 }
00303 else {
00304
00305 for(int col = 0; col<_nc; col++)
00306 (*this)[r][col] = v[col] ;
00307 }
00308
00309
00310 return tmp;
00311
00312 }
00313
00314 MatrixTem<C>
00315 setCol(long c, VectorTem<C> v, bool makeCopy = false)
00316 {
00317
00318 if(c>= _nc || c<0){
00319 std::cerr << "setCol: Colnr exceeded number of columns in MatrixTem."
00320 << std::endl;
00321 return MatrixTem<C>(0,0) ;
00322 }
00323 if(_nr != v.Size()){
00324 std::cerr << "setCol: v.nElem not equal to matrix dimension" << std::endl;
00325 return MatrixTem<C>(0,0) ;
00326 }
00327
00328 MatrixTem<C> tmp(0,0);
00329
00330 if(makeCopy) {
00331
00332 tmp = MatrixTem<C>(_nr,_nc);
00333
00334 for(int row = 0; row<_nr; row++)
00335 for(int col = 0; col<_nc; col++)
00336 if(col!=c) tmp[row][col] = (*this)[row][col] ;
00337 else tmp[row][col] = v[row] ;
00338 }
00339 else {
00340
00341 for(int row = 0; row<_nr; row++)
00342 (*this)[row][c] = v[row] ;
00343 }
00344
00345 return tmp;
00346
00347 }
00348
00350 MatrixTem<C> i() const;
00351
00352 MatrixTem<C>
00353 t() const
00354 {
00355 MatrixTem<C> m(nCol(), nRow());
00356 int i, j;
00357 for (i=0 ; i<nRow() ; i++)
00358 for (j=0 ; j<nCol() ; j++)
00359 m[j][i] = (*this)[i][j];
00360 return m;
00361 }
00362
00363
00365 MatrixTem<C>
00366 covariance(VectorTem<C> &mean) const ;
00367
00371 MatrixTem<C>
00372 svd(VectorTem<C>& W, MatrixTem<C>& V) const;
00373
00377 MatrixTem<C>
00378 klm(int newDim) const;
00379
00381
00382
00383 friend class VectorTem<C>;
00384
00385 int _nr;
00386 int _nc;
00387 C* _data;
00388
00389 };
00390
00391
00392
00393
00394 template<class C>
00395 inline VectorTem<C>
00396 operator*(const VectorTem<C> &a, const MatrixTem<C> &b)
00397 {
00398 if (a.Size() != b.nRow()) {
00399 std::cerr << "nonconformant VectorTem<C> * MatrixTem operands." << std::endl;
00400 return VectorTem<C>(0);
00401 }
00402 VectorTem<C> v(b.nCol());
00403 double sum;
00404 int i, j;
00405 for (i=0 ; i<b.nCol() ; i++) {
00406 sum = 0;
00407 for (j=0 ; j<b.nRow() ; j++)
00408 sum += a[j] * b[j][i];
00409 v[i] = sum;
00410 }
00411 return v;
00412 }
00413
00414
00415 template<class C>
00416 inline VectorTem<C>
00417 operator*(const MatrixTem<C> &a, const VectorTem<C> &b)
00418 {
00419 if (b.Size() != a.nCol()) {
00420 std::cerr << "nonconformant MatrixTem * VectorTem<C> operands." << std::endl;
00421 return VectorTem<C>(0);
00422 }
00423 VectorTem<C> v(a.nRow());
00424 double sum;
00425 int i, j;
00426 for (i=0 ; i<a.nRow() ; i++) {
00427 sum = 0;
00428 for (j=0 ; j<a.nCol() ; j++)
00429 sum += a[i][j] * b[j];
00430 v[i] = sum;
00431 }
00432 return v;
00433 }
00434
00435
00436 template<class C>
00437 static void svdcmp(C* a, VectorTem<C> &w, C* v, int n, int m);
00438
00439 template<class C>
00440 static int ludcmp(C* a, int n, short *indx, double *d);
00441
00442 template<class C>
00443 static void lubksb(C* a, int n, short *indx, double *b);
00444
00445 template<class C> MatrixTem<C>
00446 MatrixTem<C>::i() const
00447 {
00448 if (nRow() != nCol()) {
00449 std::cerr << "Inverse: matrix is not square!." << std::endl;
00450 return MatrixTem<C>(0, 0);
00451 }
00452
00453 int size = nRow();
00454 MatrixTem<C> m(size,size), tmp(*this);
00455 short* idx = new short [size];
00456 double d;
00457
00458 if (!ludcmp(tmp._data, size, idx, &d)) {
00459 std::cerr << "Inverse: singular matrix can't be inverted." << std::endl;
00460 delete [] idx;
00461 return MatrixTem<C>(0,0);
00462 }
00463
00464 double * res = new double [size];
00465
00466 for (int j = 0; j < size; j++) {
00467 for (int i = 0; i < size; i++)
00468 res[i] = 0.0;
00469 res[j] = 1.0;
00470 lubksb(tmp._data, size, idx, res);
00471 for (int i = 0; i < size; i++)
00472 m[i][j] = res[i];
00473 }
00474
00475 delete [] res;
00476 delete [] idx;
00477
00478 return m;
00479 }
00480
00481 #ifndef HxMatrix_EPS_DEF
00482 #define HxMatrix_EPS_DEF
00483 const double HxMatrix_EPS = 1e-12;
00484 #endif
00485
00486
00487
00488 template<class C>
00489 static int ludcmp(C* a, int n, short *indx, double *d)
00490 {
00491 double *vv = new double [n];
00492
00493 *d=1.0;
00494 int i, j, k;
00495 for ( i=0;i<n;i++) {
00496 double big=0.0;
00497 for (j=0;j<n;j++) {
00498 double temp = fabs(a[i*n+j]);
00499 if (temp > big)
00500 big=temp;
00501 }
00502 if (big == 0.0)
00503 return(0);
00504 vv[i]=1.0/big;
00505 }
00506 for (j=0;j<n;j++) {
00507 for (i=0;i<j;i++) {
00508 double sum=a[i*n+j];
00509 for (k=0;k<i;k++)
00510 sum -= a[i*n+k]*a[k*n+j];
00511 a[i*n+j]=sum;
00512 }
00513 double big=0.0;
00514 int imax = 0;
00515 for (i=j;i<n;i++) {
00516 double sum=a[i*n+j];
00517 for (k=0;k<j;k++)
00518 sum -= a[i*n+k]*a[k*n+j];
00519 a[i*n+j]=sum;
00520
00521 double dum = vv[i]*fabs(sum);
00522 if ( dum >= big) {
00523 big=dum;
00524 imax=i;
00525 }
00526 }
00527 if (j != imax) {
00528 for (k=0;k<n;k++) {
00529 double dum=a[imax*n+k];
00530 a[imax*n+k]=a[j*n+k];
00531 a[j*n+k]=dum;
00532 }
00533 *d = -(*d);
00534 vv[imax]=vv[j];
00535 }
00536 indx[j]=imax;
00537 if (a[j*n+j] == 0.0)
00538 a[j*n+j]=HxMatrix_EPS;
00539 if (j != n-1) {
00540 double dum=1.0/a[j*n+j];
00541 for (i=j+1;i<n;i++)
00542 a[i*n+j] *= dum;
00543 }
00544 }
00545 delete [] vv;
00546
00547 return(1);
00548 }
00549
00550 template<class C>
00551 static void lubksb(C* a, int n, short *indx, double *b)
00552 {
00553 int ii = -1;
00554
00555 int i;
00556 for (i=0;i<n;i++) {
00557 int ip=indx[i];
00558 double sum=b[ip];
00559 b[ip]=b[i];
00560 if (ii>=0)
00561 for (int j=ii;j<=i-1;j++)
00562 sum -= a[i*n+j]*b[j];
00563 else if (sum) ii=i;
00564 b[i]=sum;
00565 }
00566 for (i=n-1;i>=0;i--) {
00567 double sum=b[i];
00568 for (int j=i+1;j<n;j++)
00569 sum -= a[i*n+j]*b[j];
00570 b[i]=sum/a[i*n+i];
00571 }
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 template<class C> MatrixTem<C>
00588 MatrixTem<C>::covariance(VectorTem<C> &mean) const
00589 {
00590
00591 int i,j,k;
00592
00593 MatrixTem<C> COVxy(_nc,_nc, 0.0) ;
00594
00595 mean = VectorTem<C>(_nc) ;
00596 for (i=0; i<_nc; i++) mean[i] = 0;
00597
00598 for (k=0; k<_nr; k++)
00599 for (i=0; i<_nc; i++) {
00600 mean[i] += (*this)[k][i];
00601 for (j=i; j<_nc; j++)
00602 COVxy[i][j] += ((*this)[k][i] * (*this)[k][j]) ;
00603 }
00604
00605 for (i=0; i<_nc; i++) mean[i] /= _nr;
00606
00607 for (i=0; i<_nc; i++)
00608 for (j=i; j<_nc; j++) {
00609 COVxy[i][j] = COVxy[i][j]/_nr - mean[i]*mean[j];
00610 COVxy[j][i] = COVxy[i][j];
00611 }
00612
00613
00614 return COVxy;
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 template<class C>
00636 void tred2(MatrixTem<C> &a, VectorTem<C> &d, VectorTem<C> &e)
00637 {
00638 int i,j,k,l;
00639 double scale,hh,h,g,f;
00640
00641 int n = d.Size() ;
00642
00643 for (i=n-1; i>0; i--)
00644 {
00645 l = i-1;
00646 h = scale = 0.0;
00647 if (l>0)
00648 {
00649 for (k=0; k<=l; k++) scale += fabs(a[i][k]);
00650 if (scale == 0.0) e[i] = a[i][l];
00651 else
00652 {
00653 for (k=0; k<=l; k++)
00654 {
00655 a[i][k] /= scale;
00656 h += a[i][k]*a[i][k];
00657 }
00658 f = a[i][l];
00659 g = (f >=0.0 ? -sqrt(h) : sqrt(h));
00660 e[i] = scale*g;
00661 h -= f*g;
00662 a[i][l] = f-g;
00663 f = 0.0;
00664 for (j=0; j<=l; j++)
00665 {
00666 a[j][i] = a[i][j]/h;
00667 g = 0.0;
00668 for (k=0; k<=j; k++) g += a[j][k]*a[i][k];
00669 for (k=j+1; k<=l; k++) g += a[k][j]*a[i][k];
00670 e[j] = g/h;
00671 f += e[j]*a[i][j];
00672 }
00673 hh = f/(h+h);
00674 for (j=0; j<=l; j++)
00675 {
00676 f = a[i][j];
00677 e[j] = g = e[j]-hh*f;
00678 for (k=0; k<=j; k++) a[j][k] -= (f*e[k]+g*a[i][k]);
00679 }
00680 }
00681 }
00682 else e[i] = a[i][l];
00683 d[i] = h;
00684 }
00685
00686 d[0] = 0.0;
00687 e[0] = 0.0;
00688
00689 for (i=0; i<n; i++)
00690 {
00691 l = i-1;
00692 if (d[i])
00693 {
00694 for (j=0; j<=l; j++)
00695 {
00696 g = 0.0;
00697 for (k=0; k<=l; k++) g += a[i][k]*a[k][j];
00698 for (k=0; k<=l; k++) a[k][j] -= g*a[k][i];
00699 }
00700 }
00701 d[i] = a[i][i];
00702 a[i][i] = 1.0;
00703 for (j=0; j<=l; j++) a[j][i] = a[i][j] = 0.0;
00704 }
00705
00706 }
00707
00708 #define SIGN(a, b) ((b) < 0.0 ? -fabs(a): fabs(a))
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 template<class C>
00723 void tqli(VectorTem<C> &d, VectorTem<C> &e, MatrixTem<C> &z)
00724 {
00725
00726 int m,l,iter,i,k;
00727 double s,r,p,g,f,dd,c,b;
00728
00729 int n = e.Size() ;
00730
00731 for (i=1; i<n; i++) e[i-1]=e[i];
00732 e[n-1] = 0.0;
00733
00734
00735 for (l=0; l<n; l++)
00736 {
00737 iter=0;
00738 do
00739 {
00740 for (m=l; m<n-1; m++)
00741 {
00742 dd = fabs(d[m]) + fabs(d[m+1]);
00743 if ( (fabs(e[m]) + dd) == dd) break;
00744 }
00745 if (m != l)
00746 {
00747 if (iter++ == 30) printf("Too many iterations in tqli\n");
00748 g = (d[l+1]-d[l])/(2.0*e[l]);
00749 r = sqrt(g*g + 1.0);
00750 g = d[m] - d[l] + e[l]/(g+SIGN(r,g));
00751 s = c = 1.0;
00752 p = 0.0;
00753 for (i=m-1; i>=l; i--)
00754 {
00755 f = s*e[i];
00756 b = c*e[i];
00757 e[i+1] = (r=sqrt(f*f+g*g));
00758 if (r == 0.0)
00759 {
00760 d[i+1] -= p;
00761 e[m] = 0.0;
00762 break;
00763 }
00764 s = f/r;
00765 c = g/r;
00766 g = d[i+1]-p;
00767 r = (d[i]-g)*s + 2.0*c*b;
00768 d[i+1] = g+(p=s*r);
00769 g = c*r-b;
00770
00771 for (k=0; k<n; k++)
00772 {
00773 f = z[k][i+1];
00774 z[k][i+1] = s*z[k][i] + c*f;
00775 z[k][i] = c*z[k][i] - s*f;
00776 }
00777 }
00778 if (r==0.0 && i>=l) continue;
00779 d[l] -= p;
00780 e[l] = g;
00781 e[m] = 0.0;
00782 }
00783 } while (m != l);
00784 }
00785
00786
00787 int j;
00788 for (i=0; i<n-1; i++)
00789 {
00790 p = d[k=i];
00791 for (j=i+1; j<n; j++) if (d[j]>=p) p = d[k=j];
00792 if (k!=i) {
00793 d[k] = d[i];
00794 d[i] = p;
00795
00796 for (j=0; j<n; j++)
00797 {
00798 p = z[j][i];
00799 z[j][i] = z[j][k];
00800 z[j][k] = p;
00801 }
00802 }
00803 }
00804 }
00805
00806
00807
00808
00809
00810 template<class C> MatrixTem<C>
00811 MatrixTem<C>::klm(int newDim) const
00812 {
00813 printf("fix this function (MatrixTem::klm) before use\n");
00814 if (newDim<1 || newDim>_nc)
00815 {
00816 printf("klm: new dimensionality is invalid, dimsize is set as 1...\n");
00817 newDim = 1;
00818 }
00819
00820 MatrixTem<C> newfvec(_nr,newDim);
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 return newfvec;
00842 }
00843
00844 }
00845 }
00846 }
00847
00848 #endif