Exposed Rcpp defined C++ function crashes R session, code snippets working before. Function exposition wrong? - r

I have C++ code executed in Rcpp where I define a few functions that are then called in an exposed function using the // [[Rcpp::export]] tag. The code compiles fine but executing the exposed function returns in a fatal crash of my R session leading to immediate termination.
What mystifies me is that the code executed fine yesterday when I ran it up to the line VectorXd z = y_luet - kroneckerProduct(X_luet.transpose(), MatrixXd::Identity(p, p)) * r; and returning the vector z. Now, neither that nor the full code as displayed below work.
I have also done my homework of testing all functions individually, checking they are correct by exposing them to R before using the same technique and checking them against their slower R counterparts, obtaining numerically identical results (at greater speed).
I am wondering whether I am just using the 'define a few functions and then use them in a bigger function' approach is not appropriate as soon as the tasks become a little bigger?
The data themselves are moderate by Eigen's standards, dat is a matrix with 200 rows and 2 columns, everything else is low-dimensional, with the maximum of (row, column) not exceeding 12, i.e. the second-largest matrix is 12 by 1.
I am using Rtools and Rcpp all of the most recent vintage.
The code implements a simple iterated generalised least squares estimator, as is common in Statistics/Econometrics.
Edit
Here is some sample data in R format that should get a minimal working example:
params <- .963
G <- matrix(c(1,0),nrow = 2)
G_perp <- matrix(c(0,1),nrow = 2)
mat_Lambda_lu <- matrix(0.95,nrow=1)
dat <- matrix(c(0,0,0,-0.79642284,-1.36694331,-1.18267593,-1.48827199,0.12549353,3.03343410,7.36256542,0,0,0,0.11282054,0.24798861,0.32448004,-0.27283699,-1.2462477,-0.0104694,3.21067339), nrow = 10, ncol = 2)
k<-3
no_ur <- 1
maxiter <- 100 #or something small for conserving memory
mini <- TRUE
The above should be executed in an R environment for it work. Please let me know if it doesn't work or if there are issues.
Here is the code:
// [[Rcpp::depends(RcppEigen)]]
#include <Rcpp.h>
#include <RcppEigen.h>
#include <cmath>
#include <cstdlib>
#include <Eigen/Dense>
#include <unsupported/Eigen/src/MatrixFunctions/MatrixPower.h>
#include <unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h>
using namespace Rcpp;
using namespace Eigen;
//using Eigen::Map; // 'maps' rather than copies
//using Eigen::MatrixXd; // variable size matrix, double precision
//using Eigen::VectorXd; // variable size vector, double precision
MatrixXd makeXluet(MatrixXd dat, int k, int p, int T) {
MatrixXd X_luet(p*k, T - k);
for (int i = k; i > 0; i--)
{
X_luet.block((k-i)*p,0,p,T-k) = dat.block(i - 1, 0, T - k, p).transpose();
}
return X_luet;
}
MatrixXd makeRLuTilde(MatrixXd Rlu, MatrixXd LambdaLu, int k, int p, int q) {
MatrixXd RLuTilde(p*k, q);
MatrixPower<MatrixXd> Apow(LambdaLu);
for (int i = k; i > 0; i--) {
RLuTilde.block((k - i)*p, 0, p, q) = Rlu * Apow(i-1);
}
return RLuTilde;
}
VectorXd GLSEstimateFast(MatrixXd Xluet, MatrixXd Sigma_u, MatrixXd R, VectorXd z, int T, int k) {
return (R.transpose() * kroneckerProduct(Xluet * Xluet.transpose(), Sigma_u.inverse()) * R).inverse() * R.transpose() * kroneckerProduct(Xluet, Sigma_u.inverse()) * z;
}
MatrixXd ResMaker(MatrixXd Xluet, MatrixXd Yluet, VectorXd beta, const int k, const int p) {
Map<MatrixXd> A(beta.data(), p, k*p);
return Yluet - A * Xluet;
}
double GLSCriterion(MatrixXd res, MatrixXd Sigma_u, const int k, const int p, const int T) {
MatrixXd Lp = Sigma_u.inverse().llt().matrixL().transpose();
MatrixXd v = Lp * res;
Map<VectorXd> v2(v.data(), v.size());
return (1 / static_cast<double>(T)) * v2.transpose() * v2;
}
MatrixXd CovEstFast(MatrixXd res, const int T) {
return (1 / static_cast<double>(T)) * res * res.transpose();
}
double likeli_h(MatrixXd CovEstHat, const int T) {
return (-0.5)*static_cast<double>(T) * log(CovEstHat.determinant());
}
// [[Rcpp::export]]
double restricted_iterated_ml_cpp(Map<VectorXd> params, Map<MatrixXd> G, Map<MatrixXd> G_perp, Map<MatrixXd> mat_Lambda_lu, Map<MatrixXd> dat, const int k, const int no_ur, const int maxiter, bool mini) {
const int p = dat.cols();
const int T = dat.rows();
int p2 = static_cast<int>(pow(p, 2));
int iter = 0;
MatrixXd X_luet = makeXluet(dat, k, p, T);
MatrixXd Y_luet = dat.bottomRows(T-k).transpose();
Map<MatrixXd> D(params.data(), p - no_ur, no_ur);
MatrixXd R_lu = G + G_perp * D;
MatrixXd R_lu_tilde = makeRLuTilde(R_lu, mat_Lambda_lu, k, p, no_ur);
MatrixXd C = kroneckerProduct(R_lu_tilde.transpose(), MatrixXd::Identity(T - k, T - k));
MatrixXd C1 = C.topLeftCorner(no_ur*p, no_ur*p);
MatrixXd C2 = C.block(0, no_ur*p, no_ur*p, C.cols() - (no_ur*p));
MatrixPower<MatrixXd> Llupow(mat_Lambda_lu);
MatrixXd mat_cee = R_lu * Llupow(k);
Map<VectorXd> cee(mat_cee.data(), mat_cee.size());
MatrixXd R(no_ur*p + k * p2 - (no_ur * p), k*p2 - (no_ur * p));
R << static_cast<double>(-1) * C1.inverse()*C2,
MatrixXd::Identity(k*p2-no_ur*p, k*p2 - (no_ur * p));
VectorXd r(k * p2);
r << C1.inverse() * cee,
MatrixXd::Zero(k * p2 - (no_ur * p), 1);
Map<VectorXd> y_luet(Y_luet.data(), Y_luet.size());
VectorXd z = y_luet - kroneckerProduct(X_luet.transpose(), MatrixXd::Identity(p, p)) * r;
MatrixXd Sigma_u = MatrixXd::Identity(p, p);
VectorXd gamma = GLSEstimateFast(X_luet, Sigma_u, R, z, T, k);
VectorXd beta = R * gamma + r;
MatrixXd res = ResMaker(X_luet, Y_luet, beta, k, p);
double crit_old = GLSCriterion(res, Sigma_u, k, p, T);
double crit_new = crit_old;
do
{
crit_old = crit_new;
Sigma_u = CovEstFast(res, T);
gamma = GLSEstimateFast(X_luet, Sigma_u, R, z, T, k);
beta = R * gamma + r;
res = ResMaker(X_luet, Y_luet, beta, k, p);
crit_new = GLSCriterion(res, Sigma_u, k, p, T);
iter++;
} while ((iter<maxiter) && (crit_old-crit_new>0.001));
double ll = likeli_h(Sigma_u, T);
if (mini) {
ll = static_cast<double>(-1)*ll;
}
return ll;
}

