package umontreal.iro.lecuyer.randvar;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.probdist.*;


/**
 * This class implements normal random variate generators using
 * the acceptance-complement ratio method. 
 * For all the methods, the code was taken from UNURAN.
 * 
 */
public class NormalACRGen extends NormalGen  {



   /**
    * Creates a normal random variate generator with mean mu
    *   and standard deviation sigma, using stream s.
    * 
    */
   public NormalACRGen (RandomStream s, double mu, double sigma)  {
      super (s, null);
      setParams (mu, sigma);
   }


   /**
    * Creates a standard normal random variate generator with mean
    *   0 and standard deviation 1, using stream s.
    * 
    */
   public NormalACRGen (RandomStream s)  {
      this (s, 0.0, 1.0);
   }


   /**
    * Creates a random variate generator for the normal distribution 
    *   dist and stream s.
    * 
    */
   public NormalACRGen (RandomStream s, NormalDist dist)  {
      super (s, dist);
      if (dist != null)
         setParams (dist.getMu(), dist.getSigma());
   }
 
  
   public double nextDouble() {
      return nextDouble (stream, mu, sigma);
   }

   public static double nextDouble (RandomStream s, double mu, double sigma) {
/* **************************************************************************** 
*       SAMPLING A RANDOM NUMBER FROM THE                            
*       STANDARD NORMAL DISTRIBUTION N(0,1).
*---------------------------------------------------------------------------
* GENERATION METHOD :  Acceptance-Complement Ratio 
*--------------------------------------------------------------------------- 
* REFERENCE : 
* - UNURAN (c) 2000  W. Hoermann & J. Leydold, Institut f. Statistik, WU Wien
*         
* -  W. Hoermann and G. Derflinger (1990):                       
*     The ACR Method for generating normal random variables,       
*     OR Spektrum 12 (1990), 181-185.                             
*****************************************************************************/ 
      final double  c1   = 1.448242853;
      final double  c2   = 3.307147487;
      final double  c3   = 1.46754004;
      final double  d1   = 1.036467755;
      final double  d2   = 5.295844968;
      final double  d3   = 3.631288474;
      final double  hm   = 0.483941449;
      final double  zm   = 0.107981933;
      final double  hp   = 4.132731354;
      final double  zp   = 18.52161694;
      final double  phln = 0.4515827053;
      final double  hm1  = 0.516058551;
      final double  hp1  = 3.132731354;
      final double  hzm  = 0.375959516;
      final double  hzmp = 0.591923442;
      final double  as   = 0.8853395638;
      final double  bs   = 0.2452635696;
      final double  cs   = 0.2770276848;
      final double  b    = 0.5029324303;
      final double  x0   = 0.4571828819;
      final double  ym   = 0.187308492;
      final double  ss   = 0.7270572718; 
      final double  t    = 0.03895759111;
    
      double X;
      double rn,x,y,z;
    
      do {
         y = s.nextDouble();
         if (y > hm1) { X = hp*y - hp1; break; }
         else if (y < zm) {  
           rn = zp*y - 1;
           X = (rn > 0) ? (1 + rn) : (-1 + rn);
           break;
         } 
         else if (y < hm) {  
           rn = s.nextDouble();
           rn = rn - 1 + rn;
           z = (rn > 0) ? 2 - rn : -2 - rn;
           if ((c1 - y)*(c3 + Math.abs (z)) < c2) { X = z; break; }
           else {  
             x = rn*rn;
             if ((y + d1)*(d3 + x) < d2) { X = rn; break; }
             else if (hzmp - y < Math.exp (-(z*z + phln)/2)) { X = z; break; }
             else if (y + hzm < Math.exp (-(x + phln)/2)) { X = rn; break; }
           }
        }
      
        while (true) {
           x = s.nextDouble();
           y = ym*s.nextDouble();
           z = x0 - ss*x - y;
           if (z > 0)  rn = 2 + y/x;
           else {
             x = 1 - x;
             y = ym - y;
             rn = -(2 + y/x);
           }
           if ((y - as + x)*(cs + x) + bs < 0) { X = rn; break; }
           else if (y < x + t)
              if (rn*rn < 4*(b - Math.log (x))) { X = rn; break; }
        }
      
      } while (false);
        
      return mu + sigma*X;

   }
   /**
    * Generates a variate from the normal distribution with
    *    parameters μ = mu and σ = sigma, using
    *    stream s.
    * 
    */

 } 

 

Ads help maintain this website.