Rcpp sugar commands in armadillo
Asked Answered
S

2

1

I'm trying to use ifelse() command of Rcpp sugar with arma::vec. The code fails with error

'ifelse' was not declared in this scope

I could not find a solution. A simple example code (resulted with error) is below.

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::vec f(arma::vec x, arma::vec y) {
  arma::vec res1 = Rcpp::ifelse(x < y, x, y);
  arma::vec res = trans(res1)*y;
  return res;
}

/*** R
f(c(1,2,3),c(3,2,1))
*/
Sleigh answered 27/7, 2018 at 6:42 Comment(5)
You need to use Rcpp::ifelse, but this won't work with arma::vec.Flagpole
@F. Privé I edited the code according to your suggestion. Is there a way to use armadillo (for matrix computations) and rcpp sugar together?Sleigh
I don't think so. Rcpp sugar is for Rcpp types.Flagpole
C++ is a statically-typed object-oriented language. Something that works on one type (ie Rcpp::NumericVector) does not necessarily work on another (ie arma::vec).Druse
Thanks. I just wonder if there is some commands to coerce the types like as.double or as.data.frame in R. For example as.Numeric.Vector here. But it seems there is not.Sleigh
T
2

Using Armadillo's advanced constructors you can have Rcpp::NumericVector and arma::vec that refer to the same memory location. Then you can use both Rcpp functions and arma functions by using the correct front-end object for that piece of memory:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::vec f(Rcpp::NumericVector xr, Rcpp::NumericVector yr) {
  arma::vec x(xr.begin(), xr.size(), false, true); 
  arma::vec y(yr.begin(), yr.size(), false, true);
  Rcpp::NumericVector res1r(xr.size());
  arma::vec res1(res1r.begin(), res1r.size(), false, true);  
  res1r = Rcpp::ifelse(xr < yr, xr, yr);
  arma::vec res = trans(res1)*y;
  return res;
}

/*** R
f(c(1,2,3),c(3,2,1))
*/

I am not 100% sure that this does not have any unwanted side-effects.

Tawannatawdry answered 29/7, 2018 at 9:29 Comment(0)
C
1

This is the solution that I found I hope will work for you.

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]

arma::vec f(arma::vec x, arma::vec y) {
  int n = x.size();
  arma::vec res(n); 
    for(int i = 0; i < n; i++){
      if (x[i] < y[i]){res[i] = x[i];} else{res[i] = y[i];}
  }
  return trans(res)*y;
}

The output is

/*** R
f(c(1,2,3),c(3,2,1))
*/
     [,1]
[1,]    8
Calabro answered 27/7, 2018 at 8:32 Comment(3)
Please do NOT include RcppArmadillo.h and Rcpp.h. The former pulls in the latter. You only need one, and order matters. And what you show is redundant as well.Druse
Making the corrections that Dirk proposes, edit my answer.Sacker
@Rafael Diaz thanks but your answer is not about my question.Sleigh

© 2022 - 2024 — McMap. All rights reserved.