R won't reference/can't find a compiled loaded C Code

▼魔方 西西 提交于 2019-12-25 04:18:11

问题


I've created a new Robust HoltWinters function (based on the stats::Holt-Winters) method in R (per "Robust Forecasting with Exponential and Holt-Winters Smoothing" by Sarah Gelper1,, Roland Fried, Christophe Croux. September 26, 2008.) Why? Well...why not! But I digress...

The core of the stats::Holt-Winters method is a C code called C_HoltWinters, which I've modified to be robust (See below)

#include <stdlib.h>
#include <string.h>  // memcpy
#include <math.h>

#include <R.h>
#include "ts.h"

void HoltWinters (
          double *x, /*as.double(x) */
          double *x_adj, /*Adjust time series data, if need be                   Added*/
          int    *xl, /*lenx - Length of the current time series*/
          double *alpha, /*as.double(max(min(alpha, 1), 0)), */
          double *beta, /*as.double(max(min(beta,1), 0)), */
          double *gamma, /*as.double(max(min(gamma, 1), 0)), */ 
          double *llamda,/*as.double(max(min(llamda,1),0)),                     ADDED*/
          int    *start_time, /*as.integer(start.time),  */
          int    *seasonal, /*as.integer(!+(seasonal == "multiplicative")), */
          int    *period, /* as.integer(f),  */
          int    *dotrend, /* as.integer(!is.logical(beta) || beta),  */
          int    *doseasonal, /* as.integer(!is.logical(gamma) || gamma), */

          double *a, /*l.start - starting values for level*/
          double *b, /*b.start - starting values for Trend*/
          double *s, /*s.start - starting values for SEasonal*/
          double *l, /*t.start - starting values for LLamda                      ADDED*/
          double *k, /* Value for K                                              ADDED*/
          double *ck, /*value for ck                                             ADDED*/
          /* return values */
          double *SSE,
          double *level,
          double *trend,
          double *season

    )

{
    double res = 0, xhat = 0, stmp = 0, theta = 1, RhoK = 0, phi = 0 ;
    int i, i0, s0; /*i is the current t, i0 is the current LESS starting period, and s0 = is the seasonal current LESS Starting period*/

    /* copy start values to the beginning of the vectors */
    level[0] = *a;
    if (*dotrend == 1) trend[0] = *b;
    if (*doseasonal == 1) memcpy(season, s, *period * sizeof(double));

    for (i = *start_time - 1; i < *xl; i++) {
    /* indices for period i */
    i0 = i - *start_time + 2;
    s0 = i0 + *period - 1;

    /* forecast *for* period i */
    xhat = level[i0 - 1] + (*dotrend == 1 ? trend[i0 - 1] : 0);

    stmp = *doseasonal == 1 ? season[s0 - *period] : (*seasonal != 1);


    if (*seasonal == 1)
        xhat += stmp;
    else
        xhat *= stmp;

    /* Sum of Squared Errors */
    res   = x[i] - xhat;

    /*adjusting for robustness....Gahds*/
    RhoK = (abs(res / theta) <= *k ? *ck * (1 - pow(1 - pow((res / (*k * theta)),2),3)): *ck);
    theta = sqrt(*llamda * RhoK * pow(theta,2) + (1 - *llamda) * pow(theta,2));
    phi = (abs(res / theta) < *k ? res / theta : ((res / theta) / abs(res / theta) * (*k)));
    x_adj[i] = phi * theta + xhat;

    res = x_adj[i] - xhat;

    *SSE += res * res;

    /* estimate of level *in* period i */
    if (*seasonal == 1)
        level[i0] = *alpha       * (x_adj[i] - stmp)
              + (1 - *alpha) * (level[i0 - 1] + trend[i0 - 1]);
    else
        level[i0] = *alpha       * (x_adj[i] / stmp)
              + (1 - *alpha) * (level[i0 - 1] + trend[i0 - 1]);

    /* estimate of trend *in* period i */
    if (*dotrend == 1)
        trend[i0] = *beta        * (level[i0] - level[i0 - 1])
              + (1 - *beta)  * trend[i0 - 1];

    /* estimate of seasonal component *in* period i */
    if (*doseasonal == 1) {
        if (*seasonal == 1)
        season[s0] = *gamma       * (x_adj[i] - level[i0])
               + (1 - *gamma) * stmp;
        else
        season[s0] = *gamma       * (x_adj[i] / level[i0])
               + (1 - *gamma) * stmp;
    }
    }
}

