diff --git a/NEWS.md b/NEWS.md index e0d62e2..911384f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,13 @@ # dqrng (unreleased) * Add R side support for selecting multiple streams for parallel usage. -* Implement `long_jump()` for Xo(ro)shiro as alternative to `jump()` providing fewer streams with longer period. +* Implement `long_jump()` for Xo(ro)shiro as alternative to `jump()` + providing fewer streams with longer period. * Handle R's RNG scope properly during initialisation. -* New functions `dqsample` and `dqsample.int` using an unbiased sampling algorithm +* New functions `dqsample` and `dqsample.int` using an unbiased sampling + algorithm. +* Use `R_unif_index()` instead of `unif_rand()` to retrieve random data + from R's RNG in `generateSeedVectors()`. # dqrng 0.1.1 @@ -15,7 +19,7 @@ ## Breaking changes * An integer vector instead of a single `int` is used for seeding (Aaron Lun in [#10](https://github.com/daqana/dqrng/pull/10)) - * Single integer seeds lead to a different RNG state than before. + * Single integer seeds lead to a different RNG state than before. * `dqrng::dqset_seed()` expects a `Rcpp::IntegerVector` instead of an `int` * Support for Mersenne-Twister has been removed, Xoroshiro128+ is now the default. diff --git a/inst/include/R_randgen.h b/inst/include/R_randgen.h index 63f60c2..039361d 100644 --- a/inst/include/R_randgen.h +++ b/inst/include/R_randgen.h @@ -5,14 +5,17 @@ namespace dqrng { -/* Create a uint32_t or int seed using R's PRNGs. - * The uint32_t seed is more convnient from use within C++, +/* Create a uint32_t or int seed using R's PRNGs. + * The uint32_t seed is more convenient from use within C++, * the int seed is more convenient if it needs to be passed back to R. + * Since R's PRNG is used, calling one of these functions has to be shielded + * with calls to GetRNGState and PutRNGState, e.g. by using Rcpp::RNGScope. + * This is done automatically when using the Rcpp::export attribute. */ inline uint32_t R_random_u32 () { constexpr double upper_limit=4294967296; - double val=R::unif_rand() * upper_limit; + double val = R_unif_index(upper_limit); if (val >= upper_limit) { val=0; } // Absolutely avoid overflow. return static_cast(val); } @@ -20,10 +23,10 @@ inline uint32_t R_random_u32 () { inline int R_random_int () { const uint32_t sampled=R_random_u32(); constexpr uint32_t max_int=2147483647; // See .Machine$integer.max. - if (sampled <= max_int) { + if (sampled <= max_int) { return static_cast(sampled); } - + // Effectively reverse of the int->uint32_t cast. constexpr uint32_t max_uint=-1; return -static_cast(max_uint - sampled) - 1;