[Rcpp-commits] r3874 - in pkg/Rcpp: . R man

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Wed Oct 31 17:22:28 CET 2012


Author: jjallaire
Date: 2012-10-31 17:22:28 +0100 (Wed, 31 Oct 2012)
New Revision: 3874

Added:
   pkg/Rcpp/man/cppFunction.Rd
Modified:
   pkg/Rcpp/ChangeLog
   pkg/Rcpp/NAMESPACE
   pkg/Rcpp/R/Attributes.R
   pkg/Rcpp/man/compileAttributes.Rd
   pkg/Rcpp/man/sourceCpp.Rd
Log:
add cppFunction for inline-style definitions

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2012-10-31 13:52:52 UTC (rev 3873)
+++ pkg/Rcpp/ChangeLog	2012-10-31 16:22:28 UTC (rev 3874)
@@ -1,11 +1,15 @@
 2012-10-31  JJ Allaire <jj at rstudio.org>
 
-    * R/Attributes.R: change 'local' param to (more explicit) 'envir'
-    * src/Attributes.cpp: factored parser into it's own file; eliminated 
-    tranposition of roxygen comments.
-    * src/AttributesParser.h: attributes parser header
-    * src/AttributesParser.cpp: attributes parser implementation
-    * man/source.Cpp.Rd: documentation updates
+	* R/Attributes.R: add cppFunction for inline-style definitions; 
+	change 'local' param to (more clear and explicit) 'envir' param.
+	* src/Attributes.cpp: factored parser into it's own file; eliminated 
+	tranposition of roxygen comments.
+	* src/AttributesParser.h: attributes parser header
+	* src/AttributesParser.cpp: attributes parser implementation
+	* man/sourceCpp.Rd: documentation updates
+	* man/compileAttributes.Rd: documentation updates
+	* man/cppFunction.Rd: documentation for cppFunction
+	* NAMESPACE: export for cppFunction 
 
 2012-10-31  Romain Francois <romain at r-enthusiasts.com>
 

Modified: pkg/Rcpp/NAMESPACE
===================================================================
--- pkg/Rcpp/NAMESPACE	2012-10-31 13:52:52 UTC (rev 3873)
+++ pkg/Rcpp/NAMESPACE	2012-10-31 16:22:28 UTC (rev 3874)
@@ -16,7 +16,7 @@
 
 export( 
     Module, Rcpp.package.skeleton, populate, loadRcppModules, setRcppClass,
-       loadModule, sourceCpp, compileAttributes
+       loadModule, cppFunction, sourceCpp, compileAttributes
 )
 
 exportClass(RcppClass)

Modified: pkg/Rcpp/R/Attributes.R
===================================================================
--- pkg/Rcpp/R/Attributes.R	2012-10-31 13:52:52 UTC (rev 3873)
+++ pkg/Rcpp/R/Attributes.R	2012-10-31 16:22:28 UTC (rev 3874)
@@ -130,17 +130,52 @@
     invisible(context$exportedFunctions)
 }
 
