Search code examples
c++rvectorrcpparmadillo

In Rcpp (and RcppArmadillo), how to check if a vec contains complex numbers?


In R, we can check whether a vector (e.g., vec1=c(1+1i,2)) contains complex numbers using is.complex (e.g., is.complex(vec1)). I wonder what the equivalent function is in RcppArmadillo?

And how to extract the real part of each element in the vector in RcppArmadillo, like Re(vec1) in R?


Solution

  • For extracting the real and imaginary parts, you can use the arma::real() and arma::imag() functions. Alternatively you can use the sugar function Rcpp::Re() and Rcpp::Im():

    // [[Rcpp::depends(RcppArmadillo)]]
    #include <RcppArmadillo.h>
    
    // [[Rcpp::export]]
    arma::vec getRe(arma::cx_vec x) {
      return arma::real(x);
    }
    
    // [[Rcpp::export]]
    Rcpp::NumericVector getIm(Rcpp::ComplexVector x) {
      return Rcpp::Im(x);
    }
    
    /*** R
    set.seed(42)
    N <- 5
    vec <- complex(5, rnorm(5), rnorm(5))
    
    t(getRe(vec))
    #>            [,1]        [,2]      [,3]       [,4]       [,5]
    #> [1,] -0.9390771 -0.04167943 0.8294135 -0.4393582 -0.3140354
    Re(vec)
    #> [1] -0.93907708 -0.04167943  0.82941349 -0.43935820 -0.31403543
    
    getIm(vec)
    #> [1] -2.1290236  2.5069224 -1.1273128  0.1660827  0.5767232
    Im(vec)
    #> [1] -2.1290236  2.5069224 -1.1273128  0.1660827  0.5767232
    */
    

    If you were to use getRe(arma::vec x) above, you would get:

    Warning message:
    In getRe(vec) : imaginary parts discarded in coercion
    

    You just cannot put complex numbers in an object that is not meant to store them. This is a consequence of C++ being a strongly typed language. So there is no need for an analogue to is.complex().

    See the Armadillo documentation for further reference.