, , () R . C syadd ( ) R- , syadd.
#include <R.h>
#include <Rinternals.h>
SEXP syadd (SEXP N, SEXP V, SEXP compute_diag) {
int n = asInteger(N), diag = asInteger(compute_diag);
SEXP X = PROTECT(allocVector(REALSXP, n * n));
double *x = REAL(X), *ptr_x = x, *v_end = x + n * n;
while (ptr_x < v_end) *(ptr_x++) = NA_REAL;
double *v = REAL(V), *vj = v, *vi, *vi_end = v, tmp;
ptr_x = x; v_end = v + n;
if (diag == 1) {
while (vj < v_end) {
tmp = *vj;
ptr_x = x; vi = v;
while (vi <= vi_end) {
*ptr_x = (*vi) * tmp;
vi++; ptr_x++;
}
x += n; vi_end++; vj++;
}
} else {
while (vj < v_end) {
tmp = *vj;
ptr_x = x; vi = v;
while (vi < vi_end) {
*ptr_x = (*vi) * tmp;
vi++; ptr_x++;
}
x += n; vi_end++; vj++;
}
}
UNPROTECT(1);
return X;
}
R, (.so linux .dll windows). , Windows, linux:
R CMD SHLIB -c syadd.c
R:
syadd <- function (v, diag = TRUE) {
n <- length(v); v <- as.numeric(v); diag <- as.integer(diag)
dyn.load("syadd.so")
X <- .Call("syadd", n, v, diag)
attr(X, "dim") <- c(n, n)
return(X)
}
diag = FALSE, . R base:::outer:
v <- 1:10000
system.time(syadd(v,diag = TRUE))
gc()
system.time(outer(v,v,"+"))
gc()
syadd 0.97s, 1.91s outer. , gc(), , .
:
- ,
dyn.load(). inline cfunction. . R C - R. - , - Windows.