Top Banner
Introduction to .Call interface Hao Chai Department of Statistics and Actuarial Science The University of Iowa Productive Seminar March 6, 2012 Hao Chai (U of Iowa) Introduction to .Call interface 1 / 41
42
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Dot Call interface

Introduction to .Call interface

Hao Chai

Department of Statistics and Actuarial ScienceThe University of Iowa

Productive SeminarMarch 6, 2012

Hao Chai (U of Iowa) Introduction to .Call interface 1 / 41

Page 2: Dot Call interface

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 2 / 41

Page 3: Dot Call interface

Introduction

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 3 / 41

Page 4: Dot Call interface

Introduction

.C and .Call are two interfaces in R to call C routines. Similar foreignlanguage interface functions are .Fortran and .External.

Hao Chai (U of Iowa) Introduction to .Call interface 4 / 41

Page 5: Dot Call interface

Introduction

Advantages of R

Straight forward syntax.Easy to learn, to use, to track the results and to debug.Over 3,000 packages available to carry out many kinds of statisticalanalysis and produce professional graphics.Vectorized language....

Disadvantage of R

Loops.

Hao Chai (U of Iowa) Introduction to .Call interface 5 / 41

Page 6: Dot Call interface

Introduction

Advantages of R

Straight forward syntax.Easy to learn, to use, to track the results and to debug.Over 3,000 packages available to carry out many kinds of statisticalanalysis and produce professional graphics.Vectorized language....

Disadvantage of R

Loops.

Hao Chai (U of Iowa) Introduction to .Call interface 5 / 41

Page 7: Dot Call interface

Introduction

Toy example

Our goal is to generate a variance-covariance matrix Σ = (σij), where

σij =

