예제 #1
0
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;
		}
예제 #3
0
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;
  }
예제 #4
0
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;
  }
예제 #5
0
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;
  }
예제 #6
0
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;
  }
예제 #7
0
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;
  }
예제 #8
0
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;
  }
예제 #9
0
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;
  }
예제 #10
0
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;
  }
예제 #11
0
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;
  }
예제 #12
0
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;
  }
예제 #13
0
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;
  }
예제 #14
0
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;
  }
예제 #16
0
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;
  }
예제 #17
0
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;
  }
예제 #19
0
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;
  }
예제 #20
0
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;
  }
예제 #23
0
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();
      }
    }
  
  }
예제 #24
0
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;
  }
예제 #25
0
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;
  }
예제 #26
0
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();
      }
    }
  }