Invoke the element in `Rcpp::List` for futher use directly - rcpp

In an application, I use List to contain some variables (double, arma::mat and other types), and then take the arma::mat component in this list for futher use directly, such as matrix addition. However, some error is thrown.
Below is a toy example to throw the same error as I met:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
arma::mat f(){
arma::mat x = arma::randn(3, 4) ;
List y = List::create( ::Named("a") = arma::randn(3, 4) ) ;
return x - y["a"] ;
}
The error information is
ambiguous overload for 'operator-' (operand types are 'arma::mat'
{aka 'arma::Mat<double>'} and 'Rcpp::Vector<19>::NameProxy' {aka
'Rcpp::internal::generic_name_proxy<19, Rcpp::PreserveStorage>'})
Is there any way to use the y["a"] directly in numerical computation?

You need cast back from the SEXP type you create when adding to an (R or Rcpp, it's the same) List. Correcting that and adding a missing exports tag gives us what is below where I also added the sample invocation (another nice feature).
Code
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::export]]
arma::mat f(){
arma::mat x = arma::randn(3, 4) ;
List y = List::create( ::Named("a") = arma::randn(3, 4) ) ;
return x - Rcpp::as<arma::mat>(y["a"]);
}
/*** R
set.seed(42) # reproducible RNG draws
f()
*/
Output
> Rcpp::sourceCpp("~/git/stackoverflow/71612260/answer.cpp")
>
set.seed(42) # reproducible RNG draws
>
f()
[,1] [,2] [,3] [,4]
[1,] -0.471335 -2.337283 1.205825 0.537811
[2,] 0.119150 1.251941 0.486474 -0.513627
[3,] 3.309860 -0.654003 -0.146678 -0.835439
>

Related

Fail to call ones or eye function when using RcppArmadillo

I want to use one or eye function in Armadillo to construct matrices or vectors. However, it does not allow me to do so. Here is a sample code:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
SEXP Generate(arma::mat Mat){
arma::mat Mat_2 = ones<mat>(5,6);
}
error message reminds me of use of undeclared idenfier of 'mat'. When I remove <mat>, another massage says use of undeclared idenfier of 'ones'.
I looked up the Armadillo tutorial which includes the ones function. I wonder why my code fails to call it. Did I miss something?
There are a few problems in your code:
Why return SEXP? Use types to your advantage
Why pass Mat in if you do not use it?
No return statement
Somewhat loose use of namespaces.
A cleaned up version follows:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat Generate(int n=5, int k=6){
arma::mat m = arma::ones<arma::mat>(n,k);
return m;
}
/*** R
Generate()
*/
It compiles and runs fine:
> Rcpp::sourceCpp("~/git/stackoverflow/67006975/answer.cpp")
> Generate()
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 1 1
[2,] 1 1 1 1 1 1
[3,] 1 1 1 1 1 1
[4,] 1 1 1 1 1 1
[5,] 1 1 1 1 1 1
>

Passing a vector or matrix from R to a C function using Rcpp without a local copy?

