RcppArmadillo sample.h compiling error - r

I'm writing a package with some functions calling RcppArmadillo::sample from RcppArmadillo.
However I met the following error when compiling.
In file included from Citrus.cpp:2:
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/RcppArmadilloExtensions/sample.h: In function ‘T Rcpp::RcppArmadillo::sample(const T&, int, bool, Rcpp::NumericVector) [with T = arma::subview_col]’:
Citrus.cpp:241: instantiated from here
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/RcppArmadilloExtensions/sample.h:45: error: ‘const struct arma::subview_col’ has no member named ‘size’
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/RcppArmadilloExtensions/sample.h:48: error: no matching function for call to ‘arma::subview_col::subview_col(const int&)’
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/armadillo_bits/subview_bones.hpp:236: note: candidates are: arma::subview_col::subview_col() [with eT = double]
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/armadillo_bits/subview_meat.hpp:2608: note: arma::subview_col::subview_col(const arma::Mat&, arma::uword, arma::uword, arma::uword) [with eT = double]
./R/x86_64-unknown-linux-gnu-library/3.0/RcppArmadillo/include/armadillo_bits/subview_meat.hpp:2597: note: arma::subview_col::subview_col(const arma::Mat&, arma::uword) [with eT = double]
./R/x86_64-unknown-linux-gnu library/3.0/RcppArmadillo/include/armadillo_bits/forward_bones.hpp:29: note: arma::subview_col::subview_col(const arma::subview_col&)
make: *** [Citrus.o] Error 1
The RcppArmadillo I'm using is 0.7.700.0.0.
The same error appeared on both linux and OSX. When compiling using Rstudio, the error message as follows:
no member named 'size' in 'arma::subview_col<double>'.
no matching constructor for initialization of 'arma::subview_col<double>'
I used RcppArmadillo::sample in my previous work a lot. It suddenly doesn't work. I appreciate any help.

This feature works on pre-subset data in either arma::vec or NumericVector Always has and always will. Do not use this with an intermediary vector obtained from a subset operation (e.g. .col(), .cols(), or .submat()).
The issue you are running into is you've decided to subset the data within the call to sample. (You've omitted code to diagnose this part, so I'm speculating here.) Since sample() needs to work with both Rcpp and Armadillo data types there never was a call to Armadillo specific size member functions. Instead, the library opted to call the .size() member function of an STL container, which armadillo supported, since that was shared between both objects. However, armadillo limits where the member function was implemented to the "active" data structures and not temporaries. As a result, the .size() member function was not implemented for subview_col. So, we end up with the error of:
error: ‘const struct arma::subview_col’ has no member named ‘size’
To get around this limitation and save memory, use an advanced vec ctor that will reuse memory and, thus, avoiding the need for an intermediary arma::subview_col to be created.
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::export]]
void adv_rnd(int nrow, int ncol, bool replace = true){
// Create a matrix of given dimensions
arma::mat X(nrow, ncol);
X.randn();
// Show state before randomization
Rcpp::Rcout << "Before Randomization:" << std::endl << X << std::endl;
// Randomize each column
for(int i = 0; i < ncol; ++i){
arma::vec Y(X.colptr(i), nrow, false, true);
X.col(i) = Rcpp::RcppArmadillo::sample(Y, nrow, replace);
}
// Show state after randomization
Rcpp::Rcout << "After Randomization:" << std::endl << X << std::endl;
}
Sample output:
> adv_rnd(3,3)
Before Randomization:
-0.7197 1.2590 -0.5898
0.0253 0.1493 -0.0685
-0.6074 1.3843 0.0400
After Randomization:
-0.7197 1.2590 0.0400
-0.6074 1.2590 -0.5898
-0.6074 0.1493 -0.0685

Related

How do I resolve compile error in RcppParallel function which points to an RcppParallel header file

