簡體   English   中英

了解如何在R中處理.Internal C函數

[英]Understanding how .Internal C functions are handled in R

我想知道是否有人可以向我說明R如何從控制台提示符下鍵入的R命令執行C調用。 我對R對a)函數參數和b)函數調用本身的處理特別感到困惑。

我們舉一個例子,在這種情況下是set.seed() 想知道它是如何工作的我在提示符下輸入名稱,獲取源代碼( 在這里查看更多內容 ),看看最終有一個.Internal(set.seed(seed, i.knd, normal.kind) ,所以盡職盡責在/src/names.c.Internals部分查找相關的函數名,找到它叫做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;
}
  • 什么是CARCADRCADDR 我的研究讓我相信它們是一個受Lisp影響的有關列表的構造,但除此之外,我不明白這些函數的作用或為什么需要它們
  • checkArity()什么作用?
  • SEXP args似乎是自解釋的,但這是函數調用中傳遞的參數列表嗎?
  • SEXP op代表什么? 我認為這意味着運算符(如二進制函數,如+ ),但那么SEXP call是什么?

是否有人能夠流經我打字時發生的事情

set.seed(1)

在R控制台提示符下,直到定義skindnkind的點? 我發現我無法很好地理解這個級別的源代碼以及從解釋器到C函數的路徑。

CARCDR是您訪問pairlist對象的方式,如R語言定義的 2.1.11節所述 CAR包含第一個元素, CDR包含其余元素。 編寫R擴展的第5.10.2節給出了一個例子:

#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 ,其中還包含顯示每個函數的偏移和arity的表)。

例如, do_colsum處理col/rowSumscol/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個,您可以從rowSums.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
}

基本的C級pairlist提取功能是CARCDR (Pairlists與列表非常相似,但是作為鏈表實現,並在內部用於參數列表)。 它們具有簡單的R等價物: x[[1]]x[-1] R還提供了兩者的許多組合:

  • CAAR(x) = CAR(CAR(x))等於x[[1]][[1]]
  • CADR(x) = CAR(CDR(x)) ,相當於x[-1][[1]] ,即x[[2]]
  • CADDR(x) = CAR(CDR(CDR(x))相當於x[-1][-1][[1]] ,即x[[3]]
  • 等等

與訪問列表的第n個元素O(1)不同,訪問pairlist的第n個元素是O(n)操作。 這就是為什么沒有更好的功能來訪問pairlist的第n個元素。

內部/原始函數不按名稱進行匹配,它們僅使用位置匹配,這就是為什么它們可以使用這個簡單的系統來提取參數。

接下來,您需要了解C函數的參數是什么。 我不確定這些文件在哪里記錄,所以我可能不完全正確的結構,但我應該是一般的部分:

  • call :完成調用,可能由match.call()捕獲

  • op :從R調用的.Internal函數的索引。這是必需的,因為從.Internal函數到C函數有多對一的映射。 (例如, do_summary實現sum,mean,min,max和prod)。 該數字是names.c的第三個條目 - 對於do_setseed ,它始終為0,因此從未使用過

  • args :提供給函數的參數的一對列表。

  • env :調用函數的環境。

checkArity是一個調用Rf_checkArityCall的宏,它基本上查找參數的數量( names.c的第五列是arity)並確保提供的數字匹配。 你必須在C中完成相當多的宏和函數才能看到正在發生的事情 - 擁有一個你可以通過的R源的本地副本是非常有幫助的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM