Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rcpp and int64 NA value

Tags:

r

na

rcpp

bit64

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>
like image 255
David Avatar asked Apr 23 '20 11:04

David


People also ask

What is the minimum value of INT in RCPP?

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.

How to express the value of Nan in RCPP?

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.

What is the value of Na_logical in RCPP?

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) !

How to handle null values in RCPP?

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.


1 Answers

Alright, I think I found an answer... (not beautiful, but working).

Short Answer:

// [[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>

Longer Answer

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!

like image 81
David Avatar answered Oct 20 '22 17:10

David