00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #if !defined(ALIZE_Matrix_h)
00056 #define ALIZE_Matrix_h
00057
00058 #if defined(_WIN32)
00059 #if defined(ALIZE_EXPORTS)
00060 #define ALIZE_API __declspec(dllexport)
00061 #else
00062 #define ALIZE_API __declspec(dllimport)
00063 #endif
00064 #else
00065 #define ALIZE_API
00066 #endif
00067
00068 #include <new>
00069 #include <math.h>
00070
00071 #include <cstdio>
00072 #include <iostream>
00073 #include <fstream>
00074 #include <memory.h>
00075 #include <cstdlib>
00076
00077
00078
00079
00080 #include "RealVector.h"
00081 #include "DoubleSquareMatrix.h"
00082 #include "alizeString.h"
00083 #include "Exception.h"
00084 #include "Config.h"
00085 #include "Feature.h"
00086
00087 #define TINY 1.0e-20
00088
00089
00090 #if defined(_WIN32)
00091 #define drand48()((double)rand()/RAND_MAX)
00092 #define srand48(n)srand((n));
00093 #endif
00094
00095 using namespace std;
00096
00097 namespace alize
00098 {
00110
00111 template <class T> class ALIZE_API Matrix : public Object
00112 {
00113 friend class TestMatrix;
00114
00115 public:
00116
00121 Matrix(unsigned long rows = 0, unsigned long cols = 0)
00122 :Object(), _cols(cols), _rows(rows), _array(rows*cols, rows*cols) {}
00123
00127 explicit Matrix(const FileName& f)
00128 :Object() { load(f, Config()); }
00129
00134 explicit Matrix(const FileName& f, const Config& c)
00135 :Object() { load(f, c); }
00136
00141 template <class R> explicit Matrix(const RealVector<R>& v)
00142 {
00143 _cols = v.size();
00144 _rows = 1;
00145 _array = v;
00146 }
00147
00152 explicit Matrix(const Feature &f)
00153 {
00154 _array.setSize(f.getVectSize());
00155 _cols = f.getVectSize();
00156 _rows = 1;
00157 for (unsigned long i=0; i<f.getVectSize(); i++)
00158 _array[i]=(T)f[i];
00159 }
00160
00164 explicit Matrix(const DoubleSquareMatrix &M)
00165 {
00166 _cols = M.size();
00167 _rows =M.size();
00168 for (unsigned long i=0; i<_rows; i++)
00169 for (unsigned long j=0; j<_cols; j++)
00170 _array[i*_rows+j]=(T)M(i,j);
00171 }
00172
00176 Matrix<T>& operator=(const Matrix<T>& m)
00177 {
00178 _array = m._array;
00179 _cols = m._cols;
00180 _rows = m._rows;
00181 return *this;
00182 }
00183
00184 bool operator==(const Matrix<T>& m) const
00185 {
00186 return (_cols == m._cols && _rows == m._rows && _array == m._array);
00187 }
00188
00189 bool operator!=(const Matrix<T>& m) const { return !(*this == m); }
00190
00191 Matrix(const Matrix<T>& m)
00192 :Object(), _cols(m._cols), _rows(m._rows), _array(m._array) {}
00193
00194 virtual ~Matrix() {}
00195
00198 unsigned long cols() const { return _cols; }
00199
00202 unsigned long rows() const { return _rows; }
00203
00208 void setDimensions(const unsigned long rows, const unsigned long cols)
00209 {
00210 _cols = cols;
00211 _rows = rows;
00212 _array.setSize(cols*rows);
00213 }
00214
00218 template <class R> void setAllValues(R v) { _array.setAllValues(v); }
00219
00226 T& operator()(unsigned long row, unsigned long col)
00227 {
00228 assertIsInBounds(__FILE__, __LINE__, col, _cols);
00229 assertIsInBounds(__FILE__, __LINE__, row, _rows);
00230 return _array[row*_cols+col];
00231 }
00232
00239 T operator()(unsigned long row, unsigned long col) const
00240 {
00241 assertIsInBounds(__FILE__, __LINE__, col, _cols);
00242 assertIsInBounds(__FILE__, __LINE__, row, _rows);
00243 return _array[row*_cols+col];
00244 }
00245
00249 Matrix<T>& transpose()
00250 {
00251 unsigned long c, r, cc, rr;
00252 RealVector<T> tmp = _array;
00253 T* t = tmp.getArray();
00254 T* p = _array.getArray();
00255 for (r=0, rr=0; r<_rows; r++, rr+=_cols)
00256 for (c=0, cc=0; c<_cols; c++, cc+=_rows)
00257 p[r+cc] = t[c+rr];
00258 r = _rows;
00259 _rows = _cols;
00260 _cols = r;
00261 return *this;
00262 }
00263
00267 Matrix<T> transpose() const
00268 {
00269 Matrix<T> tmp = *this;
00270 return tmp.transpose();
00271 }
00272
00276 Matrix<T>& invert()
00277 {
00278 if(_cols!=_rows)
00279 throw Exception("Cannot invert matrix, non square matrix", __FILE__, __LINE__);
00280
00281 int n = _cols;
00282 int i,j;
00283 T** a=(T**)malloc((n+1)*sizeof(T*));
00284 for (i=0;i<=n;i++)
00285 a[i]=(T*)malloc((n+1)*sizeof(T));
00286 for(j=1;j<=n;j++)
00287 for(i=1;i<=n;i++)
00288 a[i][j] = (*this)(i-1,j-1);
00289
00290 int*indx = (int*)malloc((n+1)*sizeof(int));
00291 T** y = (T**)malloc((n+1)*sizeof(T*));
00292 for (i=0;i<=n;i++)
00293 y[i]=(T*)malloc((n+1)*sizeof(T));
00294
00295 T* d = (T*)malloc((n+1)*sizeof(T));
00296 ludcmp(a,n,indx,d);
00297 free(d);
00298
00299 T* col = (T*)malloc((n+1)*sizeof(T));
00300 for(j=1;j<=n;j++)
00301 {
00302 for(i=1;i<=n;i++)
00303 col[i]=(T)0.0;
00304 col[j]=(T)1.0;
00305 lubksb(a,n,indx,col);
00306 for(i=1;i<=n;i++)
00307 y[i][j]=col[i];
00308 }
00309
00310 for(j=1;j<=n;j++)
00311 for(i=1;i<=n;i++)
00312 (*this)(i-1,j-1) = y[i][j];
00313
00314 free(col);
00315 free(indx);
00316 for (i=0;i<=n;i++)
00317 {
00318 free(a[i]);
00319 free(y[i]);
00320 a[i] = NULL;
00321 y[i] = NULL;
00322 }
00323 free(a);
00324 free(y);
00325 return *this;
00326 }
00327
00331 Matrix<T> invert() const
00332 {
00333 Matrix<T> tmp = *this;
00334 return tmp.invert();
00335 }
00336
00342 Matrix<T> operator*(const Matrix<T>& m) const
00343 {
00344 if (_cols != m._rows)
00345 throw Exception("Cannot multiply matrices", __FILE__, __LINE__);
00346 const unsigned long cols = m._cols;
00347 Matrix<T> tmp(_rows, cols);
00348 tmp.setAllValues(0.0);
00349 T* pTmp = tmp._array.getArray();
00350 T* pM = m._array.getArray();
00351 T* p = _array.getArray();
00352 unsigned long i, j, k, i_cols, itmp_cols, kcols;
00353 for (i=0, i_cols=0, itmp_cols=0; i<_rows; i++, i_cols+=_cols, itmp_cols += cols)
00354 for (j=0; j<cols; j++)
00355 for (k=0, kcols=0; k<_cols; k++, kcols+=cols)
00356 pTmp[itmp_cols+j] += p[i_cols+k] * pM[kcols+j];
00357 return tmp;
00358 }
00359
00364 Matrix<T>& operator*=(const Matrix<T>& m)
00365 {
00366 (*this) = (*this)*m;
00367 return *this;
00368 }
00369
00374 Matrix<T>& operator*=(double v)
00375 {
00376 _array *= v;
00377 return *this;
00378 }
00379
00385 Matrix<T> operator*(double v) const
00386 {
00387 Matrix<T> tmp = *this;
00388 tmp._array *= v;
00389 return tmp;
00390 }
00391
00397 Matrix<T> operator+(const Matrix<T>& m) const
00398 {
00399 Matrix<T> tmp(*this);
00400 tmp._array += m._array;
00401 return tmp;
00402 }
00403
00408 Matrix<T>& operator+=(const Matrix<T>& m)
00409 {
00410 if (_cols != m._cols || _rows != m._rows)
00411 throw Exception("Dimensions of matrices do not match", __FILE__, __LINE__);
00412 _array += m._array;
00413 return *this;
00414 }
00415
00421 Matrix<T> operator-(const Matrix<T>& m) const
00422 {
00423 Matrix<T> tmp(*this);
00424 tmp._array -= m._array;
00425 return tmp;
00426 }
00427
00432 Matrix<T>& operator-=(const Matrix<T>& m)
00433 {
00434 if (_cols != m._cols || _rows != m._rows)
00435 throw Exception("Dimensions of matrices do not match", __FILE__, __LINE__);
00436 _array -= m._array;
00437 return *this;
00438 }
00439
00444 void save(const FileName& f) { save(f, Config()); }
00445
00451 void save(const FileName& f, const Config& c)
00452 {
00453 if (c.getParam("saveMatrixFormat")=="DT") saveDT(f,c);
00454 else if (c.getParam("saveMatrixFormat")=="DB") saveDB(f,c);
00455 else throw Exception("saveMatrixFormat unknown! DT (Dense Text) or DB (Dense Binary)",__FILE__,__LINE__);
00456 }
00457
00464 void saveDT(const FileName& f, const Config& c)
00465 {
00466 XList l;
00467 l.addLine().addElement(String::valueOf(_rows))
00468 .addElement(String::valueOf(_cols));
00469 for (unsigned long j=0; j<_rows; j++)
00470 {
00471 XLine& li = l.addLine();
00472 for (unsigned long i=0; i<_cols; i++)
00473 li.addElement(String::valueOf((*this)(j,i)));
00474 }
00475 l.save(f, c);
00476 }
00477
00483 void saveDB(const FileName&f,const Config& c)
00484 {
00485 try {
00486 ofstream outputMat(f.c_str(),ios::out|ios::binary);
00487 if(!outputMat)
00488 throw IOException("Cannot open file", __FILE__, __LINE__,f);
00489 unsigned long rows=this->rows();
00490 unsigned long cols=this->cols();
00491 T * array=_array.getArray();
00492 outputMat.write((char*)&rows,sizeof(rows));
00493 outputMat.write((char*)&cols,sizeof(cols));
00494 outputMat.write((char*)array,rows*cols*sizeof(T));
00495 outputMat.close();
00496 }
00497 catch (Exception& e) {cout << e.toString().c_str() << endl;}
00498 }
00499
00504 void load(const FileName& f) { load(f, Config()); }
00505
00511 void load(const FileName& f, const Config& c)
00512 {
00513 if (c.getParam("loadMatrixFormat")=="DT") loadDT(f,c);
00514 else if (c.getParam("loadMatrixFormat")=="DB") loadDB(f,c);
00515 else throw Exception("loadMatrixFormat unknown! DT (Dense Text) or DB (Dense Binary)",__FILE__,__LINE__);
00516 }
00523 void loadDT(const FileName& f, const Config& c)
00524 {
00525 XList l(f, c);
00526 unsigned long rows = l.getLine(0).getElement(0).toLong();
00527 unsigned long cols = l.getLine(0).getElement(1).toLong();
00528 setDimensions(rows,cols);
00529 l.rewind();
00530 l.getLine();
00531 XLine* p;
00532 String* s;
00533 unsigned long j = 0;
00534 while ((p = l.getLine()))
00535 {
00536 unsigned long i = 0;
00537 while ((s = p->getElement()))
00538 {
00539 (*this)(j, i) = (T) s->toDouble();
00540 i++;
00541 }
00542 j++;
00543 }
00544 }
00545
00551 void loadDB(const FileName&f,const Config& c)
00552 {
00553 try {
00554 ifstream inputMat(f.c_str(),ios::in|ios::binary);
00555 if(!inputMat){
00556 throw IOException("Cannot open file", __FILE__, __LINE__,f);
00557 }
00558 unsigned long rows;
00559 unsigned long cols;
00560 inputMat.read((char*)&rows,sizeof(rows));
00561 inputMat.read((char*)&cols,sizeof(cols));
00562 setDimensions(rows,cols);
00563 inputMat.read((char*)_array.getArray(),rows*cols*sizeof(T));
00564 inputMat.close();
00565 }
00566 catch (Exception& e) {cout << e.toString().c_str() << endl;}
00567 }
00568
00572 void randomInit()
00573 {
00574 try {
00575 for ( unsigned long r=0; r<_rows; r++ )
00576 for ( unsigned long c=0; c<_cols; c++ )
00577 (*this)(r,c)= (T) drand48();
00578 }
00579 catch (Exception& e) {cout << e.toString().c_str() << endl;}
00580 }
00581
00586 T* getArray() const { return _array.getArray(); }
00587
00588 virtual String toString() const
00589 {
00590 String s = Object::toString()
00591 + "\n dimensions = " + String::valueOf(_rows)+"x"+String::valueOf(_cols);
00592 for (unsigned long j=0; j<_rows; j++)
00593 {
00594 for (unsigned long i=0; i<_cols; i++)
00595 s += "\n [" + String::valueOf(j)
00596 + "," + String::valueOf(i)
00597 + "] = " + String::valueOf((*this)(j,i));
00598 s += "\n";
00599 }
00600 return s;
00601 }
00602
00603 virtual String getClassName() const { return "Matrix"; }
00604
00612 Matrix<T> crop(unsigned long line, unsigned long col, unsigned long n_rows, unsigned long n_cols)
00613 {
00614 if( (line + n_rows > _rows) || (col + n_cols > _cols) ){
00615 throw Exception("Cannot crop a such big Matrix",__FILE__,__LINE__);
00616 }
00617
00618 Matrix<T> subM(n_rows, n_cols);
00619 T* subm=subM.getArray();
00620 T* array = _array.getArray();
00621
00622 for(unsigned long i=0; i<n_rows; i++){
00623 for(unsigned long j=0; j<n_cols; j++){
00624 subm[i*n_cols+j] = array[(line+i)*_cols+col+j];
00625 }
00626 }
00627 return subM;
00628 }
00629
00635 void concatCols(const Matrix<T>& M1, const Matrix<T>& M2){
00636
00637
00638 if( M1.cols() != M2.cols() ){
00639 throw Exception("Cannot concatenate the given matrices, wrong dimensionality",__FILE__,__LINE__);
00640 }
00641
00642 unsigned long nrows = M1.rows()+M2.rows();
00643 this->setDimensions(nrows,M1.cols());
00644
00645 T* m1=M1.getArray();
00646 T* m2 = M2.getArray();
00647
00648 for(unsigned long i=0; i<M1.cols()*M1.rows(); i++){
00649 _array[i] = m1[i];
00650 }
00651 for(unsigned long i=0; i<M2.cols()*M2.rows(); i++){
00652 _array[i+M1.cols()*M1.rows()] = m2[i];
00653 }
00654 }
00655
00661 void concatRows(const Matrix<T>& M1, const Matrix<T>& M2){
00662
00663
00664 if( M1.rows() != M2.rows() ){
00665 throw Exception("Cannot concatenate the given matrices, wrong dimensionality",__FILE__,__LINE__);
00666 }
00667
00668 unsigned long ncols = M1.cols()+M2.cols();
00669 this->setDimensions(M1.rows(),ncols);
00670
00671 T* m1=M1.getArray();
00672 T* m2 = M2.getArray();
00673
00674 for(unsigned long r=0; r<M1.rows(); r++){
00675 for(unsigned long c1=0; c1<M1.cols(); c1++){
00676 _array[r*ncols + c1] = m1[r*M1.cols()+c1];
00677 }
00678
00679 for(unsigned long c2=0; c2<M2.cols(); c2++){
00680 _array[r*ncols + M1.cols() + c2] = m2[r*M2.cols()+c2];
00681 }
00682 }
00683 }
00684
00685
00686
00687 private:
00688
00689 unsigned long _cols;
00690 unsigned long _rows;
00691 RealVector<T> _array;
00692
00693 unsigned long fabs(unsigned long x) { return x; };
00694 void ludcmp(T **a, int n, int *indx, T *d)
00695 {
00696 int i,imax,j,k;
00697 T big,dum,sum,temp;
00698 T *vv;
00699 vv=(T*)malloc((n+1)*sizeof(T));
00700 for(i=0;i<=n;i++) vv[i]=(T)0.0;
00701 *d=(T)1.0;
00702
00703 for (i=1;i<=n;i++) {
00704 big=(T)0.0;
00705
00706 for (j=1;j<=n;j++)
00707 if ((temp=(T)fabs(a[i][j])) > big) big=(T)temp;
00708 if (big == 0.0) big=big;
00709 vv[i]=(T)(1.0/big);
00710 }
00711
00712 for (j=1;j<=n;j++) {
00713 for (i=1;i<j;i++) {
00714 sum=a[i][j];
00715 for (k=1;k<i;k++) sum -= a[i][k]*a[k][j];
00716 a[i][j]=sum;
00717 }
00718
00719 big=(T)0.0;
00720 for (i=j;i<=n;i++) {
00721 sum=a[i][j];
00722 for (k=1;k<j;k++) sum -= a[i][k]*a[k][j];
00723 a[i][j]=sum;
00724 if ( (dum=vv[i]*(T)fabs(sum)) >= big) {
00725 big=dum;
00726 imax=i;
00727 }
00728 }
00729 if (j != imax) {
00730 for (k=1;k<=n;k++) {
00731 dum=a[imax][k];
00732 a[imax][k]=a[j][k];
00733 a[j][k]=dum;
00734 }
00735 *d = -(*d);
00736 vv[imax]=vv[j];
00737 }
00738 indx[j]=imax;
00739 if (a[j][j] == 0.0) a[j][j]=(T)TINY;
00740 if (j != n) {
00741 dum=(T)(1.0/(a[j][j]));
00742 for (i=j+1;i<=n;i++) a[i][j] *= dum;
00743 }
00744 }
00745 free(vv);
00746 }
00747
00748 void lubksb(T **a, int n, int *indx, T b[])
00749 {
00750 int i,ii=0,ip,j;
00751 T sum;
00752 for (i=1;i<=n;i++) {
00753 ip=indx[i];
00754 sum=b[ip];
00755 b[ip]=b[i];
00756 if (ii)
00757 for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
00758 else if (sum) ii=i;
00759 b[i]=sum;
00760 }
00761 for (i=n;i>=1;i--) {
00762 sum=b[i];
00763 for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
00764 b[i]=sum/a[i][i];
00765 }
00766 }
00767
00768 };
00769
00770 typedef Matrix<double> DoubleMatrix;
00771 #if defined(_WIN32)
00772 template class Matrix<double>;
00773 template class Matrix<unsigned long>;
00774 #endif
00775
00776 }
00777
00778 #endif // ALIZE_Matrix_h
00779