/
R – C/C++ programming R – C/C++ programming

R – C/C++ programming - PowerPoint Presentation

tatiana-dople
tatiana-dople . @tatiana-dople
Follow
378 views
Uploaded On 2015-09-27

R – C/C++ programming - PPT Presentation

Katia Oleinik koleinikbuedu Scientific Computing and Visualization Boston University httpwwwbuedutechresearchtrainingtutorialslist RCC programming 2 Goal performance enhancement ID: 141952

function vector interface programming vector function programming interface sexp return call len local include rlen int load double exc1 ivalue pvector pointer

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "R – C/C++ programming" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

R – C/C++ programmingKatia Oleinikkoleinik@bu.eduScientific Computing and VisualizationBoston University

http://www.bu.edu/tech/research/training/tutorials/list

/Slide2

R-C/C++ programming2

Goal – performance enhancement.

Benefits – use of existing C/C++ libraries and memory management

Base R package provides 3 types of interfaces between R and C/C++

.C()

.Call()

.External() – used to create R packages

There are other R packages that provide interface between R and C/C++ (and other languages such as FORTRAN and Python):

Rcpp

Slide3

R-C/C++ programming3

.C()

interface

/* exC1.c – example C function to be called from R */

void

exampleC1(

int

*

iVec

){

iVec

[0] = 7;

return;

}

exC1.c

Important:

Function returns no values – it is

VOID

All the values that need to be

changed/returned by a function

must be

passed through its arguments.Slide4

R-C/C++ programming4

.C()

interface

katana:~ %

R CMD SHLIB

exC1.c

gcc

-

std

=gnu99 -I/

usr

/local/IT/R-2.13.2/lib64/R/include -I/

usr

/local/include -

fpic

-g -O2 -c exC1.c -o exC1.o

gcc

-

std=gnu99 -shared -L/

usr/local/lib64 -o exC1.so exC1.okatana:~ %

Important:

In

linux

(and

R

) environment commands are case sensitive! Slide5

R-C/C++ programming5

.C()

interface

Note:

In

windows

after the function is compiled it will be named

exC1.dll

>

#

load C function to R workspace

>

dyn.load