I'm trying to speed up numeric computation in my R code using RcppParallel and am attempting to edit an example that uses the Cpp sqrt() function to take the square root of each element of a matrix. My edited code replaces matrices with vectors and multiplies the sqrt() by a constant. (In actual use I will have 3 constants and my own operator function.)
The example comes from
https://gallery.rcpp.org/articles/parallel-matrix-transform/
The compiler identifies the error as in the 'algorithm' file on a comment line:
Line 7 no matching function for call to object of type 'SquareRootPlus::sqrtWrapper'
This is my initial attempt to use RcppParallel and I've not used
Cpp for several years.
Edit: running macOS Ventura on apple silicon,
Rcpp ver 1.0.10,
RcppParallel ver 5.1.6,
and R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
It would be called like this (if it compiled):
where c is a numerical constant aka a double and res is a numerical vector
res <- parallelMatrixSqrt(someNumericalVector, c)
My testing code is:
#include <Rcpp.h>
#include <RcppParallel.h>
using namespace RcppParallel;
using namespace Rcpp;
struct SquareRootPlus : public Worker
{
// source vector etc
const RVector<double> input;
const double constParam;
// destination vector
RVector<double> output;
// initialize with source and destination
// get the data type correctly unless auto promoted/cast
SquareRootPlus(const Rcpp::NumericVector input, const double constParam,
Rcpp::NumericVector output)
: input(input), constParam(constParam), output(output) {}
struct sqrt_wrapper { // describe worker function
public: double operator()(double a, double cp) {
return ::sqrt(a) * cp;
}
};
// take the square root of the range of elements requested
// (and multiply it by the constant)
void operator()(std::size_t begin, std::size_t end) {
std::transform(input.begin() + begin,
input.begin() + end,
output.begin() + begin,
sqrt_wrapper());
}
};
// public called routine
// [[Rcpp::export]]
Rcpp::NumericVector paralleVectorSqrt(Rcpp::NumericVector x, double c) {
// allocate the output matrix
Rcpp::NumericVector output(x.length());
// SquareRoot functor (pass input and output matrixes)
SquareRootPlus squareRoot(x, c, output);
// call parallelFor to do the work
parallelFor(0, x.length(), squareRoot);
// return the output matrix
return output;
}
That still works fine for me (Ubuntu 22.10, g++-12) -- modulo same warnings we often get from libraries like Boost, and here now from the include TBB library (and the repo should have a newer one so you can try that).
I just did (straight from the Rcpp Gallery source directory):
> library(Rcpp)
> sourceCpp("2014-06-29-parallel-matrix-transform.cpp")
In file included from /usr/local/lib/R/site-library/RcppParallel/include/tbb/tbb.h:41,
from /usr/local/lib/R/site-library/RcppParallel/include/RcppParallel/TBB.h:10,
from /usr/local/lib/R/site-library/RcppParallel/include/RcppParallel.h:21,
from 2014-06-29-parallel-matrix-transform.cpp:59:
/usr/local/lib/R/site-library/RcppParallel/include/tbb/concurrent_hash_map.h:343:23: warning: ‘template<class _Category, class _Tp, class _Distance, class _Pointer, class _Reference> struct std::iterator’ is dep
recated [-Wdeprecated-declarations]
[... more like this omitted for brevity ...]
> # allocate a matrix
> m <- matrix(as.numeric(c(1:1000000)), nrow = 1000, ncol = 1000)
> # ensure that serial and parallel versions give the same result
> stopifnot(identical(matrixSqrt(m), parallelMatrixSqrt(m)))
> # compare performance of serial and parallel
> library(rbenchmark)
> res <- benchmark(matrixSqrt(m),
+ parallelMatrixSqrt(m),
+ order="relative")
> res[,1:4]
test replications elapsed relative
2 parallelMatrixSqrt(m) 100 0.496 1.000
1 matrixSqrt(m) 100 0.565 1.139
>
and as you can see it not only builds but also runs the example call from R.
You would have to give us more detail about how you call it and what OS and package versions you use. And I won't have time now to dig into your code and do a code review for you but given that (still relatively simple) reference example works maybe you can reduce your currently-not-working approach down to something simpler that works.
Edit Your example appears to have switched from a unary function to one with two arguments in the signature. Sadly it ain't that easy. The fuller error message is (on my side with g++-12)
/usr/include/c++/12/bits/stl_algo.h:4263:31: error: no match for call to ‘(SquareRootPlus::sqrt_wrapper) (const double&)’
4263 | *__result = __unary_op(*__first);
| ~~~~~~~~~~^~~~~~~~~~
question.cpp:25:20: note: candidate: ‘double SquareRootPlus::sqrt_wrapper::operator()(double, double)’
25 | public: double operator()(double a, double cp) {
| ^~~~~~~~
question.cpp:25:20: note: candidate expects 2 arguments, 1 provided
So you need to rework / extend the example framework for this.
Edit 2: The gory details about std::transform() and its unary function are e.g. here at cppreference.com.
Edit 3: Building on the previous comment, when you step back a bit and look at what is happening here you may seen that RcppParellel excels at parceling up a large data structure, then submitting all the piece in parallel and finally reassemble the result. That still works. You simply cannot apply for 'richer signature function' via std::transform(). No more, no less. You need to work the guts of work which applies your function to the chunk it sees. Check the other RcppParallel examples for inspiration.

RcppArmadillo's sample() is ambiguous after updating R

I commonly work with a short Rcpp function that takes as input a matrix where each row contains K probabilities that sum to 1. The function then randomly samples for each row an integer between 1 and K corresponding to the provided probabilities. This is the function:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector sample_matrix(NumericMatrix x, IntegerVector choice_set) {
int n = x.nrow();
IntegerVector result(n);
for ( int i = 0; i < n; ++i ) {
result[i] = RcppArmadillo::sample(choice_set, 1, false, x(i, _))[0];
}
return result;
}
I recently updated R and all packages. Now I cannot compile this function anymore. The reason is not clear to me. Running
library(Rcpp)
library(RcppArmadillo)
Rcpp::sourceCpp("sample_matrix.cpp")
throws the following error:
error: call of overloaded 'sample(Rcpp::IntegerVector&, int, bool, Rcpp::Matrix<14>::Row)' is ambiguous
This basically tells me that my call to RcppArmadillo::sample() is ambiguous. Can anyone enlighten me as to why this is the case?
There are two things happening here, and two parts to your problem and hence the answer.
The first is "meta": why now? Well we had a bug let in the sample() code / setup which Christian kindly fixed for the most recent RcppArmadillo release (and it is all documented there). In short, the interface for the very probability argument giving you trouble here was changed as it was not safe for re-use / repeated use. It is now.
Second, the error message. You didn't say what compiler or version you use but mine (currently g++-9.3) is actually pretty helpful with the error. It is still C++ so some interpretative dance is needed but in essence it clearly stating you called with Rcpp::Matrix<14>::Row and no interface is provided for that type. Which is correct. sample() offers a few interface, but none for a Row object. So the fix is, once again, simple. Add a line to aid the compiler by making the row a NumericVector and all is good.
Fixed code
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector sample_matrix(NumericMatrix x, IntegerVector choice_set) {
int n = x.nrow();
IntegerVector result(n);
for ( int i = 0; i < n; ++i ) {
Rcpp::NumericVector z(x(i, _));
result[i] = RcppArmadillo::sample(choice_set, 1, false, z)[0];
}
return result;
}
Example
R> Rcpp::sourceCpp("answer.cpp") # no need for library(Rcpp)
R>

using `XPtr` to create pointer to a user defined function in Rcpp

--------- Adding a summary of the problem ---------------------------------
I want to create a externalpointer for a user defined function which can be passed to the another function. The user will provide function name as a string, my question is how can I convert that into a function pointer, after checking that the user provided string (say fstr) matches with the name of the function that was created by the user, i.e.
if (fstr == "<USER_DEFINED_FUNCTION_NAME>")
XPtr<funcPtr> fun(new funcPtr(&<USER_DEFINED_FUNCTION_NAME>), true);
else
Rcpp::Rcout << "Supply the correct function name" << std::endl;
since, I don't know the name of the function created by the user, essentially the problem is - how can I get the string stored in the variable fstr?
The full problem is described below. Of course, I could be thinking of this problem in a totally wrong way and there may be a better way to create a function pointer to a user defined function.
Thanks
I am writing a package which provides a wrapper around the cvode solver for solving ODEs from the SUNDIALS ODE solving C library. The C function which describes the right hand side of the ODEs must be have the signature
int <FUNCTION_NAME> (realtype t, N_Vector y, N_Vector ydot, void *user_data)
where realtype, N_Vector are datatypes defined in the library and t is time, y is the vector of states (dependent variables) and ydot is the rate of change of those variables w.r.t. time.
I have written a package which provides a wrapper around the cvode function in this library to solve ODEs expressed as above. The package source code can be found here. The cvode function can be used to solve the example in SUNDIALS provided as follows:
I create a test.cpp (pasted below) which describes the RHS of ODEs, it also has the exported function to create externalpointer for the function which gets exported to R. Note that NV_Ith_S is also defined by the library. Also, a good example about function pointers in Rcpp can be found here
First I run Rcpp::sourceCpp(test.cpp), then I run my_fun <- putFunPtrInXPtr() to create a external pointer my_fun to my test function in test.cpp. Finally, after loading the package, I run the command
time_t <- c(0.0, 0.4, seq(from = 10.4, len = 12, by = 10)) # time vector
cvode(time_t, c(1,0,0), my_fun, 1e-04, c(1e-08, 1e-08, 1e-08))
to get results on console successfully. Here the second argument is the initial conditions (IC), my_fun is the pointer to ODE function, third argument is relative tolerance and fourth argument is absolute tolerance. See details about cvode here.
My question is this - I want to change the cvode in my package so that it can take function name as a string, i.e. cvode(NumericVector time, NumericVector IC, std::string fstr, double reltol, NumericVector abstol), instead of cvode(NumericVector, NumericVector, SEXP, double, NumericVector) where the string (fstr) is the user given name which should be same as the same of the function defined in .cpp file (here test function in test.cpp).
I am thinking in my cvode function, I can write
if (fstr == "<USER_DEFINED_FUNCTION_NAME>")
XPtr<funcPtr> fun(new funcPtr(&<USER_DEFINED_FUNCTION_NAME>), true);
else
Rcpp::Rcout << "Supply the correct function name" << std::endl;
However, I cannot think of any way of getting information regarding the USER_DEFINED_FUNCTION_NAME. Essentially, I want fun to point to the USER_DEFINED_FUNCTION_NAME, but can't think of any way.
In the end, I actually want the RHS function defined in .cpp to have the signature int <FUNCTION_NAME>(double t, NumericVector y, NumericVector ydot, void *user_data), from which I create a function with the correct signature to be fed to cvode, but not sure how this is possible also.
I would be very thankful for any guidance. Thanks!
#include <Rcpp.h>
using namespace Rcpp;
#include <cvode/cvode.h> /* prototypes for CVODE fcts., consts. */
#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., macros */
#include <cvode/cvode_dense.h> /* prototype for CVDense */
#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
#include <sundials/sundials_types.h> /* definition of type realtype */
int test (realtype t, N_Vector y, N_Vector ydot, void *user_data){
// static keyword before int is not really required here
NV_Ith_S(ydot,0) = -0.04 * NV_Ith_S(y,0) + 1e04 * NV_Ith_S(y,1) * NV_Ith_S(y,2);
NV_Ith_S(ydot,2) = 3e07 * NV_Ith_S(y,1) * NV_Ith_S(y,1);
NV_Ith_S(ydot,1) = -NV_Ith_S(ydot,0) - NV_Ith_S(ydot,2);
return(0);
}
// declare funcPtr as a type for function pointer to a function with the
// signature same as function which describes the RHS for ODEs
// see reference here - http://gallery.rcpp.org/articles/passing-cpp-function-pointers/
typedef int (*funcPtr)(realtype t, N_Vector y, N_Vector ydot, void *user_data);
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
// return(XPtr<funcPtr> (new funcPtr(&test)));
XPtr<funcPtr> testptr(new funcPtr(&test), true);
return testptr;
}

