I am wondering if there is a Rcpp way to convert an element or iterator of const CharacterVector& to std::string. If I try the following code
void as(const CharacterVector& src) {
std::string glue;
for(int i = 0;i < src.size();i++) {
glue.assign(src[i]);
}
}
a compiler-time error will occurred:
no known conversion for argument 1 from ‘const type {aka SEXPREC* const}’ to ‘const char*’
So far, I use C API to do the conversion:
glue.assign(CHAR(STRING_ELT(src.asSexp(), i)));
My Rcpp version is 0.10.2.
By the way, I do know there is a Rcpp::as.
glue.assign(Rcpp::as<std::string>(src[i]));
the above code will produce a runtime-error:
Error: expecting a string
On the otherhand, the following code run correctly:
typedef std::vector< std::string > StrVec;
StrVec glue( Rcpp::as<StrVec>(src) );
However, I do not want to create a temporal long vector of string in my case.
Thanks for answering.
I am confused as that what you want -- a CharacterVector is a vector of character strings (as in R) so you can only map it to std::vector<std::string> >. Here is a very simple, very manual example (and I thought we had auto-converters for this, but maybe not. Or no more.
#include <Rcpp.h>
// [[Rcpp::export]]
std::vector<std::string> ex(Rcpp::CharacterVector f) {
std::vector<std::string> s(f.size());
for (int i=0; i<f.size(); i++) {
s[i] = std::string(f[i]);
}
return(s);
}
And here it is at work:
R> sourceCpp("/tmp/strings.cpp")
R> ex(c("The","brown","fox"))
[1] "The" "brown" "fox"
R>
In Rcpp 0.12.7, I can use Rcpp::as<std::vector<std::string> >. The following function returns the second element of the test array:
std::string test() {
Rcpp::CharacterVector test = Rcpp::CharacterVector::create("a", "z");
std::vector<std::string> test_string = Rcpp::as<std::vector<std::string> >(test);
return test_string[1];
}
Related
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>
I am new to Rcpp.
I created an rcpp function which takes a dataframe with 2 columns and a vector as input, and returns a vector.
My data are as below
set.seed(10)
min= sort(rnorm(1000,800,sd=0.1))
max= min+0.02
k=data.frame(min,max)
explist= sort(rnorm(100,800,sd=0.2))
Then I call the cfilter.cpp
k$output <- cfilter(k,explist)
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
CharacterVector cfilter(DataFrame k, NumericVector explist) {
NumericVector col1 = k["min"];
NumericVector col2 = k["max"];
NumericVector exp = explist ;
int n = col1.size();
int j = 0;
CharacterVector out(n);
for (int i=0; i<n ; i++){
out[i]=NA_STRING;
while(exp[j]<= col2[i]){
if( exp[j]>= col1[i] && exp[j]<= col2[i] ){
out[i]="Y";
break;
}
else if(exp[j]>col2[i]){
break;
}
else {
j++ ;
}
}
}
return out;
}
It run perfectly fine for 16171 times I called it. And then suddenly, in the loop 16172 it just stops with an error:
> myfile$output<- cfilter(k,explist2)
Error in .Call(<pointer: (nil)>, k, explist) :
NULL value passed as symbol address
I checked k and explist for NA values but there aren't any, there is no problem whatsoever with the input.
I have no clue how to fix this and what causes this error.
Thanks in advance for any response
I came across the same problem. I'm not an Rcpp expert, nor C++ nor, a backend coding expert.
I have circumvented this problem by re-sourcing my cpp file every time I want to make a call of the function. So, for example if following is your for loop:
for(i in 1:SampleSize){
out[[I]]<-cfilter(k,explist)
}
Do something like:
for(i in 1:SampleSize){
sourceCpp("cfilter.cpp")
out[[i]]<-cfilter(k,explist)
}
Again, I don't know exactly why this worked for me, but it worked. Based on my shallow knowledge of C++, it might be related to memory allocation and that every time you source, memory is released and hence there is no mis-allocation. But I think this is a very wild guess.
Best
I've got two Rcpp-wrapped classes, A and B. A's constructor extracts some information from its parameter, and prints it out to prove it worked.
B takes an object of A as a constructor parameter — and reports an error as if extraction in A's constructor failed. But as A did print out the extracted data, it couldn't fail.
How do I get B to accept A as a parameter without erroring out?
Minimal reproducible example:
library(Rcpp)
Rcpp::sourceCpp(code='
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
')
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
Output:
> source('testcase.R', echo=TRUE)
> library(Rcpp)
> Rcpp::sourceCpp(code='
+ #include <Rcpp.h>
+
+ struct A {
+ Rcpp::NumericVector y;
+
+ A(Rcpp::List x)
+ : y(Rcpp::as<Rcpp::NumericVector> .... [TRUNCATED]
> Aobj <- new(A, list(foo=1:3))
1 2 3
> Bobj <- new(B, Aobj)
Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
Index out of bounds: [index='foo'].
>
I'll try to explain why your solution works. With RCPP_MODULE(A) you are exposing the C++ struct A as a reference class in R. That is done automatically. However, when you call Bobj <- new(B, Aobj), there is no information how to convert from this reference class to the required C++ struct. By using RCPP_EXPOSED_CLASS(A) you are creating specialization of Rcpp::wrap and Rcpp::as to convert between C++ and R objects in both ways. Since we are only missing the R to C++ conversion, i.e. Rcpp::as, the following is also enough:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_AS(A)
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
/*** R
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
*/
When things are not working, it's good to (re-)read some documentation. Specifically, Rcpp Extending (PDF), section 3.2.
I added the following at the beginning of the C++ code:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_CLASS(A);
…and it works fine now. I admit I don't fully understand what happens here yet, but this solution is solving both the MWE and my original code problems.
With RcppEigen, I need a Matrix3d as an argument of a function. But this is not possible, it only accepts MatrixXd. I've tried to cast as follows but that doesn' work:
Rcpp::List MtoAxisAngle(Eigen::MatrixXd & m)
{
Eigen::Matrix3d m3 = m.cast();
......
Any solution ?
You can use the existing matrix in the initialization of the new matrix:
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
// [[Rcpp::export]]
Rcpp::List MtoAxisAngle(Eigen::MatrixXd & m)
{
Eigen::Matrix3d m3(m);
return Rcpp::List::create(Rcpp::Named("size") = m3.size());
}
/*** R
MtoAxisAngle(matrix(1:9,3,3))
# MtoAxisAngle(matrix(1:16,4,4))
*/
Since a call with a non-conforming matrix kills R, you should check beforehand if the size is correct.
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,