File: cfunction.Rd

package info (click to toggle)
r-cran-inline 0.3.21-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 188 kB
  • sloc: makefile: 2
file content (306 lines) | stat: -rw-r--r-- 11,413 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
\name{cfunction}

\alias{cfunction}
\alias{setCMethod}

\concept{inline function call}

\title{ Inline C, C++, Fortran function calls from R }

\description{
  Functionality to dynamically define R functions and S4 methods with in-lined C,
  C++ or Fortran code supporting .C and .Call calling conventions.
}

\usage{
  cfunction(sig=character(), body=character(), includes=character(),
            otherdefs=character(),
            language=c("C++", "C", "Fortran", "F95", "ObjectiveC", "ObjectiveC++"),
            verbose=FALSE,
            convention=c(".Call", ".C", ".Fortran"),
            Rcpp=FALSE,
            cppargs=character(), cxxargs=character(), libargs=character(),
            dim=NULL, implicit=NULL, module=NULL, name=NULL)

  ## S4 methods for signatures
  #  f='character', sig='list', body='list'
  #  f='character', sig='character', body='character'

  setCMethod(f, sig, body, ...)

  ## Further arguments:
  #  setCMethod(f, sig, body, includes="", otherdefs="", cpp=TRUE,
  #  verbose=FALSE, where=topenv(.GlobalEnv), ...)
}

\arguments{
  \item{f}{A single character value if \code{sig} and \code{body} are character vectors
    or a character vector of the same length and the length of \code{sig} or
    \code{body} with the name(s) of methods to create.}

  \item{sig}{A match of formal argument names for the function with the
    character-string names of corresponding classes. Alternatively,
    a named list of such character vectors. The names of the list elements will
    be used as function names (see example). If \code{sig} is not a list,
    the function name used in the code can be specified by the \code{name}
    argument.  }

  \item{body}{ A character vector with C, C++ or Fortran code omitting function
    declaration (only the body, i.e. in case of C starting after the function
    opening curly bracket and ending before the closing curly bracket,
    brackets excluded). In case of \code{setCMethod} with signature
    \code{list} -- a list of such character vectors. }

  \item{includes}{ A character vector of additional includes and preprocessor
    statements etc that will be put between the R includes and the user function(s).}

  \item{otherdefs}{ A characted vector with the code for any further definitions of
    functions, classes, types, forward declarations, namespace usage clauses etc
    which is inserted between the includes and the declarations of the functions
    defined in \code{sig}.}

  \item{language}{ A character value that specifies the source language of the
    inline code. The possible values for \code{language} include all those
    supported by \code{R CMD SHLIB} on any platform, which are currently C,
    C++, Fortran, F95, ObjectiveC and ObjectiveC++; they may not all be supported
    on your platform. One can specify the language either in full as above, or
    using any of the following case insensitive shortened forms: \code{c, cpp,
    c++, f, f95, objc, objcpp, objc++}. Defaults to \code{C++}.}

  \item{verbose}{ If \code{TRUE} prints the compilation output, the source
    code of the resulting program and the definitions of all declared
    methods. If \code{FALSE}, the function is silent, but it prints compiler
    warning and error messages and the source code if compilation fails. }

  \item{convention}{ Which calling convention to use?  See the Details section.}

  \item{Rcpp}{If \code{TRUE} adds inclusion of \code{Rcpp.h} to
  \code{includes}, also queries the \code{Rcpp} package about
  the location of header and library files and sets environment
  variables \code{PKG_CXXFLAGS} and \code{PKG_LIBS} accordingly so that
  the R / C++ interface provided by the \code{Rcpp} package can be
  used. Default value is \code{FALSE}.}

  \item{cppargs}{Optional character vector of tokens to be passed to
  the compiler via the \code{PKG_CPPFLAGS} environment
  variable. Elements should be fully formed as for example
  \code{c("-I/usr/local/lib/foo", "-DDEBUG")} and are passed along verbatim.}

  \item{cxxargs}{Optional character vector of tokens to be passed to
  the compiler via the \code{PKG_CXXFLAGS} environment
  variable. Elements should be fully formed as for example
  \code{c("-I/usr/local/lib/foo", "-DDEBUG")} and are passed along verbatim.}

  \item{libargs}{Optional character vector of tokens to be passed to the
  compiler via the \code{PKG_LIBS} environment variable. Elements should
  be fully formed as for example \code{c("-L/usr/local/lib/foo -lfoo",
  "--lpthread")} and are passed along verbatim.}

  \item{dim}{Optional character vector defining the dimensionality of the
  function arguments. Of same length as \code{sig}. Fortran or F95 only.}

  \item{implicit}{A character vector defining the implicit declaration in
  Fortran or F95; the default is to use the implicit typing rules for Fortran,
  which is \code{integer} for names starting with the letters \code{I} through
  \code{N}, and \code{real} for names beginning with any other letter.
  As \code{R} passes double precision, this is not the best choice.
  Safest is to choose \code{implicit = "none"} which will require all names
  in the subroutine to be explicitly declared.}

  \item{module}{Name(s) of any modules to be used in the \code{Fortran} or
  \code{F95} subroutine.}

  \item{name}{Function name to be used in the code. Only used if \code{sig} is
    not a list. This is useful if the DLL created is to be used in conjunction
    with the \code{ode} function of the \code{deSolve} package.
  }

  \item{...}{ Reserved.}
}

