Jiexing Wu
Jiexing Wu

Reputation: 313

Data type conversion error in using Rcpp

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

Answers (1)

coatless
coatless

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

Related Questions