("

exC1.so

")

>Slide6

R-C/C++ programming6

.C()

interface

>

#

load C function to R workspace

>

dyn.load

("

exC1.so

")

>

# create a vector

>

iv <- 1:3Slide7

R-C/C++ programming7

.C()

interface

>

#

load C function to R workspace

>

dyn.load

("

exC1.so

")

>

# create a vector

>

iv <- 1:3

>

#

call c-function

> out <-

.C

(

"

exampleC1

"

,

newVec

=

as.integer

(iv))Slide8

R-C/C++ programming8

.C()

interface

>

#

load C function to R workspace

>

dyn.load

("

exC1.so

")

>

# create a vector

>

iv <- 1:3

>

#

call c-function

> out <-

.C

(

"

exampleC1

"

,

newVec

=

as.integer

(iv))

>

out

$

newVec

[1] 7 2

3Slide9

R-C/C++ programming9

.C()

interface

Note:

Allocate memory to the vectors passed to

.C

in R by creating vectors of the right length

The first argument to

.C

is a character string of the C function name

The rest of the arguments are

R

objects to be passed to the C function.

All arguments should be coerced to the correct R storage mode to prevent mismatching of types that can lead to errors

C returns a

list

object

The second argument in this example is given a name

newVec. This name is used to access the component in the returned list object.Slide10

R-C/C++ programming10

.C()

interface

Note:

R has to allocate memory for the arrays passed to and from C.

R has to pass objects of correct type

R copies its arguments prior to passing them to C and then creates a copy of the values passed back from C.Slide11

R-C/C++ programming11

/* exC2.c – example C function to be called from R */

/*

normalize the vector */

i

nclude

<

math.h

>

include <

string.h

>

void

exampleC2(

char

**c,

double

*A, double *B, int *

ierr){

double

len

= 0;

/*local variable – vector length */

int

i

;

for

(

i

=0;

i

<3;

i

++)

len

+=

pow

( A[

i

]), 2);

/* check if the vector is degenerate */

if

(

len

< 0.000001){

ierr

[0] = -1;

/*error – null vector */

stncpy

(c,

“Error”

, 5

);

return

;

}

/* calculate output vector

len

=

pow

(

len

, 0.5);

for (i=0; i<3; i++) B[i] = A[i] / len ; ierr[0] = 0; strncpy(c, “OK”, 2); return; }

exC2.cSlide12

R-C/C++ programming12

.C()

interface

katana:~ %

R CMD SHLIB

exC2.c

gcc

-

std

=gnu99 -I/

usr

/local/IT/R-2.13.2/lib64/R/include -I/

usr

/local/include -

fpic

-g -O2 -c exC2.c -o exC2.o

gcc

-

std=gnu99 -shared -L/

usr/local/lib64 -o exC2.so exC2.o Slide13

R-C/C++ programming13

.C()

interface

>

#

load C function to R workspace

>

dyn.load

("

exC2.so

")

>

# create error vector

>

ierr_in

<- 0

>

# create

input vector> A_in

<-

c(2, 3, 6)

>

#

create output vector

>

B_in

<-

c(0, 0, 0)

>

# create

message vector (make sure it is long enough!)

>

C_in

<-

c(

"

"

)Slide14

R-C/C++ programming14

.C()

interface

>

#

execute C function

>

out

<-

.C

(

"

exampleC2

"

,

+

C_out

= as.character(

C_in), +

A_out

=

as.numeric

(

A_in

),

+

B_out

=

as.numeric

(

B_in

),

+

ierr_out

=

as.integer

(

ierr_in

))Slide15

R-C/C++ programming15

.C()

interface

>

out

$

C_out

[1]

"

OK

"

$

A_out

[1]

2 3 6

$

B_out

[1] 0.2857143 0.4285714 0.8571429

$

ierr_out

[1]

0Slide16

R-C/C++ programming16

.C()

interface

>

# create input vector

>

A_in

<-

c(0, 0, 0)

>

#

execute C function

>

out

<-

.C

(

"

exampleC2",

"exampleC2", + C_out

=

as.character

(

C_in

),

+

A_out

=

as.numeric

(

A_in

),

+

B_out

=

as.numeric

(

B_in

),

+

ierr_out

=

as.integer

(

ierr_in

))Slide17

R-C/C++ programming17

.C()

interface

>

out

$

C_out

[1]

"

error

"

$

A_out

[1]

0 0 0

$

B_out

[1]

0 0 0

$

ierr_out

[1]

-1Slide18

R-C/C++ programming18

.C()

interface

Note:

To compile more than one C file:

R

CMD SHLIB

file1.c file2.c file3.c

The resulting file will be named

file1.soSlide19

R-C/C++ programming19

.Call()

interface

does not copy arguments before and after calling c-function

it is possible to find the length of the input vector inside c-function

an easier access to wide-range of R – objects

NA (missing values) handling

Access to vectors’ attributesSlide20

R-C/C++ programming20

.Call()

interface

passing a value

/* exC3.c – example C function to be called from R with .Call interface*/

/*

access R object (scalar value) inside c-function */

i

nclude

<

R

.h

>

/* 2 standard includes for .Call interface) */

include

<

Rdefines.h

> SEXP exampleC3 (

SEXP

iValue

){

return (

R_NilValue

);

/*

“void” function must return “NULL” value */

}

exC3.c

Note:

All objects passed between R and C/C++ are of type

SEXP – S

imple

EXP

ression

.

2 standard includes needed for

.Call

interface

If function is void it should return

R_NilValue

object.Slide21

R-C/C++ programming21

.Call()

interface

passing a value

/* exC3.c – example C function to be called from R with .Call interface*/

/*

access R object (scalar value) inside c-function */

i

nclude

<

R

.h

>

include

<

Rdefines.h

>

SEXP exampleC3 ( SEXP

iValue

){

int

local_iValue

;

/* convert R object to c-accessible variable

*/

local_iValue

=

INTEGER_VALUE

(

iValue

);

return (

R_NilValue

);

}

exC3.cSlide22

R-C/C++ programming22

.Call()

interface

passing a value

/* exC3.c – example C function to be called from R with .Call interface*/

/*

access R object (scalar value) inside c-function */

i

nclude

<

R

.h

>

include

<

Rdefines.h

>

SEXP exampleC3 ( SEXP

iValue

){

int

local_iValue

;

/* convert R object to c-accessible variable */

local_iValue

=

INTEGER_VALUE

(

iValue

);

/*

print value of the local variable*/

printf

(" In exampleC3

iValue

= %d\n",

local_iValue

);

return (

R_NilValue

);

}

exC3.cSlide23

R-C/C++ programming23

.Call()

interface –

passing a value

>

#

load C function to R workspace – same as before

>

dyn.load

(

"

exC3.so

"

)

>

#

call C function

> out

<-

.Call("

exampleC3

",

7

)

In

exampleC3

iValue

=

7

>

#

explore output

>

out

NULLSlide24

R-C/C++ programming24

.Call()

interface

passing a

vector

/*

exC4.c - example C function to be called from R */

/*

normalize

the vector and return its length

*/

i

nclude

<

R

.h

>

include <Rdefines.h>

include

<

Rmath.h

>

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

return (

rLen

);

/*

return a value */

}

exC4.c

Note:

Rmath.h

include provides access to many R-functions include

rnorm

(),

rgamma

()

,

etc.

Function should return

SEXP

object.

.Call()

interface allows for changing the function arguments –

be careful

!Slide25

R-C/C++ programming25

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

/* output value – length of a vector */

double

*

pVector

;

/*

local variable - pointer to the input vector */

double

vLen = 0;

/* local variable to calculate intermediate values */

int

len

;

/* local variable – size of the input vector */

int

i

;

/* local variable – loop index */

return (

rLen

);

/*

return a value */

}

exC4.cSlide26

R-C/C++ programming26

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

double

*

pVector

;

double

vLen

=

0;

int len;

int i;

/* get the pointer to the vector */

pVector

=

NUMERIC_POINTER

(

Vector

)

;

return (

rLen

);

/*

return a value */

}

exC4.c

Note:

Use

INTEGER_POINTER()

and

CHARACTER_POINTER

()

to get pointer to integer and character arrays respectfully Slide27

R-C/C++ programming27

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

double

*

pVector

;

double

vLen

=

0;

int len;

int i;

/* get the pointer to the vector */

pVector

=

NUMERIC_POINTER

(

Vector

)

;

/*

number of elements in the array */

len

=

length(

Vector

)

;

return (

rLen

);

/*

return a value */

}

