double
librandom::GammaRandomDev::unscaled_gamma( RngPtr r ) const
{
  // algorithm depends on order a
  if ( a == 1 )
    return -std::log( r->drandpos() );
  else if ( a < 1 )
  {
    // Johnk's rejection algorithm, see [1], p. 418
    double X;
    double Y;
    double S;
    do
    {
      X = std::pow( r->drand(), ju );
      Y = std::pow( r->drand(), jv );
      S = X + Y;
    } while ( S > 1 );
    if ( X > 0 )
      return -std::log( r->drandpos() ) * X / S;
    else
      return 0;
  }
  else
  {
    // Best's rejection algorithm, see [1], p. 410
    bool accept = false;
    double X = 0.0;
    do
    {
      const double U = r->drand();
      if ( U == 0 || U == 1 )
        continue; // accept guaranteed false
      const double V = r->drand();
      const double W = U * ( 1 - U ); // != 0
      const double Y = std::sqrt( bc / W ) * ( U - 0.5 );
      X = bb + Y;
      if ( X > 0 )
      {
        const double Z = 64 * W * W * W * V * V;
        accept = Z <= 1 - 2 * Y * Y / X;
        if ( !accept )
          accept = std::log( Z ) <= 2 * ( bb * std::log( X / bb ) - Y );
      }
    } while ( !accept );

    return X;
  }
}
double librandom::NormalRandomDev::operator()( RngPtr r ) const
{
  // Box-Muller algorithm, see Knuth TAOCP, vol 2, 3rd ed, p 122
  // we waste one number
  double V1;
  double V2;
  double S;

  do
  {
    V1 = 2 * r->drand() - 1;
    V2 = 2 * r->drand() - 1;
    S = V1 * V1 + V2 * V2;
  } while ( S >= 1 );

  if ( S != 0 )
    S = V1 * std::sqrt( -2 * std::log( S ) / S );

  return mu_ + sigma_ * S;
}
double librandom::LognormalRandomDev::operator()( RngPtr r ) const
{
  // We could forward here to a NormalRandomDev, but that would
  // require keeping such an object. Given that the Box-Muller code
  // is short, we just duplicate it here.

  // Box-Muller algorithm, see Knuth TAOCP, vol 2, 3rd ed, p 122
  // we waste one number
  double V1;
  double V2;
  double S;

  do
  {
    V1 = 2 * r->drand() - 1;
    V2 = 2 * r->drand() - 1;
    S = V1 * V1 + V2 * V2;
  } while ( S >= 1 );

  if ( S != 0 )
    S = V1 * std::sqrt( -2 * std::log( S ) / S );

  return std::exp( mu_ + sigma_ * S );
}