/* * NICE-Core - efficient algebra and computer vision methods * - libbasicvector - A simple vector library * See file License for license information. */ #include "core/vector/Algorithms.h" #include #include #ifdef NICE_USELIB_LINAL #include #endif namespace NICE { template inline T mean(const VectorT &v) { //#ifdef NICE_USELIB_IPP T m; IppStatus ret = ippsMean(v.getDataPointer(),v.size(),&m,ippAlgHintFast); if(ret!=ippStsNoErr) _THROW_EVector(ippGetStatusString(ret)); return m; //#else // _THROW_EVector("Not yet implementent without IPP."); //#endif // NICE_USELIB_IPP } template inline T det(const MatrixT &A) { #ifdef NICE_USELIB_IPP size_t msize=A.cols(); if(msize!=A.rows()) _THROW_EMatrix("det(MatrixT): matrix is not symmetric"); size_t tsize=sizeof(T); T buffer[msize*msize+msize]; T result; IppStatus ret = ippmDet_m(A.getDataPointer(),msize*tsize,tsize,msize,buffer,&result); // ippStsSingularErr not defined if(ret==ippStsSingularErr) return static_cast(0); if(ret!=ippStsNoErr) _THROW_EMatrix(ippGetStatusString(ret)); return result; #else #ifdef NICE_USELIB_LINAL return LinAl::det(A.linal()); #else _THROW_EVector("Not yet implementent without IPP."); #endif #endif // NICE_USELIB_IPP } template inline T det(const RowMatrixT &A) { #ifdef NICE_USELIB_IPP size_t msize=A.cols(); if(msize!=A.rows()) _THROW_EMatrix("det(MatrixT): matrix is not symmetric"); size_t tsize=sizeof(T); T buffer[msize*msize+msize]; T result; IppStatus ret = ippmDet_m(A.getDataPointer(),msize*tsize,tsize,msize,buffer,&result); // ippStsSingularErr not defined if(ret==ippStsSingularErr) return static_cast(0); if(ret!=ippStsNoErr) _THROW_EMatrix(ippGetStatusString(ret)); return result; #else #ifdef NICE_USELIB_LINAL return LinAl::det(A.linal()); #else _THROW_EVector("Not yet implementent without IPP."); #endif #endif // NICE_USELIB_IPP } template void choleskyDecomp ( const MatrixT & A, MatrixT & G, bool resetUpperTriangle ) { if ( A.rows() != A.cols() ) fthrow(Exception, "Matrix is not quadratic !"); const int size = A.rows(); G.resize ( size, size ); if ( resetUpperTriangle ) G.set(0.0); int i,j,k; double sum; for (i=0;i=0;k--) sum -= G(i,k)*G(j,k); if (i == j) { // The following applies if A, with rounding errors, is not positive definite if (isZero(sum, 1e-16)) { G(i,i)=0.0; divide=false; } else if (sum<0.0) { // A is (numerically) not positive definite. fthrow(Exception, "Cholesky decomposition failed (sum=" << sum << ")"); } G(i,i)=sqrt(sum); } else { if (!divide) G(j,i)=0.0; else G(j,i)=sum/G(i,i); } } } } template void choleskyInvert ( const MatrixT & Gmatrix, MatrixT & AinvMatrix ) { if ( Gmatrix.rows() != Gmatrix.cols() ) fthrow(Exception, "Matrix is not quadratic !"); AinvMatrix.resize ( Gmatrix.rows(), Gmatrix.cols() ); const T *G = Gmatrix.getDataPointer(); T *Ainv = AinvMatrix.getDataPointer(); int i,k,j; T sum; int size = Gmatrix.rows(); for (j=0;j=0;k--) sum -= G[k*size+i]*Ainv[k+j*size]; if (almostZero(G[i*size+i])) Ainv[i+j*size]=0.0; else Ainv[i+j*size]=sum/G[i*size+i]; } for (i=size-1;i>=0;i--) { for (sum=Ainv[i+j*size],k=i+1;k void choleskySolve ( const MatrixT & Gmatrix, const VectorT & b, VectorT & x ) { if ( Gmatrix.rows() != Gmatrix.cols() ) fthrow(Exception, "Matrix is not quadratic !"); if ( b.size() != Gmatrix.cols() ) fthrow(Exception, "Matrix or right hand side of the linear system has wrong dimensions !"); int size = Gmatrix.rows(); const T* G = Gmatrix.getDataPointer(); int i,k; double sum; x.resize(size); // Solve L y = b, storing y in x. for (i=0;i=0;k--) sum -= G[k*size+i]*x[k]; x[i]=sum/G[i*size+i]; } // Solve LT x = y for (i=size-1;i>=0;i--) { for (sum=x[i],k=i+1;k double triangleMatrixDet ( const MatrixT & Gmatrix, bool ignoreZero ) { if ( Gmatrix.rows() != Gmatrix.cols() ) fthrow(Exception, "Matrix is not quadratic !"); int i; int size = Gmatrix.rows(); const T* G = Gmatrix.getDataPointer(); double ret = 1.0; for (i=0;i double triangleMatrixLogDet ( const MatrixT & Gmatrix, bool ignoreZero ) { int i; int size = Gmatrix.rows(); const T* G = Gmatrix.getDataPointer(); double ret = 0.0; for (i=0;i::infinity(); } ret += log(G[i*size+i]); } return ret; } template inline void lnIP(VectorT &v) { #ifdef NICE_USELIB_IPP IppStatus ret = ippsLn_I(v.getDataPointer(),v.size()); if(ret!=ippStsNoErr) _THROW_EVector(ippGetStatusString(ret)); #else _THROW_EVector("Not yet implementent without IPP."); #endif // NICE_USELIB_IPP } template inline VectorT *ln(const VectorT &v, VectorT *buffer) { #ifdef NICE_USELIB_IPP VectorT *result; if(buffer==NULL || buffer->size()!=v.size()) { result=new VectorT(v.size()); } else { result=buffer; } IppStatus ret = ippsLn(v.getDataPointer(),result->getDataPointer(),v.size()); if(ret!=ippStsNoErr) _THROW_EVector(ippGetStatusString(ret)); return result; #else _THROW_EVector("Not yet implementent without IPP."); #endif // NICE_USELIB_IPP } template inline VectorT *createGaussFunc(float sigma, VectorT *buffer) { #ifdef NICE_USELIB_IPP int resultlength; VectorT *result; if(buffer==NULL || buffer->size()<3) { int length=static_cast(2.0*sigma*sigma-0.5); if(length<1) length=0; float base[] = {0.25, 0.5, 0.25}; resultlength=3+length*2; result= new VectorT(resultlength); ippsCopy(base, result->getDataPointer(), 3); T tmp[resultlength]; for(int i=0;igetDataPointer(),3+i*2,tmp); ippsCopy(tmp, result->getDataPointer(), 3+(i+1)*2); } } else { resultlength=buffer->size(); result=buffer; float ssq=sigma*sigma; if(sigma<=0) { ssq=(resultlength-1)/4; } float norm=sqrt(2.*M_PI*ssq); float l=-(resultlength-1)/2.0; for(int i=0;i inline void solveLinearEquationQR(const MatrixT &A, const VectorT &b, VectorT &x) { #ifdef NICE_USELIB_IPP // FIXME: this method seems to be buggy :) size_t in_s = A.cols(); if (in_s != b.size()) _THROW_EMatrix("solveLinearEquationQR: size of input vector b does not fit"); size_t out_s = A.rows(); if (x.size() == 0) { x.resize(out_s); } if (out_s != x.size()) _THROW_EMatrix("solveLinearEquationQR: size of output vector x does not fit"); T QR[in_s*out_s]; int stride = sizeof(T); int stride_src = out_s*sizeof(T); T Buffer[in_s]; IppStatus status = ippmQRDecomp_m(A.getDataPointer(),stride_src, stride, Buffer, QR, stride_src, stride, out_s, in_s); if (status != ippStsOk) _THROW_EVector(ippGetStatusString(status)); status = ippmQRBackSubst_mv(QR, stride_src, stride, Buffer, b.getDataPointer(), stride, x.getDataPointer(), stride, out_s, in_s); if (status != ippStsOk) _THROW_EVector(ippGetStatusString(status)); #else _THROW_EVector("Not yet implementent without IPP."); #endif // NICE_USELIB_IPP } template inline void solveMDLgreedy(const MatrixT &C, VectorT &h) { #ifdef NICE_USELIB_IPP if (C.rows() != C.cols()) _THROW_EMatrix("solveMDLgreedy: matrix C is not quadratic"); size_t size = h.size(); if (C.rows() != size) _THROW_EMatrix("solveMDLgreedy: size of output vector h does not fit"); VectorT temp(size); T maximum = 0.0; T current = 0.0; int position = -1; h *= 0; int Stride = sizeof(T); int srcStride = size * sizeof(T); do { position = -1; for (uint i = 0; i < size; i++) { if (not h(i)) { h(i) = 1; ippmMul_tv_32f(C.getDataPointer(), srcStride, Stride, size, size, h.getDataPointer(), Stride, size, temp.getDataPointer(), Stride); temp *= h; current = temp.Sum(); if (current > maximum) { maximum = current; position = i; } h(i) = 0; } } if (position > -1) h(position) = 1; } while (position > -1); #else _THROW_EVector("Not yet implementent without IPP."); #endif // NICE_USELIB_IPP } template MatrixT invert(const MatrixT& w) { #ifdef NICE_USELIB_IPP size_t size = w.cols(); if (size != w.rows()) { _THROW_EMatrix("invert: matrix is not square."); } MatrixT result(w.rows(), w.cols()); T* buffer = new T[size * size + size]; int stride1 = sizeof(T); int stride2 = size * sizeof(T); IppStatus status = ippmInvert_m(w.getDataPointer(), stride1, stride2, buffer, result.getDataPointer(), stride1, stride2, size); if (status != ippStsOk) { _THROW_EVector(ippGetStatusString(status)); } return result; #else #ifdef NICE_USELIB_LINAL LinAl::MatrixCF copy(w.linal()); try { copy.LUinvert(); } catch (std::exception& e) { fthrowc(Exception, "Invert failed", e); } MatrixT result(copy); return result; #else _THROW_EVector("Not yet implementent without IPP or LinAl."); #endif #endif // NICE_USELIB_IPP } template void invert3x3UpperTriangle(MatrixT& w) { w(0, 2) = (w(0, 1) * w(1, 2) - w(0, 2) * w(1, 1)) / (w(0, 0) * w(1, 1) * w(2, 2)); w(1, 2) = -w(1, 2) / (w(1, 1) * w(2, 2)); w(2, 2) = 1.0 / w(2, 2); w(0, 1) = -w(0, 1) / (w(0, 0) * w(1, 1)); w(1, 1) = 1.0 / w(1, 1); w(0, 0) = 1.0 / w(0, 0); } template void invert3x3LowerTriangle(MatrixT& w) { w(2, 0) = (w(1, 0) * w(2, 1) - w(2, 0) * w(1, 1)) / (w(0, 0) * w(1, 1) * w(2, 2)); w(2, 1) = -w(2, 1) / (w(1, 1) * w(2, 2)); w(2, 2) = 1.0 / w(2, 2); w(1, 0) = -w(1, 0) / (w(0, 0) * w(1, 1)); w(1, 1) = 1.0 / w(1, 1); w(0, 0) = 1.0 / w(0, 0); } }