Rcpp no matching function for call to abs

when using Rcpp, I want to use function abs, I just write Rcpp::abs(-1), but always an error:
no matching function for call to abs
Actually when I write Rcpp:ab, there are some hint that there exists Rcpp::abs(). I have tried some other function Rcpp::NumericVector, it works. I know I can use std::abs(-1), I just wonder why Rcpp::abs(-1) do not work, my system is windows, and I install Rtools.
Rcpp::abs() requires an Rcpp object, e.g. *Vector and *Matrix.
Unfortunately, -1 is of a primitive type, e.g. not an Rcpp object.
So, the following would work:
#include <Rcpp.h>
// [[Rcpp::export]]
void show_rcpp_abs() {
Rcpp::NumericVector A = NumericVector::create(-1);
Rcpp::Rcout << "A" << Rcpp::abs(A) << std::endl;
double B = std::abs(-1.0);
Rcpp::Rcout << "B" << B << std::endl;
}

RCpp long long unsigned int error issue

I am a newbie to Rcpp and C++. I am trying to convert the following R code into RCpp.
library (compiler)
robzscore<-cmpfun(function(x) {
byec <- sum(!is.na(x))
byer <- rank(x, na.last="keep", ties.method="average") - 0.5
as.data.frame(suppressWarnings(qnorm(byer/byec)), row.names=NULL)
})
I am struggling with writing the syntax for the part where i need to get the ranks. For example, this is what I wrote (in a separate cpp file that I am compiling using sourceCpp) based on other codes I found on SO as an equivalent of the rank(x,...) function in R assuming there are no NAs (and not handling ties):
#include <Rcpp.h>
#include <algorithm>
#include <iostream>
using namespace Rcpp;
template <typename T>
std::vector<size_t> sort_indexes(const std::vector<T> &v) {
// initialize original index locations
std::vector<size_t> idx(v.size());
for (size_t i=0; i!=idx.size();++i) idx[i]=i;
// sort indexes based on comparing values in v
std::sort(idx.begin(),idx.end(),[&v](size_t i1, size_t i2) {return v[i1]<v[i2];});
// return the values
return idx;
}
// [[Rcpp::export]]
NumericVector do_rank(NumericVector x) {
std::vector<float> y=as<std::vector<float> >(x);
return wrap(sort_indexes(y));
}
The error is get are:
lambda expressions only available with -std=c++0x or -std=gnu++0x [enabled by default] - followed by - no matching function for call to 'sort(std::vector<long long unsigned int>::iterator, std::vector<long long unsigned int>::interator, sort_indexes(const std::vector<T> &) [ with T=float]::<lambda(long long unsigned int, long long u
nsigned int)>)' at the place where my code says std::sort(idx.begin(),...).
~/R/win-library/3.0/Rcpp/include/Rcpp/internal/wrap.h : invalid conversion from 'long long unsigned int' to 'SEXP' [-fpermissive].
I suspect the main issue with some error I made in the syntax I used to handle Rcpp (converting Rcpp to C++ data structure or vice versa).
Can someone help me interpret the errors and/or what could be the right way?
Thanks,

Resources