Reputation: 313
I am learning Rcpp and write the following two functions. The second function simply computes sum(log_gamma(x)) - log_gamma(sum(x)) where x is a vector.
Three data type conversion errors are returned, all of which I am not able to resolve. Can someone help me correct the codes? Thanks.
file330c72cf6532.cpp:8:37: error: cannot convert 'Rcpp::sugar::Vectorized<Rf_lgammafn, true, Rcpp::Vector<14, Rcpp::PreserveStorage> >' to 'SEXP' in initialization
SEXP lgamma_x = lgamma(x);
^
file330c72cf6532.cpp:10:45: error: cannot convert 'SEXP' to 'double' in initialization
double up = sum_cpp(lgamma_x_vec);
^
file330c72cf6532.cpp:11:44: error: cannot convert 'Rcpp::sugar::Vectorized<Rf_lgammafn, true, Rcpp::Vector<14, Rcpp::PreserveStorage> >' to 'double' in initialization
double down = lgamma(sum_cpp(x));
^
cppFunction(
'double sum_cpp(NumericVector x){
double tmp = 0;
int n = x.size();
for(int j = 0; j<n; j++){
tmp = tmp + x[j];
}
return tmp;
}')
cppFunction('double LogB_cpp(NumericVector x){
Function sum_cpp( "sum_cpp" ) ;
SEXP lgamma_x = lgamma(x);
NumericVector lgamma_x_vec(lgamma_x);
double up = sum_cpp(lgamma_x_vec);
double down = lgamma(sum_cpp(x));
return up - down;}')
Upvotes: 2
Views: 1572
Reputation: 20746
There are two glaring errors being made here. The first issue is the use of a C++ as a regular R function when it shouldn't be (e.g. sum_cpp
). The second is the issue with lgamma
being a sugar expression returning an Rcpp::NumericVector
and not a scalar (e.g. double
).
The first issue comes up because you are using cppFunction()
, which has its usage as a primary means to prototype C++ code. For more extended C++ usage, it is preferred that sourceCpp()
is used. The use of sourceCpp()
brings light to Rcpp attributes, which provide a means to surface C++ functions into R. Specifically, within the C++ script, one should use // [[Rcpp::exports]]
above the desired C++ function. In addition, if you need to use a C++ function within another, it must be defined prior to its usage. Thus, define sum_cpp
before LogB_cpp
in the C++ file. For an example of this, please see the Rcpp Quick Reference guide.
Regarding the second issue, this is easily corrected by either saving it as a NumericVector
or using [0]
to obtain the first result as a double.
Furthermore, for some reason you initially were saving into a SEXP
and then converting into a NumericVector
that step isn't need and has been omitted from below.
For example, place the following into gamma_source.cpp:
#include <Rcpp.h>
// [[Rcpp::export]]
double sum_cpp(Rcpp::NumericVector x){
double tmp = 0;
int n = x.size();
for(int j = 0; j<n; j++){
tmp = tmp + x[j];
}
return tmp;
}
// [[Rcpp::export]]
double LogB_cpp(Rcpp::NumericVector x){
Rcpp::NumericVector calc_lgamma = lgamma(x);
double up = sum_cpp(calc_lgamma);
Rcpp::NumericVector sum_lgamma = lgamma(sum_cpp(x));
double down = sum_lgamma[0];
// Alternatively, you could do:
// double down = lgamma(sum_cpp(x))[0];
return up - down;
}
Then type: sourceCpp("gamma_source.cpp")
. This assumes the working directory is the same as where "gamma_source.cpp" is. Otherwise, append the path.)
Example:
library("Rcpp")
sourceCpp("gamma_source.cpp")
x = c(1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5)
LogB_cpp(x)
## [1] 9.481571
Upvotes: 2