//----------------------------------------------------------------------
 double PoissonBartPosteriorSampler::draw_mean(Bart::TreeNode *leaf) {
   const Bart::PoissonSufficientStatistics &suf(
       dynamic_cast<const Bart::PoissonSufficientStatistics &>(
           leaf->compute_suf()));
   double ivar = suf.sum_of_weights() + 1.0 / mean_prior_variance();
   double posterior_mean = suf.weighted_sum_of_residuals() / ivar;
   double posterior_sd = sqrt(1.0 / ivar);
   return rnorm_mt(rng(), posterior_mean, posterior_sd);
 }
 //----------------------------------------------------------------------
 double ProbitBartPosteriorSampler::draw_mean(Bart::TreeNode *leaf) {
   const Bart::ProbitSufficientStatistics &suf(
       dynamic_cast<const Bart::ProbitSufficientStatistics &>(
           leaf->compute_suf()));
   double prior_variance = mean_prior_variance();
   double ivar = suf.sample_size() + (1.0 / prior_variance);
   double posterior_mean = suf.sum() / ivar;
   double posterior_sd = sqrt(1.0 / ivar);
   return rnorm_mt(rng(), posterior_mean, posterior_sd);
 }
 //----------------------------------------------------------------------
 // Drawing the mean at a leaf node is like drawing the intercept in
 // a logistic regression model after the other linear effects have
 // been subtracted out.
 double LogitBartPosteriorSampler::draw_mean(Bart::TreeNode *leaf) {
   const Bart::LogitSufficientStatistics &suf(
       dynamic_cast<const Bart::LogitSufficientStatistics &>(
           leaf->compute_suf()));
   double prior_variance = mean_prior_variance();
   double ivar = (1.0 / prior_variance) + suf.sum_of_information();
   double posterior_mean = suf.information_weighted_residual_sum() / ivar;
   double posterior_sd = sqrt(1.0 / ivar);
   return rnorm_mt(rng(), posterior_mean, posterior_sd);
 }
 double GaussianBartPosteriorSampler::draw_mean(Bart::TreeNode *leaf) {
   double sigsq = model_->sigsq();
   const Bart::GaussianBartSufficientStatistics &suf(
       dynamic_cast<const Bart::GaussianBartSufficientStatistics &>(
           leaf->compute_suf()));
   double ivar = suf.n() / sigsq + 1.0 / mean_prior_variance();
   double mean = (suf.sum() / sigsq) / ivar;
   double sd = sqrt(1.0 / ivar);
   double value = rnorm_mt(rng(), mean, sd);
   return value;
 }
  //----------------------------------------------------------------------
  // Omits a factor of (2*pi)^{N/2} \exp{-.5 * (N - 1) * s^2 } from
  // the integrated likelihood.
  double ProbitBartPosteriorSampler::log_integrated_probit_likelihood(
      const Bart::ProbitSufficientStatistics &suf) const {
    double n = suf.sample_size();
    if (n <= 0) {
      return negative_infinity();
    }
    double ybar = suf.sum() / n;  // handle n == 0;
    double prior_variance = mean_prior_variance();

    double ivar = n + (1.0 / prior_variance);
    double posterior_variance = 1.0 / ivar;
    double posterior_mean = suf.sum() / ivar;
    double ans =  log(posterior_variance / prior_variance)
        - n * square(ybar)
        + square(posterior_mean) / posterior_variance;
    return .5 * ans;
  }
  //----------------------------------------------------------------------
  double PoissonBartPosteriorSampler::log_integrated_likelihood(
      const Bart::SufficientStatisticsBase &abstract_suf) const {
    const Bart::PoissonSufficientStatistics &suf(
        dynamic_cast<const Bart::PoissonSufficientStatistics &>(
            abstract_suf));
    double prior_variance = mean_prior_variance();
    double ivar = suf.sum_of_weights() + (1.0 / prior_variance);
    double posterior_mean = suf.weighted_sum_of_residuals() / ivar;
    double posterior_variance = 1.0 / ivar;

    // We omit facors in the integrated likelihood that will cancel in
    // the MH ratio for splitting nodes in the same tree.  The omitted
    // is the log of (2 * pi)^(-n/2) * \prod(w[i] ^.5)
    double ans =
        .5 * (log(posterior_variance / prior_variance)
              +(square(posterior_mean) / posterior_variance));
    return ans;
  }
  double GaussianBartPosteriorSampler::log_integrated_gaussian_likelihood(
      const Bart::GaussianBartSufficientStatistics &suf) const {
    double n = suf.n();
    if (n < 5) {
      return negative_infinity();
    }
    double prior_variance = mean_prior_variance();
    double sigsq = model_->sigsq();

    double ybar = suf.ybar();
    double sample_variance = suf.sample_var();

    double ivar = (n / sigsq) + (1.0 / prior_variance);
    double posterior_variance = 1.0 / ivar;
    double posterior_mean = (n * ybar / sigsq) / ivar;

    double ans = -n * (log_2_pi + log(sigsq)) +
                 log(posterior_variance / prior_variance) -
                 (n - 1) * sample_variance / sigsq - n * square(ybar) / sigsq +
                 square(posterior_mean) / posterior_variance;
    return .5 * ans;
  }
  // As documented above, this function returns the log integrated
  // likelihood, with the following factor omitted from the
  // likelihood.
  //
  // (2 * pi)^{-n/2} \prod_i w[i]^{1/2} exp(-.5 \sum_i w[i]y[i]^2)
  double LogitBartPosteriorSampler::log_integrated_logit_likelihood(
      const Bart::LogitSufficientStatistics &suf) const {
    double information = suf.sum_of_information();
    if (information <= 0) {
      // The node is empty.  Note that information can never be
      // negative.  The <= comparison is used because it is not safe
      // to ask information == 0 on a double.
      return 0;
    }
    double prior_variance = mean_prior_variance();
    double ivar = information + (1.0 / prior_variance);
    double posterior_variance = 1.0 / ivar;
    double posterior_mean = suf.information_weighted_sum() / ivar;

    // This function omits a factor of (2 * pi)^(-n/2) * \prod_i
    // w[i]^{-.5} from the integrated likelihood, because it will
    // cancel in the relevant MH acceptance ratios.
    double ans =  .5 * (
        log(posterior_variance / prior_variance)
        + (square(posterior_mean) / posterior_variance));
    return ans;
  }