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;
  }
}
Beispiel #2
0
unsigned long librandom::BinomialRandomDev::uldev(RngPtr rng) const
{
    assert(rng.valid());
    
    // BP algorithm (steps numbered as in Fishman 1979)
    // Steps 1-7 are in init_()
    unsigned long X;
    double V;
    long Y;
    
    bool not_finished = 1;
    while (not_finished)
        {
        //8,9
        X = n_+1;
        while( X > n_)
            {
            X = poisson_dev_.uldev(rng);
            }
        
        //10
        V = exp_dev_(rng);
        
        //11
        Y = n_ - X;
        
        //12
        if ( V < static_cast<double>(m_-Y)*phi_ - f_[m_+1] + f_[Y+1] )
            {
            not_finished = 1;
            }
        else
            {
            not_finished = 0;
            }        
        }
    if (p_ <= 0.5)
        {
        return X;
        }
    else
        {
        return static_cast<unsigned long>(Y);
        }
}
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 );
}
long
librandom::PoissonRandomDev::ldev( RngPtr r ) const
{

  // make sure we have an RNG
  assert( r.valid() );

  // the result for lambda == 0 is well defined,
  // added the following two lines of code
  // Diesmann, 26.7.2002
  if ( mu_ == 0.0 )
    return 0;

  unsigned long K = 0; // candidate

  if ( mu_ < 10.0 )
  {
    // Case B in Ahrens & Dieter: table lookup

    double U = ( *r )();

    K = 0; // be defensive
    while ( U > P_[ K ] && K != n_tab_ )
      ++K;

    return K; // maximum value: K == n_tab_ == 46
  }
  else
  {
    // Case A in Ahrens & Dieter

    // Step N ******************************************************

    // draw normal random number
    /* Ratio method (Kinderman-Monahan); see Knuth v2, 3rd ed, p130 */
    /* K+M, ACM Trans Math Software 3 (1977) 257-260. */

    double U, V, T;

    do
    {
      V = ( *r )();
      do
      {
        U = ( *r )();
      } while ( U == 0 );
      /* Const 1.715... = sqrt(8/e) */
      T = 1.71552776992141359295 * ( V - 0.5 ) / U;
    } while ( T * T > -4.0 * std::log( U ) );

    /* maximum for T at this point:

       T*T <= -4 ln U ~ -4 * ln 1e-308 ~ 2837

       => |T| < 54
    */
    double G = mu_ + s_ * T;

    if ( G >= 0 )
    {

      K = static_cast< unsigned long >( std::floor( G ) );

      // Step I ******************************************************
      // immediate acceptance
      if ( K >= L_ )
      {
        return K;
      }

      // Step S ******************************************************
      // squeeze acceptance
      U = ( *r )();
      if ( d_ * U >= std::pow( mu_ - K, 3 ) )
      {
        return K;
      }

      // Step P : see init ******************************************

      // Step Q ****************************************************
      double px, py, fx, fy;
      proc_f_( K, px, py, fx, fy );
      // re-use U from step S, okay since we only apply tighter
      // squeeze criterium
      if ( fy * ( 1 - U ) <= py * std::exp( px - fx ) )
      {
        return K;
      }

      // fall through to E
    }

    // Step E ******************************************************
    double critH;
    do
    {

      double E;

      do
      {
        U = ( *r )();
        E = -std::log( ( *r )() );

        U = U + U - 1;
        T = U >= 0 ? 1.8 + E : 1.8 - E;
      } while ( T <= -0.6744 );

      /* maximum for T at this point:

         0 < E < - ln 1e-308 ~ 709

         => |T| < 710
      */

      // Step H ******************************************************
      K = static_cast< unsigned long >( std::floor( mu_ + s_ * T ) );
      double px, py, fx, fy;
      proc_f_( K, px, py, fx, fy );

      critH = py * std::exp( px + E ) - fy * std::exp( fx + E );

    } while ( c_ * std::abs( U ) > critH );

    return K;

  } // mu < 10
}