I see. I still think that logic can be pushed into Stan.
Let's get down to the implementation level, then. Here's RStan's function:
template <class Model, class RNG_t>
void run_markov_chain(stan::mcmc::base_mcmc* sampler_ptr,
const stan_args& args,
bool is_warmup,
mcmc_output<Model>& outputter,
stan::mcmc::sample& init_s,
Model& model,
std::vector<Rcpp::NumericVector>& chains,
int& iter_save_i,
const std::vector<size_t>& qoi_idx,
std::vector<double>& sum_pars,
double& sum_lp,
std::vector<Rcpp::NumericVector>& sampler_params,
std::vector<Rcpp::NumericVector>& iter_params,
std::string& adaptation_info,
RNG_t& base_rng) {
int start = 0;
int end = args.get_ctrl_sampling_warmup();
if (!is_warmup) {
start = end;
end = args.get_iter();
}
for (int m = start; m < end; ++m) {
stan::common::print_progress(m, 0, args.get_iter(),
args.get_ctrl_sampling_refresh(), is_warmup,
"\r", "", rstan::io::rcout);
R_CheckUserInterrupt();
init_s = sampler_ptr -> transition(init_s);
if (args.get_ctrl_sampling_save_warmup() && (((m - start) % args.get_ctrl_sampling_thin()) == 0)) {
outputter.output_sample_params(base_rng, init_s, sampler_ptr, model,
chains, is_warmup,
sampler_params, iter_params,
sum_pars, sum_lp, qoi_idx,
iter_save_i, &rstan::io::rcout);
iter_save_i++;
outputter.output_diagnostic_params(init_s, sampler_ptr);
}
}
}