15. Rmath

  • math.h
  • Rmath.h

Rmath.hの中には、正規分布やベータ分布などの関数から、piや平方根などの定数が定義されている。

Rmath.h内で、math.hがインクルードされているため、C言語ライブラリも使用可能。 ほかにも、 src/nmath の中にある関数が動的リンクされているようで、 関数の実態については、 src/nmath を参照すること。

15.1. 分布

  • norm
  • beta
  • gamma
  • unif (uniform)

15.2. コード

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

SEXP choice_rnorm() {
    SEXP res;

    res = PROTECT(NEW_NUMERIC(5));

    for(int i = 0; i < 5; i++) {

        REAL(res)[i] = rnorm(0, 1);

    }

    UNPROTECT(1);

   return res;
}
dyn.load("choice_rnorm.so")

.Call("choice_rnorm")
# [1] -8.773321 -8.773321 -8.773321 -8.773321 -8.773321

.Call("choice_rnorm")
# [1] -8.773321 -8.773321 -8.773321 -8.773321 -8.773321

for文を使っているが、乱数をふっていないため定数となっている。

返り値はdouble型で、 引数は第一引数が平均値、第二引数が標準偏差。

15.3. 乱数

  • GetRNGstate
  • PutRNGstate

乱数をふるときには、 GetRNGstatePutRNGstate を対で使う。

引数も、返り値もvoid型。

15.4. コード

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

SEXP rnorm_c(SEXP arg_p) {
    int times;

    if( length(arg_p) != 1 ) {
        error("argument's length is not 1");
    }

    if( IS_INTEGER(arg_p) ) {
        times = INTEGER_POINTER(arg_p)[0];
    } else if( IS_NUMERIC(arg_p) ) {
        times = (int)NUMERIC_POINTER(arg_p)[0];
    } else {
        error("argument is not integer, or numeric");
    }

    SEXP res;

    res = PROTECT( NEW_NUMERIC(times) );

    GetRNGstate();

    for(int i = 0; i < times; i++) {

        REAL(res)[i] = rnorm(0, 1);

    }

    PutRNGstate();

    UNPROTECT(1);
    return res;

}
dyn.load("rnorm_c.so")

return_rnorm <- function(times) {
    RES <- .Call("rnorm_c", times)

    list(res = RES)
}

return_rnorm(1)$res
# [1] -0.5865062


return_rnorm(5)$res
# [1] -0.3854486  0.6042691 -0.2057999  0.8156022 -1.4987004

return_rnorm(5L)$res
# [1] -0.3844218 -0.3170639 -1.7558294  1.6429369  0.2188673

return_rnorm(c(1, 2))$res
# return_rnorm(c(1, 2)) でエラー: argument's length is not 1
# 実行が停止されました

return_rnorm("a")$res
# return_rnorm("a") でエラー: argument is not integer, or numeric
# 実行が停止されました