Here's an illustration of what I am currently doing with two functions.
In both cases I am creating a local copies: either an instance of std::vector<GLfloat> or of std::vector<GLdouble>.
Isn't there a shortcut not involving copies, where I could go from Rcpp::NumericMatrix to GLfloat */GLdouble * in a more direct way?
#include <Rcpp.h>
#include <GLFW/glfw3.h>
using namespace Rcpp;
//' #export
// [[Rcpp::export("glLoadMatrixf")]]
void gl_load_matrixf(Rcpp::NumericMatrix m) {
std::vector<GLfloat> float_v = Rcpp::as<std::vector<GLfloat> >(m);
const GLfloat * _float_v = &float_v[0];
glLoadMatrixf(_float_v);
}
//' #export
// [[Rcpp::export("glLoadMatrixd")]]
void gl_load_matrixd(Rcpp::NumericMatrix m) {
std::vector<GLdouble> double_v = Rcpp::as<std::vector<GLdouble> >(m);
const GLdouble * _double_v = &double_v[0];
glLoadMatrixd(_double_v);
}
On my system GLfloat and GLdouble are defined as:
typedef float GLfloat;
typedef double GLdouble;
And R's numeric data type is always a double. So you can use &m[0] or m.begin() directly to get something convertible to a GLdouble * without the need to copy the data. For GLfloat this is not possible, since it requires a (lossy) cast to go from the (64 bit) double used by R to a (32 bit) float.
Some code as illustration:
Sys.setenv(PKG_LIBS="-lGL -lglfw")
Rcpp::sourceCpp(code = '
#include <Rcpp.h>
#include <GLFW/glfw3.h>
using namespace Rcpp;
// [[Rcpp::export("glLoadMatrixd")]]
void gl_load_matrixd(Rcpp::NumericMatrix m) {
const GLdouble * _double_v = &m[0];
glLoadMatrixd(_double_v);
}
')
glLoadMatrixd(matrix(runif(10), 2, 5))
BTW, I have no idea what dimensions such a matrix should have. 2x5 is probably incorrect ...

Use a C++ function as an argument for another C++ function called by an exported Rcpp function

I saw that it is possible to pass an R function as argument into C++ using Rcpp. For example, you can do:
// [[Rcpp::export]]
arma::mat example_cpp_func(Rcpp::Function my_r_func, arma::mat a){
return Rcpp::as<arma::mat>(my_r_func(a));
}
That is fine but I'm searching for something slightly different.
Let be the following functions:
arma::mat f1(arma::mat& a){
return a;
}
arma::mat func_2(Rcpp::Function g, arma::mat a){
return Rcpp::as<arma::mat>(g(a));
}
I want to call func_2 in a third function using func_1 as argument. Is that possible? For example, I'm seeking to do:
// [[Rcpp::export]]
arma::mat func_3(arma::mat a){
return func_2(func_1, a);
## ^^^^ Pass a C++ function as a parameter
}
This is possible with R, but when I tried with Rcpp/RcppArmadillo I get the following error:
could not convert ‘f1’ from ‘arma::mat ()(arma::mat&)’ {aka ‘arma::Mat ()(arma::Mat&)’} to ‘Rcpp::Function’ {aka ‘Rcpp::Function_Impl’}
Here's a complete example using the approach Ralf wrote in #1. You can use pure C/C++ function pointers here, although you can do more complex things with C++11.
#include<RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
typedef arma::mat (*functype)(arma::mat&);
arma::mat f1(arma::mat& a){
return a+1;
}
arma::mat f2(functype g, arma::mat a){
return g(a);
}
//[[Rcpp::export]]
arma::mat f3(arma::mat a){
return f2(f1, a);
}
R side:
> f3(matrix(1))
[,1]
[1,] 2
The error message says all there is: To C++ f1 is a function that expects an arma::mat as argument and returns an arma::mat. This is quite different from an Rcpp::Function, which is a thin wrapper around a R function. I see three possibilities:
Write an alternative f2 function which expects a function pointer or std::function (requires C++11) with appropriate arguments.
Add an argument of type Rcpp::Function to f3 which is used in the call to f2.
Get an appropriate R function with Rcpp::Environment and Rcpp:Function.
Without further information about the use case it is difficult to offer more advice.

RcppArmadillo with cxxfunction - how to load header file with function definition?

I am using RcppArmadillo via cxxfunction. I would like to load functions defined as C++ header files. This works with cxxfunction alone, but not when RcppArmadillo is added into the mix. A minimal working example is given below. Any help would be appreciated!
//My header file
#ifndef GUARD_myFunc
#define GUARD_myFunc
#include <Rcpp.h>
NumericMatrix myFunc(NumericMatrix Xin) {
NumericMatrix Xout=Xin;
return Xout;
}
#endif
-
##### My R script
rm(list=ls())
require("inline")
require("Rcpp")
require("RcppArmadillo")
X<-matrix(rnorm(9),3,3)
###works with RcppArmadillo
src1<-'Rcpp::NumericMatrix XR(XS);
arma::mat X(XR.begin(), XR.nrow(), XR.ncol(), false);
return Rcpp::List::create(Rcpp::Named("X")=X);
'
Cfunc1<-cxxfunction(sig=signature(XS="numeric"), body=src1, plugin="RcppArmadillo")
print(X)
print(Cfunc1(X))
###works with myFunc.h
settings <- getPlugin("Rcpp")
settings$env$PKG_CXXFLAGS <- paste("-I", getwd(), sep="")
src2<-'Rcpp::NumericMatrix XR(XS);
Rcpp::NumericMatrix XU=myFunc(XR);
return Rcpp::List::create(Rcpp::Named("X")=XU);
'
Cfunc2<-cxxfunction(sig=signature(XS="numeric"), body=src2, includes=c('#include "myFunc.h"'),settings=settings)
print(X)
print(Cfunc2(X))
###Does not work with RcppArmadillo and myFunc.h
src3<-'Rcpp::NumericMatrix XR(XS);
Rcpp::NumericMatrix XU=myFunc(XR);
arma::mat X(XU.begin(), XU.nrow(), XU.ncol(), false);
return Rcpp::List::create(Rcpp::Named("X")=X);
'
Cfunc3<-cxxfunction(sig=signature(XS="numeric"), body=src3, plugin="RcppArmadillo", includes=c('#include "myFunc.h"'),settings=settings)
print(X)
print(Cfunc3(X))

Error using Rcpp::Nullable with RcppArmadillo types

I'm using RcppArmadillo in my R package and I would like to use the Rcpp::Nullable in the parameter list.
NumericVector d_snb(NumericVector& x,
Nullable<arma::mat> size_param = R_NilValue,
const int& infinite = 100000, const bool& log_v = false)
This gives an error like:
Error: package or namespace load failed for ‘packagex’ in dyn.load(file, DLLpath = DLLpath, ...): unable to load shared object '/usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so': dlopen(/usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so, 6):
Symbol not found: __Z5d_snbRN4Rcpp6VectorILi14ENS_15PreserveStorageEEENS_8NullableIS2_EES5_S5_RKiRKb
Referenced from: /usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so
Expected in: flat namespace in /usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so
Error: loading failed
Execution halted
The only possible solution right now seems to get the parameter as NumericVector and then get contents and then cast it into Armadillo types.
NumericVector d_snb(NumericVector& x,
Nullable<NumericVector> size_param = R_NilValue ...)
{
...
if(size_param.isNotNull()) {
arma::mat test(NumericVector(size_param));
param_check++;
}
...
}
This gives a warning:
d_snb.cpp:36:21: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
arma::mat test(NumericVector(size_param));
^~~~~~~~~~~~~~~~~~~~~~~~~~~
d_snb.cpp:36:22: note: add a pair of parentheses to declare a variable
arma::mat test(NumericVector(size_param));
^
( )
1 warning generated.
What's the best way to go about this ?
Yes, Rcpp::Nullable<> works only around SEXP-based Rcpp types.
So you have to do the two-step procedure you found. But I think you can do one simpler: arma::mat test = Rcpp::as<arma::mat>(size_param);
Here is a complete example which compiles (but does 'nothing'):
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
void d_snb(Rcpp::NumericVector& x,
Rcpp::Nullable<Rcpp::NumericVector> size_param = R_NilValue) {
if (size_param.isNotNull()) {
arma::vec test = Rcpp::as<arma::vec>(size_param);
test.print("vector");
}
Rcpp::Rcout << x << std::endl;
}
And a quick demo:
R> sourceCpp("/tmp/so44102346.cpp")
R> d_snb(c(1,2,3))
1 2 3
R> d_snb(c(1,2,3), c(4,5,6))
vector
4.0000
5.0000
6.0000
1 2 3
R>

Resources