Generating Stable Distributions

The following are some C-code fragments you may find useful in generating values from stable distributions. These all make use of a routine called "randomfl()", which should be a small-space random number generator which returns a double distributed uniformly in the range 0.0 to 1.0. Use your favourite random number generator for this function. The following routines are useful depending on whether you want to compute the L1 distance, L2, Lp for arbitrary p between 0 and 2, or "L0" (Lp with p close to zero).

Code written by Graham Cormode except where otherwise acknowledged. This is made freely available for all to use, but please notify me if you find it of use, I would like to know where it is being used. Email graham a dimacs.rutgers.edu.
Processing Massive Data Sets home page

Cauchy distribution, p-stable with p=1

long double cauchy() {

  // return a value from the cauchy distribution
  // this is distributed Cauchy(1,0)

  return(tan(PI*(randomfl() - 0.5)));
}

Gaussian Distribution, p-stable with p=2

long double gasdev() {

  // Pick random values distributed N(0,1) using the Box-Muller transform
  // Taken from Numerical Recipes in C 
  // picks two at a time, returns one per call (buffers the other)

  static int iset=0;
  static long double gset;
  long double fac,rsq,v1,v2;
  if (iset == 0) {
    do {
      v1 = 2.0*randomfl()-1.0;
      v2 = 2.0*randomfl()-1.0;
      rsq=v1*v1+v2*v2;
    } while (rsq >= 1.0 || rsq == 0.0);
    
    fac = sqrt((long double) -2.0*log((long double)rsq)/rsq);
    gset=v1*fac;
    iset=1;
    return v2*fac;
  }
  else {
    iset = 0;
    return gset;
  }
}

Stable distributions for arbitrary p

Call this with parameter p to generate values from a p-stable distribution.
double stabledevd(float alpha) {

  // we set beta = 0 by analogy with the normal and cauchy case
  // in order to get symmetric stable distributions. 

  double theta, W, holder, left, right;

  theta=PI*(randomfl() - 0.5);
  W = -log(randomfl()); // takes natural log

  // if beta == 0 then c(alpha,beta)=1; theta_0 = 0
  // expression reduces to sin alpha.theta / (cos theta) ^1/alpha
  //  * (cos (theta - alpha theta)/W) ^(1-alpha)/alpha

  left = (sin(alpha*theta)/pow(cos(theta), 1.0/alpha));
  right= pow(cos(theta*(1.0 - alpha))/W, ((1.0-alpha)/alpha));
  holder=left*right;
  return(holder);
}

Faster code for p close to zero

The following code replaces the stable distribution with a distribution that is in the domain of attraction of a stable distribution with parameter alpha. Thanks to John Nolan for suggesting this approach and some helpful comments. See "Comparing Data Streams Using Hamming Norms" in IEEE Transactions on Knowledge and Data Engineering, 2003.
double altstab(double alpha) 
{
  double u,v,result;
  
  u=randomfl();
  v=randomfl();
  result=pow(u,-1.0/alpha);
  if (v<0.5) result=-result;
  
  return(result);
}
(Commercial use prohibited without author's permission)