改变R包内的`SEXP`结构

时间:2018-03-15 14:43:00

标签: c++ c rcpp r-package

我开发了一个R包,它提供了SUNDIALS(ODE求解库)的CVODE函数的包装器。

该软件包包含源函数(在srcinst/include文件夹中)并动态编译静态链接(.a)和.dll文件(同时编译包),因此它不需要在系统上安装SUNDIALS包作为先决条件。包源可以在

找到

https://github.com/sn248/Rcppsbmod

但是,SUNDIALS要求ODE函数具有以下签名

int ODE_fun (realtype time, N_Vector y, N_Vector ydot, void *user_data);

realtypeN_Vector是SUNDIALS库定义的数据类型。因此,示例ODE函数将定义如下

#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 */

#define Ith(v,i)  NV_Ith_S(v,i-1)

#define k1  0.04
#define k2  1e04
#define k3  3e07


int test1 (realtype t, N_Vector y, N_Vector ydot){  // , void *user_data

  // static keyword before int is not really required here

  realtype y1 = Ith(y, 1);
  realtype y2 = Ith(y, 2);
  realtype y3 = Ith(y, 3);

  realtype yd1 = Ith(ydot, 1);
  realtype yd2 = Ith(ydot, 2);
  realtype yd3 = Ith(ydot, 3);

  yd1 = -k1 * y1 + k2 * y2 * y3;
  yd3 = k3 * y2 * y2;
  yd2 = -y1 - y3;


  return(0);
}

但是,编译此函数需要cvode.hnvector_serial.h头文件,因此需要安装SUNDIALS。

但是,我希望用户能够仅使用Rcpp来定义ODE,即

#include <Rcpp.h>
using namespace Rcpp;

#define k1  0.04
#define k2  1e04
#define k3  3e07


int test2 (double t, NumericVector y, NumericVector ydot, void *user_data) {

  ydot[0] = -k1 * y[0] + k2 * y[1] * y[2];
  ydot[2] = k3 * y[1] * y[1];
  ydot[1] = -y[0] - y[2];

  return(0);
}

然后将从具有签名

的包中作为cvode(此处为SEXP参数)提供给ODE_fun函数
cvode(NumericVector time_vec, NumericVector IC, 
      SEXP ODE_fun, double reltolerance, NumericVector abstolerance)

目前ODE_fun是一个带有typedef

的函数指针
typedef int (*funcPtr)(realtype t, N_Vector y, N_Vector ydot, void *user_data);

test1使用以下代码转换为XPtr

// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {

    XPtr<funcPtr> testptr(new funcPtr(&test), false);
    return testptr;

}

可以在包wiki找到运行示例示例的整个过程。

我不确定如何输入test2(仅使用Rcpp定义的ODE函数)并将其转换为包中CVODE解算器所需签名的函数。任何建议或指示,或者如果有更好的方法来达到我的目的,我们将非常欢迎!

谢谢

0 个答案:

没有答案