示例#1
0
double librandom::GammaRandomDev::operator()(RngPtr r) const
{
  assert(r.valid());  // make sure we have RNG
  
  // 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;
    }

}
示例#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);
        }
}
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
}