// Find the upper and lower limits of a slice containing x for a
 // potentially multimodal distribution.  Uses Neal's (2003 Annals of
 // Statistics) doubling algorithm.
 bool SSS::find_limits_unbounded(double x){
   hi_ = x + suggested_dx_;
   lo_ = x - suggested_dx_;
   logphi_ = logf_(hi_);
   logplo_ = logf_(lo_);
   if(unimodal_){
     find_limits_unbounded_unimodal(x);
     return true;
   }else{
     int doubling_count = 0;
     while(!done_doubling()){
       double u = runif_mt(rng(), -1, 1);
       if(u>0) double_hi(x);
       else double_lo(x);
       if (++doubling_count > 100) {
         // The slice has been doubled 100 times.  This is almost
         // certainly beecause of an error in the target distribution
         // or a crazy starting value.
         return false;
       }
     }
   }
   check_upper_limit(x);
   check_lower_limit(x);
   return true;
 }
 // Driver function to find the limits of a slice containing 'x'.
 // Logic varies according to whether the distribution is bounded
 // above, below, both, or neither.
 void SSS::find_limits(double x){
   logp_slice_ = logf_(x) - rexp_mt(rng(), 1.0);
   check_finite(x,logp_slice_);
   bool limits_successfully_found = true;
   if(doubly_bounded()){
     lo_ = lower_bound_;
     logplo_ = logf_(lo_);
     hi_ = upper_bound_;
     logphi_ = logf_(hi_);
   }else if (lower_bounded()){
     lo_ = lower_bound_;
     logplo_ = logf_(lo_);
     limits_successfully_found = find_upper_limit(x);
   }else if(upper_bounded()){
     limits_successfully_found = find_lower_limit(x);
     hi_ = upper_bound_;
     logphi_ = logf_(hi_);
   }else{ // unbounded
     limits_successfully_found = find_limits_unbounded(x);
   }
   check_slice(x);
   if (limits_successfully_found) {
     check_probs(x);
   }
 }
  // Find the upper and lower limits of a slice when the target
  // distribution is known to be unimodal.
  void SSS::find_limits_unbounded_unimodal(double x){
    hi_ = x + suggested_dx_;
    logphi_ = logf_(hi_);
    while(logphi_ >= logp_slice_) double_hi(x);
    check_upper_limit(x);

    lo_ = x - suggested_dx_;
    logplo_ = logf_(lo_);
    while(logplo_ >= logp_slice_) double_lo(x);
    check_lower_limit(x);
  }
 // Makes the upper end of the slice twice as far away from x, and
 // updates the density value
 void SSS::double_hi(double x){
   double dx = hi_ - x;
   hi_ = x + 2 * dx;
   if(!std::isfinite(hi_)){
     handle_error("infinite upper limit", x);
   }
   logphi_ = logf_(hi_);
 }
 bool SSS::find_lower_limit(double x){
   lo_ = x - suggested_dx_;
   logplo_ = logf_(lo_);
   int doubling_count = 0;
   while(logplo_ >= logp_slice_ || (!unimodal_ && runif_mt(rng()) > .5)){
     double_lo(x);
     if (++doubling_count > 100) {
       // The slice has been doubled over 100 times.  This is almost
       // certainly because of an error in the implementation of the
       // target distribution, or a crazy starting value.
       return false;
     }
   }
   check_lower_limit(x);
   return true;
 }
 double SSS::draw(double x){
   find_limits(x);
   double logp_cand = 0;
   int number_of_tries = 0;
   do{
     double x_cand = runif_mt(rng(), lo_, hi_);
     logp_cand = logf_(x_cand);
     if(logp_cand < logp_slice_){
       contract(x,x_cand, logp_cand);
       ++number_of_tries;
     } else return x_cand;
     if(number_of_tries > 100){
       ostringstream err;
       err << "number of tries exceeded.  candidate value is "
           << x_cand << " with logp_cand = " << logp_cand << endl;
       handle_error(err.str(), x);
     }
   }while(logp_cand < logp_slice_);
   handle_error("should never get here", x);
   return 0;
 }
 double SSS::logp(double x)const{ return logf_(x);}
 // Makes the lower end of the slice twice as far away from x, and
 // updates the density value
 void SSS::double_lo(double x){
   double dx = x - lo_;
   lo_  = x-2*dx;
   if(!std::isfinite(lo_)) handle_error("infinite lower limit", x);
   logplo_ = logf_(lo_);
 }
 virtual double operator()(double u, double &g, double &h)const{
   double ans = logf_(u,g,h) + s_ * u;
   g += s_;  // derivative is with respect to u
   return ans;
 }
 virtual double operator()(double u)const{
   return logf_(u) + s_ * u; }
 double DBARS::f(double x)const{return logf_(x);}