////////////////////////////////////////////////////////////////////// // // NxM Matrix header // // File: matrixnm.h // Description : matrixnm template class declaration and inlined implementation // // History: // -:Created by Anton Knyazev // ////////////////////////////////////////////////////////////////////// #ifndef matrixnm_h #define matrixnm_h #pragma once enum mtxflags { mtx_invalid=1, mtx_normal=2, mtx_orthogonal=4, mtx_PSD=8, mtx_PD_flag=16, mtx_PD=mtx_PSD|mtx_PD_flag, mtx_symmetric=32, mtx_diagonal_flag=64, mtx_diagonal=mtx_symmetric|mtx_normal|mtx_diagonal_flag, mtx_identity_flag=128, mtx_identity=mtx_PD|mtx_diagonal|mtx_orthogonal|mtx_normal|mtx_symmetric|mtx_identity_flag, mtx_singular=256, mtx_foreign_data=1024, // this flag means that data was not allocated by matrix mtx_allocate=32768 // prohibts using matrix pool for data }; template class matrix_product_tpl { public: matrix_product_tpl(int nrows1,int ncols1,ftype *pdata1,int flags1, int ncols2,ftype *pdata2,int flags2) { data1=pdata1; data2=pdata2; nRows1=nrows1;nCols1=ncols1; nCols2=ncols2; flags = flags1 & flags2 & (mtx_orthogonal | mtx_PD) & ~mtx_foreign_data; } void assign_to(ftype *pdst) const { int i,j,k; ftype sum; for(i=0;i class matrix_tpl { public: matrix_tpl() { nRows=nCols=3; flags=mtx_foreign_data; data=0; } matrix_tpl( int nrows, int ncols, int _flags=0, ftype *pdata=(ftype*)-1 ) { nRows = nrows; nCols = ncols; flags = _flags & ~mtx_allocate; int sz = nRows*nCols; if (pdata!=(ftype*)-1) { data = pdata; flags |= mtx_foreign_data; #ifdef USE_MATRIX_POOLS } else if (sz<=36 && !(_flags & mtx_allocate)) { if (mtx_pool_pos+sz > mtx_pool_size) mtx_pool_pos = 0; data = mtx_pool+mtx_pool_pos; mtx_pool_pos += sz; flags |= mtx_foreign_data; #endif } else data = new ftype[sz]; } matrix_tpl(const matrix_tpl& src) { if (src.flags & mtx_foreign_data) { nRows=src.nRows; nCols=src.nCols; flags=src.flags; data=src.data; } else { matrix_tpl(src.nRows,src.nCols,src.flags,0); for(int i=nRows*nCols-1;i>=0;i--) data[i]=src.data[i]; } } ~matrix_tpl() { if (data && !(flags & mtx_foreign_data)) delete [] data; } matrix_tpl& operator=(const matrix_tpl &src) { if (!data || !(flags & mtx_foreign_data) && nRows*nCols=0;i--) data[i] = src.data[i]; return *this; } template matrix_tpl& operator=(const matrix_tpl &src) { if (!data || !(flags & mtx_foreign_data) && nRows*nCols=0;i--) data[i] = src.data[i]; return *this; } matrix_tpl& operator=(const matrix_product_tpl &src) { nRows=src.nRows1; nCols=src.nCols2; flags = flags&mtx_foreign_data | src.flags; src.assign_to(data); return *this; } matrix_tpl& operator+=(const matrix_product_tpl &src) { src.add_assign_to(data); return *this; } matrix_tpl& operator-=(const matrix_product_tpl &src) { src.sub_assign_to(data); return *this; } matrix_tpl& allocate() { int i,sz=nRows*nCols; ftype *prevdata = data; if (!data) data = new ftype[sz]; if (flags & mtx_foreign_data) for(i=0;i=0;i--) data[i]=0; return *this; } matrix_tpl& identity() { zero(); for(int i=min(nRows,nCols)-1;i>=0;i--) data[i*(nCols+1)] = 1; return *this; } matrix_tpl& invert(); // in-place inversion matrix_tpl operator!() const { // returns inverted matrix if (flags & mtx_orthogonal) return T(); matrix_tpl res = *this; res.invert(); return res; } matrix_tpl& transpose() { // in-place transposition if (nRows==nCols) { if (flags & mtx_symmetric) return *this; int i,j; ftype t; for(i=0;i(*this); int i,j; matrix_tpl res(nCols,nRows, flags & ~mtx_foreign_data); for(i=0;i matrix_tpl operator*(const matrix_tpl &op1, const matrix_tpl &op2) { matrix_tpl res(op1.nRows, op2.nCols); res.flags = res.flags & mtx_foreign_data | op1.flags & op2.flags & (mtx_orthogonal | mtx_PD) & ~mtx_foreign_data; int i,j,k; ftype1 sum; for(i=0;i matrix_product_tpl operator*(const matrix_tpl &op1, const matrix_tpl &op2) { return matrix_product_tpl(op1.nRows,op1.nCols,op1.data,op1.flags, op2.nCols,op2.data,op2.flags); } /*template matrix_tpl& operator*=(matrix_tpl &op1, const matrix_tpl &op2) { return op1 = (op1 * op2); }*/ template matrix_tpl& operator*=(matrix_tpl &op1,ftype op2) { for(int i=op1.nRows*op1.nCols-1; i>=0; i--) op1.data[i]*=op2; op1.flags &= ~(mtx_identity_flag | mtx_PD); return op1; } template matrix_tpl& operator+=(matrix_tpl &op1, const matrix_tpl &op2) { for(int i=op1.nRows*op1.nCols-1; i>=0; i--) op1.data[i] += op2.data[i]; op1.flags = op1.flags & mtx_foreign_data | op1.flags & op2.flags & (mtx_symmetric | mtx_PD); return op1; } template matrix_tpl& operator-=(matrix_tpl &op1, const matrix_tpl &op2) { for(int i=op1.nRows*op1.nCols-1; i>=0; i--) op1.data[i] -= op2.data[i]; op1.flags = op1.flags & mtx_foreign_data | op1.flags & op2.flags & mtx_symmetric; return op1; } template matrix_tpl operator+(const matrix_tpl &op1, const matrix_tpl &op2) { matrix_tpl res; res=op1; res+=op2; return res; } template matrix_tpl operator-(const matrix_tpl &op1, const matrix_tpl &op2) { matrix_tpl res; res=op1; res-=op2; return res; } template ftype3 *mul_vector_by_matrix(const matrix_tpl &mtx, const ftype2 *psrc,ftype3 *pdst) { int i,j; for(i=0;i matrix; typedef matrix_tpl matrixf; #if defined(LINUX) #define DECLARE_MTXNxM_POOL(ftype,sz) template<> ftype matrix_tpl::mtx_pool[sz] = {}; template<> int matrix_tpl::mtx_pool_pos=0; \ template<> int matrix_tpl::mtx_pool_size=sz; #else #define DECLARE_MTXNxM_POOL(ftype,sz) template<> ftype matrix_tpl::mtx_pool[sz]; template<> int matrix_tpl::mtx_pool_pos=0; \ template<> int matrix_tpl::mtx_pool_size=sz; #endif //LINUX extern int g_bHasSSE; #ifdef PIII_SSE void PIII_Mult00_6x6_6x6(float *src1, float *src2, float *dst); inline void matrix_product_tpl::assign_to(float *pdst) const { if ((g_bHasSSE^1|nRows1-6|nCols1-6|nCols2-6)==0) PIII_Mult00_6x6_6x6(data1,data2, pdst); else { int i,j,k; float sum; for(i=0;i