Related

Solving DDE system

im trying to solve a differentiel delay equation system with c++. Im a newbie in terms of coding, so please if you have recommendations, tell me, I would like to improve my writing! What i want to do: initialize the history-array and then start to solve the differential equation by overwriting the history-array. But the problem is, I get the error message:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 9999) >= this->size() (which is 9999)
It seems that the history-arrays are out of range. I tried to put a std::cout in after the second if-condition to check if the code is going through the second for-loop, but he isn't. Since im learning c++ by doing right now, the problem isn't really clear to me. I hope someone sees the error. And dont hesitate to improve my code, I would really appreciate!
Thanks for your help!
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <fstream>
const double pi = 3.14159265358979323846;
//delay
int tau = 1;
//initial values
double x = 1.0;
double y = 1.0;
double t = 0.0;
//constants and parameters
double K = 0.25;
double lam = 0.5;
double omega = pi;
double dx, dy;
//step-size
double dt = pow(10.0, -4.0);
//number of steps
int Delta = static_cast<int>(tau/dt);
std::vector<double> hist_x((static_cast<int>(tau/dt) - 1), 0.0);
std::vector<double> hist_y((static_cast<int>(tau/dt) - 1), 0.0);
std::vector<double> t_val;
std::vector<double> x_val;
std::vector<double> y_val;
double euler(double f, double di, double time_step){
f = f + time_step * di;
return f;
}
int main()
{
std::ofstream file_x;
std::ofstream file_y;
std::ofstream file_t;
file_x.open("x_val.txt");
file_y.open("y_val.txt");
file_t.open("t_val.txt");
for(int n = 0; n < 2; n++){
if(n==0){
for(int j; j < Delta; j++){
dx = lam * x + omega * x;
dy = lam * y - omega * x;
x = euler(x, dx, dt);
y = euler(y, dy, dt);
t = t + dt;
x_val.push_back(x);
y_val.push_back(y);
t_val.push_back(t);
hist_x.at(j) = x;
hist_y.at(j) = y;
file_x<<x_val.at(j)<<std::endl;
file_y<<y_val.at(j)<<std::endl;
file_t<<t_val.at(j)<<std::endl;
}
}
if(!(n==0)){
for(int k = 0; k < Delta; k++){
//f1(x,y)
dx = lam * x + omega * x - K * ( x - hist_x.at(k) );
//f2(x,y)
dy = lam * y - omega * x - K * ( y - hist_y.at(k) );
x = euler(x, dx, dt);
y = euler(y, dy, dt);
t = t + dt;
x_val.push_back(x);
y_val.push_back(y);
t_val.push_back(t);
hist_x.at(k) = x;
hist_y.at(k) = y;
file_x<<x_val.at(k + n * Delta)<<std::endl;
file_y<<y_val.at(k + n * Delta)<<std::endl;
file_t<<t_val.at(k + n * Delta)<<std::endl;
}
}
}
file_x.close();
file_y.close();
file_t.close();
}
for(int j; j < Delta; j++){
You forgot to initialize j; you meant:
for (int j = 0; j < Delta; j++)
{
int Delta = static_cast<int>(tau/dt);
std::vector<double> hist_x((static_cast<int>(tau/dt) - 1), 0.0);
std::vector<double> hist_y((static_cast<int>(tau/dt) - 1), 0.0);
You index from 0 to Delta−1, this means the vectors need to have Delta elements, and you allocate one less; correct:
std::vector<double> hist_x(Delta, 0.0);
std::vector<double> hist_y(Delta, 0.0);

Rcpp multiple functions in a file and no matching function

I am trying to run the function weights below in R. Functions mN and PsiN below work individually, and I do not need to export them into R (i.e. their only purpose is to keep the function weights looking neater).
For some reason, only mN gives me the error "no matching function call" within the function weights. Any idea as to why?
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
arma::vec mN(double kappa, double ni, arma::vec m, arma::vec C) {
arma::vec mN;
double kappaN;
kappaN = kappa + ni;
mN = (kappa/kappaN) * m + (ni/kappaN) * C;
return mN;
}
arma::mat PsiN(double ni, double kappa, double kappaN,
arma::mat y, arma::vec indic, arma::vec C, arma::vec m,
arma::mat Psi) {
double r = indic.n_elem;
double p = y.n_cols;
double n = y.n_rows;
arma::mat S(p, p);
arma::mat PN(p, p);
if (r == 1) {
PN = Psi + kappa*ni/kappaN * ( (C - m ) * (C - m).t() );
} else {
for (int i = 0; i < n; i++) {
S += y.row(i).t() * y.row(i);
}
PN = Psi + S + kappa*ni/kappaN * ( (C - m ) * (C - m).t() ) ;
}
return PN;
}
// [[Rcpp::export]]
arma::vec weights(int alpha, int v, int kappa, int m,
arma::vec nj, arma::mat x, arma::mat Psi,
List C, List indic) {
int p = x.n_cols;
int n = x.n_rows;
int kappaN;
int vN;
int crp;
arma::vec Q;
arma::vec mu;
arma::mat Sigma;
for (int i = 0; i < n; i++) {
kappaN = kappa + nj[i];
vN = v + nj[i] - p + 1;
Sigma = PsiN(nj[i], kappa, kappaN, x, indic[i], C[i], m, Psi);
Sigma = Sigma*(kappaN + 1)/(kappaN*(vN - p + 1));
mu = mN(kappa, kappaN, nj[i], m, C[i]);
crp = log(nj[i]) - log(n + alpha - 1);
Q[i] = (crp - lgamma((vN + p)/2) - lgamma(vN/2) - p/2*(log(vN) + log(
datum::pi)) - 1/2*log_det(Sigma) - (vN + p)/2 * (log(1 + 1/v*(x - mu).t()*Sigma.i()*(x-mu)))) ;
}
return Q;
}
Your function signature for mN is
arma::vec mN(double, double, arma::vec, arma::vec)
But you call it as
mu = mN(kappa, kappaN, nj[i], m, C[i]);
where kappa is int, kappaN is int, nj[i] is double, m is int and C is a List of SEXPs.
Note that unlike R, you can't in general mix doubles and ints in C++ with abandon. In particular, I'll also point out that declarations like
double r = indic.n_elem;
double p = y.n_cols;
double n = y.n_rows;
should all be ints or unsigned ints.
The function signatures in the definition:
arma::vec mN(double kappa, double ni, arma::vec m, arma::vec C)
does not match its usage:
mu = mN(kappa, kappaN, nj[i], m, C[i]);
You have to decide whether the function needs 4 or 5 arguments.

Using devtools to build an R package that imports cuda code

I'm trying to utilize gpu machines in oder to improve performance of a matrix multiplication operation.
I tried to make sense of this post and utilize cuda code from this repos and build it all in an R package using devtools.
What I did is write a cuda file named matrixMultiplication.cu:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define BLOCK_SIZE 16
__global__ void runGpuMatrixMult(double *a, double *b, double *c, int m, int n, int k)
{
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
int sum = 0;
if( col < k && row < m)
{
for(int i = 0; i < n; i++)
{
sum += a[row * n + i] * b[i * k + col];
}
c[row * k + col] = sum;
}
}
extern "C"
void gpuMatrixMult(double &A, double &B, double &C, int& m, int& n, int& k) {
// allocate memory in host RAM
double *h_A, *h_B, *h_C;
cudaMallocHost((void **) &h_A, sizeof(int)*m*n);
cudaMallocHost((void **) &h_B, sizeof(int)*n*k);
cudaMallocHost((void **) &h_C, sizeof(int)*m*k);
// Allocate memory space on the device
int *d_A, *d_B, *d_C;
cudaMalloc((void **) &d_A, sizeof(int)*m*n);
cudaMalloc((void **) &d_B, sizeof(int)*n*k);
cudaMalloc((void **) &d_C, sizeof(int)*m*k);
// copy matrix A and B from host to device memory
cudaMemcpy(d_A, h_A, sizeof(int)*m*n, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, sizeof(int)*n*k, cudaMemcpyHostToDevice);
unsigned int grid_rows = (m + BLOCK_SIZE - 1) / BLOCK_SIZE;
unsigned int grid_cols = (k + BLOCK_SIZE - 1) / BLOCK_SIZE;
dim3 dimGrid(grid_cols, grid_rows);
dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
// Launch kernel
runGpuMatrixMult<<<dimGrid, dimBlock>>>(d_A, d_B, d_C, m, n, k);
// Transfer results from device to host
cudaMemcpy(h_C, d_C, sizeof(int)*m*k, cudaMemcpyDeviceToHost);
cudaThreadSynchronize();
// free memory
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
cudaFreeHost(h_A);
cudaFreeHost(h_B);
cudaFreeHost(h_C);
return 0;
}
Then a cpp file named matrixUtils.cpp:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
extern "C"
void gpuMatrixMult(double const&A, double const&B, double const& C, int& m, int& n, int& k);
//' gpuMatrixMultCaller calls matrixMultiplication.cu::gpuMatrixMult
//'
//' #export
//[[Rcpp::export]]
SEXP gpuMatrixMultCaller(double const& A, double const& B, double& C, int m, int n, int k) {
gpuMatrixMult(A, B, C, m, n, k);
return R_NilValue;
}
Finally, I have an R file named utils.R which has a wrapper function that calls gpuMatrixMultCaller:
#' gpuMatrixMultWrapper calls matrixUtils.cpp::gpuMatrixMultCaller which runs a GPU matrix multiplication
#' Returns the product of the input matrices
gpuMatrixMultWrapper <- function(A,B)
{
m <- nrow(A)
n <- ncol(A)
k <- ncol(B)
C <- bigmemory::deepcopy(A)
gpuMatrixMultCaller(A, B, C, m, n, k)
return(C)
}
When I run devtools::document I get this error:
Error in dyn.load(dllfile) :
unable to load shared object '/home/code/packages/utils/src/utils.so':
/home/code/packages/utils/src/utils.so: undefined symbol: gpuMatrixMult
The NAMESPACE file does have: useDynLib(utils) at the bottom line and in the DESCRIPTION file I specify: LinkingTo: Rcpp, RcppArmadillo
So my questions are:
Is it even possible to build an R pacakge which imports cuda code? using devtools? If not should the cuda part simply be coded in the cpp file?
If so what am I missing? I tried adding #include <cuda.h> in matrixUtils.cpp but got: fatal error: cuda.h: No such file or directory
Thanks a lot

Segment fault when using Rcpp/Armadillo and openMP prarallel with user-defined function

I was trying to use rcpp/armadillo with openmp to speed up a loop in R. The loop takes a matrix with each row containing indices of a location vector(or matrix if it's 2D locations) as input(and other matrix/vec to be used). Inside the loop, I extracted each row of input indices matrix and find the corresponding locations, calculate distance matrix, and covariance matrix, do cholesky and backsolve, save the backsolve results to a new matrix. Here is the rcpp code:
`#include <iostream>
#include <RcppArmadillo.h>
#include <omp.h>
#include <Rcpp.h>
// [[Rcpp::plugins(openmp)]]
using namespace Rcpp;
using namespace arma;
using namespace std;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
mat NZentries_new2 (int m, int nnp, const mat& locs, const umat& revNNarray, const mat& revCondOnLatent, const vec& nuggets, const vec covparms){
// initialized the output matrix
mat Lentries=zeros(nnp,m+1);
// initialized objects in parallel part
int n0; //number of !is_na elements
uvec inds;//
vec revCon_row;//
uvec inds00;//
vec nug;//
mat covmat;//
vec onevec;//
vec M;//
mat dist;//
int k;//
omp_set_num_threads(2);// selects the number of cores to use.
#pragma omp parallel for shared(locs,revNNarray,revCondOnLatent,nuggets,nnp,m,Lentries) private(k,M,dist,onevec,covmat,nug,n0,inds,revCon_row,inds00) default(none) schedule(static)
for (k = 0; k < nnp; k++) {
// extract a row to work with
inds=revNNarray.row(k).t();
revCon_row=revCondOnLatent.row(k).t();
if (k < m){
n0=k+1;
} else {
n0=m+1;
}
// extract locations
inds00=inds(span(m+1-n0,m))-ones<uvec>(n0);
nug=nuggets.elem(inds00) % (ones(n0)-revCon_row(span(m+1-n0,m))); // vec is vec, cannot convert to mat
dist=calcPWD2(locs.rows(inds00));
#pragma omp critical
{
//calculate covariance matrix
covmat= MaternFun(dist,covparms) + diagmat(nug) ; // summation from arma
}
// get last row of inverse Cholesky
onevec = zeros(n0);
onevec[n0-1] = 1;
M=solve(chol(covmat,"upper"),onevec);
// save the entries to matrix
Lentries(k,span(0,n0-1)) = M.t();
}
return Lentries;
}`
The current version works fine but speed is slow(almost the same as no parallel version), if I take the line in omp critical bracket out, it cause segment fault and R will be crashed. This MaterFun is a function I defined as below with several other small functions. So my question is that why MaternFun has to stay in the critical part.
// [[Rcpp::export]]
mat MaternFun( mat distmat, vec covparms ){
int d1 = distmat.n_rows;
int d2 = distmat.n_cols;
int j1;
int j2;
mat covmat(d1,d2);
double scaledist;
double normcon = covparms(0)/(pow(2.0,covparms(2)-1)*Rf_gammafn(covparms(2)));
for (j1 = 0; j1 < d1; j1++){
for (j2 = 0; j2 < d2; j2++){
if ( distmat(j1,j2) == 0 ){
covmat(j1,j2) = covparms(0);
} else {
scaledist = distmat(j1,j2)/covparms(1);
covmat(j1,j2) = normcon*pow( scaledist, covparms(2) )*
Rf_bessel_k(scaledist,covparms(2),1.0);
}
}
}
return covmat;
}
// [[Rcpp::export]]
double dist2(double lat1,double long1,double lat2,double long2) {
double dist = sqrt(pow(lat1 - lat2, 2) + pow(long1 - long2, 2)) ;
return (dist) ;
}
// [[Rcpp::export]]
mat calcPWD2( mat x) {//Rcpp::NumericMatrix
int outrows = x.n_rows ;
int outcols = x.n_rows ;
mat out(outrows, outcols) ;
for (int arow = 0 ; arow < outrows ; arow++) {
for (int acol = 0 ; acol < outcols ; acol++) {
out(arow, acol) = dist2(x(arow, 0),x(arow, 1),
x(acol, 0),x(acol, 1)) ; //extract element from mat
}
}
return (out) ;
}
Here is some sample inputs for testing the MaterFun in R:
library(fields)
distmat=rdist(1:5) # distance matrix
covparms=c(1,0.2,1.5)
The issue is there are two calls to R math functions (Rf_bessel_k and Rf_gammafn) that require the access to be single threaded instead of parallel.
To get around this, let's add a dependency on boost via BH to obtain the cyl_bessel_k and tgamma functions. Alternatively, there is always the option of reimplementing R's besselK and gamma in C++ so it doesn't use the single-threaded R variant.
This gives:
#include <Rcpp.h>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/gamma.hpp>
// [[Rcpp::depends(BH)]]
// [[Rcpp::export]]
double besselK_boost(double x, double v) {
return boost::math::cyl_bessel_k(v, x);
}
// [[Rcpp::export]]
double gamma_fn_boost(double x) {
return boost::math::tgamma(x);
}
Test Code
x0 = 9.536743e-07
nu = -10
all.equal(besselK(x0, nu), besselK_boost(x0, nu))
# [1] TRUE
x = 2
all.equal(gamma(x), gamma_fn_boost(x))
# [1] TRUE
Note: The order of parameters for boost's variant differs from R's:
cyl_bessel_k(v, x)
Rf_bessel_k(x, v, expon.scaled = FALSE)
From here, we can modify the MaternFun. Unfortunately, because calcPWD2 is missing, the furthest we can go is switching to use boost and incorporating in OpenMP protections.
#include <RcppArmadillo.h>
#include <boost/math/special_functions/bessel.hpp>
#include <boost/math/special_functions/gamma.hpp>
#ifdef _OPENMP
#include <omp.h>
#endif
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins(openmp)]]
// [[Rcpp::export]]
arma::mat MaternFun(arma::mat distmat, arma::vec covparms) {
int d1 = distmat.n_rows;
int d2 = distmat.n_cols;
int j1;
int j2;
arma::mat covmat(d1,d2);
double scaledist;
double normcon = covparms(0) /
(pow(2.0, covparms(2) - 1) * boost::math::tgamma(covparms(2)));
for (j1 = 0; j1 < d1; ++j1){
for (j2 = 0; j2 < d2; ++j2){
if ( distmat(j1, j2) == 0 ){
covmat(j1, j2) = covparms(0);
} else {
scaledist = distmat(j1, j2)/covparms(1);
covmat(j1, j2) = normcon * pow( scaledist, covparms(2) ) *
boost::math::cyl_bessel_k(covparms(2), scaledist);
}
}
}
return covmat;
}

Rcpp function crashes

My problem:
I am using R.3.0.1 together with RStudio 0.97.551 on a 64bit Windows7 PC and I have begun to outsource a function to C/C++ using Rcpp. The function compiles, but evaluating it within an R function produces a runtime error. I am not able to find out why and how to fix this.
Details
Below is my cpp-file... let's say it's called "vector.cpp"
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector l5(double z, double k, double s, double K, double theta, double x, double h, NumericVector m){
int n = m.size();
NumericVector a(n);
NumericVector bu(n);
NumericVector b(n);
NumericVector c(n);
for(int i=0; i<n+1; i++){
a[i] = pow(z,m[i]) * (pow((x*pow(h,m[i])/K), theta) - 1) * (K/theta);
for (int j=0; j<i; j++){
bu[i] += pow(z,j) * (1 - z) * fmax(((pow((s/K), theta) - 1) * (K/theta)), ((pow((x*pow(h, j)/K), theta) - 1) * (K/theta)));
}
b[i] = k *bu[i];
c[i] = k * pow(z, m[i]) * fmax(((pow((s/K), theta) - 1) * (K/theta)), ((pow((x*pow(h, m[i])/K), theta) - 1) * (K/theta)));
}
return wrap(a-b-c);
}
which I compile in R (or RStudio) using the command
sourceCpp(<path to file>/vector.cpp)
It compiles - so far so good. However, when I go on to use the function l5 within other R functions it often leads R to crash (both in RStudio and the plain R GUI). In fact, also evaluating it itself isn't any more stable. To reproduce this, e.g. try evaluating l6 multiple times
l6 <- function(zs, ks, ss, Ks, thetas, xs, hs){
z=zs
k=ks
s=ss
K=Ks
theta=thetas
x=xs
h=hs
m=0:30
res <- l5(z, k, s, K, theta,x, h, m)
return(res)
}
and run
l6(0.9, 0.1, 67, 40, 0.5, 44, 1.06)
Specifically, it produces the following runtime error
This application has requested Runtime to terminate it in an unusual way.
So what is wrong with my function?
Solution
As Dirk suggested below there is an elementary mistake in the for loop, where i runs from 0 to n and thus has n+1 elements, but I intialized only vectors of length n. To avoid this mistake I now implemented the function using iterators
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector l5(double z, double k, double s, double K, double theta, double x, double h, NumericVector m){
int n = m.size();
NumericVector a(n);
NumericVector bu(n);
NumericVector b(n);
NumericVector c(n);
for(NumericVector::iterator i = m.begin(); i != m.end(); ++i){
a[*i] = pow(z, m[*i]) * (pow((x*pow(h, m[*i])/K), theta) - 1) * (K/theta);
for(int j=0; j<*i; j++){
bu[*i] += pow(z,j) * (1 - z) * fmax(((pow((s/K), theta) - 1) * (K/theta)), ((pow((x*pow(h, j)/K), theta) - 1) * (K/theta)));
}
b[*i] = k *bu[*i];
c[*i] = k * pow(z, m[*i]) * fmax(((pow((s/K), theta) - 1) * (K/theta)), ((pow((x*pow(h, m[*i])/K), theta) - 1) * (K/theta)));
}
return wrap(a-b-c);
}
Many thanks again!
You are making an elementary C/C++ error:
for(int i=0; i<n+1; i++)
will be accessed n+1 times, but you allocated n spaces.

Resources