Skip to content

Commit df401f7

Browse files
authored
Merge pull request #532 from coatless/modernize-rcppgibbs
Modernize rcppgibbs
2 parents d360ba2 + f49ad0f commit df401f7

File tree

4 files changed

+165
-8
lines changed

4 files changed

+165
-8
lines changed

ChangeLog

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
2016-08-04 James J Balamuta <[email protected]>
22

33
* src/attributes.cpp: Correct variable re-declaration
4-
4+
* inst/examples/RcppGibbs/RcppGibbs.R: Updated example to use Rcpp
5+
attributes instead of cxxfunction
6+
* inst/examples/RcppGibbs/timeRNGs.R: Idem
7+
58
2016-08-03 Dirk Eddelbuettel <[email protected]>
69

710
* .gitattributes: Added to have ChangeLog and NEWS.Rd merge via union

inst/NEWS.Rd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
call the standalone Rmath library. (James Balamuta in \ghpr{514}
2828
addressing issue \ghit{28}).
2929
}
30+
\item Changes in Rcpp Examples:
31+
\itemize{
32+
\item Examples that used cxxfunction() from the inline package have been
33+
rewritten to use either sourceCpp() or cppFunction()
34+
(James Balamuta in \ghpr{532} addressing issue \ghit{56}).
35+
}
3036
}
3137
}
3238

inst/examples/RcppGibbs/RcppGibbs.R

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,12 @@ RCgibbs <- cmpfun(Rgibbs)
8383
## mat <- Rgibbs(10000,10); dim(mat)
8484
## would give: [1] 10000 2
8585

86-
8786
## Now for the Rcpp version -- Notice how easy it is to code up!
87+
88+
## NOTE: This is the old way to compile Rcpp code inline.
89+
## The code here has left as a historical artifact and tribute to the old way.
90+
## Please use the code under the "new" inline compilation section.
91+
8892
gibbscode <- '
8993
9094
using namespace Rcpp; // inline does that for us already
@@ -114,7 +118,7 @@ gibbscode <- '
114118
'
115119

