Upcoming changes in dqrng


Ralf Stubner


April 23, 2024

The next version of dqrng is going to include many changes, so it might make sense to start blogging about them before the actual release. This release will be version 0.4.0 since there are several braking changes. It also sees several new contributors. At the moment, I am in contact with various authors of packages that depend on dqrng and who’s tests are failing due to the breaking changes. They will have to upload new versions of their packages before I can submit dqrng.

Breaking changes

  • The default RNG has changed from Xoroshiro128+ to Xoroshiro128++. The older generators Xoroshiro128+ and Xoshiro256+ are still available but should only be used for backward compatibility or for generating floating point numbers, i.e. not sampling etc. More details about this change plus some (inconclusive) benchmarks can be found in a previous post (#57 fixing #56).

  • One of the new features is the ability to access the global RNG directly. This requires passing a pointer to the calling program, which is done via an “external pointer” wrapped as Rcpp::XPtr. It therefore made sense to change the dqrng::rng64_t type used for storing the RNG internally to also use Rcpp::XPtr instead of std::shared_ptr. The functions from dqrng_sample.h now expect a reference to dqrng::random_64bit_generator instead of dqrng::rng64_t (#70 fixing #63).

  • The two argument constructor and seed function from PCG has surprising properties: it is not identical to the one argument version followed by set_stream(stream). For consistency with the new clone(stream) method, the two argument versions are no longer used. This influences code that uses multiple streams with PCG together with the tooling from this package, e.g. the example code in the vignette on parallel RNG usage. In addition, setting the stream on PCG64 via dqset.seed(seed, stream) or at the C++ level using the interface provided by dqrng will be relative to the current stream, i.e. setting stream=0 will not change the RNG. This is for consistency with the other provided RNGs. You still get the standard behavior if you are using the C++ classes for PCG directly.

Other changes

  • Decoupled the ‘sitmo’ package. It is now possible to use, e.g., the distribution functions from the header-only library without having an explicit LinkingTo: sitmo.

  • Make the internal RNG accessible from the outside had been a plan for quite some time, since this should simplify the development of new functionality using the C++ interface. I am grateful to Henrik Sloot for implementing this feature together with the class dqrng::random_64bit_accessor. This class supports UniformRandomBitGenerator and can therefore be used together with any C++11 distribtion function. In addition, the methods from the abstract parent class random_64bit_generator are inherited (fixing #41 in #58).

  • As discussed in a previous post, Xoroshiro128**/++ and Xoshiro256**/++ have been added to xoshiro.h

  • In another post I had allready discussed how uniform and normal distributions can be registered as user-supplied RNG within R. This happens automatically if the option dqrng.register_methods is set to TRUE. With this change one can make use of all distribution functions available for R together with the faster RNGs from this package. While the additional function calls do cost a bit of performance compared with native distribution functions, one can still see a nice performance boost from the change of RNG.

  • Add missing inline attributes and limit the included Rcpp headers in dqrng_types.h (#75 together with Paul Liétar)

  • Sometimes it is useful to record the internal state of the RNG. In base R, one can use .Random.seed, but so far this was not possible with dqrng. To circumvent this, I/O methods for the RNG’s internal state have been added. These use character vectors, since the internal states are unsigned 64bit and 128bit numbers, which cannot be safely represented in R. (fixing #66 in #78)

  • The abstract call random_64bit_generator has been extended with additional convenience methods. Most examples in the vignettes are now making use of these methods (fixing #64 in #79):

    • A clone(stream) method to ease parallel computation, e.g. using the global RNG.
    • New methods variate<dist>(param), generate<dist>(container, param) etc. using and inspired by randutils.
  • The scalar functions dqrng::runif, dqrng::rnorm and dqrng::rexp available from dqrng.h have been deprecated and will be removed in a future release. Please use the more flexible and faster dqrng::random_64bit_accessor together with variate<Dist>() instead. The same applies to dqrng::uniform01 from dqrng_distribution.h, which can be replaced by the member function dqrng::random_64bit_generator::uniform01.

  • A good discussion with Philippe Grosjean lead to a new template function dqrng::extra::parallel_generate in dqrng_extra/parallel_generate.h as an example for using the global RNG in a parallel context (fixing #77 in #82). In addition, this function also shows how one can use parallel random numbers but get results that are independent of the amount of parallelism used.