\value{
  If \code{sig} is a single character vector, \code{cfunction} returns a single
  \code{\link{function}}; if it is a list, it returns a list of functions.

  \code{setCMethod} declares new methods with given names and signatures and
  returns invisible \code{NULL}.
}

\details{

  To declare multiple functions in the same library one can use \code{setCMethod}
  supplying lists of signatures and implementations. In this case, provide as
  many method names in \code{f} as you define methods. Avoid clashes when selecting
  names of the methods to declare, i.e. if you provide the same name several times
  you must ensure that signatures are different but can share the same generic!

  The source code in the \code{body} should not include the header or
  "front-matter" of the function or the close, e.g. in C or C++ it
  must start after the C-function opening curly bracket and end before
  the C-function closing curly bracket, brackets should not be
  included. The header will be automatically generated from the R-\code{signature}
  argument. Arguments will will carry the same name as used in the signature,
  so avoid variable names that are not legal in the target language
  (e.g. names with dots).

  C/C++: If \code{convention == ".Call"} (the default), the \code{\link{.Call}} mechanism
  is used and its result is returned directly as the result of the call of the
  generated function.  As the last line of the generated C/C++ code a
  \code{return R_NilValue;} is added in this case and a warning is generated
  in case the user has forgotten to provide a return value. To suppress the
  warning and still return NULL, add \code{return R_NilValue;} explicitly.

  Special care is needed with types, memory allocation and protection
  -- exactly the same as if the code was not inline: see the
  Writing R Extension manual for information on \code{\link{.Call}}.

  If \code{convention == ".C"} or \code{convention == ".Fortran"}, the
  \code{\link{.C}} or \code{\link{.Fortran}} mechanism respectively is
  used, and the return value is a list containing all arguments.

  Attached R includes include \code{R.h} for \code{".C"}, and
  additionally \code{Rdefines.h} and \code{R_ext\\Error.h} for
  \code{".Call"}.
}

\seealso{ \code{
    \link{Foreign} Function Interface
}}

