了解如何在 R 中处理内部 C 函数

2023-12-29

我想知道是否有人可以向我说明 R 如何执行C从控制台提示符下键入的 R 命令进行调用。我特别困惑的是R对 a) 函数参数和 b) 函数调用本身的处理。

让我们举个例子,在这种情况下set.seed()。想知道它是如何工作的,我在提示符下输入名称,获取源代码(在这里查看更多相关内容 https://stackoverflow.com/q/19226816/1478381),看到最终有一个.Internal(set.seed(seed, i.knd, normal.kind),所以尽职尽责地在中查找相关的函数名称.Internals的部分/src/names.c,发现它的名字叫do_setseed并且在RNG.c这导致我...

SEXP attribute_hidden do_setseed (SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP skind, nkind;
    int seed;

    checkArity(op, args);
    if(!isNull(CAR(args))) {
    seed = asInteger(CAR(args));
    if (seed == NA_INTEGER)
        error(_("supplied seed is not a valid integer"));
    } else seed = TimeToSeed();
    skind = CADR(args);
    nkind = CADDR(args);
    //...
      //DO RNG here 
    //...
    return R_NilValue;
}
  • 什么是CAR, CADR, CADDR?我的研究让我相信他们是Lisp影响了有关列表的构造,但除此之外我不明白这些函数的作用或为什么需要它们.
  • 什么是checkArity() do?
  • SEXP args似乎不言自明,但这是一个列表 函数调用中传递的参数?
  • 什么是SEXP op代表?我认为这意味着运算符(就像在二进制函数中,例如+),但是那么什么是SEXP call for?

有谁能够了解我打字时发生的情况

set.seed(1)

在 R 控制台提示符下,直到skind and nkind被定义?我发现我无法很好地理解这个级别的源代码以及从解释器到 C 函数的路径。


CAR and CDR是您访问配对列表对象的方式,如中所述第 2.1.11 条R语言定义 http://cran.r-project.org/doc/manuals/R-lang.html#Pairlist-objects. CAR包含第一个元素,并且CDR包含其余元素。给出了一个例子第 5.10.2 节编写 R 扩展 http://cran.r-project.org/doc/manuals/R-exts.html#Calling-_002eExternal:

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

SEXP convolveE(SEXP args)
{
    int i, j, na, nb, nab;
    double *xa, *xb, *xab;
    SEXP a, b, ab;

    a = PROTECT(coerceVector(CADR(args), REALSXP));
    b = PROTECT(coerceVector(CADDR(args), REALSXP));
    ...
}
/* The macros: */
first = CADR(args);
second = CADDR(args);
third = CADDDR(args);
fourth = CAD4R(args);
/* provide convenient ways to access the first four arguments.
 * More generally we can use the CDR and CAR macros as in: */
args = CDR(args); a = CAR(args);
args = CDR(args); b = CAR(args);

还有一个TAG宏来访问赋予实际参数的名称。

checkArity确保传递给函数的参数数量是正确的。args是传递给函数的实际参数。op是偏移指针“用于处理多个 R 函数的 C 函数”(引用自src/main/names.c,其中还包含显示每个函数的偏移量和数量的表格)。

例如,do_colsum把手col/rowSums and col/rowMeans.

/* Table of  .Internal(.) and .Primitive(.)  R functions
 * =====     =========        ==========
 * Each entry is a line with
 *
 *  printname  c-entry     offset  eval  arity   pp-kind   precedence  rightassoc
 *  ---------  -------     ------  ----  -----   -------   ----------  ----------
{"colSums",    do_colsum,  0,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"colMeans",   do_colsum,  1,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowSums",    do_colsum,  2,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowMeans",   do_colsum,  3,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},

注意arity上表中的值为 4,因为(即使rowSums等人只有 3 个参数)do_colsum有 4 个,您可以从.Internal打电话进来rowSums:

> rowSums
function (x, na.rm = FALSE, dims = 1L) 
{
    if (is.data.frame(x)) 
        x <- as.matrix(x)
    if (!is.array(x) || length(dn <- dim(x)) < 2L) 
        stop("'x' must be an array of at least two dimensions")
    if (dims < 1L || dims > length(dn) - 1L) 
        stop("invalid 'dims'")
    p <- prod(dn[-(1L:dims)])
    dn <- dn[1L:dims]
    z <- if (is.complex(x)) 
        .Internal(rowSums(Re(x), prod(dn), p, na.rm)) + (0+1i) * 
            .Internal(rowSums(Im(x), prod(dn), p, na.rm))
    else .Internal(rowSums(x, prod(dn), p, na.rm))
    if (length(dn) > 1L) {
        dim(z) <- dn
        dimnames(z) <- dimnames(x)[1L:dims]
    }
    else names(z) <- dimnames(x)[[1L]]
    z
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解如何在 R 中处理内部 C 函数 的相关文章

随机推荐