From 0e38823a128572ff333eab42567fad8d5664bd62 Mon Sep 17 00:00:00 2001 From: nathan-russell Date: Wed, 14 Dec 2016 11:58:58 -0500 Subject: [PATCH] Use vector for dynamic memory in sample --- ChangeLog | 11 ++- Rcpp.Rproj | 1 + inst/include/Rcpp/sugar/functions/sample.h | 82 +++++++--------------- 3 files changed, 36 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c628c9bd..1140315af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,13 @@ -2016-12-13 Nathan Russell +2016-12-14 Nathan Russell - * inst/include/Rcpp/sugar/functions/sample.h: Use malloc.h instead of + * inst/include/Rcpp/sugar/functions/sample.h: Use vector instead of + manual memory management. + +2016-12-13 Nathan Russell + + * inst/include/Rcpp/sugar/functions/sample.h: Use malloc.h instead of alloca.h when building on Windows - * inst/include/Rcpp/date_datetime/Date.h: Include time.h when building + * inst/include/Rcpp/date_datetime/Date.h: Include time.h when building on Windows * inst/include/Rcpp/date_datetime/Datetime.h: Idem diff --git a/Rcpp.Rproj b/Rcpp.Rproj index 4c1b672a3..8b300884d 100644 --- a/Rcpp.Rproj +++ b/Rcpp.Rproj @@ -13,6 +13,7 @@ RnwWeave: Sweave LaTeX: pdfLaTeX AutoAppendNewline: Yes +StripTrailingWhitespace: Yes BuildType: Package PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/inst/include/Rcpp/sugar/functions/sample.h b/inst/include/Rcpp/sugar/functions/sample.h index 63c6fb893..249640b04 100644 --- a/inst/include/Rcpp/sugar/functions/sample.h +++ b/inst/include/Rcpp/sugar/functions/sample.h @@ -26,14 +26,10 @@ #ifndef Rcpp__sugar__sample_h #define Rcpp__sugar__sample_h -#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__) -#include -#else -#include -#endif - -// In order to mirror the behavior of `base::sample` -// as closely as possible, this file contains adaptations +#include + +// In order to mirror the behavior of `base::sample` +// as closely as possible, this file contains adaptations // of several functions in R/src/main/random.c: // // * do_sample - general logic as well as the empirical sampling routine. @@ -43,12 +39,12 @@ // * walker_ProbSampleReplace, ProbSampleReplace, and ProbSampleNoReplace - // algorithms for sampling according to a supplied probability vector. // -// For each of the sampling routines, two signatures are provided: +// For each of the sampling routines, two signatures are provided: // -// * A version that returns an integer vector, which can be used to -// generate 0-based indices (one_based = false) or 1-based indices -// (one_based = true) -- where the latter corresponds to the -// bahavior of `base::sample.int`. +// * A version that returns an integer vector, which can be used to +// generate 0-based indices (one_based = false) or 1-based indices +// (one_based = true) -- where the latter corresponds to the +// bahavior of `base::sample.int`. // // * A version which takes an input Vector<> (rather than an integer 'n'), // and samples its elements -- this corresponds to `base::sample`. @@ -150,26 +146,19 @@ inline Vector SampleReplace(Vector& p, int k, const Vector WalkerSample(const Vector& p, int n, int nans, bool one_based) { Vector a = no_init(n), ans = no_init(nans); - double *q, rU; int i, j, k; - int *HL, *H, *L; + std::vector q(n); + double rU; - int adj = one_based ? 1 : 0; + std::vector HL(n); + std::vector::iterator H, L; - if (n <= SMALL) { - R_CheckStack2(n * (sizeof(int) + sizeof(double))); - HL = static_cast(::alloca(n * sizeof(int))); - q = static_cast(::alloca(n * sizeof(double))); - } else { - HL = static_cast(Calloc(n, int)); - q = static_cast(Calloc(n, double)); - } + int adj = one_based ? 1 : 0; - H = HL - 1; L = HL + n; + H = HL.begin() - 1; L = HL.begin() + n; for (i = 0; i < n; i++) { q[i] = p[i] * n; if (q[i] < 1.0) { @@ -179,7 +168,7 @@ inline Vector WalkerSample(const Vector& p, int n, int nans, bo } } - if (H >= HL && L < HL + n) { + if (H >= HL.begin() && L < HL.begin() + n) { for (k = 0; k < n - 1; k++) { i = HL[k]; j = *L; @@ -188,7 +177,7 @@ inline Vector WalkerSample(const Vector& p, int n, int nans, bo L += (q[j] < 1.0); - if (L >= HL + n) { + if (L >= HL.begin() + n) { break; } } @@ -204,11 +193,6 @@ inline Vector WalkerSample(const Vector& p, int n, int nans, bo ans[i] = (rU < q[k]) ? k + adj : a[k] + adj; } - if (n > SMALL) { - Free(HL); - Free(q); - } - return ans; } @@ -221,20 +205,14 @@ inline Vector WalkerSample(const Vector& p, int nans, const Vect Vector a = no_init(n); Vector ans = no_init(nans); - double *q, rU; int i, j, k; - int *HL, *H, *L; - - if (n <= SMALL) { - R_CheckStack2(n * (sizeof(int) + sizeof(double))); - HL = static_cast(::alloca(n * sizeof(int))); - q = static_cast(::alloca(n * sizeof(double))); - } else { - HL = static_cast(Calloc(n, int)); - q = static_cast(Calloc(n, double)); - } + std::vector q(n); + double rU; + + std::vector HL(n); + std::vector::iterator H, L; - H = HL - 1; L = HL + n; + H = HL.begin() - 1; L = HL.begin() + n; for (i = 0; i < n; i++) { q[i] = p[i] * n; if (q[i] < 1.0) { @@ -244,7 +222,7 @@ inline Vector WalkerSample(const Vector& p, int nans, const Vect } } - if (H >= HL && L < HL + n) { + if (H >= HL.begin() && L < HL.begin() + n) { for (k = 0; k < n - 1; k++) { i = HL[k]; j = *L; @@ -253,7 +231,7 @@ inline Vector WalkerSample(const Vector& p, int nans, const Vect L += (q[j] < 1.0); - if (L >= HL + n) { + if (L >= HL.begin() + n) { break; } } @@ -269,14 +247,8 @@ inline Vector WalkerSample(const Vector& p, int nans, const Vect ans[i] = (rU < q[k]) ? ref[k] : ref[a[k]]; } - if (n > SMALL) { - Free(HL); - Free(q); - } - return ans; } -#undef SMALL // Adapted from `ProbSampleNoReplace` // Index version @@ -425,7 +397,7 @@ typedef Nullable< Vector > probs_t; } // sugar // Adapted from `do_sample` -inline Vector +inline Vector sample(int n, int size, bool replace = false, sugar::probs_t probs = R_NilValue, bool one_based = true) { if (probs.isNotNull()) { @@ -461,7 +433,7 @@ sample(int n, int size, bool replace = false, sugar::probs_t probs = R_NilValue, } template -inline Vector +inline Vector sample(const Vector& x, int size, bool replace = false, sugar::probs_t probs = R_NilValue) { int n = x.size();