@@ -887,12 +887,16 @@ prep_fun_cpp <- function(fun_start, fun_end, model_lines) {
887887 }
888888 fun_body <- gsub(" // [[stan::function]]" , " // [[Rcpp::export]]\n " , fun_body , fixed = TRUE )
889889 fun_body <- gsub(" std::ostream\\ *\\ s*pstream__\\ s*=\\ s*nullptr" , " " , fun_body )
890- if (cmdstan_version() < " 2.35.0" ) {
891- fun_body <- gsub(" boost::ecuyer1988&\\ s*base_rng__" , " SEXP base_rng_ptr" , fun_body )
892- } else {
893- fun_body <- gsub(" stan::rng_t&\\ s*base_rng__" , " SEXP base_rng_ptr" , fun_body )
890+ if (grepl(" (stan::rng_t|boost::ecuyer1988)" , fun_body )) {
891+ if (cmdstan_version() < " 2.35.0" ) {
892+ fun_body <- gsub(" boost::ecuyer1988&\\ s*base_rng__" , " SEXP base_rng_ptr, SEXP seed" , fun_body )
893+ } else {
894+ fun_body <- gsub(" stan::rng_t&\\ s*base_rng__" , " SEXP base_rng_ptr, SEXP seed" , fun_body )
895+ }
896+ rng_seed <- " Rcpp::XPtr<stan::rng_t> base_rng(base_rng_ptr);base_rng->seed(Rcpp::as<int>(seed));"
897+ fun_body <- gsub(" return" , paste(rng_seed , " return" ), fun_body )
898+ fun_body <- gsub(" base_rng__," , " *(base_rng.get())," , fun_body , fixed = TRUE )
894899 }
895- fun_body <- gsub(" base_rng__," , " *(Rcpp::XPtr<stan::rng_t>(base_rng_ptr).get())," , fun_body , fixed = TRUE )
896900 fun_body <- gsub(" pstream__" , " &Rcpp::Rcout" , fun_body , fixed = TRUE )
897901 fun_body <- paste(fun_body , collapse = " \n " )
898902 gsub(pattern = " ,\\ s*)" , replacement = " )" , fun_body )
@@ -953,6 +957,9 @@ compile_functions <- function(env, verbose = FALSE, global = FALSE) {
953957 fundef <- get(fun , envir = fun_env )
954958 funargs <- formals(fundef )
955959 funargs $ base_rng_ptr <- env $ rng_ptr
960+ # To allow for exported RNG functions to respect the R 'set.seed()' call,
961+ # we need to derive a seed deterministically from the current RNG state
962+ funargs $ seed <- quote(sample.int(.Machine $ integer.max , 1 ))
956963 formals(fundef ) <- funargs
957964 assign(fun , fundef , envir = fun_env )
958965 }
0 commit comments