/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2012 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLMath/src/DynMatrixUtils.cpp ** ** Module : ICLMath ** ** Authors: Christof Elbrechter, Daniel Dornbusch ** ** ** ** ** ** Commercial License ** ** ICL can be used commercially, please refer to our website ** ** www.iclcv.org for more details. ** ** ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the ** ** GNU General Public License version 3.0 as published by the ** ** Free Software Foundation and appearing in the file LICENSE.GPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the GNU General Public License ** ** version 3.0 requirements will be met: ** ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** *********************************************************************/ #include #include #include #include #ifdef HAVE_MKL #include "mkl_types.h" #include "mkl_cblas.h" #endif #ifdef HAVE_EIGEN3 #include #endif using namespace icl::utils; // check matrix dimensions: (m1.cols == m2.cols) and (m1.rows == m2.rows) //#define CHECK_DIM(m1,m2,RET) // ICLASSERT_RETURN_VAL( (m1.cols() == m2.cols()) && (m1.rows() == m2.rows()), RET) #define CHECK_DIM( m1, m2, RET ) \ ICLASSERT_THROW( (m1.cols() == m2.cols()) && (m1.rows() == m2.rows()), IncompatibleMatrixDimensionException(__FUNCTION__) ) // check matrix dimensions: (m1.cols == m2.rows) and (m1.rows == m2.cols) #define CHECK_DIM_T( m1, m2, RET ) \ ICLASSERT_THROW( (m1.cols() == m2.rows()) && (m1.rows() == m2.cols()), IncompatibleMatrixDimensionException(__FUNCTION__) ) // check matrix dimensions: m1.cols == m2.cols #define CHECK_DIM_CC( m1, m2, RET ) \ ICLASSERT_THROW( m1.cols() == m2.cols(), IncompatibleMatrixDimensionException(__FUNCTION__) ) // check matrix dimensions: m1.cols == m2.rows #define CHECK_DIM_CR( m1, m2, RET ) \ ICLASSERT_THROW( m1.cols() == m2.rows(), IncompatibleMatrixDimensionException(__FUNCTION__) ) // check matrix dimensions: m1.rows == m2.cols #define CHECK_DIM_RC( m1, m2, RET ) \ ICLASSERT_THROW( m1.rows() == m2.cols(), IncompatibleMatrixDimensionException(__FUNCTION__) ) // check matrix dimensions: m1.rows == m2.rows #define CHECK_DIM_RR( m1, m2, RET ) \ ICLASSERT_THROW( m1.rows() == m2.rows(), IncompatibleMatrixDimensionException(__FUNCTION__) ) namespace icl{ namespace math{ #ifdef HAVE_IPP /////////////////////////////////////////////////////////////////////////// // Caller-functions /////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// template static inline DynMatrix &ipp_unary_func_i(DynMatrix &m){ func(m.begin(),m.dim()); return m; } template static inline DynMatrix &ipp_unary_func(const DynMatrix &m, DynMatrix &dst){ dst.setBounds(m.cols(),m.rows()); func(m.begin(),dst.begin(),m.dim()); return dst; } template static inline DynMatrix &ipp_unary_func_c_i(DynMatrix &m,T val){ func(val,m.begin(),m.dim()); return m; } template static inline DynMatrix &ipp_unary_func_c(const DynMatrix &m,T val, DynMatrix &dst){ dst.setBounds(m.cols(),m.rows()); func(m.begin(),val,dst.begin(),m.dim()); return dst; } template static inline DynMatrix &ipp_binary_func(const DynMatrix &a, const DynMatrix &b, DynMatrix &dst){ CHECK_DIM(a,b,dst); dst.setBounds(a.cols(),a.rows()); func(b.begin(),a.begin(),dst.begin(),a.dim()); // direction is reversed (ipps->order) return dst; } /////////////////////////////////////////////////////////////////////////// // Unary functions //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// double reciprocal(const double &x) { return 1.0/x; } #define ICL_UNARY_HELP_FUNC(name,func) \ IppStatus ipps##name##_32f_I(float *p, int len){ \ std::transform(p,p+len,p,func); \ return ippStsNoErr; \ } \ IppStatus ipps##name##_64f_I(double *p, int len){ \ std::transform(p,p+len,p,func); \ return ippStsNoErr; \ } \ IppStatus ipps##name##_32f(const float *s, float *d, int len){ \ std::transform(s,s+len,d,func); \ return ippStsNoErr; \ } \ IppStatus ipps##name##_64f(const double *s, double *d, int len){ \ std::transform(s,s+len,d,func); \ return ippStsNoErr; \ } ICL_UNARY_HELP_FUNC(Sin_icl,::sin) ICL_UNARY_HELP_FUNC(Cos_icl,::cos) ICL_UNARY_HELP_FUNC(Tan_icl,::tan) ICL_UNARY_HELP_FUNC(Arcsin_icl,::asin) ICL_UNARY_HELP_FUNC(Arccos_icl,::acos) ICL_UNARY_HELP_FUNC(Reciprocal_icl,icl::math::reciprocal) #undef ICL_UNARY_HELP_FUNC #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template \ DynMatrix &matrix_##op(DynMatrix &m){ \ ERROR_LOG("not implemented for this type!"); \ return m; \ } \ template<> DynMatrix &matrix_##op(DynMatrix &m){ \ return ipp_unary_func_i(m); \ } \ template<> DynMatrix &matrix_##op(DynMatrix &m){ \ return ipp_unary_func_i(m); \ } \ template DynMatrix &matrix_##op(DynMatrix &m); \ template DynMatrix &matrix_##op(DynMatrix &m); \ \ template \ DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst){ \ ERROR_LOG("not implemented for this type!"); \ return dst; \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst){ \ return ipp_unary_func(m,dst); \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst){ \ return ipp_unary_func(m,dst); \ } \ template DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst); \ template DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst); INSTANTIATE_DYN_MATRIX_MATH_OP(abs,Abs) INSTANTIATE_DYN_MATRIX_MATH_OP(log,Ln) INSTANTIATE_DYN_MATRIX_MATH_OP(exp,Exp) INSTANTIATE_DYN_MATRIX_MATH_OP(sqrt,Sqrt) INSTANTIATE_DYN_MATRIX_MATH_OP(sqr,Sqr) INSTANTIATE_DYN_MATRIX_MATH_OP(sin,Sin_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(cos,Cos_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(tan,Tan_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(arcsin,Arcsin_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(arccos,Arccos_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(arctan,Arctan) INSTANTIATE_DYN_MATRIX_MATH_OP(reciprocal,Reciprocal_icl) #undef INSTANTIATE_DYN_MATRIX_MATH_OP template struct pow_functor{ const T val; inline pow_functor(const T val):val(val){} inline double operator()(const T &x) const{ return pow(x,val); } }; IppStatus ippsPow_icl_32f_I(float e, float *p, int len){ std::transform(p,p+len,p,pow_functor(e)); return ippStsNoErr; } IppStatus ippsPow_icl_64f_I(double e, double *p, int len){ std::transform(p,p+len,p,pow_functor(e)); return ippStsNoErr; } IppStatus ippsPow_icl_32f(const float *s,float e, float *d, int len){ std::transform(s,s+len,d,pow_functor(e)); return ippStsNoErr; } IppStatus ippsPow_icl_64f(const double *s,double e, double *d, int len){ std::transform(s,s+len,d,pow_functor(e)); return ippStsNoErr; } #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template DynMatrix &matrix_##op(DynMatrix &m, T val){ \ ERROR_LOG("not implemented for this type!"); \ return m; \ } \ template<> DynMatrix &matrix_##op(DynMatrix &m, float val){ \ return ipp_unary_func_c_i(m,val); \ } \ template<> DynMatrix &matrix_##op(DynMatrix &m, double val){ \ return ipp_unary_func_c_i(m,val); \ } \ template DynMatrix &matrix_##op(const DynMatrix &,T, DynMatrix &m){ \ ERROR_LOG("not implemented for this type!"); \ return m; \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &s,float val, DynMatrix &dst){ \ return ipp_unary_func_c(s,val,dst); \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &s,double val, DynMatrix &dst){ \ return ipp_unary_func_c(s,val,dst); \ } INSTANTIATE_DYN_MATRIX_MATH_OP(powc,Pow_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(addc,AddC) INSTANTIATE_DYN_MATRIX_MATH_OP(subc,SubC) INSTANTIATE_DYN_MATRIX_MATH_OP(mulc,MulC) INSTANTIATE_DYN_MATRIX_MATH_OP(divc,DivC) #undef INSTANTIATE_DYN_MATRIX_MATH_OP /////////////////////////////////////////////////////////////////////////// // Binary functions /////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// IppStatus ippsArctan2_icl_32f(const float *a, const float *b, float *dst, int len){ std::transform(b,b+len,a,dst,::atan2); return ippStsNoErr; } IppStatus ippsArctan2_icl_64f(const double *a, const double *b, double *dst, int len){ std::transform(b,b+len,a,dst,::atan2); return ippStsNoErr; } IppStatus ippsPow_icl_32f(const float *a, const float *b, float *dst, int len){ std::transform(a,a+len,b,dst,::pow); return ippStsNoErr; } IppStatus ippsPow_icl_64f(const double *a, const double *b, double *dst, int len){ std::transform(a,a+len,b,dst,::pow); return ippStsNoErr; } #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template \ DynMatrix &matrix_##op(const DynMatrix &a, const DynMatrix &b, DynMatrix &dst) \ throw (IncompatibleMatrixDimensionException){ \ ERROR_LOG("not implemented for this type!"); \ return dst; \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &a, const DynMatrix &b, DynMatrix &dst) \ throw (IncompatibleMatrixDimensionException){ \ return ipp_binary_func(a,b,dst); \ } \ template<> DynMatrix &matrix_##op(const DynMatrix &a, const DynMatrix &b, DynMatrix &dst) \ throw (IncompatibleMatrixDimensionException){ \ return ipp_binary_func(a,b,dst); \ } \ INSTANTIATE_DYN_MATRIX_MATH_OP(arctan2,Arctan2_icl) INSTANTIATE_DYN_MATRIX_MATH_OP(add,Add) INSTANTIATE_DYN_MATRIX_MATH_OP(sub,Sub) INSTANTIATE_DYN_MATRIX_MATH_OP(mul,Mul) INSTANTIATE_DYN_MATRIX_MATH_OP(div,Div) INSTANTIATE_DYN_MATRIX_MATH_OP(pow,Pow_icl) #undef INSTANTIATE_DYN_MATRIX_MATH_OP /////////////////////////////////////////////////////////////////////////// // Other functions //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// template T matrix_min(const DynMatrix &m, int *x, int *y){ ERROR_LOG("not implemented for this type!"); return 0; } template T matrix_max(const DynMatrix &m, int *x, int *y){ ERROR_LOG("not implemented for this type!"); return 0; } #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,type,suffix,ippf) \ template<> type matrix_##op(const DynMatrix &m, int *x, int *y){ \ type mVal = 0; \ if(x || y){ \ int mIdx = 0; \ ipps##ippf##Indx_##suffix(m.begin(),m.dim(),&mVal,&mIdx); \ if(x) *x = mIdx%m.cols(); \ if(y) *y = mIdx/m.cols(); \ }else{ \ ipps##ippf##_##suffix(m.begin(),m.dim(),&mVal); \ } \ return mVal; \ } INSTANTIATE_DYN_MATRIX_MATH_OP(min,float,32f,Min) INSTANTIATE_DYN_MATRIX_MATH_OP(max,float,32f,Max) INSTANTIATE_DYN_MATRIX_MATH_OP(min,double,64f,Min) INSTANTIATE_DYN_MATRIX_MATH_OP(max,double,64f,Max) #undef INSTANTIATE_DYN_MATRIX_MATH_OP template void matrix_minmax(const DynMatrix &m, T dst[2], int *minx, int *miny, int *maxx, int *maxy){ ERROR_LOG("not implemented for this type!"); } template<> void matrix_minmax(const DynMatrix &m, float dst[2], int *minx, int *miny, int *maxx, int *maxy){ if(minx || miny || maxx || maxy){ int minIdx = 0; int maxIdx = 0; ippsMinMaxIndx_32f(m.begin(),m.dim(),dst+0,&minIdx,dst+1,&maxIdx); if(minx) *minx = minIdx%m.cols(); if(miny) *miny = minIdx/m.cols(); if(maxx) *maxx = maxIdx%m.cols(); if(maxy) *maxy = maxIdx/m.cols(); }else{ ippsMinMax_32f(m.begin(),m.dim(),dst+0,dst+1); } } template<> void matrix_minmax(const DynMatrix &m, double dst[2], int *minx, int *miny, int *maxx, int *maxy){ if(minx || miny || maxx || maxy){ int minIdx = 0; int maxIdx = 0; ippsMinMaxIndx_64f(m.begin(),m.dim(),dst+0,&minIdx,dst+1,&maxIdx); if(minx) *minx = minIdx%m.cols(); if(miny) *miny = minIdx/m.cols(); if(maxx) *maxx = maxIdx%m.cols(); if(maxy) *maxy = maxIdx/m.cols(); }else{ ippsMinMax_64f(m.begin(),m.dim(),dst+0,dst+1); } } #else // ************************************************************************** // No IPP fallbacks // ************************************************************************** #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template \ void elem_i_##op(T &t){ \ t = func(t); \ } \ template \ T elem_##op(const T &t){ \ return func(t); \ } \ template \ DynMatrix &matrix_##op(DynMatrix &m){ \ std::for_each(m.begin(),m.end(),elem_i_##op); \ return m; \ } \ template \ DynMatrix &matrix_##op(const DynMatrix &m, DynMatrix &dst){ \ dst.setBounds(m.cols(),m.rows()); \ std::transform(m.begin(),m.end(),dst.begin(),elem_##op); \ return dst; \ } \ template DynMatrix &matrix_##op(DynMatrix &m); \ template DynMatrix &matrix_##op(DynMatrix &m); static inline double sqr(double x) { return x*x; } static inline double reciprocal(double x) { return x ? 1.0/x : 0 ; } INSTANTIATE_DYN_MATRIX_MATH_OP(abs,::fabs) INSTANTIATE_DYN_MATRIX_MATH_OP(log,::log) INSTANTIATE_DYN_MATRIX_MATH_OP(exp,::exp) INSTANTIATE_DYN_MATRIX_MATH_OP(sqrt,::sqrt) INSTANTIATE_DYN_MATRIX_MATH_OP(sqr,icl::sqr) INSTANTIATE_DYN_MATRIX_MATH_OP(reciprocal,icl::reciprocal) INSTANTIATE_DYN_MATRIX_MATH_OP(sin,::sin) INSTANTIATE_DYN_MATRIX_MATH_OP(cos,::cos) INSTANTIATE_DYN_MATRIX_MATH_OP(tan,::tan) INSTANTIATE_DYN_MATRIX_MATH_OP(arcsin,::asin) INSTANTIATE_DYN_MATRIX_MATH_OP(arccos,::acos) INSTANTIATE_DYN_MATRIX_MATH_OP(arctan,::atan) #undef INSTANTIATE_DYN_MATRIX_MATH_OP #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template struct op##_inplace_functor{ \ const T val; \ inline op##_inplace_functor(const T &val):val(val){} \ inline void operator()(T &x) const{ \ x = func(x,val); \ } \ }; \ template struct op##_functor{ \ const T val; \ inline op##_functor(const T val):val(val){} \ inline double operator()(const T &x) const{ \ return func(x,val); \ } \ }; \ template \ DynMatrix &matrix_##op(DynMatrix &m, T val){ \ std::for_each(m.begin(),m.end(),op##_inplace_functor(val)); \ return m; \ } \ template \ DynMatrix &matrix_##op(const DynMatrix &m, T val, DynMatrix &dst){ \ std::transform(m.begin(),m.end(),dst.begin(),op##_functor(val)); \ return dst; \ } \ template DynMatrix &matrix_##op(DynMatrix&, float); \ template DynMatrix &matrix_##op(DynMatrix&, double); \ template DynMatrix &matrix_##op(const DynMatrix&, float, DynMatrix&); \ template DynMatrix &matrix_##op(const DynMatrix&, double, DynMatrix&); template static inline T addc(const T &a, const T &b){ return a+b; } template static inline T subc(const T &a, const T &b){ return a-b; } template static inline T divc(const T &a, const T &b){ return a/b; } template static inline T mulc(const T &a, const T &b){ return a*b; } INSTANTIATE_DYN_MATRIX_MATH_OP(powc,::pow) INSTANTIATE_DYN_MATRIX_MATH_OP(addc,icl::addc) INSTANTIATE_DYN_MATRIX_MATH_OP(subc,icl::subc) INSTANTIATE_DYN_MATRIX_MATH_OP(mulc,icl::mulc) INSTANTIATE_DYN_MATRIX_MATH_OP(divc,icl::divc) #undef INSTANTIATE_DYN_MATRIX_MATH_OP // binary functions #define INSTANTIATE_DYN_MATRIX_MATH_OP(op,func) \ template \ DynMatrix &matrix_##op(const DynMatrix &a, const DynMatrix &b, DynMatrix &dst) \ throw (IncompatibleMatrixDimensionException){ \ CHECK_DIM(a,b,dst); \ dst.setBounds(a.cols(),a.rows()); \ std::transform(a.begin(),a.end(),b.begin(),dst.begin(),func); \ return dst; \ } \ template DynMatrix &matrix_##op(const DynMatrix&, const DynMatrix&, DynMatrix&) \ throw (IncompatibleMatrixDimensionException); \ template DynMatrix &matrix_##op(const DynMatrix&, const DynMatrix&, DynMatrix&) \ throw (IncompatibleMatrixDimensionException); INSTANTIATE_DYN_MATRIX_MATH_OP(pow,::pow) INSTANTIATE_DYN_MATRIX_MATH_OP(add,icl::addc) INSTANTIATE_DYN_MATRIX_MATH_OP(sub,icl::subc) INSTANTIATE_DYN_MATRIX_MATH_OP(mul,icl::mulc) INSTANTIATE_DYN_MATRIX_MATH_OP(div,icl::divc) INSTANTIATE_DYN_MATRIX_MATH_OP(arctan2,::atan2) #undef INSTANTIATE_DYN_MATRIX_MATH_OP // others template T matrix_min(const DynMatrix &m, int *x, int *y){ ICLASSERT_RETURN_VAL(m.cols(),0); const T *a = std::min_element(m.begin(),m.end()); int idx = (int)(a-m.begin()); if(x) *x = idx%m.cols(); if(y) *y = idx/m.cols(); return *a; } template float matrix_min(const DynMatrix &m, int *x, int *y); template double matrix_min(const DynMatrix &m, int *x, int *y); template T matrix_max(const DynMatrix &m, int *x, int *y){ ICLASSERT_RETURN_VAL(m.cols(),0); const T *a = std::max_element(m.begin(),m.end()); int idx = (int)(a-m.begin()); if(x) *x = idx%m.cols(); if(y) *y = idx/m.cols(); return *a; } template float matrix_max(const DynMatrix &m, int *x, int *y); template double matrix_max(const DynMatrix &m, int *x, int *y); template void matrix_minmax(const DynMatrix &m, T dst[2], int *minx, int *miny, int *maxx, int *maxy){ dst[0] = matrix_min(m,minx,miny); dst[1] = matrix_max(m,maxx,maxy); } template void matrix_minmax(const DynMatrix &m, float dst[2],int*,int*,int*,int*); template void matrix_minmax(const DynMatrix &m, double dst[2],int*,int*,int*,int*); #endif //HAVE_IPP /// ------------------------------------------------------------ /// ipp and non-ipp mixed ... /// ------------------------------------------------------------ // MEAN *************************** template T matrix_mean(const DynMatrix &m){ return std::accumulate(m.begin(),m.end(),T(0))/m.dim(); } #ifdef HAVE_IPP template<> float matrix_mean(const DynMatrix &m){ float v=0; ippsMean_32f(m.begin(),m.dim(),&v,ippAlgHintNone); return v; } template<> double matrix_mean(const DynMatrix &m){ double v=0; ippsMean_64f(m.begin(),m.dim(),&v); return v; } #endif // HAVE_IPP template float matrix_mean(const DynMatrix&); template double matrix_mean(const DynMatrix&); // VAR *************************** template struct var_functor{ T mean,&accu; static inline T util_sqr(const T &t){ return t*t; } var_functor(const T &mean, T &accu):mean(mean),accu(accu){} void operator()(const T&x) const { accu += util_sqr(mean-x); } }; template T matrix_var(const DynMatrix &m){ if(m.dim()<2){ return 0; } T var = 0; std::for_each(m.begin(),m.end(),var_functor(matrix_mean(m),var)); return var/(m.dim()-1); } #ifdef HAVE_IPP template<> float matrix_var(const DynMatrix &m){ float v=0; ippsStdDev_32f(m.begin(),m.dim(),&v,ippAlgHintNone); return v*v; } template<> double matrix_var(const DynMatrix &m){ double v=0; ippsStdDev_64f(m.begin(),m.dim(),&v); return v*v; } #endif // HAVE_IPP template float matrix_var(const DynMatrix&); template double matrix_var(const DynMatrix&); // VAR (2)*************************** template T matrix_var(const DynMatrix &m, T mean, bool empiricalMean){ if(m.dim()<2){ return 0; } T var = 0; std::for_each(m.begin(),m.end(),var_functor(mean,var)); int norm = empiricalMean ? (m.dim()-1) : m.dim(); return var/norm; } template float matrix_var(const DynMatrix&, float, bool); template double matrix_var(const DynMatrix&, double, bool); // MEANVAR *************************** template void matrix_meanvar(const DynMatrix &m, T *mean, T*var){ T meanVal = matrix_mean(m); T varVal = matrix_var(m,meanVal,true); if(mean) *mean=meanVal; if(var) *var=varVal; } #ifdef HAVE_IPP template<> void matrix_meanvar(const DynMatrix &m, float *mean, float *var){ ICLASSERT_RETURN(mean && var); ippsMeanStdDev_32f(m.begin(),m.dim(),mean,var,ippAlgHintNone); *var = (*var)*(*var); } template<> void matrix_meanvar(const DynMatrix &m, double *mean, double*var){ ICLASSERT_RETURN(mean && var); ippsMeanStdDev_64f(m.begin(),m.dim(),mean,var); *var = (*var)*(*var); } #endif // HAVE_IPP template void matrix_meanvar(const DynMatrix&,float*,float*); template void matrix_meanvar(const DynMatrix&,double*,double*); // STDDEV *************************** template T matrix_stddev(const DynMatrix &m){ return ::sqrt(matrix_var(m)); } template float matrix_stddev(const DynMatrix&); template double matrix_stddev(const DynMatrix&); template T matrix_stddev(const DynMatrix &m, T mean, bool empiricalMean){ return ::sqrt(matrix_var(m,mean,empiricalMean)); } template float matrix_stddev(const DynMatrix&,float,bool); template double matrix_stddev(const DynMatrix&,double,bool); template struct muladd_functor_1{ T alpha,gamma; inline muladd_functor_1(const T &alpha, const T &gamma):alpha(alpha),gamma(gamma){} inline T operator()(const T&a) const{ return alpha*a + gamma; } }; template struct muladd_functor_2{ T alpha,beta,gamma; inline muladd_functor_2(const T &alpha, const T &beta,const T &gamma):alpha(alpha),beta(beta),gamma(gamma){} inline T operator()(const T&a, const T&b) const{ return alpha*a + beta*b + gamma; } }; template DynMatrix &matrix_muladd(const DynMatrix &a,T alpha, const DynMatrix &b, T beta, T gamma, DynMatrix &dst) throw (IncompatibleMatrixDimensionException){ CHECK_DIM(a,b,dst); if(!alpha) return matrix_muladd(b,beta,gamma,dst); if(!beta) return matrix_muladd(a,alpha,gamma,dst); dst.setBounds(a.cols(),a.rows()); std::transform(a.begin(),a.end(),b.begin(),dst.begin(),muladd_functor_2(alpha,beta,gamma)); return dst; } template DynMatrix &matrix_muladd(const DynMatrix&,float,const DynMatrix&,float,float,DynMatrix&) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_muladd(const DynMatrix&,double,const DynMatrix&,double,double,DynMatrix&) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_muladd(const DynMatrix &a,T alpha, T gamma, DynMatrix &dst){ dst.setBounds(a.cols(),a.rows()); if(!alpha){ std::fill(dst.begin(),dst.end(),gamma); }else{ std::transform(a.begin(),a.end(),dst.begin(),muladd_functor_1(alpha,gamma)); } return dst; } template DynMatrix &matrix_muladd(const DynMatrix&,float,float,DynMatrix&); template DynMatrix &matrix_muladd(const DynMatrix&,double,double,DynMatrix&); template struct mask_functor{ T operator()(const unsigned char &mask,const T &m) const{ return mask ? m : 0; } }; template DynMatrix &matrix_mask(const DynMatrix &mask, DynMatrix &m) throw (IncompatibleMatrixDimensionException){ CHECK_DIM(mask,m,m); std::transform(mask.begin(),mask.end(),m.begin(),m.begin(),mask_functor()); return m; } template DynMatrix &matrix_mask(const DynMatrix &mask, DynMatrix &m) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_mask(const DynMatrix &mask, DynMatrix &m) throw (IncompatibleMatrixDimensionException); /// applies masking operation (m(i,j) is set to 0 if mask(i,j) is 0) template DynMatrix &matrix_mask(const DynMatrix &mask, const DynMatrix &m, DynMatrix &dst) throw (IncompatibleMatrixDimensionException){ CHECK_DIM(mask,m,dst); dst.setBounds(m.cols(),m.rows()); std::transform(mask.begin(),mask.end(),m.begin(),dst.begin(),mask_functor()); return dst; } template DynMatrix &matrix_mask(const DynMatrix &mask, const DynMatrix &m, DynMatrix &dst) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_mask(const DynMatrix &mask, const DynMatrix &m, DynMatrix &dst) throw (IncompatibleMatrixDimensionException); template struct matrix_distance_op{ T e; matrix_distance_op(const T &e):e(e){} inline T operator()(const T &a, const T&b) const{ return ::pow(a-b,e); } }; template T matrix_distance(const DynMatrix &m1, const DynMatrix &m2, T norm) throw (IncompatibleMatrixDimensionException){ CHECK_DIM(m1,m2,-1); ICLASSERT_RETURN_VAL(norm > 0,-1); T result = std::inner_product(m1.begin(),m1.end(),m2.begin(),T(0),std::plus(),matrix_distance_op(norm)); return pow(result,1/norm); } template float matrix_distance(const DynMatrix &m1, const DynMatrix &m2, float) throw (IncompatibleMatrixDimensionException); template double matrix_distance(const DynMatrix &, const DynMatrix &, double) throw (IncompatibleMatrixDimensionException); template struct matrix_divergence_op{ inline T operator()(const T &a, const T&b) const{ return a * log(a/b) - a + b; } }; template T matrix_divergence(const DynMatrix &m1, const DynMatrix &m2) throw (IncompatibleMatrixDimensionException){ CHECK_DIM(m1,m2,-1); return std::inner_product(m1.begin(),m1.end(),m2.begin(),T(0),std::plus(),matrix_divergence_op()); } template float matrix_divergence(const DynMatrix&, const DynMatrix&) throw (IncompatibleMatrixDimensionException); template double matrix_divergence(const DynMatrix&, const DynMatrix&) throw (IncompatibleMatrixDimensionException); /// matrix functions for transposed matrices ... template DynMatrix &matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: return src1.mult(src2,dst); case SRC1_T: return src1.transp().mult(src2,dst); case SRC2_T: return src1.mult(src2.transp(),dst); case BOTH_T: return src1.transp().mult(src2.transp(),dst); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template DynMatrix &big_matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ return matrix_mult_t( src1, src2, dst, transpDef ); } template DynMatrix &matrix_add_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: return matrix_add(src1,src2,dst); case SRC1_T: return matrix_add(src1.transp(),src2,dst); case SRC2_T: return matrix_add(src1,src2.transp(),dst); case BOTH_T: return matrix_add(src1.transp(),src2.transp(),dst); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template DynMatrix &matrix_sub_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: return matrix_sub(src1,src2,dst); case SRC1_T: return matrix_sub(src1.transp(),src2,dst); case SRC2_T: return matrix_sub(src1,src2.transp(),dst); case BOTH_T: return matrix_sub(src1.transp(),src2.transp(),dst); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } #ifdef HAVE_IPP template DynMatrix &ipp_func_t_call(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, func f)throw (IncompatibleMatrixDimensionException){ IppStatus status = f(src1.begin(),src1.stride1(),src1.stride2(),src1.cols(),src1.rows(), src2.begin(),src2.stride1(),src2.stride2(),src2.cols(),src2.rows(), dst.begin(),dst.stride1(), dst.stride2()); if(status != ippStsNoErr){ throw IncompatibleMatrixDimensionException(ippGetStatusString(status)); } return dst; } template DynMatrix &ipp_func_t_call_2(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, func f)throw (IncompatibleMatrixDimensionException){ IppStatus status = f(src1.begin(),src1.stride1(),src1.stride2(), src2.begin(),src2.stride1(),src2.stride2(), dst.begin(),dst.stride1(), dst.stride2(), dst.cols(),dst.rows()); if(status != ippStsNoErr){ throw IncompatibleMatrixDimensionException(ippGetStatusString(status)); } return dst; } template<> DynMatrix &matrix_add_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_mm_32f); case SRC1_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src2.cols(),src2.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_tm_32f); case SRC2_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src2,src1,dst,ippmAdd_tm_32f); case BOTH_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.rows(),src1.cols()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_tt_32f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &matrix_add_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_mm_64f); case SRC1_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src2.cols(),src2.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_tm_64f); case SRC2_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src2,src1,dst,ippmAdd_tm_64f); case BOTH_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.rows(),src1.cols()); return ipp_func_t_call_2(src1,src2,dst,ippmAdd_tt_64f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &matrix_sub_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_mm_32f); case SRC1_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src2.cols(),src2.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_tm_32f); case SRC2_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src2,src1,dst,ippmSub_tm_32f); case BOTH_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.rows(),src1.cols()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_tt_32f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &matrix_sub_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_mm_64f); case SRC1_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src2.cols(),src2.rows()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_tm_64f); case SRC2_T: CHECK_DIM_T(src1,src2,dst); dst.setBounds(src1.cols(),src1.rows()); return ipp_func_t_call_2(src2,src1,dst,ippmSub_tm_64f); case BOTH_T: CHECK_DIM(src1,src2,dst); dst.setBounds(src1.rows(),src1.cols()); return ipp_func_t_call_2(src1,src2,dst,ippmSub_tt_64f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM_CR(src1,src2,dst); dst.setBounds(src2.cols(),src1.rows()); return ipp_func_t_call(src1,src2,dst,ippmMul_mm_32f); case SRC1_T: CHECK_DIM_RR(src1,src2,dst); dst.setBounds(src2.cols(),src1.cols()); return ipp_func_t_call(src1,src2,dst,ippmMul_tm_32f); case SRC2_T: CHECK_DIM_CC(src1,src2,dst); dst.setBounds(src2.rows(),src1.rows()); return ipp_func_t_call(src1,src2,dst,ippmMul_mt_32f); case BOTH_T: CHECK_DIM_RC(src1,src2,dst); dst.setBounds(src2.rows(),src1.cols()); return ipp_func_t_call(src1,src2,dst,ippmMul_tt_32f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM_CR(src1,src2,dst); dst.setBounds(src2.cols(),src1.rows()); return ipp_func_t_call(src1,src2,dst,ippmMul_mm_64f); case SRC1_T: CHECK_DIM_RR(src1,src2,dst); dst.setBounds(src2.cols(),src1.cols()); return ipp_func_t_call(src1,src2,dst,ippmMul_tm_64f); case SRC2_T: CHECK_DIM_CC(src1,src2,dst); dst.setBounds(src2.rows(),src1.rows()); return ipp_func_t_call(src1,src2,dst,ippmMul_mt_64f); case BOTH_T: CHECK_DIM_RC(src1,src2,dst); dst.setBounds(src2.rows(),src1.cols()); return ipp_func_t_call(src1,src2,dst,ippmMul_tt_64f); default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } #endif // HAVE_IPP // optimized specialization only if MKL was found #ifdef HAVE_MKL template<> DynMatrix &big_matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM_CR(src1,src2,dst); dst.setBounds(src2.cols(),src1.rows()); cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, src1.rows(), src2.cols(), src1.cols(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.cols()); return dst; case SRC1_T: CHECK_DIM_RR(src1,src2,dst); dst.setBounds(src2.cols(),src1.cols()); cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans, src1.cols(), src2.cols(), src1.rows(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.cols()); return dst; case SRC2_T: CHECK_DIM_CC(src1,src2,dst); dst.setBounds(src2.rows(),src1.rows()); cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, src1.rows(), src2.rows(), src1.cols(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.rows()); return dst; case BOTH_T: CHECK_DIM_RC(src1,src2,dst); dst.setBounds(src2.rows(),src1.cols()); cblas_sgemm(CblasRowMajor, CblasTrans, CblasTrans, src1.cols(), src2.rows(), src1.rows(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.rows()); return dst; default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } template<> DynMatrix &big_matrix_mult_t(const DynMatrix &src1, const DynMatrix &src2, DynMatrix &dst, int transpDef) throw (IncompatibleMatrixDimensionException){ switch(transpDef){ case NONE_T: CHECK_DIM_CR(src1,src2,dst); dst.setBounds(src2.cols(),src1.rows()); cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, src1.rows(), src2.cols(), src1.cols(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.cols()); return dst; case SRC1_T: CHECK_DIM_RR(src1,src2,dst); dst.setBounds(src2.cols(),src1.cols()); cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, src1.cols(), src2.cols(), src1.rows(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.cols()); return dst; case SRC2_T: CHECK_DIM_CC(src1,src2,dst); dst.setBounds(src2.rows(),src1.rows()); cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, src1.rows(), src2.rows(), src1.cols(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.rows()); return dst; case BOTH_T: CHECK_DIM_RC(src1,src2,dst); dst.setBounds(src2.rows(),src1.cols()); cblas_dgemm(CblasRowMajor, CblasTrans, CblasTrans, src1.cols(), src2.rows(), src1.rows(), 1.0, src1.begin(), src1.cols(), src2.begin(), src2.cols(), 0.0, dst.begin(), src2.rows()); return dst; default: ERROR_LOG("undefined definition of transposed matrices: "<< transpDef); } return dst; } #endif template DynMatrix &matrix_mult_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_mult_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &big_matrix_mult_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &big_matrix_mult_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_add_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_add_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_sub_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); template DynMatrix &matrix_sub_t(const DynMatrix&,const DynMatrix&,DynMatrix&,int) throw (IncompatibleMatrixDimensionException); // undefine macros #undef CHECK_DIM #undef CHECK_DIM_T #undef CHECK_DIM_CC #undef CHECK_DIM_CR #undef CHECK_DIM_RC #undef CHECK_DIM_RR #ifndef HAVE_EIGEN3 // C++ fallback for SVD static int svd_internal(int m,int n,int withu,int withv,double eps,double tol, double **a,double *q,double **u,double **v){ /** found here: http://www.crbond.com/download/misc/svd.c*/ /* svd.c -- Singular value decomposition. Translated to 'C' from the * original Algol code in "Handbook for Automatic Computation, * vol. II, Linear Algebra", Springer-Verlag. * * (C) 2000, C. Bond. All rights reserved. * * This is almost an exact translation from the original, except that * an iteration counter is added to prevent stalls. This corresponds * to similar changes in other translations. * * Returns an error code = 0, if no errors and 'k' if a failure to * converge at the 'kth' singular value. * */ int i,j,k,l(0),l1,iter,retval; double c,f,g,h,s,x,y,z; double *e; e = (double *)calloc(n,sizeof(double)); retval = 0; /* Copy 'a' to 'u' */ for (i=0;i x) x = y; } /* end i */ /* accumulation of right-hand transformations */ if (withv) { for (i=n-1;i>=0;i--) { if (g != 0.0) { h = u[i][i+1] * g; for (j=l;j=0;i--) { l = i + 1; g = q[i]; for (j=l;j=0;k--) { iter = 0; test_f_splitting: for (l=k;l>=0;l--) { if (fabs(e[l]) <= eps) goto test_f_convergence; if (fabs(q[l-1]) <= eps) goto cancellation; } /* end l */ /* cancellation of e[l] if l > 0 */ cancellation: c = 0.0; s = 1.0; l1 = l - 1; for (i=l;i<=k;i++) { f = s * e[i]; e[i] *= c; if (fabs(f) <= eps) goto test_f_convergence; g = q[i]; h = q[i] = sqrt(f*f + g*g); c = g / h; s = -f / h; if (withu) { for (j=0;j 30) { retval = k; break; } x = q[l]; y = q[k-1]; g = e[k-1]; h = e[k]; f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y); g = sqrt(f*f + 1.0); f = ((x-z)*(x+z) + h*(y/((f<0)?(f-g):(f+g))-h))/x; /* next QR transformation */ c = s = 1.0; for (i=l+1;i<=k;i++) { g = e[i]; y = q[i]; h = s * g; g *= c; e[i-1] = z = sqrt(f*f+h*h); c = f / z; s = h / z; f = x * c + g * s; g = -x * s + g * c; h = y * s; y *= c; if (withv) { for (j=0;j &M){ double **m = svd_get_mat(M.rows(),M.cols()); for(unsigned int i=0;i i.ev; } }; } static void svd_copy_mat_sort(double **m, DynMatrix &M, const std::vector &idxlut){ for(unsigned int j=0;j &M, const std::vector &idxlut){ for(unsigned int j=0;j void svd_eigen(const DynMatrix &M, DynMatrix &U, DynMatrix &s, DynMatrix &Vt) throw (ICLException){ typedef Eigen::Matrix EigenMat; int sdim = iclMin(M.rows(),M.cols()); Eigen::Map m(const_cast(M.begin()),M.rows(),M.cols()); Eigen::JacobiSVD svd(m, Eigen::ComputeThinU | Eigen::ComputeFullV); Eigen::Map ms(s.begin(),sdim,s.cols()); std::fill(s.begin()+sdim, s.end(), 0); Eigen::Map mV(Vt.begin(),Vt.rows(),Vt.cols()); ms = svd.singularValues(); if(M.cols() > M.rows()){ // wrap eigen matrix around the left part of the ICL-Matrix std::fill(U.begin(),U.end(),0); Eigen::Map > mU(U.begin(),U.rows(),sdim, Eigen::OuterStride<>(U.cols())); mU = svd.matrixU(); }else{ Eigen::Map mU(U.begin(),U.rows(),U.cols()); mU = svd.matrixU(); } mV = svd.matrixV(); } #endif template void svd_dyn(const DynMatrix &A, DynMatrix &U, DynMatrix &s, DynMatrix &V) throw (ICLException){ (void)A; (void)U; (void)s; (void)V; } template<> void svd_dyn(const DynMatrix &M, DynMatrix &U, DynMatrix &s, DynMatrix &Vt) throw (ICLException){ U.setBounds(M.cols(), M.rows()); Vt.setBounds(M.cols(), M.cols()); s.setBounds(1,M.cols()); #if defined HAVE_IPP_SVD int niter = M.rows(); while (true) { IppStatus status = ippsSVDSort_64f_D2(M.begin(), U.begin(), M.rows(), s.begin(), Vt.begin(), M.cols(), M.cols(), niter); switch (status) { case ippStsNoErr: return; case ippStsSVDCnvgErr: // indicates that the algorithm did not converge in niter steps. niter *= 2; break; default: throw ICLException(ippGetStatusString(status)); } } #elif defined HAVE_EIGEN3 svd_eigen(M,U,s,Vt); #else double ** _M = svd_get_mat(M); double ** _U = svd_get_mat(iclMax(M.rows(),M.cols()),iclMax(M.rows(),M.cols())); double ** _V = svd_get_mat(M.cols(),M.cols()); double * _s = new double[M.cols()]; int r = svd_internal(M.rows(),M.cols(), 1, 1, 10e-18,10e-18, _M, _s, _U, _V); if(r) { throw ICLException("error in svd (c++): no convergence for singular value '" + str(r) +"'"); } std::vector idxlut(M.cols()); for(unsigned int i=0;i void svd_dyn(const DynMatrix &A, DynMatrix &U, DynMatrix &s, DynMatrix &V) throw (ICLException){ U.setBounds(A.cols(), A.rows()); V.setBounds(A.cols(), A.cols()); s.setBounds(1,A.cols()); #if defined HAVE_EIGEN3 && !defined HAVE_IPP svd_eigen(A,U,s,V); #else DynMatrix A64f(A.cols(),A.rows()),U64f(U.cols(),U.rows()),s64f(1,s.rows()),V64f(V.cols(),V.rows()); std::copy(A.begin(),A.end(),A64f.begin()); svd_dyn(A64f,U64f,s64f,V64f); std::copy(U64f.begin(),U64f.end(),U.begin()); std::copy(V64f.begin(),V64f.end(),V.begin()); std::copy(s64f.begin(),s64f.end(),s.begin()); #endif } } // namespace math }