{a · b|i−j |, if i 6= j ;1, if i = j .

We have at least three methods:

A simple R function matgen R:

matgen_R = function(P, a, b)

{

Covmatrix = matrix(rep(1, P * P), nrow = P)

for (i in 1 : P)

for (j in 1 : P)

if (i != j)

Covmatrix[i, j] = exp(log(a) + log(b)

* abs(i - j))

Covmatrix

}

Hao Chai (U of Iowa) Introduction to .Call interface 6 / 41

Page 8: Dot Call interface

Introduction

Toy example

An R function using matrix indexing matgen Rind:

matgen_Rind = function(P, a, b)

{

Covmatrix = matrix(rep(1, P * P), nrow = P)

for (i in 1 : (P - 1))

{Covmatrix[cbind((1 + i) : P, 1 : (P - i))] =

exp(log(a) + log(b) * abs(i))

Covmatrix[cbind(1 : (P - i), (1 + i) : P)] =

exp(log(a) + log(b) * abs(i))}

Covmatrix

}

Hao Chai (U of Iowa) Introduction to .Call interface 7 / 41

Page 9: Dot Call interface

Introduction

An R function calling C routines matgen RC:

matgen_RC = function(P, a, b)

{

.Call("matrix_gen", as.integer(P), as.double(a),

as.double(b))

}

Also we can use R compiler to compile the first two pure R functions andget matgen Rcmp and matgen Rindcmp.

Hao Chai (U of Iowa) Introduction to .Call interface 8 / 41

Page 10: Dot Call interface

Introduction

Toy example

Result

> P = 1000

test elapsed user.self relative

5 matgen Rindcmp(P, 0.5, 0.9) 0.80 0.75 1.004 matgen Rind(P, 0.5, 0.9) 0.97 0.86 1.211 matgen RC(P, 0.5, 0.9) 1.04 1.01 1.302 matgen Rcmp(P, 0.5, 0.9) 19.98 19.51 24.983 matgen R(P, 0.5, 0.9) 65.44 64.45 81.80

Hao Chai (U of Iowa) Introduction to .Call interface 9 / 41

Page 11: Dot Call interface

C part

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 10 / 41

Page 12: Dot Call interface

C part

Header files

To enable the communication between R and C, the following header filesare needed in the C code.

#include <R.h>

#include <Rinternals.h> /% For .C or .Call %/

#include <Rdefines.h> /% For .External %/

#include <R_ext/Rdynload.h>

Hao Chai (U of Iowa) Introduction to .Call interface 11 / 41

Page 13: Dot Call interface

C part .C interface

To use .C interface, main() function in C code needs to be replaced by

static void CFuncName(arg1, arg2, ...)

Arguments above have to be of pointer type. Therefore, we need tocoerce the scalar arguments to scalars in C.

C function can only return values to R through its arguments. Inother words, there are two kinds of arguments: arguments that passvalues from R to C and arguments that return values from C to R.

The C code using .C interface in the toy example is

Hao Chai (U of Iowa) Introduction to .Call interface 12 / 41

Page 14: Dot Call interface

C part .C interface

.C interface in toy example

#include <R.h>

#include <Rinternals.h>

#include <R_ext/Rdynload.h>

#include <math.h>

static void matrix_gen(double *Rp, double *Ra, double *Rb,

double *Rmatrix)

{

R_len_t i, j, p = Rp[0];

double a = Ra[0], b = Rb[0];

for (i = 0; i < p; i++)

for (j = 0; j < p; j++)

if (i == j) Rmatrix[i * p + j] = 1;

else Rmatrix[i * p + j] = exp(log(a) + abs(i - j)

* log(b));

}

Hao Chai (U of Iowa) Introduction to .Call interface 13 / 41

Page 15: Dot Call interface

C part .C interface

Mapping types between R and C

Table: Comparison of R and C data types.1

R storage mode C types

logical int *integer int *double double *

character char **complex Rcomplex *

1Cited from “Writing R Extensions”Hao Chai (U of Iowa) Introduction to .Call interface 14 / 41

Page 16: Dot Call interface

C part .Call interface

What can we expect from .Call?2

Pass R objects to C

Create R objects in C

Manipulate R objects in C

Return R objects from C

Call R functions from C

2See Brian CaffoHao Chai (U of Iowa) Introduction to .Call interface 15 / 41

Page 17: Dot Call interface

C part .Call interface

To use .Call interface, main() function in C code needs to be replaced by

SEXP CFuncName(SEXP arg1, SEXP arg2, ...)

SEXP is a structure in C standing for S expression.

The returned value from C will also be SEXP type.

If new SEXP objects are defined within the C function, usePROTECT to protect them in the memory so that it will not becleaned by R as garbage.

Hao Chai (U of Iowa) Introduction to .Call interface 16 / 41

Page 18: Dot Call interface

C part .Call interface

Basic structure of C functions

SEXP CFuncName(SEXP arg1, arg2, ...)

{

[arg1 = coerceVector(arg1, INTSXP)]

# Coerce the vector to the right type.

SEXP Robj, return_val; # Define new R objects.

PROTECT(return_val = allocMatrix(REALSXP, arg1, arg2))

# Protect return_val.

[body of function]

UNPROTECT(1)

return(return_val) # Return the values to R.

}

Hao Chai (U of Iowa) Introduction to .Call interface 17 / 41

Page 19: Dot Call interface

C part .Call interface

Useful data types in Rinternals.h

Table: SEXPTYPE and R equivalent 3

SEXPTYPE R equivalent

REALSXP numeric with storage mode doubleINTSXP integerLGLSXP logicalSTRSXP characterVECSXP list (generic vector)DOTSXP a ‘...’ objectENVSXP environment

3Cited from “Writing R Extensions”Hao Chai (U of Iowa) Introduction to .Call interface 18 / 41

Page 20: Dot Call interface

C part .Call interface

Useful macros in Rinternals.h

There are plenty of useful functions defined in Rinternals.h. Usefulfunctions can be found in “Writing R Extensions” or “R Internals”.

Table: List of useful functions in Rinternals.h4

Name Usage Example

coerceVector Coerce R object to SEXPTYPE arg1=..(arg1,INTSXP)allocVector Allocate memory for R vector Robj=..(STRSXP,2)allocMatrix Allocate memory for R matrix Robj=..(STRSXP,2,2)

nrows Get the No. of rows of a matrix ..nrow(Rmatrix)ncols Get the No. of cols of a matrix ..ncol(Rmatrix)

PROTECT Protect an R object See examples.UNPROTECT UNPROTECT some R objects See examples.

4.. represents the function name in the same row.Hao Chai (U of Iowa) Introduction to .Call interface 19 / 41

Page 21: Dot Call interface

C part .Call interface

Useful functions in Rinternals.h

Table: List of useful functions in Rinternals.h Cont.5

Name Usage Example

STRING ELT Returns the memo. add. of R string ..(Rstr, 0)VECTOR ELT Returns the memo. add. of R list ..(Rlist, 1)

INTEGER Return the memo. add. of R int ..(Rint)REAL Return the memo. add. of R real ..(Rdoub)CHAR Convert a Rchar to characters ..(Rchar)

SET VECTOR ELT Assign value to an element of R list See example

5.. represents the function name in the same row.Hao Chai (U of Iowa) Introduction to .Call interface 20 / 41

Page 22: Dot Call interface

C part .Call interface

Special Values

There are some constants for special values in R

R NaN

R PosInf

R NegInf

R NaReal

R NilValue

There are also some macros for error checking in C ISNA, ISNAN,R FINITE, NA INTEGER, NA LOGICAL, NA STRING, NA REAL

Hao Chai (U of Iowa) Introduction to .Call interface 21 / 41

Page 23: Dot Call interface

C part .Call interface

.Call interface in toy example

#include <R.h>

#include <Rinternals.h>

#include <R_ext/Rdynload.h>

#include "math.h"

SEXP matrix_gen(SEXP RP, SEXP Ra, SEXP Rb)

{

R_len_t i, j, p = INTEGER(RP)[0];

SEXP Rmatrix;

RP = coerceVector(RP, INTSXP);

Ra = coerceVector(Ra, REALSXP);

Rb = coerceVector(Rb, REALSXP);

PROTECT(Rmatrix = allocMatrix(REALSXP, p, p));

Hao Chai (U of Iowa) Introduction to .Call interface 22 / 41

Page 24: Dot Call interface

C part .Call interface

.Call interface in toy example

double *mat, a = REAL(Ra)[0], b = REAL(Rb)[0];

mat = REAL(Rmatrix);

for (i = 0; i < p; i++)

for (j = 0; j < p; j++)

if (i == j) mat[i * p + j] = 1;

else mat[i * p + j] = exp(log(a) +

abs(i - j) * log(b));

UNPROTECT(1);

return(Rmatrix);

}

Hao Chai (U of Iowa) Introduction to .Call interface 23 / 41

Page 25: Dot Call interface

R part

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 24 / 41

Page 26: Dot Call interface

R part

Interfaces in R

To create a dynamic library, run the following code in the command line:

R CMD SHLIB CFileName.c

CFileName.dll or CFileName.so will be generated in the same directory.Then load the dynamic library which is generated by C code using

> dyn.load("CFileName.so")

in Linux/MacOS, or

> dyn.load("CFileName.dll")

in Windows, or a universal solution

> dyn.load(paste("CFileName", .Platform$dynlib.ext,

+ sep = ""))

Hao Chai (U of Iowa) Introduction to .Call interface 25 / 41

Page 27: Dot Call interface

R part

There are three interfaces in R to load the dynamic library generated by C.

1 .C(”CFuncName”, arg1, arg2, ...)

2 .Call(”CFuncName”, arg1, arg2, ...)

3 .External(”CFuncName”, arg1, arg2, ...)

There are some options when using .C, such as NAOK andPACKAGE. For detailed information, refer to “Writing R Extensions”.

Hao Chai (U of Iowa) Introduction to .Call interface 26 / 41

Page 28: Dot Call interface

Examples

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 27 / 41

Page 29: Dot Call interface

Examples

Pass numeric values to C

func1 is a function with two arguments Rn and Rvec. It returns the largestelement of the first Rn elements of vector Rvec.

SEXP func1(SEXP Rvec, SEXP Rn)

{

Rvec = coerceVector(Rvec, REALSXP);

R_len_t i = 0, n = INTEGER(Rn)[0];

double *vec, max = REAL(Rvec)[0];

SEXP return_val;

PROTECT(return_val = allocVector(REALSXP, 1));

vec = REAL(Rvec);

for (i = 1; i < n; i++)

if (vec[i] >= max) max = vec[i];

REAL(return_val)[0] = max;

UNPROTECT(1);

return(return_val);

}Hao Chai (U of Iowa) Introduction to .Call interface 28 / 41

Page 30: Dot Call interface

Examples

Pass numeric values to C

In R, we do the following

a = c(7, 4, 8, 9, 2, 5)

n = 4

dyn.load("f:/presentation/intro2dotCall/illust.dll")

.Call("func1", as.double(a), as.integer(n))

Hao Chai (U of Iowa) Introduction to .Call interface 29 / 41

Page 31: Dot Call interface

Examples

Pass strings, return a list

func2 is able to calculate the quadratic form or the linear product of amatrix and a vector. It has three arguments: Rstr, Ry and RM. Ry is avector, RM is a matrix. If Rstr is ”quadratic”, then t(Ry) %*% RM %*%Ry is returned. If Rstr is ”linear”, then RM %*% Ry is returned. If Rstr is”both”, then both of the above will be returned as an R list.

Hao Chai (U of Iowa) Introduction to .Call interface 30 / 41

Page 32: Dot Call interface

Examples

Pass strings, return a list

SEXP func2(SEXP RM, SEXP Ry, SEXP Rstr)

{

Rstr = coerceVector(Rstr, STRSXP);

RM = coerceVector(RM, REALSXP);

Ry = coerceVector(Ry, REALSXP);

SEXP return_lst, vec, num;

double *M = REAL(RM), *y = REAL(Ry);

double result1 = 0, *result2;

R_len_t i, j, nr, nc, l;

const char *method;

method = CHAR(STRING_ELT(Rstr, 0));

nr = nrows(RM);

nc = ncols(RM);

l = length(Ry);

Hao Chai (U of Iowa) Introduction to .Call interface 31 / 41

Page 33: Dot Call interface

Examples

if (((strcmp(method, "both") == 0) ||

(strcmp(method,"linear") == 0)) && (nc != l))

error("The matrix and the vector need to be conformable!");

if (((strcmp(method, "both") == 0) ||

(strcmp(method, "quadratic") == 0)) &&

((nc != l) || (nr != l)))

error("The matrix and the vector need to be conformable!");

if (strcmp(method, "both") == 0)

{

PROTECT(return_lst = allocVector(VECSXP, 2));

PROTECT(vec = allocVector(REALSXP, nr));

PROTECT(num = allocVector(REALSXP, 1));

result2 = REAL(vec);

result1 = REAL(num)[0];

}

else PROTECT(return_lst = allocVector(VECSXP, 1));

Hao Chai (U of Iowa) Introduction to .Call interface 32 / 41

Page 34: Dot Call interface

Examples

if (strcmp(method, "linear") == 0)

{

PROTECT(vec = allocVector(REALSXP, nr));

result2 = REAL(vec);

}

if (strcmp(method, "quadratic") == 0)

{

PROTECT(num = allocVector(REALSXP, 1));

result1 = REAL(num)[0];

}

if ((strcmp(method, "quadratic") == 0) ||

(strcmp(method, "both") == 0))

for (i = 0; i < nr; i++)

for (j = 0; j < nc; j++)

result1 = result1 + M[i + j * nr] * y[i] * y[j];

Hao Chai (U of Iowa) Introduction to .Call interface 33 / 41

Page 35: Dot Call interface

Examples

if ((strcmp(method, "linear") == 0) ||

(strcmp(method, "both") == 0))

for (i = 0; i < nr; i++)

{

result2[i] = 0;

for (j = 0; j < nc; j++)

result2[i] = result2[i] + M[i + j * nr] * y[j];

}

Hao Chai (U of Iowa) Introduction to .Call interface 34 / 41

Page 36: Dot Call interface

Examples

if (strcmp(method, "quadratic") == 0)

SET_VECTOR_ELT(return_lst, 0, num);

if (strcmp(method, "linear") == 0)

SET_VECTOR_ELT(return_lst, 0, vec);

if (strcmp(method, "both") == 0)

{

SET_VECTOR_ELT(return_lst, 0, num);

SET_VECTOR_ELT(return_lst, 1, vec);

}

UNPROTECT(2);

if (strcmp(method, "both") == 0)

UNPROTECT(1);

return(return_lst);

}

Hao Chai (U of Iowa) Introduction to .Call interface 35 / 41

Page 37: Dot Call interface

Examples

Pass strings, return a list

The R code to call the function func2 is

dyn.load("f:/presentation/intro2dotCall/illust.dll")

M <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), nrow = 3)

