简体   繁体   中英

Convert C array pointers to Rcpp with call by reference in R

I have the following codes in C. I am new to Rcpp and I want to convert the C codes I have to Rcpp.

C code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


void calculate(const double *d, double *w, int col, int x) {
  int i,j; 
  for (i = 0; i < col; i++){
    for (j = 0; j < x; j++){
      w[j * col + i]++;
    } 
  } 
}

int main(){

    int i, col = 2, row = 6;
    int x = 5, y = 3, a = 0; 
    double d[] = {1.0, 0.8, 0.2, 1.0, 0.4, 0.6, 0.6, 0.4, 0.8, 1.0, 1.0, 0.2};
    double *w = (double*)calloc((row - a) * col * x, sizeof(double));


    for (i = 0; i < row - a; i++) {
        calculate(d + (i + a) * col, w + i * col * x, col, x);
    }

}

Rcpp code:

NumericVector calculate(NumericVector d, NumericVector w, int col, int x) {
  int i,j; 
  for (i = 0; i < col; i++){
    for (j = 0; j < x; j++){
      w[j * col + i]++;
    } 
  } 
  return w;
}

int i, col = 2, row = 6;
int x = 5, y = 3, a = 0; 
NumericVector w((row - a) * col * x);

for (i = 0; i < row - a; i++) {
    w = calculate(d + (i + a) * col, w + i * col * x, col, x);
}

This is my conversion that does not seem to work. My question is how to pass these parameters d + (i + a) * col and w + i * col * x as pointers in Rcpp, since its not an indexing?

If the below line in your code works as intended,

NumericVector w((row - a) * col * x);

why not do the same in your for loop?

for (i = 0; i < row - a; i++) {
    NumericVector nvx(d + (i + a) * col);
    NumericVector nvy(w + i * col * x);
    w = calculate(nvx, nvy, col, x);
}

My question is how to pass these parameters d + (i + a) * col and w + i * col * x as pointers in Rcpp, since its not an indexing?

You can use numericVector.begin() to get a pointer to the first element which you can then use. Here is an example

// [[Rcpp::plugins(cpp11)]]
#include <Rcpp.h>
#include <memory>    // unique_ptr
#include <algorithm> // fill
using namespace Rcpp;

void calculate(const double *d, double *w, int col, int x) {
  for (int i = 0; i < col; i++)
    for (int j = 0; j < x; j++)
      w[j * col + i]++;
}

// [[Rcpp::export]]
void show_example(){
  /* Rcpp version */
  int const col = 2, 
            row = 6,
              x = 5, 
              // y = 3, never used?
              a = 0, 
          n_out = (row - a) * col * x;

  NumericVector w_rcpp(n_out);
  for(int i = 0; i < row - a; i++)
    calculate(nullptr /* never used? */, w_rcpp.begin() + i * col * x, col, x);

  /* old C++ version. (uses std::unique_ptr to take care of memory 
   * allocation) */
  std::unique_ptr<double[]> w_cpp(new double[n_out]);

  /* fill with zeros to get the same*/
  std::fill(w_cpp.get(), w_cpp.get() + n_out, 0);
  for (int i = 0; i < row - a; ++i)
    calculate(nullptr /* never used? */, w_cpp.get() + i * col * x, col, x);

  /* Compare the result */
  Rcpp::Rcout << "Rcpp: " << w_rcpp << '\n' 
              << "Cpp:  ";
  for(int i = 0; i < n_out; ++i)
    Rcpp::Rcout << *(w_cpp.get() + i) << ' ';
  Rcpp::Rcout << '\n';
}

/*** R
show_example()
#R> Rcpp: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
#R> Cpp:  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
*/

Though, now you do not have any bound checks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM