-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow registering as user-supplied RNG (#67)
* Change RNG initialization The actual RNG is only seeded in init() instead of (re)created. This allows for calling dqset.seed(NULL) w/o resetting the RNG to the default type. * Register RNG as user-defined if option dqrng.register_methods is set The RNG gets initialized by R via user_unif_init() making it unnecessary to call dqset_seed(NULL). * Unscramble the seed from R This way set.seed(<num>) and dqset.seed(<num>) give the same result. It is the task of the RNG to initialize its state in a sensible manner. * Save and restore previous state of RNGkid * New methods register_methods() and restore_methods() for registering the RNG
- Loading branch information
Showing
15 changed files
with
338 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
state <- new.env(parent = emptyenv()) | ||
state$RNGkind <- rep.int("default", 3) | ||
|
||
#' @title Registering as user-supplied RNG | ||
#' | ||
#' @description The random-number generators (RNG) from this package can be | ||
#' registered as user-supplied RNG. This way all \code{r<dist>} functions make | ||
#' use of the provided fast RNGs. | ||
#' | ||
#' @param kind Which methods should be registered? Either \code{"both"} or \code{"rng"}. | ||
#' | ||
#' @return Invisibly returns a three-element character vector of the RNG, normal | ||
#' and sample kinds \emph{before} the call. | ||
#' | ||
#' @details Caveats: | ||
#' \itemize{ | ||
#' \item While \code{runif} and \code{dqrunif} as well as \code{rnorm} and | ||
#' \code{dqrnorm} will produce the same results, this is not the case for | ||
#' \code{rexp} and \code{dqrexp}. | ||
#' \item The \code{dqr<dist>} functions are still faster than \code{r<dist>} | ||
#' when many random numbers are generated. | ||
#' \item You can use only the RNG from this package using | ||
#' \code{register_method("rng")} or both the RNG and the Ziggurat method | ||
#' for normal draws with \code{register_method("both")}. The latter | ||
#' approach is used by default. Using only the Ziggurat method will give | ||
#' \emph{undefined} behavior and is not supported! | ||
#' \item Calling \code{dqset.seed(NULL)} re-initializes the RNG from R's RNG. | ||
#' This no longer makes sense when the RNG has been registered as user-supplied | ||
#' RNG. In that case \code{set.seed{NULL}} needs to be used. | ||
#' \item With R's in-build RNGs one can get access to the internal state using | ||
#' \code{.Random.seed}. This is not possible here, since the internal state | ||
#' is a private member of the used C++ classes. | ||
#' } | ||
#' | ||
#' You can automatically register these methods when loading this package by | ||
#' setting the option \code{dqrng.register_methods} to \code{TRUE}, e.g. | ||
#' with \code{options(dqrng.register_methods=TRUE)}. | ||
#' | ||
#' Notes on seeding: | ||
#' \itemize{ | ||
#' \item When a user-supplied RNG is registered, it is also seeded from the | ||
#' previously used RNG. You will therefore get reproducible (but different) | ||
#' whether you call \code{set.seed()} before or after \code{register_methods()}. | ||
#' \item When called with a single integer as argument, both \code{set.seed()} | ||
#' and \code{dqset.seed()} have the same effect. However, \code{dqset.seed()} | ||
#' allows you to call it with two integers thereby supplying 64 bits of | ||
#' initial state instead of just 32 bits. | ||
#' } | ||
#' @seealso \code{\link{RNGkind}} and \code{\link{Random.user}} | ||
#' | ||
#' @examples | ||
#' register_methods() | ||
#' # set.seed and dqset.seed influence both (dq)runif and (dq)rnorm | ||
#' set.seed(4711); runif(5) | ||
#' set.seed(4711); dqrunif(5) | ||
#' dqset.seed(4711); rnorm(5) | ||
#' dqset.seed(4711); dqrnorm(5) | ||
#' # similarly for other r<dist> functions | ||
#' set.seed(4711); rt(5, 10) | ||
#' dqset.seed(4711); rt(5, 10) | ||
#' # but (dq)rexp give different results | ||
#' set.seed(4711); rexp(5, 10) | ||
#' set.seed(4711); dqrexp(5, 10) | ||
#' restore_methods() | ||
|
||
#' @rdname user-supplied-rng | ||
#' @export | ||
register_methods <- function(kind = c("both", "rng")) { | ||
kind <- match.arg(kind) | ||
switch(kind, | ||
both = state$RNGkind <- RNGkind("user", "user"), | ||
rng = state$RNGkind <- RNGkind("user")) | ||
} | ||
|
||
#' @rdname user-supplied-rng | ||
#' @export | ||
restore_methods <- function() { | ||
RNGkind(state$RNGkind[1], state$RNGkind[2], state$RNGkind[3]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,16 @@ | ||
.onLoad <- function(libname, pkgname) { | ||
if (!exists(".Random.seed", mode="numeric", envir=globalenv())) | ||
set.seed(NULL) | ||
original_seed <- get(".Random.seed", mode="numeric", envir=globalenv()) | ||
on.exit(assign(".Random.seed", original_seed, envir=globalenv())) | ||
dqset_seed(seed = NULL, stream = NULL) | ||
if (getOption("dqrng.register_methods", FALSE)) | ||
register_methods() | ||
else { | ||
if (!exists(".Random.seed", mode="numeric", envir=globalenv())) | ||
set.seed(NULL) | ||
original_seed <- get(".Random.seed", mode="numeric", envir=globalenv()) | ||
on.exit(assign(".Random.seed", original_seed, envir=globalenv())) | ||
dqset_seed(seed = NULL, stream = NULL) | ||
} | ||
} | ||
|
||
.onUnload <- function(libpath) { | ||
if (getOption("dqrng.register_methods", FALSE)) | ||
restore_methods() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.