用于C功能的R包装器无法正常工作

问题描述 投票:2回答:1

目前,我正在向C介绍自己,以扩展我的R函数。我用C语言写了一个函数进行一些计算,它们工作正常。但是,一旦我用R本身编写包装器,似乎就会出现一些错误。将我的C函数视为“ colV”,并将“ abc”作为任意矩阵。

[R] .Call("colV", abc, ncol(abc), nrow(abc))语句工作得很好(每次,无论我使用它的频率如何,都可以,但是

colV = function(x){
  nc = ncol(x)
  nr = nrow(x)
  .Call("colV", x, nc, nr)
}

在第三次使用时提供了错误的结果:

> colV(abc)
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> colV(abc)
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> colV(abc)
[1] -8.370087e+22  6.254796e-01  6.774042e-01  1.709462e+00  7.250386e-01

如果再次声明包装器,则前两次运行正常,再次尝试运行第三次,则出现相同的结果。请注意,除了外观外,第一个值实际上会更改!

有人知道包装纸怎么了吗?如前所述,如果我仅使用.Call语句,则始终返回正确的结果:

> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386
> .Call("colV", abc, ncol(abc), nrow(abc))
[1] 1.4274933 0.6254796 0.6774042 1.7094617 0.7250386

[此外,使用.C-Interface时我还没有遇到这个问题,但是由于速度和内存原因,这不是我的解决方案。提前致谢艾琳

编辑:这是C代码:

#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>


SEXP colV(SEXP y, SEXP n, SEXP r){
    int *nc = INTEGER(n);
    double *x = REAL(y);
    int d = length(y);
    int *nr = INTEGER(r);
    int i, j, z;
    //int d = nr * nc;
    double colMean[(*nc)];
    double xSq[(d)];
    double colMsq[(*nc)];
    double xSm[(*nc)];
    SEXP result;
    PROTECT(result = allocVector(REALSXP, (*nc)));
    memset(REAL(result), 0, (*nc) * sizeof(double));
    double *colVar = REAL(result);
    //PROTECT(colVar = NEW_DOUBLE(nc));
    int fr = ((*nr) - 1);


    for(z = 0; z < (d); z++){
        xSq[z] = x[z] * x[z];
    }

    for(i = 0; i < (*nc); i++){
        for(j = 0; j < (*nr); j++){
            colMean[i] += (x[(j + ((*nr) * i)) ]);
            xSm[i] += (xSq[(j + (*nr * i))]);
        }
        colMean[i] = (colMean[i] / (*nr));
        colMsq[i] = (*nr) * (colMean[i] * colMean[i]);
        colVar[i] = ((xSm[i] - colMsq[i]) / fr);
    }
    UNPROTECT(1);
    return(result);
}
r c function call wrapper
1个回答
0
投票

编辑:如评论中所述,此(下)有效,但是对于另一个不同的c函数,也会发生相同的问题。直接使用.Call可以提供预期的结果,而将.Call放入包装中会出现错误。我仍然不知道为什么。

我现在找到了解决问题的方法,但是我不明白为什么是解决方法。如果有人可以解释,请随时这样做!

更改循环中colMean部分的计算正在更改所有内容:

...
for(i = 0; i < (*nc); i++){
        for(j = 0; j < (*nr); j++){
            colMean[i] += ((x[(j + ((*nr) * i)) ]) / (*nr));
            xSm[i] += (xSq[(j + (*nr * i))]);
        }
        //colMean[i] = (colMean[i] / (*nr));
        colMsq[i] = (*nr) * (colMean[i] * colMean[i]);
        colVar[i] = ((xSm[i] - colMsq[i]) / fr);
    }
...

因此将nr除法直接移到加法语句中解决了这个问题。

祝大家有个愉快的一天/晚上!

© www.soinside.com 2019 - 2024. All rights reserved.