123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- /*
- * 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 <core/basics/Log.h>
- #include <core/vector/SVD.h>
- #ifdef NICE_USELIB_LINAL
- #include <LinAl/algorithms.h>
- #endif
- namespace NICE {
- template<class T>
- inline T mean(const VectorT<T> &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<class T>
- inline T det(const MatrixT<T> &A) {
- #ifdef NICE_USELIB_IPP
- size_t msize=A.cols();
- if(msize!=A.rows())
- _THROW_EMatrix("det(MatrixT<T>): 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<T>(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<class T>
- inline T det(const RowMatrixT<T> &A) {
- #ifdef NICE_USELIB_IPP
- size_t msize=A.cols();
- if(msize!=A.rows())
- _THROW_EMatrix("det(MatrixT<T>): 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<T>(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<class T>
- void choleskyDecomp ( const MatrixT<T> & A, MatrixT<T> & 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<size;i++) {
- bool divide=true;
- for (j=0;j<i;j++) G(j,i)=0.0;
- for (;j<size;j++) {
- sum=A(i,j);
- for (k=i-1;k>=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<class T>
- void choleskyInvert ( const MatrixT<T> & Gmatrix, MatrixT<T> & 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<size;j++) {
- for (i=0;i<size;i++) {
- sum = (i==j)?1.0:0.0;
- for (k=i-1;k>=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<size;k++) sum -= G[i*size+k]*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];
- }
- }
- }
- template<class T>
- void choleskySolve ( const MatrixT<T> & Gmatrix, const VectorT<T> & b, VectorT<T> & 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<size;i++) {
- for (sum=b[i],k=i-1;k>=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<size;k++) sum -= G[i*size+k]*x[k];
- x[i]=sum/G[i*size+i];
- }
- }
- template<class T>
- double triangleMatrixDet ( const MatrixT<T> & 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<size;i++) {
- if (almostZero(G[i*size+i])) {
- if (ignoreZero) continue;
- else return 0.0;
- }
- ret *= G[i*size+i];
- }
- return ret;
- }
- template<class T>
- double triangleMatrixLogDet ( const MatrixT<T> & Gmatrix, bool ignoreZero )
- {
- int i;
- int size = Gmatrix.rows();
- const T* G = Gmatrix.getDataPointer();
- double ret = 0.0;
- for (i=0;i<size;i++) {
- if (almostZero(G[i*size+i])) {
- if (ignoreZero) continue;
- else return - std::numeric_limits<double>::infinity();
- }
- ret += log(G[i*size+i]);
- }
- return ret;
- }
- template<class T>
- inline void lnIP(VectorT<T> &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<class T>
- inline VectorT<T> *ln(const VectorT<T> &v, VectorT<T> *buffer) {
- #ifdef NICE_USELIB_IPP
- VectorT<T> *result;
- if(buffer==NULL || buffer->size()!=v.size()) {
- result=new VectorT<T>(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<class T>
- inline VectorT<T> *createGaussFunc(float sigma, VectorT<T> *buffer)
- {
- #ifdef NICE_USELIB_IPP
- int resultlength;
- VectorT<T> *result;
- if(buffer==NULL || buffer->size()<3) {
- int length=static_cast<int>(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<T>(resultlength);
- ippsCopy(base, result->getDataPointer(), 3);
- T tmp[resultlength];
- for(int i=0;i<length;i++) {
- ippsConv(base,3,result->getDataPointer(),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<resultlength;l+=1.0,i++) {
- (*result)[i]=exp(-l*l/(2*ssq))/norm;
- }
- }
- return result;
- #else
- _THROW_EVector("Not yet implementent without IPP.");
- #endif // NICE_USELIB_IPP
- }
- template<class T>
- inline void solveLinearEquationQR(const MatrixT<T> &A, const VectorT<T> &b, VectorT<T> &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<class T>
- inline void solveMDLgreedy(const MatrixT<T> &C, VectorT<T> &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<T> 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<class T>
- MatrixT<T> invert(const MatrixT<T>& w) {
- #ifdef NICE_USELIB_IPP
- size_t size = w.cols();
- if (size != w.rows()) {
- _THROW_EMatrix("invert: matrix is not square.");
- }
- MatrixT<T> 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<T> copy(w.linal());
- try {
- copy.LUinvert();
- } catch (std::exception& e) {
- fthrowc(Exception, "Invert failed", e);
- }
- MatrixT<T> result(copy);
- return result;
- #else
- _THROW_EVector("Not yet implementent without IPP or LinAl.");
- #endif
- #endif // NICE_USELIB_IPP
- }
- template<class T>
- void invert3x3UpperTriangle(MatrixT<T>& 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<class T>
- void invert3x3LowerTriangle(MatrixT<T>& 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);
- }
- }
|