xtensor-stack / xtensor-r

R bindings for xtensor
BSD 3-Clause "New" or "Revised" License
87 stars 15 forks source link

How to convert `rarray_optional` -> `SEXP` #99

Closed DavisVaughan closed 5 years ago

DavisVaughan commented 5 years ago

I'm having a bit of trouble working with the optional support. Mainly, I can't get the result back out into something to convert to R. It looks like the optional support is working, I just can't get the result out.

1) Below, sum_print_optional_int() shows that things are working right.

2) The commented out version of sum_print_optional_int() shows that I have to use auto as the result of the sum(<rarray_optional>) operation. Is this right? I can't coerce directly to another rarray_optional?

3) sum_optional_int() is me attempting to get the results of the sum() into something I can return to R. But I don't know how.

// [[Rcpp::depends(xtensor)]]
// [[Rcpp::plugins(cpp14)]]

#include <xtensor-r/rarray.hpp>
#include <xtensor-r/roptional.hpp>
#include <xtensor/xio.hpp>
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
SEXP sum_print_optional_int(SEXP x) {
  xt::rarray_optional<int> x_rarray(x);
  std::cout << x_rarray << std::endl;

  auto res = xt::sum(x_rarray);
  std::cout << res << std::endl;

  return SEXP(IntegerVector::create(1));
}

// SEXP sum_print_optional_int(SEXP x) {
//   xt::rarray_optional<int> x_rarray(x);
//   std::cout << x_rarray << std::endl;
//
//   # THIS DOESNT WORK
//   xt::rarray_optional<int> res = xt::sum(x_rarray);
//   std::cout << res << std::endl;
//
//   return SEXP(IntegerVector::create(1));
// }

// [[Rcpp::export]]
SEXP sum_optional_int(SEXP x) {
  xt::rarray_optional<int> x_rarray(x);
  auto res = xt::sum(x_rarray);

  // doesnt work
  // SEXP out = SEXP(res);

  // doesnt work
  // xt::rarray<int> out(res);

  return SEXP(IntegerVector::create(1));
}

As you can see here, the NA are propagating correctly:

Rcpp::sourceCpp("~/Desktop/test.cpp")

trash <- sum_print_optional_int(1:5)
# {1, 2, 3, 4, 5}
# 15

with_na <- c(1L, NA_integer_, 2L)
trash <- sum_print_optional_int(with_na)
# {  1, N/A,   2}
# N/A
DavisVaughan commented 5 years ago

I'm also not sure it works right with matrices. It seems to print right for vectors, but with matrices it doesn't print the N/A. However, it does compute the right value.

Rcpp::sourceCpp("~/Desktop/test.cpp")

vec <- c(1L, 2L, 3L, 4L, NA_integer_, 6L)
mat <- matrix(vec, ncol = 1)

trash <- sum_print_optional_int(vec)
# {  1,   2,   3,   4, N/A,   6}
# N/A

trash <- sum_print_optional_int(mat)
# {{          1},
#  {          2},
#  {          3},
#  {          4},
#  {-2147483648},
#  {          6}}
# N/A
SylvainCorlay commented 5 years ago

Indeed, I think that we need a operator SEXP() which would return SEXP(m_value) in rcontainer_optional.