cfunction               package:inline               R Documentation

_I_n_l_i_n_e _C, _C++, _F_o_r_t_r_a_n _f_u_n_c_t_i_o_n _c_a_l_l_s _f_r_o_m _R

_D_e_s_c_r_i_p_t_i_o_n:

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

_U_s_a_g_e:

       cfunction(sig=character(), body=character(), includes=character(),
                 otherdefs=character(), 
                 language=c("C++", "C", "Fortran", "F95", "ObjectiveC", "ObjectiveC++"),
                 verbose=FALSE, 
                 convention=c(".Call", ".C", ".Fortran") )

       ## 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), ...)

_A_r_g_u_m_e_n_t_s:

       f: A single character value if 'sig' and 'body' are character
          vectors or a character vector of the same length and the
          length of 'sig' or 'body' with the name(s) of methods to
          create.

     sig: A match of formal argument names for the function with the
          character-string names of corresponding classes.
          Alternatively,  a list of such character vectors. 

    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 'setCMethod' with signature 'list' - a list of such
          character vectors. 

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

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
          'sig'.

language: A character value that specifies the source language of the
          inline code. The possible values for 'language' include all
          those  supported by '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: 'c, cpp, 
          c++, f, f95, objc, objcpp, objc++'. Defaults to 'C++'.

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

convention: Which calling convention to use?  See the Details section.

     ...: Reserved.

_D_e_t_a_i_l_s:

     To declare multiple functions in the same library one can use
     'setCMethod' supplying lists of signatures and implementations. In
     this case, provide as many method names in '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 '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-'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 'convention == ".Call"' (the default), the '.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  '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 '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 '.Call'.  

     If 'convention == ".C"' or 'convention == ".Fortran"', the '.C' or
     '.Fortran' mechanism respectively is used, and the return value is
     a list containing all arguments.

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

_V_a_l_u_e:

     If 'sig' is a single character vector, 'cfunction' returns a
     single 'function'; if it is a list, it returns a list of
     functions.

     'setCMethod' declares new methods with given names and signatures
     and returns invisible 'NULL'.

_A_u_t_h_o_r(_s):

     Oleg Sklyar <osklyar@ebi.ac.uk> Duncan Murdoch Mike Smith

_S_e_e _A_l_s_o:

     ' Foreign Function Interface '

_E_x_a_m_p_l_e_s:

     ## A simple Fortran example
     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")

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

     ## 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]) }

