inline bool princomp ( Mat<typename T1::elem_type>& coeff_out, Mat<typename T1::elem_type>& score_out, Col<typename T1::pod_type>& latent_out, Col<typename T1::elem_type>& tsquared_out, const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); const bool status = op_princomp::direct_princomp(coeff_out, score_out, latent_out, tsquared_out, X); if(status == false) { coeff_out.reset(); score_out.reset(); latent_out.reset(); tsquared_out.reset(); arma_bad("princomp(): failed to converge", false); } return status; }
void expectedColReset() { cout << "- Compute expectedColReset() ... "; Col<double> expected = _genColVec; expected.reset(); save<double>("Col.reset", expected); cout << "done." << endl; }
inline bool eigs_sym ( Col<typename T1::pod_type >& eigval, const SpBase<typename T1::elem_type,T1>& X, const uword n_eigvals, const char* form = "lm", const typename T1::elem_type tol = 0.0, const typename arma_real_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Mat<typename T1::elem_type> eigvec; const bool status = sp_auxlib::eigs_sym(eigval, eigvec, X, n_eigvals, form, tol); if(status == false) { eigval.reset(); arma_bad("eigs_sym(): failed to converge", false); } return status; }
inline typename enable_if2< is_supported_blas_type<typename T1::pod_type>::value, bool >::result eig_pair ( Col< std::complex<typename T1::pod_type> >& eigvals, Mat< std::complex<typename T1::pod_type> >& eigvecs, const Base< typename T1::elem_type, T1 >& A_expr, const Base< typename T1::elem_type, T2 >& B_expr ) { arma_extra_debug_sigprint(); arma_debug_check( (void_ptr(&eigvals) == void_ptr(&eigvecs)), "eig_pair(): parameter 'eigval' is an alias of parameter 'eigvec'" ); const bool status = auxlib::eig_pair(eigvals, eigvecs, true, A_expr.get_ref(), B_expr.get_ref()); if(status == false) { eigvals.reset(); eigvecs.reset(); arma_debug_warn("eig_pair(): decomposition failed"); } return status; }
inline bool eig_sym ( Col<typename T1::pod_type>& eigval, Mat<typename T1::elem_type>& eigvec, const Base<typename T1::elem_type,T1>& X, const char* method = "dc", const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eig_sym(): eigval is an alias of eigvec" ); const char sig = (method != NULL) ? method[0] : char(0); arma_debug_check( ((sig != 's') && (sig != 'd')), "eig_sym(): unknown method specified" ); const bool status = (sig == 'd') ? auxlib::eig_sym_dc(eigval, eigvec, X) : auxlib::eig_sym(eigval, eigvec, X); if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_sym(): failed to converge", false); } return status; }
inline bool eig_pair ( Col< std::complex<T> >& eigval, Mat< std::complex<T> >& eigvec, const Base< std::complex<T>, T1 >& A, const Base< std::complex<T>, T2 >& B, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_pair(): eigval is an alias of eigvec" ); Mat< std::complex<T> > dummy_eigvec; const bool status = auxlib::eig_pair(eigval, dummy_eigvec, eigvec, A, B, 'r'); if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_pair(): failed to converge", false); } return status; }
inline bool eig_gen ( Col< std::complex<T> >& eigval, const Base<T, T1>& X, const typename arma_blas_type_only<T>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Mat<T> l_eigvec; Mat<T> r_eigvec; const bool status = auxlib::eig_gen(eigval, l_eigvec, r_eigvec, X, 'n'); if(status == false) { eigval.reset(); arma_bad("eig_gen(): failed to converge", false); } return status; }
inline typename enable_if2< is_supported_blas_type<typename T1::pod_type>::value, Col< std::complex<typename T1::pod_type> > >::result eig_gen ( const Base<typename T1::elem_type, T1>& expr ) { arma_extra_debug_sigprint(); typedef typename T1::pod_type T; typedef typename std::complex<T> eT; Col<eT> eigvals; Mat<eT> eigvecs; const bool status = auxlib::eig_gen(eigvals, eigvecs, false, expr.get_ref()); if(status == false) { eigvals.reset(); arma_bad("eig_gen(): decomposition failed"); } return eigvals; }
inline bool eig_pair ( Col< std::complex<eT> >& eigval, const Base< eT, T1 >& A, const Base< eT, T2 >& B, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Mat<eT> l_eigvec; Mat<eT> r_eigvec; const bool status = auxlib::eig_pair(eigval, l_eigvec, r_eigvec, A, B, 'n'); if(status == false) { eigval.reset(); arma_bad("eig_pair(): failed to converge", false); } return status; }
inline Col< std::complex<T> > eig_pair ( const Base< std::complex<T>, T1>& A, const Base< std::complex<T>, T1>& B, const typename arma_blas_type_only< std::complex<T> >::result* junk1 = 0, const typename arma_cx_only< std::complex<T> >::result* junk2 = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk1); arma_ignore(junk2); Mat< std::complex<T> > l_eigvec; Mat< std::complex<T> > r_eigvec; Col< std::complex<T> > eigval; const bool status = auxlib::eig_pair(eigval, l_eigvec, r_eigvec, A, B, 'n'); if(status == false) { eigval.reset(); arma_bad("eig_pair(): failed to converge"); } return eigval; }
inline typename enable_if2< is_supported_blas_type<typename T1::pod_type>::value, bool >::result eig_pair ( Col< std::complex<typename T1::pod_type> >& eigvals, const Base< typename T1::elem_type, T1 >& A_expr, const Base< typename T1::elem_type, T2 >& B_expr ) { arma_extra_debug_sigprint(); typedef typename T1::pod_type T; Mat< std::complex<T> > eigvecs; const bool status = auxlib::eig_pair(eigvals, eigvecs, false, A_expr.get_ref(), B_expr.get_ref()); if(status == false) { eigvals.reset(); arma_debug_warn("eig_pair(): decomposition failed"); } return status; }
inline bool eigs_sym ( Col<typename T1::pod_type >& eigval, Mat<typename T1::elem_type>& eigvec, const SpBase<typename T1::elem_type,T1>& X, const uword n_eigvals, const char* form = "lm", const typename T1::elem_type tol = 0.0, const typename arma_real_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eigs_sym(): paramater 'eigval' is an alias of parameter 'eigvec'" ); const bool status = sp_auxlib::eigs_sym(eigval, eigvec, X, n_eigvals, form, tol); if(status == false) { eigval.reset(); arma_debug_warn("eigs_sym(): decomposition failed"); } return status; }
arma_warn_unused inline Col<typename T1::pod_type> eigs_sym ( const SpBase<typename T1::elem_type,T1>& X, const uword n_eigvals, const char* form = "lm", const typename T1::elem_type tol = 0.0, const typename arma_real_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Mat<typename T1::elem_type> eigvec; Col<typename T1::pod_type > eigval; const bool status = sp_auxlib::eigs_sym(eigval, eigvec, X, n_eigvals, form, tol); if(status == false) { eigval.reset(); arma_stop_runtime_error("eigs_sym(): decomposition failed"); } return eigval; }
inline bool eig_sym ( Col<typename T1::pod_type>& eigval, const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); // unwrap_check not used as T1::elem_type and T1::pod_type may not be the same. // furthermore, it doesn't matter if X is an alias of eigval, as auxlib::eig_sym() makes a copy of X const bool status = auxlib::eig_sym(eigval, X); if(status == false) { eigval.reset(); arma_debug_warn("eig_sym(): decomposition failed"); } return status; }
inline bool svd ( Mat<typename T1::elem_type>& U, Col<typename T1::pod_type >& S, Mat<typename T1::elem_type>& V, const Base<typename T1::elem_type,T1>& X, const char* method = "", const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; arma_debug_check ( ( ((void*)(&U) == (void*)(&S)) || (&U == &V) || ((void*)(&S) == (void*)(&V)) ), "svd(): two or more output objects are the same object" ); bool use_divide_and_conquer = false; const char sig = method[0]; switch(sig) { case '\0': case 's': break; case 'd': use_divide_and_conquer = true; break; default: { arma_stop("svd(): unknown method specified"); return false; } } // auxlib::svd() makes an internal copy of X const bool status = (use_divide_and_conquer == false) ? auxlib::svd(U, S, V, X) : auxlib::svd_dc(U, S, V, X); if(status == false) { U.reset(); S.reset(); V.reset(); arma_bad("svd(): failed to converge", false); } return status; }
inline bool eig_sym ( Col<typename T1::pod_type>& eigval, Mat<typename T1::elem_type>& eigvec, const Base<typename T1::elem_type,T1>& X, const char* method = "dc", const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; const char sig = (method != NULL) ? method[0] : char(0); arma_debug_check( ((sig != 's') && (sig != 'd')), "eig_sym(): unknown method specified" ); arma_debug_check( void_ptr(&eigval) == void_ptr(&eigvec), "eig_sym(): parameter 'eigval' is an alias of parameter 'eigvec'" ); const Proxy<T1> P(X.get_ref()); const bool is_alias = P.is_alias(eigvec); Mat<eT> eigvec_tmp; Mat<eT>& eigvec_out = (is_alias == false) ? eigvec : eigvec_tmp; bool status = false; if(sig == 'd') { status = auxlib::eig_sym_dc(eigval, eigvec_out, P.Q); } if(status == false) { status = auxlib::eig_sym(eigval, eigvec_out, P.Q); } if(status == false) { eigval.reset(); eigvec.reset(); arma_debug_warn("eig_sym(): decomposition failed"); } else { if(is_alias) { eigvec.steal_mem(eigvec_tmp); } } return status; }
inline bool eig_gen ( Col<std::complex<T> >& eigval, Mat<std::complex<T> >& eigvec, const Base<std::complex<T>, T1>& X, const char side = 'r', const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); //std::cout << "complex" << std::endl; arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_gen(): eigval is an alias of eigvec" ); Mat< std::complex<T> > dummy_eigvec; bool status; switch(side) { case 'r': status = auxlib::eig_gen(eigval, dummy_eigvec, eigvec, X, side); break; case 'l': status = auxlib::eig_gen(eigval, eigvec, dummy_eigvec, X, side); break; default: arma_stop("eig_gen(): parameter 'side' is invalid"); status = false; } if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_gen(): failed to converge", false); } return status; }
inline bool svd_econ ( Mat<typename T1::elem_type>& U, Col<typename T1::pod_type >& S, Mat<typename T1::elem_type>& V, const Base<typename T1::elem_type,T1>& X, const char mode = 'b', const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; arma_debug_check ( ( ((void*)(&U) == (void*)(&S)) || (&U == &V) || ((void*)(&S) == (void*)(&V)) ), "svd_econ(): two or more output objects are the same object" ); arma_debug_check ( ( (mode != 'l') && (mode != 'r') && (mode != 'b') ), "svd_econ(): parameter 'mode' is incorrect" ); // auxlib::svd_econ() makes an internal copy of X const bool status = auxlib::svd_econ(U, S, V, X, mode); if(status == false) { U.reset(); S.reset(); V.reset(); arma_bad("svd_econ(): failed to converge", false); } return status; }
arma_deprecated inline bool eig_gen ( Col< std::complex<typename T1::pod_type> >& eigval, Mat<typename T1::elem_type>& l_eigvec, Mat<typename T1::elem_type>& r_eigvec, const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check ( ((&l_eigvec) == (&r_eigvec)), "eig_gen(): l_eigvec is an alias of r_eigvec" ); arma_debug_check ( ( (((void*)(&eigval)) == ((void*)(&l_eigvec))) || (((void*)(&eigval)) == ((void*)(&r_eigvec))) ), "eig_gen(): eigval is an alias of l_eigvec or r_eigvec" ); const bool status = auxlib::eig_gen(eigval, l_eigvec, r_eigvec, X, 'b'); if(status == false) { eigval.reset(); l_eigvec.reset(); r_eigvec.reset(); arma_bad("eig_gen(): failed to converge", false); } return status; }
inline Col<typename T1::pod_type> eig_sym ( const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Col<typename T1::pod_type> out; const bool status = auxlib::eig_sym(out, X); if(status == false) { out.reset(); arma_bad("eig_sym(): decomposition failed"); } return out; }
inline Col<typename T1::pod_type> svd ( const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); Col<typename T1::pod_type> out; const bool status = auxlib::svd(out, X); if(status == false) { out.reset(); arma_bad("svd(): failed to converge"); } return out; }
inline bool svd ( Col<typename T1::pod_type>& S, const Base<typename T1::elem_type,T1>& X, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); // it doesn't matter if X is an alias of S, as auxlib::svd() makes a copy of X const bool status = auxlib::svd(S, X); if(status == false) { S.reset(); arma_bad("svd(): failed to converge", false); } return status; }
inline void op_princomp::direct_princomp ( Mat<eT>& coeff_out, Mat<eT>& score_out, Col<eT>& latent_out, Col<eT>& tsquared_out, const Mat<eT>& in ) { arma_extra_debug_sigprint(); const u32 n_rows = in.n_rows; const u32 n_cols = in.n_cols; if(n_rows > 1) // more than one sample { // subtract the mean - use score_out as temporary matrix score_out = in - repmat(mean(in), n_rows, 1); // singular value decomposition Mat<eT> U; Col<eT> s; const bool svd_ok = svd(U,s,coeff_out,score_out); if(svd_ok == false) { arma_print("princomp(): singular value decomposition failed"); coeff_out.reset(); score_out.reset(); latent_out.reset(); tsquared_out.reset(); return; } //U.reset(); // TODO: do we need this ? U will get automatically deleted anyway // normalize the eigenvalues s /= std::sqrt(n_rows - 1); // project the samples to the principals score_out *= coeff_out; if(n_rows <= n_cols) // number of samples is less than their dimensionality { score_out.cols(n_rows-1,n_cols-1).zeros(); //Col<eT> s_tmp = zeros< Col<eT> >(n_cols); Col<eT> s_tmp(n_cols); s_tmp.zeros(); s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); s = s_tmp; // compute the Hotelling's T-squared s_tmp.rows(0,n_rows-2) = eT(1) / s_tmp.rows(0,n_rows-2); const Mat<eT> S = score_out * diagmat(Col<eT>(s_tmp)); tsquared_out = sum(S%S,1); } else { // compute the Hotelling's T-squared const Mat<eT> S = score_out * diagmat(Col<eT>( eT(1) / s)); tsquared_out = sum(S%S,1); } // compute the eigenvalues of the principal vectors latent_out = s%s; } else // single sample - row { if(n_rows == 1) { coeff_out = eye< Mat<eT> >(n_cols, n_cols); score_out.copy_size(in); score_out.zeros(); latent_out.set_size(n_cols); latent_out.zeros(); tsquared_out.set_size(1); tsquared_out.zeros(); } else { coeff_out.reset(); score_out.reset(); latent_out.reset(); tsquared_out.reset(); } } }
inline bool eig_gen ( Col< std::complex<eT> >& eigval, Mat< std::complex<eT> >& eigvec, const Base<eT, T1>& X, const char side = 'r', const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); //std::cout << "real" << std::endl; arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_gen(): eigval is an alias of eigvec" ); Mat<eT> dummy_eigvec; Mat<eT> tmp_eigvec; bool status; switch(side) { case 'r': status = auxlib::eig_gen(eigval, dummy_eigvec, tmp_eigvec, X, side); break; case 'l': status = auxlib::eig_gen(eigval, tmp_eigvec, dummy_eigvec, X, side); break; default: arma_stop("eig_gen(): parameter 'side' is invalid"); status = false; } if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_gen(): failed to converge", false); } else { const uword n = eigval.n_elem; if(n > 0) { eigvec.set_size(n,n); for(uword j=0; j<n; ++j) { if( (j < n-1) && (eigval[j] == std::conj(eigval[j+1])) ) { // eigvec.col(j) = Mat< std::complex<eT> >( tmp_eigvec.col(j), tmp_eigvec.col(j+1) ); // eigvec.col(j+1) = Mat< std::complex<eT> >( tmp_eigvec.col(j), -tmp_eigvec.col(j+1) ); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>( tmp_eigvec.at(i,j), tmp_eigvec.at(i,j+1) ); eigvec.at(i,j+1) = std::complex<eT>( tmp_eigvec.at(i,j), -tmp_eigvec.at(i,j+1) ); } ++j; } else { // eigvec.col(i) = tmp_eigvec.col(i); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>(tmp_eigvec.at(i,j), eT(0)); } } } } } return status; }
inline bool eig_pair ( Col< std::complex<eT> >& eigval, Mat< std::complex<eT> >& eigvec, const Base< eT, T1 >& A, const Base< eT, T2 >& B, const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); arma_debug_check( ( ((void*)(&eigval)) == ((void*)(&eigvec)) ), "eig_pair(): eigval is an alias of eigvec" ); Mat<eT> dummy_eigvec; Mat<eT> tmp_eigvec; const bool status = auxlib::eig_pair(eigval, dummy_eigvec, tmp_eigvec, A, B, 'r'); if(status == false) { eigval.reset(); eigvec.reset(); arma_bad("eig_pair(): failed to converge", false); } else { const uword n = eigval.n_elem; eigvec.set_size(n,n); if(n > 0) { // from LAPACK docs: // If the j-th and (j+1)-th eigenvalues form a complex conjugate pair, then // v(j) = VR(:,j)+i*VR(:,j+1) and v(j+1) = VR(:,j)-i*VR(:,j+1). for(uword j=0; j<n; ++j) { if( (j < n-1) && (eigval[j] == std::conj(eigval[j+1])) ) { // eigvec.col(j) = Mat< std::complex<eT> >( tmp_eigvec.col(j), tmp_eigvec.col(j+1) ); // eigvec.col(j+1) = Mat< std::complex<eT> >( tmp_eigvec.col(j), -tmp_eigvec.col(j+1) ); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>( tmp_eigvec.at(i,j), tmp_eigvec.at(i,j+1) ); eigvec.at(i,j+1) = std::complex<eT>( tmp_eigvec.at(i,j), -tmp_eigvec.at(i,j+1) ); } ++j; } else { // eigvec.col(i) = tmp_eigvec.col(i); for(uword i=0; i<n; ++i) { eigvec.at(i,j) = std::complex<eT>(tmp_eigvec.at(i,j), eT(0)); } } } } } return status; }
inline void op_princomp::direct_princomp ( Mat< std::complex<T> >& coeff_out, Mat< std::complex<T> >& score_out, Col<T>& latent_out, const Mat< std::complex<T> >& in ) { arma_extra_debug_sigprint(); typedef std::complex<T> eT; const u32 n_rows = in.n_rows; const u32 n_cols = in.n_cols; if(n_rows > 1) // more than one sample { // subtract the mean - use score_out as temporary matrix score_out = in - repmat(mean(in), n_rows, 1); // singular value decomposition Mat<eT> U; Col< T> s; const bool svd_ok = svd(U,s,coeff_out,score_out); if(svd_ok == false) { arma_print("princomp(): singular value decomposition failed"); coeff_out.reset(); score_out.reset(); latent_out.reset(); return; } // U.reset(); // normalize the eigenvalues s /= std::sqrt(n_rows - 1); // project the samples to the principals score_out *= coeff_out; if(n_rows <= n_cols) // number of samples is less than their dimensionality { score_out.cols(n_rows-1,n_cols-1).zeros(); Col<T> s_tmp = zeros< Col<T> >(n_cols); s_tmp.rows(0,n_rows-2) = s.rows(0,n_rows-2); s = s_tmp; } // compute the eigenvalues of the principal vectors latent_out = s%s; } else // single sample - row { if(n_rows == 1) { coeff_out = eye< Mat<eT> >(n_cols, n_cols); score_out.copy_size(in); score_out.zeros(); latent_out.set_size(n_cols); latent_out.zeros(); } else { coeff_out.reset(); score_out.reset(); latent_out.reset(); } } }