Advertisement
celestialgod

eigen decomposition in Rcpp and LAPACK (eigen_sym_cpp.cpp)

Jan 1st, 2017
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.20 KB | None | 0 0
  1. // [[Rcpp::depends(RcppEigen)]]
  2. #include <RcppEigen.h>
  3. #include <R_ext/Lapack.h>
  4. #include <R_ext/BLAS.h>
  5.  
  6. using Eigen::Map;
  7. using Eigen::MatrixXd;
  8. using Eigen::VectorXd;
  9. using Eigen::VectorXi;
  10.  
  11. //[[Rcpp::export]]
  12. Rcpp::List eigen_sym_cpp(Rcpp::NumericMatrix xr, int num_eig = -1, bool eigenvalues_only = false, double tol = 1.5e-8)
  13. {
  14.   MatrixXd A = MatrixXd::Map(xr.begin(), xr.nrow(), xr.ncol());
  15.  
  16.   // settings
  17.   char jobz = eigenvalues_only ? 'N' : 'V', range = (num_eig == -1) ? 'A' : 'I', uplo = 'U';
  18.   int N = A.rows(), info = 0;
  19.   // deside the number of eigenvalues
  20.   int il = (num_eig == -1) ? 1 : (N - num_eig + 1), M = N - il + 1;
  21.   // the tolerance and not used arguments vl, vu
  22.   double abstol = tol, vl = 0.0, vu = 0.0;
  23.   // query the optimal size of the WORK array and IWORK array
  24.   int lwork = -1, liwork = -1, iwork_query;
  25.  
  26.   VectorXi isuppz(2 * M);
  27.   VectorXd W(M);
  28.   MatrixXd Z(N, M);
  29.   // perform dsyerv and get the optimal size of the WORK array and IWORK array
  30.   double work_qeury;
  31.   F77_CALL(dsyevr)(&jobz, &range, &uplo, &N, A.data(), &N, &vl, &vu,
  32.            &il, &N, &abstol, &M, W.data(), Z.data(), &N, isuppz.data(),
  33.            &work_qeury, &lwork, &iwork_query, &liwork, &info);
  34.  
  35.   // get the optimal sizeㄋ of the WORK array and IWORK array
  36.   lwork = (int) work_qeury;
  37.   liwork = iwork_query;
  38.   VectorXd work(lwork);
  39.   VectorXi iwork(liwork);
  40.   // perform dsyerv and get the results of eigen decomposition
  41.   F77_CALL(dsyevr)(&jobz, &range, &uplo, &N, A.data(), &N, &vl, &vu,
  42.            &il, &N, &abstol, &M, W.data(), Z.data(), &N, isuppz.data(),
  43.            work.data(), &lwork, iwork.data(), &liwork, &info);
  44.  
  45.   // reverse the eigenvalues to sort in the descending order
  46.   W.reverseInPlace();
  47.  
  48.   // return eigenvalues only
  49.   if (eigenvalues_only)
  50.     return Rcpp::List::create(
  51.       Rcpp::Named("LAPACK_info") = info,
  52.       Rcpp::Named("values") = W
  53.     );
  54.  
  55.   // reverse the eigenvectors to sort in the order of eigenvalues
  56.   MatrixXd Z2 = Z.rowwise().reverse();
  57.  
  58.   // reutrn eigenvalues and eigenvectors
  59.   return Rcpp::List::create(
  60.     Rcpp::Named("LAPACK_info") = info,
  61.     Rcpp::Named("vectors") = Z2,
  62.     Rcpp::Named("values") = W
  63.   );
  64. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement