- 『R Internals version 2.14.1』の目次はこちら
- (.Primitive と.Inetrnal) vs. (.External)
- どちらもCやFortranの関数呼び出し
- (.Primitive と.Inetrnal)はデフォルトで読まれる(らしい)
- (.External)はあとから入れるパッケージで呼び出すもの
- .Primitive vs .Internal (1)
- .Primitive は直接C(やら)が呼ばれる
- .InternalはCを呼びに行くという処理(この処理自体は.Primitiveな処理)を介してC(やら)の関数へと連結される
- .Primitive vs .Internal (2)
- .Primitive の方は「文法」的なもの(が多い/ほとんど)
- .Internal の方はいわゆる処理関数
- .Internalの中身を探せ
- ソース付きバージョンをとってくると "src/main/names.c"というファイルとともに、その他のCのソースファイルがとれてくる
- この"names.c"ファイルというのは、Rでの関数と、それに対応するCの関数が書いてある(以下のような感じ)
/* Random Numbers */
{"rchisq", do_random1, 0, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
{"rexp", do_random1, 1, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
{"rgeom", do_random1, 2, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
{"rpois", do_random1, 3, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
{"rt", do_random1, 4, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
{"rsignrank", do_random1, 5, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
-
- したがって、Rの関数 rchisq()の中身を見ようとして以下のようにやると、.Internal()に"rchisq"が渡されているのがわかる
> rchisq
function (n, df, ncp = 0)
{
if (missing(ncp))
.Internal(rchisq(n, df))
else .Internal(rnchisq(n, df, ncp))
}
<bytecode: 0x018f6508>
<environment: namespace:stats>
-
- .Internal()で呼ばれる関数は、"names.c"の中に定義してあるから、そのファイルを開いて、文字列検索すると、以下のような行がある
{"rchisq", do_random1, 0, 11, 2, {PP_FUNCALL, PREC_FN, 0}},
-
- これを見て、Cのdo_random1()関数が呼び出されることが分かる
- Cのdo_random1()関数は独立したCのソースファイルにはなっていないが、"random.c"というファイルが"src/main/"にあり、その中に、という記載があって、これが処理。パラメタが1個の分布、2個の分布に分けて関数がかき分けてあることが分かる
SEXP attribute_hidden do_random1(SEXP call, SEXP op, SEXP args, SEXP rho)
{
SEXP x, a;
int i, n, na;
checkArity(op, args);
if (!isVector(CAR(args)) || !isNumeric(CADR(args)))
invalid(call);
if (LENGTH(CAR(args)) == 1) {
n = asInteger(CAR(args));
if (n == NA_INTEGER || n < 0)
invalid(call);
}
else n = LENGTH(CAR(args));
PROTECT(x = allocVector(REALSXP, n));
if (n == 0) {
UNPROTECT(1);
return(x);
}
na = LENGTH(CADR(args));
if (na < 1) {
for (i = 0; i < n; i++)
REAL(x)[i] = NA_REAL;
warning(_("NAs produced"));
}
else {
Rboolean naflag = FALSE;
PROTECT(a = coerceVector(CADR(args), REALSXP));
GetRNGstate();
switch (PRIMVAL(op)) {
RAND1(0, rchisq);
RAND1(1, rexp);
RAND1(2, rgeom);
RAND1(3, rpois);
RAND1(4, rt);
RAND1(5, rsignrank);
default:
error(_("internal error in do_random1"));
}
if (naflag)
warning(_("NAs produced"));
PutRNGstate();
UNPROTECT(1);
}
UNPROTECT(1);
return x;
}