inline bool glue_solve_tri::apply(Mat<eT>& out, const Base<eT,T1>& A_expr, const Base<eT,T2>& B_expr, const uword flags) { arma_extra_debug_sigprint(); const bool fast = bool(flags & solve_opts::flag_fast ); const bool equilibrate = bool(flags & solve_opts::flag_equilibrate); const bool no_approx = bool(flags & solve_opts::flag_no_approx ); const bool triu = bool(flags & solve_opts::flag_triu ); const bool tril = bool(flags & solve_opts::flag_tril ); arma_extra_debug_print("glue_solve_tri::apply(): enabled flags:"); if(fast ) { arma_extra_debug_print("fast"); } if(equilibrate) { arma_extra_debug_print("equilibrate"); } if(no_approx ) { arma_extra_debug_print("no_approx"); } if(triu ) { arma_extra_debug_print("triu"); } if(tril ) { arma_extra_debug_print("tril"); } bool status = false; if(equilibrate) { arma_debug_warn("solve(): option 'equilibrate' ignored for triangular matrices"); } const unwrap_check<T1> U(A_expr.get_ref(), out); const Mat<eT>& A = U.M; arma_debug_check( (A.is_square() == false), "solve(): matrix marked as triangular must be square sized" ); const uword layout = (triu) ? uword(0) : uword(1); status = auxlib::solve_tri(out, A, B_expr.get_ref(), layout); // A is not modified if( (status == false) && (no_approx == false) ) { arma_extra_debug_print("glue_solve_tri::apply(): solving rank deficient system"); arma_debug_warn("solve(): system seems singular; attempting approx solution"); Mat<eT> triA = (triu) ? trimatu( A_expr.get_ref() ) : trimatl( A_expr.get_ref() ); status = auxlib::solve_approx_svd(out, triA, B_expr.get_ref()); // triA is overwritten } if(status == false) { out.reset(); } return status; }
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 syl ( Mat <typename T1::elem_type> & out, const Base<typename T1::elem_type,T1>& in_A, const Base<typename T1::elem_type,T2>& in_B, const Base<typename T1::elem_type,T3>& in_C, 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 unwrap_check<T1> tmp_A(in_A.get_ref(), out); const unwrap_check<T2> tmp_B(in_B.get_ref(), out); const unwrap_check<T3> tmp_C(in_C.get_ref(), out); const Mat<eT>& A = tmp_A.M; const Mat<eT>& B = tmp_B.M; const Mat<eT>& C = tmp_C.M; const bool status = auxlib::syl(out, A, B, C); if(status == false) { out.soft_reset(); arma_debug_warn("syl(): solution not found"); } return status; }
inline bool schur ( Mat<typename T1::elem_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); typedef typename T1::elem_type eT; Mat<eT> U; const bool status = auxlib::schur(U, S, X.get_ref(), false); if(status == false) { S.reset(); arma_debug_warn("schur(): decomposition failed"); } 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, 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 schur ( Mat<typename T1::elem_type>& U, Mat<typename T1::elem_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); arma_debug_check( void_ptr(&U) == void_ptr(&S), "schur(): 'U' is an alias of 'S'" ); const bool status = auxlib::schur(U, S, X.get_ref(), true); if(status == false) { U.reset(); S.reset(); arma_debug_warn("schur(): decomposition failed"); } 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 qr_econ ( Mat<typename T1::elem_type>& Q, Mat<typename T1::elem_type>& R, 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( (&Q == &R), "qr_econ(): Q and R are the same object"); const bool status = auxlib::qr_econ(Q, R, X); if(status == false) { Q.soft_reset(); R.soft_reset(); arma_debug_warn("qr_econ(): decomposition failed"); } return status; }
inline bool hess ( Mat<typename T1::elem_type>& H, 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); typedef typename T1::elem_type eT; Col<eT> tao; const bool status = auxlib::hess(H, X.get_ref(), tao); if(H.n_rows > 2) { for(uword i=0; i < H.n_rows-2; ++i) { H(span(i+2, H.n_rows-1), i).zeros(); } } if(status == false) { H.soft_reset(); arma_debug_warn("hess(): 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; }
inline bool lu ( Mat<typename T1::elem_type>& L, Mat<typename T1::elem_type>& U, Mat<typename T1::elem_type>& P, 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 == &U) || (&L == &P) || (&U == &P) ), "lu(): two or more output objects are the same object"); const bool status = auxlib::lu(L, U, P, X); if(status == false) { L.reset(); U.reset(); P.reset(); arma_debug_warn("lu(): decomposition failed"); } return status; }
inline bool op_logmat_cx::helper(Mat<eT>& A, const uword m) { arma_extra_debug_sigprint(); const vec indices = regspace<vec>(1,m-1); mat tmp(m,m,fill::zeros); tmp.diag(-1) = indices / sqrt(square(2.0*indices) - 1.0); tmp.diag(+1) = indices / sqrt(square(2.0*indices) - 1.0); vec eigval; mat eigvec; const bool eig_ok = eig_sym(eigval, eigvec, tmp); if(eig_ok == false) { arma_debug_warn("logmat(): eig_sym() failed"); return false; } const vec nodes = (eigval + 1.0) / 2.0; const vec weights = square(eigvec.row(0).t()); const uword N = A.n_rows; Mat<eT> B(N,N,fill::zeros); Mat<eT> X; for(uword i=0; i < m; ++i) { // B += weights(i) * solve( (nodes(i)*A + eye< Mat<eT> >(N,N)), A ); //const bool solve_ok = solve( X, (nodes(i)*A + eye< Mat<eT> >(N,N)), A, solve_opts::fast ); const bool solve_ok = solve( X, trimatu(nodes(i)*A + eye< Mat<eT> >(N,N)), A ); if(solve_ok == false) { arma_debug_warn("logmat(): solve() failed"); return false; } B += weights(i) * X; } A = B; return true; }
inline void op_sqrtmat::apply(Mat< std::complex<typename T1::elem_type> >& out, const mtOp<std::complex<typename T1::elem_type>,T1,op_sqrtmat>& in) { arma_extra_debug_sigprint(); const bool status = op_sqrtmat::apply_direct(out, in.m); if(status == false) { arma_debug_warn("sqrtmat(): given matrix seems singular; may not have a square root"); } }
inline void running_stat<eT>::operator() (const std::complex< typename running_stat<eT>::T >& sample) { arma_extra_debug_sigprint(); if( arma_isfinite(sample) == false ) { arma_debug_warn("running_stat: sample ignored as it is non-finite" ); return; } running_stat_aux::update_stats(*this, sample); }
inline typename enable_if2< (is_supported_blas_type<typename T1::elem_type>::value && is_cx<typename T1::elem_type>::yes), bool >::result sqrtmat(Mat<typename T1::elem_type>& Y, const Base<typename T1::elem_type,T1>& X) { arma_extra_debug_sigprint(); const bool status = op_sqrtmat_cx::apply_direct(Y, X.get_ref()); if(status == false) { arma_debug_warn("sqrtmat(): given matrix seems singular; may not have a square root"); } return status; }
inline typename enable_if2< is_real<typename T1::pod_type>::value, bool >::result null(Mat<typename T1::elem_type>& out, const Base<typename T1::elem_type, T1>& X, const typename T1::pod_type tol = 0.0) { arma_extra_debug_sigprint(); const bool status = op_null::apply_direct(out, X.get_ref(), tol); if(status == false) { arma_debug_warn("null(): svd failed"); } return status; }
inline typename enable_if2< is_supported_blas_type<typename T1::elem_type>::value, bool >::result expmat_sym(Mat<typename T1::elem_type>& Y, const Base<typename T1::elem_type,T1>& X) { arma_extra_debug_sigprint(); const bool status = op_expmat_sym::apply_direct(Y, X.get_ref()); if(status == false) { Y.reset(); arma_debug_warn("expmat_sym(): transformation 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); 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 typename enable_if2 < is_supported_blas_type<typename T1::elem_type>::value, bool >::result roots(Mat< std::complex<typename T1::pod_type> >& out, const Base<typename T1::elem_type, T1>& X) { arma_extra_debug_sigprint(); const bool status = op_roots::apply_direct(out, X.get_ref()); if(status == false) { arma_debug_warn("roots(): eigen decomposition failed"); } return status; }
arma_warn_unused inline typename enable_if2< is_supported_blas_type<typename T1::elem_type>::value, typename T1::elem_type >::result det ( const Op<T1,op_inv>& X ) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const eT tmp = det(X.m); if(tmp == eT(0)) { arma_debug_warn("det(): denominator is zero" ); } return eT(1) / tmp; }
inline typename enable_if2 < is_real<typename T1::elem_type>::value, bool >::result wishrnd(Mat<typename T1::elem_type>& W, const Base<typename T1::elem_type, T1>& S, typename T1::elem_type df) { arma_extra_debug_sigprint(); const bool status = op_wishrnd::apply_direct(W, S.get_ref(), df, uword(1)); if(status == false) { arma_debug_warn("wishrnd(): given matrix is not symmetric positive definite"); return false; } return true; }
inline arma_warn_unused typename T1::elem_type det ( const Op<T1,op_inv>& X, const bool slow = false, 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 eT tmp = det(X.m, slow); arma_debug_warn( (tmp == eT(0)), "det(): warning: denominator is zero" ); return eT(1) / tmp; }
arma_warn_unused inline typename enable_if2 < is_real<typename T1::elem_type>::value, bool >::result mvnrnd(Mat<typename T1::elem_type>& out, const Base<typename T1::elem_type, T1>& M, const Base<typename T1::elem_type, T2>& C, const uword N) { arma_extra_debug_sigprint(); const bool status = glue_mvnrnd::apply_direct(out, M.get_ref(), C.get_ref(), N); if(status == false) { arma_debug_warn("mvnrnd(): given covariance matrix is not symmetric positive semi-definite"); return false; } return true; }
inline typename enable_if2 < is_real<typename T1::pod_type>::value, bool >::result expmat(Mat<typename T1::elem_type>& B, const Base<typename T1::elem_type,T1>& A) { arma_extra_debug_sigprint(); const bool status = op_expmat::apply_direct(B, A); if(status == false) { arma_debug_warn("expmat(): given matrix appears ill-conditioned"); B.reset(); return false; } return true; }
arma_hot inline void running_stat_vec<obj_type>::operator() (const Base<typename running_stat_vec<obj_type>::T, T1>& X) { arma_extra_debug_sigprint(); const quasi_unwrap<T1> tmp(X.get_ref()); const Mat<T>& sample = tmp.M; if( sample.is_empty() ) { return; } if( sample.is_finite() == false ) { arma_debug_warn("running_stat_vec: sample ignored as it has non-finite elements"); return; } running_stat_vec_aux::update_stats(*this, sample); }
inline bool spsolve ( Mat<typename T1::elem_type>& out, const SpBase<typename T1::elem_type, T1>& A, const Base<typename T1::elem_type, T2>& B, const char* solver = "superlu", const spsolve_opts_base& settings = spsolve_opts_none(), const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0 ) { arma_extra_debug_sigprint(); arma_ignore(junk); const bool status = spsolve_helper(out, A.get_ref(), B.get_ref(), solver, settings); if(status == false) { arma_debug_warn("spsolve(): solution not found"); } return status; }
inline bool hess ( Mat<typename T1::elem_type>& U, Mat<typename T1::elem_type>& H, 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( void_ptr(&U) == void_ptr(&H), "hess(): 'U' is an alias of 'H'" ); typedef typename T1::elem_type eT; Col<eT> tao; const bool status = auxlib::hess(H, X.get_ref(), tao); if(H.n_rows == 0) { U.reset(); } else if(H.n_rows == 1) { U.ones(1, 1); } else if(H.n_rows == 2) { U.eye(2, 2); } else { U.eye(size(H)); Col<eT> v; for(uword i=0; i < H.n_rows-2; ++i) { // TODO: generate v in a more efficient manner; // TODO: the .ones() operation is an overkill, as most of v is overwritten afterwards v.ones(H.n_rows-i-1); v(span(1, H.n_rows-i-2)) = H(span(i+2, H.n_rows-1), i); U(span::all, span(i+1, H.n_rows-1)) -= tao(i) * (U(span::all, span(i+1, H.n_rows-1)) * v * v.t()); } U(span::all, H.n_rows-1) = U(span::all, H.n_rows-1) * (eT(1) - tao(H.n_rows-2)); for(uword i=0; i < H.n_rows-2; ++i) { H(span(i+2, H.n_rows-1), i).zeros(); } } if(status == false) { U.soft_reset(); H.soft_reset(); arma_debug_warn("hess(): decomposition failed"); } return status; }
inline bool spsolve_helper ( Mat<typename T1::elem_type>& out, const SpBase<typename T1::elem_type, T1>& A, const Base<typename T1::elem_type, T2>& B, const char* solver, const spsolve_opts_base& settings, 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 = (solver != NULL) ? solver[0] : char(0); arma_debug_check( ((sig != 'l') && (sig != 's')), "spsolve(): unknown solver" ); bool status = false; if(sig == 's') // SuperLU solver { const superlu_opts& opts = (settings.id == 1) ? static_cast<const superlu_opts&>(settings) : superlu_opts(); arma_debug_check( ( (opts.pivot_thresh < double(0)) || (opts.pivot_thresh > double(1)) ), "spsolve(): pivot_thresh out of bounds" ); status = sp_auxlib::spsolve(out, A.get_ref(), B.get_ref(), opts); } else if(sig == 'l') // brutal LAPACK solver { if(settings.id != 0) { arma_debug_warn("spsolve(): ignoring settings not applicable to LAPACK based solver"); } Mat<eT> AA; bool conversion_ok = false; try { Mat<eT> tmp(A.get_ref()); // conversion from sparse to dense can throw std::bad_alloc AA.steal_mem(tmp); conversion_ok = true; } catch(std::bad_alloc&) { arma_debug_warn("spsolve(): not enough memory to use LAPACK based solver"); } if(conversion_ok) { arma_debug_check( (AA.n_rows != AA.n_cols), "spsolve(): matrix A must be square sized" ); status = auxlib::solve(out, AA, B.get_ref(), true); } } if(status == false) { out.reset(); } return status; }
inline bool op_logmat_cx::apply_common(Mat< std::complex<T> >& out, Mat< std::complex<T> >& S, const uword n_iters) { arma_extra_debug_sigprint(); typedef typename std::complex<T> eT; Mat<eT> U; const bool schur_ok = auxlib::schur(U,S); if(schur_ok == false) { arma_extra_debug_print("logmat(): schur decomposition failed"); return false; } //double theta[] = { 1.10e-5, 1.82e-3, 1.62e-2, 5.39e-2, 1.14e-1, 1.87e-1, 2.64e-1 }; double theta[] = { 0.0, 0.0, 1.6206284795015624e-2, 5.3873532631381171e-2, 1.1352802267628681e-1, 1.8662860613541288e-1, 2.642960831111435e-1 }; // theta[0] and theta[1] not really used const uword N = S.n_rows; uword p = 0; uword m = 6; uword iter = 0; while(iter < n_iters) { const T tau = norm( (S - eye< Mat<eT> >(N,N)), 1 ); if(tau <= theta[6]) { p++; uword j1 = 0; uword j2 = 0; for(uword i=2; i<=6; ++i) { if( tau <= theta[i]) { j1 = i; break; } } for(uword i=2; i<=6; ++i) { if((tau/2.0) <= theta[i]) { j2 = i; break; } } // sanity check, for development purposes only arma_debug_check( (j2 > j1), "internal error: op_logmat::apply_direct(): j2 > j1" ); if( ((j1 - j2) <= 1) || (p == 2) ) { m = j1; break; } } const bool sqrtmat_ok = op_sqrtmat_cx::apply_direct(S,S); if(sqrtmat_ok == false) { arma_extra_debug_print("logmat(): sqrtmat() failed"); return false; } iter++; } if(iter >= n_iters) { arma_debug_warn("logmat(): reached max iterations without full convergence"); } S.diag() -= eT(1); if(m >= 1) { const bool helper_ok = op_logmat_cx::helper(S,m); if(helper_ok == false) { return false; } } out = U * S * U.t(); out *= eT(eop_aux::pow(double(2), double(iter))); return true; }
inline bool glue_solve_gen::apply(Mat<eT>& out, const Base<eT,T1>& A_expr, const Base<eT,T2>& B_expr, const uword flags) { arma_extra_debug_sigprint(); typedef typename get_pod_type<eT>::result T; const bool fast = bool(flags & solve_opts::flag_fast ); const bool equilibrate = bool(flags & solve_opts::flag_equilibrate); const bool no_approx = bool(flags & solve_opts::flag_no_approx ); arma_extra_debug_print("glue_solve_gen::apply(): enabled flags:"); if(fast ) { arma_extra_debug_print("fast"); } if(equilibrate) { arma_extra_debug_print("equilibrate"); } if(no_approx ) { arma_extra_debug_print("no_approx"); } T rcond = T(0); bool status = false; Mat<eT> A = A_expr.get_ref(); if(A.n_rows == A.n_cols) { arma_extra_debug_print("glue_solve_gen::apply(): detected square system"); if(fast) { arma_extra_debug_print("glue_solve_gen::apply(): (fast)"); if(equilibrate) { arma_debug_warn("solve(): option 'equilibrate' ignored, as option 'fast' is enabled"); } status = auxlib::solve_square_fast(out, A, B_expr.get_ref()); // A is overwritten } else { arma_extra_debug_print("glue_solve_gen::apply(): (refine)"); status = auxlib::solve_square_refine(out, rcond, A, B_expr, equilibrate); // A is overwritten } if( (status == false) && (no_approx == false) ) { arma_extra_debug_print("glue_solve_gen::apply(): solving rank deficient system"); if(rcond > T(0)) { arma_debug_warn("solve(): system seems singular (rcond: ", rcond, "); attempting approx solution"); } else { arma_debug_warn("solve(): system seems singular; attempting approx solution"); } Mat<eT> AA = A_expr.get_ref(); status = auxlib::solve_approx_svd(out, AA, B_expr.get_ref()); // AA is overwritten } } else { arma_extra_debug_print("glue_solve_gen::apply(): detected non-square system"); if(equilibrate) { arma_debug_warn( "solve(): option 'equilibrate' ignored for non-square matrix" ); } if(fast) { status = auxlib::solve_approx_fast(out, A, B_expr.get_ref()); // A is overwritten if(status == false) { Mat<eT> AA = A_expr.get_ref(); status = auxlib::solve_approx_svd(out, AA, B_expr.get_ref()); // AA is overwritten } } else { status = auxlib::solve_approx_svd(out, A, B_expr.get_ref()); // A is overwritten } } if(status == false) { out.reset(); } return status; }