116120
# Compile and Load
117-
RcppGibbs <- cxxfunction(signature(n="int", thin = "int"),
121+
RcppGibbs_old <- cxxfunction(signature(n="int", thin = "int"),
118122
gibbscode, plugin="Rcpp")
119123

120124

@@ -146,7 +150,7 @@ gslgibbscode <- '
146150
'
147151

148152
## Compile and Load
149-
GSLGibbs <- cxxfunction(signature(ns="int", thns = "int"),
153+
GSLGibbs_old <- cxxfunction(signature(ns="int", thns = "int"),
150154
body=gslgibbscode, includes=gslgibbsincl,
151155
plugin="RcppGSL")
152156

@@ -158,6 +162,69 @@ GSLGibbs <- cxxfunction(signature(ns="int", thns = "int"),
158162
# libargs="-lgsl -lgslcblas")
159163

160164

165+
## NOTE: Within this section, the new way to compile Rcpp code inline has been
166+
## written. Please use the code next as a template for your own project.
167+
168+
## Use of the cppFunction() gives the ability to immediately compile embed C++
169+
## without having to worry about header specification or Rcpp attributes.
170+
171+
cppFunction('
172+
NumericMatrix RcppGibbs(int N, int thn){
173+
// Note: n and thin are SEXPs which the Rcpp automatically converts to ints
174+
175+
// Setup storage matrix
176+
NumericMatrix mat(N, 2);
177+
178+
// The rest of the code follows the R version
179+
double x = 0, y = 0;
180+
181+
for (int i = 0; i < N; i++) {
182+
for (int j = 0; j < thn; j++) {
183+
x = R::rgamma(3.0,1.0/(y*y+4));
184+
y = R::rnorm(1.0/(x+1),1.0/sqrt(2*x+2));
185+
}
186+
mat(i,0) = x;
187+
mat(i,1) = y;
188+
}
189+
190+
return mat; // Return to R
191+
}')
192+
193+
194+
## Use of the sourceCpp() is preferred for users who wish to source external
195+
## files or specify their headers and Rcpp attributes within their code.
196+
## Code here is able to easily be extracted and placed into its own C++ file.
197+
198+
## Compile and Load
199+
sourceCpp(code="
200+
#include <RcppGSL.h>
201+
#include <gsl/gsl_rng.h>
202+
#include <gsl/gsl_randist.h>
203+
204+
using namespace Rcpp; // just to be explicit
205+
206+
// [[Rcpp::depends(RcppGSL)]]
207+
208+
// [[Rcpp::export]]
209+
NumericMatrix GSLGibbs(int N, int thin){
210+
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
211+
double x = 0, y = 0;
212+
NumericMatrix mat(N, 2);
213+
for (int i = 0; i < N; i++) {
214+
for (int j = 0; j < thin; j++) {
215+
x = gsl_ran_gamma(r,3.0,1.0/(y*y+4));
216+
y = 1.0/(x+1)+gsl_ran_gaussian(r,1.0/sqrt(2*x+2));
217+
}
218+
mat(i,0) = x;
219+
mat(i,1) = y;
220+
}
221+
gsl_rng_free(r);
222+
223+
return mat; // Return to R
224+
}")
225+
226+
227+
161228
## Now for some tests
162229
## You can try other values if you like
163230
## Note that the total number of interations are N*thin!

inst/examples/RcppGibbs/timeRNGs.R

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ suppressMessages(library(Rcpp))
33
suppressMessages(library(inline))
44
suppressMessages(library(rbenchmark))
55

6-
rcppGamma <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
6+
## NOTE: This is the old way to compile Rcpp code inline.
7+
## The code here has left as a historical artifact and tribute to the old way.
8+
## Please use the code under the "new" inline compilation section.
9+
10+
rcppGamma_old <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
711
NumericVector x(xs);
812
int n = x.size();
913
@@ -20,7 +24,7 @@ rcppGamma <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
2024
')
2125

2226

23-
gslGamma <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
27+
gslGamma_old <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
2428
include='#include <gsl/gsl_rng.h>
2529
#include <gsl/gsl_randist.h>',
2630
body='
@@ -39,7 +43,7 @@ gslGamma <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
3943
')
4044

4145

42-
rcppNormal <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
46+
rcppNormal_old <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
4347
NumericVector x(xs);
4448
int n = x.size();
4549
@@ -56,7 +60,7 @@ rcppNormal <- cxxfunction(signature(xs="numeric"), plugin="Rcpp", body='
5660
')
5761

5862

59-
gslNormal <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
63+
gslNormal_old <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
6064
include='#include <gsl/gsl_rng.h>
6165
#include <gsl/gsl_randist.h>',
6266
body='
@@ -75,6 +79,83 @@ gslNormal <- cxxfunction(signature(xs="numeric"), plugin="RcppGSL",
7579
')
7680

7781

82+
## NOTE: Within this section, the new way to compile Rcpp code inline has been
83+
## written. Please use the code next as a template for your own project.
84+
85+
cppFunction('
86+
NumericVector rcppGamma(NumericVector x){
87+
int n = x.size();
88+
89+
const double y = 1.234;
90+
for (int i=0; i<n; i++) {
91+
x[i] = R::rgamma(3.0, 1.0/(y*y+4));
92+
}
93+
94+
// Return to R
95+
return x;
96+
}')
97+
98+
## This approach is a bit sloppy. Generally, you will want to use
99+
## sourceCpp() if there are additional includes that are required.
100+
cppFunction('
101+
NumericVector gslGamma(NumericVector x){
102+
int n = x.size();
103+
104+
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
105+
const double y = 1.234;
106+
for (int i=0; i<n; i++) {
107+
x[i] = gsl_ran_gamma(r,3.0,1.0/(y*y+4));
108+
}
109+
gsl_rng_free(r);
110+
111+
// Return to R
112+
return x;
113+
}', includes = '#include <gsl/gsl_rng.h>
114+
#include <gsl/gsl_randist.h>',
115+
depends = "RcppGSL")
116+
117+
118+
cppFunction('
119+
NumericVector rcppNormal(NumericVector x){
120+
int n = x.size();
121+
122+
const double y = 1.234;
123+
for (int i=0; i<n; i++) {
124+
x[i] = R::rnorm(1.0/(y+1),1.0/sqrt(2*y+2));
125+
}
126+
127+
// Return to R
128+
return x;
129+
}')
130+
131+
132+
## Here we demonstrate the use of sourceCpp() to show the continuity
133+
## of the code artifact.
134+
135+
sourceCpp(code = '
136+
#include <RcppGSL.h>
137+
#include <gsl/gsl_rng.h>
138+
#include <gsl/gsl_randist.h>
139+
140+
using namespace Rcpp;
141+
142+
// [[Rcpp::depends("RcppGSL")]]
143+
144+
// [[Rcpp::export]]
145+
NumericVector gslNormal(NumericVector x){
146+
int n = x.size();
147+
148+
gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937);
149+
const double y = 1.234;
150+
for (int i=0; i<n; i++) {
151+
x[i] = 1.0/(y+1)+gsl_ran_gaussian(r,1.0/sqrt(2*y+2));
152+
}
153+
gsl_rng_free(r);
154+
155+
// Return to R
156+
return x;
157+
}')
158+
78159
x <- rep(NA, 1e6)
79160
res <- benchmark(rcppGamma(x),
80161
gslGamma(x),

0 commit comments

Comments
 (0)