So I compile it, in windows sigh, with R (3.2.2):

R CMD SHLIB C_R_HoltWinters.c
gcc -m64 -I"C:/PROGRA~1/R/R-32~1.2/include" -DNDEBUG     -I"d:/RCompile/r-compiling/local/local320/include"     -O2 -Wall  -std=gnu99 -mtune=core2 -c C_R_HoltWinters.c -o C_R_HoltWinters.o
gcc -m64 -shared -s -static-libgcc -o C_R_HoltWinters.dll tmp.def C_R_HoltWinters.o -Ld:/RCompile/r-compiling/local/local320/lib/x64 -Ld:/RCompile/r-compiling/local/local320/lib -LC:/PROGRA~1/R/R-32~1.2/bin/x64 -lR

Load it into R:

dyn.load('C_R_HoltWinters.dll')

Checking to see if it's there

    > getLoadedDLLs()
                                                                                     Filename Dynamic.Lookup
base                                                                                     base          FALSE
utils                           C:/Program Files/RRO/R-3.2.2/library/utils/libs/x64/utils.dll          FALSE
methods                     C:/Program Files/RRO/R-3.2.2/library/methods/libs/x64/methods.dll          FALSE
RevoUtilsMath   C:/Program Files/RRO/R-3.2.2/library/RevoUtilsMath/libs/x64/RevoUtilsMath.dll           TRUE
grDevices               C:/Program Files/RRO/R-3.2.2/library/grDevices/libs/x64/grDevices.dll          FALSE
graphics                  C:/Program Files/RRO/R-3.2.2/library/graphics/libs/x64/graphics.dll          FALSE
stats                           C:/Program Files/RRO/R-3.2.2/library/stats/libs/x64/stats.dll          FALSE
tools                           C:/Program Files/RRO/R-3.2.2/library/tools/libs/x64/tools.dll          FALSE
internet                                    C:/PROGRA~1/RRO/R-32~1.2/modules/x64/internet.dll           TRUE
(embedding)                                                                       (embedding)          FALSE
C_R_HoltWinters                                              C:/scripts/R/C_R_HoltWinters.dll           TRUE

Ah, yup, there it is. So, just for poops and chuckles I run a test on it:

 > is.loaded('C_R_HoltWinters')
[1] FALSE
> is.loaded("C_R_HoltWinters")
[1] FALSE
> is.loaded(C_R_HoltWinters)
Error in is.loaded(C_R_HoltWinters) : object 'C_R_HoltWinters' not found

Okay....it should be there but it's not. Maybe it knows something I don't so I try to run it:

> .C("C_R_HoltWinters", blahblahblah)
    Error in .C("C_R_HoltWinters") : 
      C symbol name "C_R_HoltWinters" not in load table
> .Call("C_R_HoltWinters", blahblahblah)
    Error in .Call("C_R_HoltWinters") : 
      C symbol name "C_R_HoltWinters" not in load table

But when I load a different c code called foo and run it, it runs fine.

Why isn't R able to reference C_R_HoltWinters.dll? Will this also break if I put it into a package?

Thanks


回答1:


OK, the problem here is a confusion between the symbol names (which may represent functions in C) and the shared library. After running dyn.load('C_R_HoltWinters.dll'), you can check that it was loaded by looking at getLoadedDlls(). Now, what is.loaded is looking for are the symbols that are defined inside this DLL. So, the following code will show you that the function "HoltWinters", defined in your C code, is available to be called from R:

>  is.loaded("HoltWinters")
[1] TRUE

And this is the function name that you should use on .C calls as well.



来源:https://stackoverflow.com/questions/36438723/r-wont-reference-cant-find-a-compiled-loaded-c-code

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!