y <- c(1, 0, -1)

.Call("func2", M, as.double(y), "both")

Hao Chai (U of Iowa) Introduction to .Call interface 36 / 41

Page 38: Dot Call interface

Other

Outline

1 Introduction

2 C part.C interface.Call interface

3 R part

4 Examples

5 Other

Hao Chai (U of Iowa) Introduction to .Call interface 37 / 41

Page 39: Dot Call interface

Other

Evaluating R expressions in C

It is also possible to evaluate R expressions in C code. The followingfunctions/macros are useful in this case. More details can be found in“Writing R extensions”.

defineVar

findVar

findFun

install

Hao Chai (U of Iowa) Introduction to .Call interface 38 / 41

Page 40: Dot Call interface

Other

Some misc.

The “Writing R Extensions” manual is the main source for this talk.

More functions and macros can be found in Rinternals.h, oralternatively Rdefines.h. Choose one and stick to it.

Several times, when ran .Call in R, R crashed. Very likely, it wascaused by the difference between number of arguments in .Call andnumber of arguments in the original C functions.

Related C and R files are available at Related files.

Hao Chai (U of Iowa) Introduction to .Call interface 39 / 41

Page 41: Dot Call interface

Other

Refrences

Writing R ExtensionsR InternalsUsing .Call in R by Brian Caffo.dot Call Interface by Gopi Goswami.Rinternals.h

Hao Chai (U of Iowa) Introduction to .Call interface 40 / 41

Page 42: Dot Call interface

Other

Thank you!

Hao Chai (U of Iowa) Introduction to .Call interface 41 / 41