How can I pass an NA value from Rcpp to R in a 64 bit vector?
My first approach would be:
// [[Rcpp::export]]
Rcpp::NumericVector foo() {
Rcpp::NumericVector res(2);
int64_t val = 1234567890123456789;
std::memcpy(&(res[0]), &(val), sizeof(double));
res[1] = NA_REAL;
res.attr("class") = "integer64";
return res;
}
But it yields
#> foo()
integer64
[1] 1234567890123456789 9218868437227407266
I need to get
#> foo()
integer64
[1] 1234567890123456789 <NA>
Although, functions and operators defined in Rcpp handle the minimum value of int appropriately as NA (that is, make the result of operation on NA element as NA ). Standard C++ functions and operators treat the minimum value of int as integer value.
To express the value of Inf -Inf NaN in Rcpp, use the symbol R_PosInf R_NegInf R_NaN. On the other hand, for NA, different symbol of NA are defined for each Vector type.
In Rcpp, TRUE is represented by 1, FALSE by 0, and NA by NA_LOGICAL (minimum value of int: -2147483648). Use the operator & (logical product) | (logical sum) !
In RTYPE, specify SEXPTYPE of the vector to be evaluated. Here is the list of SEXPTYPE of the major Vector class. You use R_NilValue to handle NULL in Rcpp. The code example below shows how to check NULL in the elements of a List object and how to assign NULL to clear the value of an attribute.
Alright, I think I found an answer... (not beautiful, but working).
// [[Rcpp::export]]
Rcpp::NumericVector foo() {
Rcpp::NumericVector res(2);
int64_t val = 1234567890123456789;
std::memcpy(&(res[0]), &(val), sizeof(double));
# This is the magic:
int64_t v = 1ULL << 63;
std::memcpy(&(res[1]), &(v), sizeof(double));
res.attr("class") = "integer64";
return res;
}
which results in
#> foo()
integer64
[1] 1234567890123456789 <NA>
Inspecting how bit64
stores an NA
# the last value is the max value of a 64 bit number
a <- bit64::as.integer64(c(1, 2, NA, 9223372036854775807))
a
#> integer64
#> [1] 1 2 <NA> <NA>
bit64::as.bitstring(a[3])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"
bit64::as.bitstring(a[4])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"
Created on 2020-04-23 by the reprex package (v0.3.0)
we see that it is a 10000...
. This can be recreated in Rcpp
with int64_t val = 1ULL << 63;
. Using memcpy()
instead of a simple assign with =
ensures that no bits are changed!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With