Skip to content

Commit f62d4a7

Browse files
committed
Rcpp-quickref updates (Closes #484)
Updated the Important Notes with #include <Rcpp.h> Updated Inline section to use cppFunction() and mentioned evalCpp() Added section on Rcpp Attributes and Plugins Updated Environment with comments Updated Rcpp function section to include an example pass of an R function & emphasized loss of performance Moved Module, Environment, and Function section to the end.
1 parent 8a0d504 commit f62d4a7

File tree

3 files changed

+202
-88
lines changed

3 files changed

+202
-88
lines changed

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2016-07-17 James J Balamuta <[email protected]>
2+
3+
* vignettes/Rcpp-quickref.Rnw: Added sections on Rcpp attributes and
4+
plugins. Facelifts on important notes, inline, environments, and
5+
calling R functions.
6+
17
2016-07-15 James J Balamuta <[email protected]>
28

39
* vignettes/Rcpp-FAQ.Rnw: Added section on default function parameters

inst/NEWS.Rd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
}
4242
\item Changes in Rcpp Documentation:
4343
\itemize{
44+
\item The Rcpp Quick Reference vignette received a facelift with
45+
new sections on Rcpp attributes and plugins begin added.
46+
Furthermore, content was improved in the following
47+
sections: important notes, inline compiling, environments,
48+
and calling R functions.
49+
(James Balamuta in \ghpr{509} fixing \ghit{484}).
4450
\item A section on default parameters was added to the Rcpp FAQ vignette
4551
(James Balamuta in \ghpr{505} fixing \ghit{418}).
4652
\item The Rcpp-attributes vignette is now mentioned more prominently in

vignettes/Rcpp-quickref.Rnw

Lines changed: 190 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ prettyDate <- format(Sys.Date(), "%B %e, %Y")
6464
// If you experience compiler errors, please check that you have an appropriate version of g++. See `Rcpp-FAQ' for more information.
6565
6666
// Many of the examples here imply the following:
67+
#include <Rcpp.h>
6768
using namespace Rcpp;
68-
// The inline package adds this for you. Alternately, use e.g.:
69+
// The cppFunction will automatically add this.
70+
71+
// Or, prefix Rcpp objects with the Rcpp namespace e.g.:
6972
Rcpp::NumericVector xx(10);
7073
@
7174
@@ -90,7 +93,7 @@ NumericVector xx = NumericVector::create(
9093
1.0, 2.0, 3.0, 4.0 );
9194
NumericVector yy = NumericVector::create(
9295
Named["foo"] = 1.0,
93-
_["bar"] = 2.0 ); // short for Named
96+
_["bar"] = 2.0 ); // _ short for Named
9497
@
9598
9699
\paragraph{Extract and set single elements}~
@@ -147,20 +150,23 @@ NumericVector zz1 = xx( _, 1);
147150
NumericMatrix zz2 = xx( Range(0,2), Range(0,2));
148151
@
149152
150-
\paragraph{Inline}~
153+
\paragraph{Inline C++ Compile in R}~
151154
\newline
152155
<<lang=cpp>>=
153-
## Note - this is R code. inline allows rapid testing.
154-
require(inline)
155-
testfun = cxxfunction(
156-
signature(x="numeric", i="integer"),
157-
body = '
158-
NumericVector xx(x);
159-
int ii = as<int>(i);
160-
xx = xx * ii;
161-
return( xx );
162-
', plugin="Rcpp")
163-
testfun(1:5, 3)
156+
## Note - this is R code.
157+
## cppFunction in Rcpp allows rapid testing.
158+
require(Rcpp)
159+
160+
cppFunction("
161+
NumericVector exfun(NumericVector x, int i){
162+
x = x*i;
163+
return x;
164+
}")
165+
166+
exfun(1:5, 3)
167+
168+
## Use evalCpp to evaluate C++ expressions
169+
evalCpp("std::numeric_limits<double>::max()")
164170
@
165171
166172
\paragraph{Interface with R}~
@@ -222,95 +228,74 @@ double s2 = std::inner_product(res.begin(),
222228
res.end(), res.begin(), 0.0);
223229
@
224230

225-
\paragraph{Function}~
231+
\paragraph{Rcpp Attributes}~
226232
\newline
227233
<<lang=cpp>>=
228-
Function rnorm("rnorm");
229-
rnorm(100, _["mean"] = 10.2, _["sd"] = 3.2 );
230-
@
234+
// Add code below into C++ file Rcpp_example.cpp
231235
232-
\paragraph{Environment}~
233-
\newline
234-
<<lang=cpp>>=
235-
Environment stats("package:stats");
236-
Environment env( 2 ); // by position
236+
#include <Rcpp.h>
237+
using namespace Rcpp;
237238
238-
// special environments
239-
Environment::Rcpp_namespace();
240-
Environment::base_env();
241-
Environment::base_namespace();
242-
Environment::global_env();
243-
Environment::empty_env();
239+
// Place the export tag right above function declaration.
240+
241+
// [[Rcpp::export]]
242+
double muRcpp(NumericVector x){
243+
int n = x.size(); // Size of vector
244+
double sum = 0; // Sum value
245+
246+
// For loop, note cpp index shift to 0
247+
for(int i = 0; i < n; i++){
248+
// Shorthand for sum = sum + x[i]
249+
sum += x[i];
250+
}
251+
252+
return sum/n; // Obtain and return the Mean
253+
}
244254
245-
Function rnorm = stats["rnorm"];
246-
glob["x"] = "foo";
247-
glob["y"] = 3;
248-
std::string x = glob["x"];
255+
// Place dependent functions above call or
256+
// declare the function definition with:
257+
double muRcpp(NumericVector x);
258+
259+
// [[Rcpp::export]]
260+
double varRcpp(NumericVector x, bool bias = true){
261+
// Calculate the mean using C++ function
262+
double mean = muRcpp(x);
263+
double sum = 0;
264+
int n = x.size();
265+
266+
for(int i = 0; i < n; i++){
267+
sum += pow(x[i] - mean, 2.0); // Square
268+
}
269+
270+
return sum/(n-bias); // Return variance
271+
}
249272
250-
glob.assign( "foo" , 3 );
251-
int foo = glob.get( "foo" );
252-
int foo = glob.find( "foo" );
253-
CharacterVector names = glob.ls()
254-
bool b = glob.exists( "foo" );
255-
glob.remove( "foo" );
273+
## In R:
274+
require(Rcpp)
275+
sourceCpp("path/to/file/Rcpp_example.cpp")
276+
x = 1:5;
277+
all.equal(muRcpp(x), mean(x)); all.equal(var(x),varRcpp(x))
278+
## TRUE
279+
@
256280

257-
glob.lockBinding("foo");
258-
glob.unlockBinding("foo");
259-
bool b = glob.bindingIsLocked("foo");
260-
bool b = glob.bindingIsActive("foo");
261281

262-
Environment e = stats.parent();
263-
Environment e = glob.new_child();
264-
@
265282

266-
\paragraph{Modules}~
283+
\paragraph{Rcpp Extensions}~
267284
\newline
268285
<<lang=cpp>>=
269-
// Warning -- At present, module-based objects do not persist across quit(save="yes")/reload cycles. To be safe, save results to R objects and remove module objects before exiting R.
286+
// Enable C++11
287+
// [[Rcpp::plugins(cpp11)]]
270288
271-
// To create a module-containing package from R, use:
272-
Rcpp.package.skeleton("mypackage",module=TRUE)
273-
// You will need to edit the RcppModules: line of the DESCRIPTION file to match your module name (in this example, from yada to mod_bar).
289+
// Enable OpenMP (excludes macOS)
290+
// [[Rcpp::plugins(openmp)]]
274291
275-
class Bar {
276-
public:
277-
Bar(double x_) :
278-
x(x_), nread(0), nwrite(0) {}
279-
280-
double get_x( ) {
281-
nread++; return x;
282-
}
283-
284-
void set_x( double x_) {
285-
nwrite++; x = x_;
286-
}
287-
288-
IntegerVector stats() const {
289-
return IntegerVector::create(
290-
_["read"] = nread,
291-
_["write"] = nwrite);
292-
}
293-
private:
294-
double x; int nread, nwrite;
295-
};
296-
297-
RCPP_MODULE(mod_bar) {
298-
class_<Bar>( "Bar" )
299-
.constructor<double>()
300-
.property( "x", &Bar::get_x, &Bar::set_x,
301-
"Docstring for x" )
302-
.method( "stats", &Bar::stats,
303-
"Docstring for stats")
304-
;}
305-
306-
## The following is R code.
307-
require(mypackage); show(Bar)
308-
b <- new(Bar, 10); b$x <- 10
309-
b_persist <- list(stats=b$stats(), x=b$x)
310-
rm(b)
292+
// Use the RcppArmadillo package
293+
// Requires different header file from Rcpp.h
294+
#include <RcppArmadillo.h>
295+
// [[Rcpp::depends(RcppArmadillo)]]
311296
@
312297

313-
\newpage
298+
314299

315300
\paragraph{Rcpp sugar}~
316301
\newline
@@ -386,4 +371,121 @@ double zz = Rf_rnorm(0, 2);
386371
387372
388373
374+
\newpage
375+
376+
\paragraph{Environment}~
377+
\newline
378+
<<lang=cpp>>=
379+
// Obtain an R environment
380+
Environment stats("package:stats");
381+
Environment env( 2 ); // by position
382+
383+
// Special environments
384+
Environment::Rcpp_namespace();
385+
Environment::base_env();
386+
Environment::base_namespace();
387+
Environment::global_env();
388+
Environment::empty_env();
389+
390+
// Extract function from specific
391+
// environment
392+
Function rnorm = stats["rnorm"];
393+
394+
// Assign into the environment
395+
glob["x"] = "foo";
396+
glob["y"] = 3;
397+
398+
// Retrieve information from environment
399+
std::string x = glob["x"];
400+
glob.assign( "foo" , 3 );
401+
int foo = glob.get( "foo" );
402+
int foo = glob.find( "foo" );
403+
CharacterVector names = glob.ls()
404+
bool b = glob.exists( "foo" );
405+
glob.remove( "foo" );
406+
407+
// Administration
408+
glob.lockBinding("foo");
409+
glob.unlockBinding("foo");
410+
bool b = glob.bindingIsLocked("foo");
411+
bool b = glob.bindingIsActive("foo");
412+
413+
// Retrieve related environments
414+
Environment e = stats.parent();
415+
Environment e = glob.new_child();
416+
@
417+
418+
\paragraph{Calling Functions in R}~
419+
\newline
420+
<<lang=cpp>>=
421+
// Do NOT expect to have a performance gain
422+
// when calling R functions from R!
423+
424+
// Retrieve functions from default loaded environment
425+
Function rnorm("rnorm");
426+
rnorm(100, _["mean"] = 10.2, _["sd"] = 3.2 );
427+
428+
// Passing in an R function and obtaining results
429+
// Make sure the function conforms with return type!
430+
NumericVector callFunction(NumericVector x,
431+
Function f) {
432+
NumericVector res = f(x);
433+
return res;
434+
}
435+
436+
## In R:
437+
x = 1:5
438+
callFunction(x, sum)
439+
@
440+
441+
\newpage
442+
443+
\paragraph{Modules}~
444+
\newline
445+
<<lang=cpp>>=
446+
// Warning -- At present, module-based objects do not persist across quit(save="yes")/reload cycles. To be safe, save results to R objects and remove module objects before exiting R.
447+
448+
// To create a module-containing package from R, use:
449+
Rcpp.package.skeleton("mypackage",module=TRUE)
450+
// You will need to edit the RcppModules: line of the DESCRIPTION file to match your module name (in this example, from yada to mod_bar).
451+
452+
class Bar {
453+
public:
454+
Bar(double x_) :
455+
x(x_), nread(0), nwrite(0) {}
456+
457+
double get_x( ) {
458+
nread++; return x;
459+
}
460+
461+
void set_x( double x_) {
462+
nwrite++; x = x_;
463+
}
464+
465+
IntegerVector stats() const {
466+
return IntegerVector::create(
467+
_["read"] = nread,
468+
_["write"] = nwrite);
469+
}
470+
private:
471+
double x; int nread, nwrite;
472+
};
473+
474+
RCPP_MODULE(mod_bar) {
475+
class_<Bar>( "Bar" )
476+
.constructor<double>()
477+
.property( "x", &Bar::get_x, &Bar::set_x,
478+
"Docstring for x" )
479+
.method( "stats", &Bar::stats,
480+
"Docstring for stats")
481+
;}
482+
483+
## The following is R code.
484+
require(mypackage); show(Bar)
485+
b <- new(Bar, 10); b$x <- 10
486+
b_persist <- list(stats=b$stats(), x=b$x)
487+
rm(b)
488+
@
489+
490+
389491
\end{document}

0 commit comments

Comments
 (0)