#include #include #include #include namespace icl{ #ifdef HAVE_IPP template static DynMatrix apply_dyn_matrix_inv(const DynMatrix &s){ if(s.cols() != s.rows()){ throw InvalidMatrixDimensionException("inverse matrix can only be calculated on square matrices"); } unsigned int wh = s.cols(); DynMatrix d(wh,wh); std::vector buffer(wh*wh+wh); IppStatus st = ippFunc(s.data(),wh*sizeof(T),sizeof(T), buffer.data(), d.data(),wh*sizeof(T),sizeof(T), wh); if(st != ippStsNoErr){ throw SingularMatrixException("matrix is too singular"); } return d; } template static T apply_dyn_matrix_det(const DynMatrix &s){ if(s.cols() != s.rows()){ throw InvalidMatrixDimensionException("matrix determinant can only be calculated on square matrices"); } unsigned int wh = s.cols(); std::vector buffer(wh*wh+wh); T det(0); IppStatus st = ippFunc(s.data(),wh*sizeof(T),sizeof(T), wh,buffer.data(),&det); if(st != ippStsNoErr){ ERROR_LOG("matrix determinant could not be calculated"); } return det; } #endif template static double dot(const DynMatrix &a, const DynMatrix &b){ ICLASSERT_RETURN_VAL(a.dim() == b.dim(),0.0); double s = 0; for(unsigned int i=0;i optimization: Use a boolean array for that template static void get_minor_matrix(const DynMatrix &M,int col, int row, DynMatrix &D){ /// we assert M is squared here, and D has size M.size()-Size(1,1) int nextCol=0,nextRow=0; const unsigned int dim = M.cols(); for(unsigned int i=0;i DynMatrix DynMatrix::inv() const throw (InvalidMatrixDimensionException,SingularMatrixException){ double detVal = det(); if(!detVal) throw SingularMatrixException("Determinant was 0 -> (matrix is singular to machine precision)"); detVal = 1.0/detVal; DynMatrix M(cols()-1,cols()-1),I(cols(),cols()); for(unsigned int i=0;i T DynMatrix::det() const throw (InvalidMatrixDimensionException){ unsigned int order = cols(); if(order != rows()) throw(InvalidMatrixDimensionException("Determinant can only be calculated on squared matrices")); switch(order){ case 0: throw(InvalidMatrixDimensionException("Matrix order must be > 0")); case 1: return *m_data; case 2: return m_data[0]*m_data[3]-m_data[1]*m_data[2]; case 3: { const T *src = m_data; const T &a = *src++; const T &b = *src++; const T &c = *src++; const T &d = *src++; const T &e = *src++; const T &f = *src++; const T &g = *src++; const T &h = *src++; const T &i = *src++; return ( a*e*i + b*f*g + c*d*h ) - ( g*e*c + h*f*a + i*d*b); } case 4: { const T *src = m_data; const T &m00=*src++; const T &m01=*src++; const T &m02=*src++; const T &m03=*src++; const T &m10=*src++; const T &m11=*src++; const T &m12=*src++; const T &m13=*src++; const T &m20=*src++; const T &m21=*src++; const T &m22=*src++; const T &m23=*src++; const T &m30=*src++; const T &m31=*src++; const T &m32=*src++; const T &m33=*src++; return m03 * m12 * m21 * m30-m02 * m13 * m21 * m30-m03 * m11 * m22 * m30+m01 * m13 * m22 * m30+ m02 * m11 * m23 * m30-m01 * m12 * m23 * m30-m03 * m12 * m20 * m31+m02 * m13 * m20 * m31+ m03 * m10 * m22 * m31-m00 * m13 * m22 * m31-m02 * m10 * m23 * m31+m00 * m12 * m23 * m31+ m03 * m11 * m20 * m32-m01 * m13 * m20 * m32-m03 * m10 * m21 * m32+m00 * m13 * m21 * m32+ m01 * m10 * m23 * m32-m00 * m11 * m23 * m32-m02 * m11 * m20 * m33+m01 * m12 * m20 * m33+ m02 * m10 * m21 * m33-m00 * m12 * m21 * m33-m01 * m10 * m22 * m33+m00 * m11 * m22 * m33; } default:{ // the determinant value T det = 0; DynMatrix D(order-1,order-1); for(unsigned int i=0;i void DynMatrix::decompose_QR(DynMatrix &Q, DynMatrix &R) const throw (QRDecompException){ DynMatrix A = *this; // Working copy DynMatrix a(1,rows()), q(1,rows()); Q.setBounds(cols(),rows()); R.setBounds(cols(),cols()); std::fill(R.begin(),R.end(),0.0); for (unsigned int i=0;i DynMatrix DynMatrix::pinv() const throw (InvalidMatrixDimensionException,SingularMatrixException,QRDecompException){ DynMatrix Q(1,1),R(1,1); if(cols() > rows()){ transp().decompose_QR(Q,R); return (R.inv() * Q.transp()).transp(); }else{ decompose_QR(Q,R); return R.inv() * Q.transp(); } } #ifdef HAVE_IPP template<> DynMatrix DynMatrix::inv() const throw (InvalidMatrixDimensionException,SingularMatrixException){ return apply_dyn_matrix_inv(*this); } template<> DynMatrix DynMatrix::inv() const throw (InvalidMatrixDimensionException,SingularMatrixException){ return apply_dyn_matrix_inv(*this); } template<> float DynMatrix::det() const throw (InvalidMatrixDimensionException){ return apply_dyn_matrix_det(*this); } template<> double DynMatrix::det() const throw (InvalidMatrixDimensionException){ return apply_dyn_matrix_det(*this); } #endif template DynMatrix DynMatrix::inv()const throw (InvalidMatrixDimensionException,SingularMatrixException); template DynMatrix DynMatrix::inv()const throw (InvalidMatrixDimensionException,SingularMatrixException); template float DynMatrix::det()const throw (InvalidMatrixDimensionException); template double DynMatrix::det()const throw (InvalidMatrixDimensionException); template void DynMatrix::decompose_QR(DynMatrix &Q, DynMatrix &R) const throw (InvalidMatrixDimensionException,SingularMatrixException,QRDecompException); template void DynMatrix::decompose_QR(DynMatrix &Q, DynMatrix &R) const throw (InvalidMatrixDimensionException,SingularMatrixException,QRDecompException); template DynMatrix DynMatrix::pinv() const throw (InvalidMatrixDimensionException,SingularMatrixException,QRDecompException); template DynMatrix DynMatrix::pinv() const throw (InvalidMatrixDimensionException,SingularMatrixException,QRDecompException); template static inline std::ostream &icl_to_stream(std::ostream &s, T t){ return s << t; } template static inline std::istream &icl_from_stream(std::istream &s, T &t){ return s >> t; } template<> inline std::ostream &icl_to_stream(std::ostream &s, uint8_t t){ return s << (int)t; } template<> inline std::istream &icl_from_stream(std::istream &s, uint8_t &t){ int tmp; s >> tmp; t = (uint8_t)tmp; return s; } template std::ostream &operator<<(std::ostream &s,const DynMatrix &m){ for(unsigned int i=0;i(s,m(j,i)) << " "; } s << "|"; if(i std::istream &operator>>(std::istream &s,DynMatrix &m){ char c; for(unsigned int i=0;i> c; // trailing '|' if ( ((c >= '0') && (c <= '9')) || c=='-' ){ s.unget(); } for(unsigned int j=0;j(s,m(j,i)); s >> c; if( c != ',') s.unget(); } s >> c; // ending '|' if ( ((c >= '0') && (c <= '9')) || c=='-' ){ s.unget(); } } return s; } #define X(T) \ template std::ostream &operator<<(std::ostream&,const DynMatrix&); \ template std::istream &operator>>(std::istream&,DynMatrix&) X(uint8_t); X(int16_t); X(int32_t); X(float); X(double); X(std::complex); X(std::complex); }