\examples{

x <- as.numeric(1:10)
n <- as.integer(10)

\dontrun{
## A simple Fortran example - n and x: assumed-size vector
code <- "
      integer i
      do 1 i=1, n(1)
    1 x(i) = x(i)**3
"
cubefn <- cfunction(signature(n="integer", x="numeric"), code, convention=".Fortran")
print(cubefn)

cubefn(n, x)$x

## Same Fortran example - now n is one number
code2 <- "
      integer i
      do 1 i=1, n
    1 x(i) = x(i)**3
"
cubefn2 <- cfunction(signature(n="integer", x="numeric"), implicit = "none",
  dim = c("", "(*)"), code2, convention=".Fortran")

cubefn2(n, x)$x

## Same in F95, now x is fixed-size vector (length = n)
code3 <- "x = x*x*x"
cubefn3 <- cfunction(sig = signature(n="integer", x="numeric"), implicit = "none",
  dim = c("", "(n)"), code3, language="F95")
cubefn3(20, 1:20)
print(cubefn3)

## Same example in C
code4 <- "
      int i;
      for (i = 0; i < *n; i++)
        x[i] = x[i]*x[i]*x[i];
"
cubefn4 <- cfunction(signature(n="integer", x="numeric"), code4, language = "C", convention = ".C")
cubefn4(20, 1:20)

## Give the function in the source code a name
cubefn5 <- cfunction(signature(n="integer", x="numeric"), code4, language = "C", convention = ".C",
  name = "cubefn")
code(cubefn5)
}

 ## use of a module in F95
modct <- "module modcts
double precision, parameter :: pi = 3.14159265358979
double precision, parameter :: e = 2.71828182845905
end"

getconstants <- "x(1) = pi
x(2) = e"

cgetcts <- cfunction(getconstants, module = "modcts", implicit = "none",
  includes = modct, sig = c(x = "double"), dim = c("(2)"), language = "F95")

cgetcts(x = 1:2)
print(cgetcts)

## Use of .C convention with C code
## Defining two functions, one of which calls the other
sigSq <- signature(n="integer", x="numeric")
codeSq <- "
  for (int i=0; i < *n; i++) {
    x[i] = x[i]*x[i];
  }"
sigQd <- signature(n="integer", x="numeric")
codeQd <- "
  squarefn(n, x);
  squarefn(n, x);
"

fns <- cfunction( list(squarefn=sigSq, quadfn=sigQd),
                  list(codeSq, codeQd),
                  convention=".C")

squarefn <- fns[["squarefn"]]
quadfn <- fns[["quadfn"]]

squarefn(n, x)$x
quadfn(n, x)$x

## Alternative declaration using 'setCMethod'
setCMethod(c("squarefn", "quadfn"), list(sigSq, sigQd),
           list(codeSq, codeQd), convention=".C")

squarefn(n, x)$x
quadfn(n, x)$x

## Use of .Call convention with C code
## Multyplying each image in a stack with a 2D Gaussian at a given position
code <- "
  SEXP res;
  int nprotect = 0, nx, ny, nz, x, y;
  PROTECT(res = Rf_duplicate(a)); nprotect++;
  nx = INTEGER(GET_DIM(a))[0];
  ny = INTEGER(GET_DIM(a))[1];
  nz = INTEGER(GET_DIM(a))[2];
  double sigma2 = REAL(s)[0] * REAL(s)[0], d2 ;
  double cx = REAL(centre)[0], cy = REAL(centre)[1], *data, *rdata;
  for (int im = 0; im < nz; im++) {
    data = &(REAL(a)[im*nx*ny]); rdata = &(REAL(res)[im*nx*ny]);
    for (x = 0; x < nx; x++)
      for (y = 0; y < ny; y++) {
        d2 = (x-cx)*(x-cx) + (y-cy)*(y-cy);
        rdata[x + y*nx] = data[x + y*nx] * exp(-d2/sigma2);
      }
  }
  UNPROTECT(nprotect);
  return res;
"
funx <- cfunction(signature(a="array", s="numeric", centre="numeric"), code)

x <- array(runif(50*50), c(50,50,1))
res <- funx(a=x, s=10, centre=c(25,15))
if (interactive()) image(res[,,1])

## Same but done by registering an S4 method
setCMethod("funy", signature(a="array", s="numeric", centre="numeric"), code, verbose=TRUE)

res <- funy(x, 10, c(35,35))
if (interactive()) { x11(); image(res[,,1]) }

}

\author{
  Oleg Sklyar, Duncan Murdoch, Mike Smith, Dirk Eddelbuettel
}

\keyword{file}