exC4.c

Note:

We can get the size of the input R-vector !Slide28

R-C/C++ programming28

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

double

*

pVector

;

double

vLen

=

0;

int len;

int i;

pVector

=

NUMERIC_POINTER

(

Vector

)

;

len

=

length(

Vector

)

;

/*

allocate storage for integer variable (array works also!) */

PROTECT(

rLen

=

NEW_NUMERIC(

1

)

)

;

UNPROTECT(

1

)

;

return (

rLen

);

/*

return a value */

}

exC4.c

Note:

To allocate integer and character arrays use

NEW_INTEGER(

len

)

and

NEW_CHARACTER(

len

)

functions respectfully

PROTECT()

and

UNPROTECT()

command

must be balanced

!Slide29

R-C/C++ programming29

SEXP

exampleC4 (

SEXP

Vector ){

SEXP

rLen

;

double

*

pVector

;

double

vLen

=

0;

int len;

int i;

pVector

=

NUMERIC_POINTER

(

Vector

)

;

len

=

length(

Vector

)

;

PROTECT(

rLen

=

NEW_NUMERIC(

1

)

)

;

/* calculate the length */

for

(

i

=0;

i

<

len

;

i

++

)

vLen

+=

pow

(

pVector

[

i

], 2

);

if (

vLen

> 0.000001

){

vLen

=

pow

(

vLen,0.5

)

;

/* Here we are working with a pointer

- it WILL change R vector */ for( i=0; i < len; i++ )pVector[i] /= vLen; } /* copy the value of local variable into R-object */ REAL(rLen)[0] = vLen; UNPROTECT(1);

return (

rLen

);

/*

return a value */

}

exC4.cSlide30

R-C/C++ programming30

.Call()

interface –

passing

an array

>

#

load C function to R workspace – same as before

>

dyn.load

(

"

exC4.so

"

)

>

#

define and input array

>

A_in

<- c( 2, 3, 6)

>

#

call C function

>

out

<-

.Call("

exampleC4

",

A_in

)

>

# input array changed !!!

>

A_in

[1] 0.2857143 0.4285714

0.8571429

>

out

[1] 7Slide31

31

This tutorial has been made possible by

Scientific

Computing and Visualization

group

at

Boston University

.

Katia Oleinik

koleinik@bu.edu