-# Define a single C++ function.
-cppFunction <- function(code) {
+# Define a single C++ function
+cppFunction <- function(code, 
+                        plugin = NULL,
+                        includes = NULL,
+                        envir = parent.frame(),
+                        rebuild = FALSE,
+                        verbose = getOption("verbose")) {
     
-    # add scaffolding 
-    code <- paste("#include <Rcpp.h>", "using namespace Rcpp;",
-                  "// [[Rcpp::export]]", code, sep="\n")
+    # generate required scaffolding
+    if (!is.null(plugin)) {
+        depends <- paste(plugin, sep=", ")
+        scaffolding <- paste("// [[Rcpp::depends(", depends, ")]]", sep="")
+        scaffolding <- c(scaffolding, "", .rcppExportsIncludes(plugin), 
+                         recursive=T)
+    }
+    else {
+        scaffolding <- "#include <Rcpp.h>"
+    }
+    scaffolding <- c(scaffolding, 
+                     "",
+                     "using namespace Rcpp;", 
+                     "",
+                     includes,
+                     "// [[Rcpp::export]]",
+                     recursive = T)
+        
+    # prepend scaffolding to code
+    code <- paste(c(scaffolding, code, recursive = T), collapse="\n")
     
-    # source cpp into environment we create to hold the function
-    envir <- new.env()
-    exported <- sourceCpp(code = code, envir = envir)
+    # print the generated code if we are in verbose mode
+    if (verbose) {
+        cat("\nGenerated code for function definition:",
+            "\n--------------------------------------------------------\n\n")
+        cat(code)
+    }
     
+    # source cpp into specified environment. if envir is set to NULL
+    # then create a new one (the caller can get a hold of the function
+    # via the return value)
+    if (is.null(envir))
+        envir <- new.env()
+    exported <- sourceCpp(code = code, 
+                          envir = envir, 
+                          rebuild = rebuild, 
+                          verbose = verbose)
+    
     # verify that a single function was exported and return it
     if (length(exported) == 0)
         stop("No function definition found")
@@ -148,7 +183,7 @@
         stop("More than one function definition")
     else {
         functionName <- exported[[1]]
-        get(functionName, envir)
+        invisible(get(functionName, envir))
     }
 }
 

Modified: pkg/Rcpp/man/compileAttributes.Rd
===================================================================
--- pkg/Rcpp/man/compileAttributes.Rd	2012-10-31 13:52:52 UTC (rev 3873)
+++ pkg/Rcpp/man/compileAttributes.Rd	2012-10-31 16:22:28 UTC (rev 3874)
@@ -12,10 +12,10 @@
 %- maybe also 'usage' for other objects documented here.
 \arguments{
   \item{pkgdir}{
-    Directory containing the package to compile attributes for (defaults to the current working directory)
+    Directory containing the package to compile attributes for (defaults to the current working directory).
 }
   \item{verbose}{
-    \code{TRUE} to print detailed information about generated code to the console
+    \code{TRUE} to print detailed information about generated code to the console.
 }
 }
 \details{

Added: pkg/Rcpp/man/cppFunction.Rd
===================================================================
--- pkg/Rcpp/man/cppFunction.Rd	                        (rev 0)
+++ pkg/Rcpp/man/cppFunction.Rd	2012-10-31 16:22:28 UTC (rev 3874)
@@ -0,0 +1,82 @@
+\name{cppFunction}
+\alias{cppFunction}
+\title{
+Define an R Function with a C++ Implementation
+}
+\description{
+Dynamically define an R function with C++ source code. Compiles and links a shared library with bindings to the C++ function then defines an R function that uses \code{.Call} to invoke the library.
+}
+\usage{
+cppFunction(code, plugin = NULL, includes = NULL, 
+            envir = parent.frame(), rebuild = FALSE, 
+            verbose = getOption("verbose"))
+}
+
+\arguments{
+  \item{code}{
+    Source code for the function definition.
+}
+  \item{plugin}{
+    The name of an \link[inline:plugins]{inline plugin} to use for the compilation.
+}
+  \item{includes}{
+    User includes, inserted after the includes provided by the plugin.
+}
+  \item{envir}{
+    The \link[base:environment]{environment} in which to define the R function. May be \code{NULL} in which case the defined function can be obtained from the return value of \code{cppFunction}.
+}
+  \item{rebuild}{
+    Force a rebuild of the shared library.
+}
+  \item{verbose}{
+    \code{TRUE} to print detailed information about generated code to the console.
+}
+}
+\details{
+   Functions defined using \code{cppFunction} must have return types that are compatible with \code{Rcpp::wrap} and parameter types that are compatible with \code{Rcpp::as}.
+        
+    The shared library will not be rebuilt if the underlying code has not changed since the last compilation.
+}
+\value{
+    An R function that uses \code{.Call} to invoke the underlying C++ function.
+}
+
+\note{
+    You can also define R functions with C++ implementations using the \code{\link{sourceCpp}} function, which allows you to separate the C++ code into it's own source file. For many use cases this is an easier and more maintainable approach.
+}
+
+
+\seealso{
+\code{\link{sourceCpp}}
+}
+\examples{
+\dontrun{
+
+cppFunction(
+    'int fibonacci(const int x) {
+        if (x == 0) return(0); 
+        if (x == 1) return(1);
+        return (fibonacci(x - 1)) + fibonacci(x - 2);
+    }')
+
+cppFunction(plugin = "RcppArmadillo",
+    'List fastLm(NumericVector yr, NumericMatrix Xr) {
+        
+        int n = Xr.nrow(), k = Xr.ncol();
+        
+        arma::mat X(Xr.begin(), n, k, false); 
+        arma::colvec y(yr.begin(), yr.size(), false);
+        
+        arma::colvec coef = arma::solve(X, y);
+        arma::colvec resid = y - X*coef;
+        
+        double sig2 = arma::as_scalar(arma::trans(resid)*resid/(n-k) );
+        arma::colvec stderrest = arma::sqrt(
+            sig2 * arma::diagvec(arma::inv(arma::trans(X)*X)));
+        
+        return List::create(Named("coefficients") = coef,
+            Named("stderr")       = stderrest
+        );
+    }')
+}
+}

Modified: pkg/Rcpp/man/sourceCpp.Rd
===================================================================
--- pkg/Rcpp/man/sourceCpp.Rd	2012-10-31 13:52:52 UTC (rev 3873)
+++ pkg/Rcpp/man/sourceCpp.Rd	2012-10-31 16:22:28 UTC (rev 3874)
@@ -16,24 +16,21 @@
     A character string giving the pathname of a file
 }
   \item{code}{
-    A character string with C++ source code to compile
+    A charcter string with source code. If supplied, the code is taken from this string instead of a file. 
 }
   \item{envir}{
-    Environment where the R functions should be made available
+    Environment where the R functions should be made available.
 }
   \item{rebuild}{
-    Force a rebuild of the shared library by passing \code{--preclean} to \code{R CMD SHLIB} 
+    Force a rebuild of the shared library.
 }
   \item{show.output}{
-    \code{TRUE} to print \code{R CMD SHLIB} output to the console
+    \code{TRUE} to print \code{R CMD SHLIB} output to the console.
 }
   \item{verbose}{
-    \code{TRUE} to print detailed information about generated code to the console
+    \code{TRUE} to print detailed information about generated code to the console.
 }
-  \item{code}{
-    Code. If supplied, the code is taken from this string instead of a file.  
 }
-}
 \details{
     If the \code{code} parameter is provided then the \code{file} parameter is ignored.
 



More information about the Rcpp-commits mailing list