568 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			568 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* RAND.C - Random number generation module. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Copyright (c) 1995-2012 by Radford M. Neal.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Permission is granted for anyone to copy, use, modify, and distribute
							 | 
						||
| 
								 | 
							
								 * these programs and accompanying documents for any purpose, provided
							 | 
						||
| 
								 | 
							
								 * this copyright notice is retained and prominently displayed, and note
							 | 
						||
| 
								 | 
							
								 * is made of any changes made to these programs.  These programs and
							 | 
						||
| 
								 | 
							
								 * documents are distributed without any warranty, express or implied.
							 | 
						||
| 
								 | 
							
								 * As the programs were written for research purposes only, they have not
							 | 
						||
| 
								 | 
							
								 * been tested to the degree that would be advisable in any important
							 | 
						||
| 
								 | 
							
								 * application.  All use of these programs is entirely at the user's own
							 | 
						||
| 
								 | 
							
								 * risk.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Random generation routines at the end of this file are taken from the
							 | 
						||
| 
								 | 
							
								   GNU C library, see the copyright notice there. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* NOTE:  See rand.html for documentation on these procedures. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <stdint.h>
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include <math.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "rand.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static long int this_nrand48 (unsigned short int [3]);
							 | 
						||
| 
								 | 
							
												       	     /* Local version of nrand48 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* This module uses the 'this_nrand48' pseudo-random number generator from the
							 | 
						||
| 
								 | 
							
								   GNU C library, included below, but renamed to 'this_nrand48'.  The
							 | 
						||
| 
								 | 
							
								   output of this generator is combined with a file of real random numbers.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Many of the methods used in this module may be found in the following
							 | 
						||
| 
								 | 
							
								   reference:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Devroye, L. (1986) Non-Uniform Random Variate Generation, 
							 | 
						||
| 
								 | 
							
								        New York: Springer-Verlag.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   The methods used here are not necessarily the fastest available.  They're
							 | 
						||
| 
								 | 
							
								   selected to be reasonably fast while also being easy to write.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* CONSTANT PI.  Defined here if not in <math.h>. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef M_PI
							 | 
						||
| 
								 | 
							
								#define M_PI 3.14159265358979323846
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* TABLES OF REAL RANDOM NUMBERS.  A file of 100000 real random numbers
							 | 
						||
| 
								 | 
							
								   (NOT pseudo-random) is used in conjunction with pseudo-random numbers
							 | 
						||
| 
								 | 
							
								   for extra insurance.  These are employed in the form of five tables
							 | 
						||
| 
								 | 
							
								   of 5000 32-bit integers.  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   The file must be located at the path given by RAND_FILE, which should
							 | 
						||
| 
								 | 
							
								   be defined on the "cc" command line. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Table_size 5000			/* Number of words in each table */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int rn[N_tables][Table_size];	/* Random number tables */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* STATE OF RANDOM NUMBER GENERATOR. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int initialized = 0;		/* Has module been initialized? */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static rand_state state0;		/* Default state structure */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static rand_state *state;		/* Pointer to current state */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* INITIALIZE MODULE.  Sets things up using the default state structure,
							 | 
						||
| 
								 | 
							
								   set as if rand_seed had been called with a seed of one. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void initialize (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int i, j, k, w;
							 | 
						||
| 
								 | 
							
								  char b;
							 | 
						||
| 
								 | 
							
								  FILE *f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!initialized)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    f = fopen(RAND_FILE,"rb");
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    if (f==NULL)
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"Can't open file of random numbers (%s)\n",RAND_FILE);
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (i = 0; i<N_tables; i++)
							 | 
						||
| 
								 | 
							
								    { for (j = 0; j<Table_size; j++)
							 | 
						||
| 
								 | 
							
								      { w = 0;
							 | 
						||
| 
								 | 
							
								        for (k = 0; k<4; k++)
							 | 
						||
| 
								 | 
							
								        { if (fread(&b,1,1,f)!=1)
							 | 
						||
| 
								 | 
							
								          { fprintf(stderr,"Error reading file of random numbers (%s)\n",
							 | 
						||
| 
								 | 
							
								                            RAND_FILE);
							 | 
						||
| 
								 | 
							
								            exit(1);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          w = (w<<8) | (b&0xff);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        rn[i][j] = w;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    state = &state0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    initialized = 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rand_seed(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* SET CURRENT STATE ACCORDING TO SEED. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rand_seed
							 | 
						||
| 
								 | 
							
								( int seed
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!initialized) initialize();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  state->seed = seed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  state->state48[0] = seed>>16;
							 | 
						||
| 
								 | 
							
								  state->state48[1] = seed&0xffff;
							 | 
						||
| 
								 | 
							
								  state->state48[2] = rn[0][(seed&0x7fffffff)%Table_size];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<N_tables; j++) 
							 | 
						||
| 
								 | 
							
								  { state->ptr[j] = seed%Table_size;
							 | 
						||
| 
								 | 
							
								    seed /= Table_size;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* SET STATE STRUCTURE TO USE. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rand_use_state
							 | 
						||
| 
								 | 
							
								( rand_state *st
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  if (!initialized) initialize();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  state = st;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* RETURN POINTER TO CURRENT STATE. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rand_state *rand_get_state (void)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  if (!initialized) initialize();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return state;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE RANDOM 31-BIT INTEGER.  Not really meant for use outside this
							 | 
						||
| 
								 | 
							
								   module. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rand_word(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int v;
							 | 
						||
| 
								 | 
							
								  int j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!initialized) initialize();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  v = this_nrand48(state->state48);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<N_tables; j++)
							 | 
						||
| 
								 | 
							
								  { v ^= rn[j][state->ptr[j]];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<N_tables && state->ptr[j]==Table_size-1; j++) 
							 | 
						||
| 
								 | 
							
								  { state->ptr[j] = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (j<N_tables) 
							 | 
						||
| 
								 | 
							
								  { state->ptr[j] += 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return v & 0x7fffffff;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE UNIFORMLY FROM [0,1). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_uniform (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (double)rand_word() / (1.0+(double)0x7fffffff);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE UNIFORMLY FORM (0,1). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_uniopen (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return (0.5+(double)rand_word()) / (1.0+(double)0x7fffffff);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE RANDOM INTEGER FROM 0, 1, ..., (n-1). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rand_int
							 | 
						||
| 
								 | 
							
								( int n
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  return (int) (n * rand_uniform());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE INTEGER FROM 0, 1, ..., (n-1), WITH GIVEN DISTRIBUTION. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rand_pickd
							 | 
						||
| 
								 | 
							
								( double *p,
							 | 
						||
| 
								 | 
							
								  int n
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  double t, r;
							 | 
						||
| 
								 | 
							
								  int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  t = 0;
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { if (p[i]<0) abort();
							 | 
						||
| 
								 | 
							
								    t += p[i];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (t<=0) abort();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  r = t * rand_uniform();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { r -= p[i];
							 | 
						||
| 
								 | 
							
								    if (r<0) return i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Return value with non-zero probability if we get here due to roundoff. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++) 
							 | 
						||
| 
								 | 
							
								  { if (p[i]>0) return i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  abort(); 
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* SAME PROCEDURE AS ABOVE, BUT WITH FLOAT ARGUMENT. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rand_pickf
							 | 
						||
| 
								 | 
							
								( float *p,
							 | 
						||
| 
								 | 
							
								  int n
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  double t, r;
							 | 
						||
| 
								 | 
							
								  int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  t = 0;
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { if (p[i]<=0) abort();
							 | 
						||
| 
								 | 
							
								    t += p[i];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (t<=0) abort();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  r = t * rand_uniform();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { r -= p[i];
							 | 
						||
| 
								 | 
							
								    if (r<0) return i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Return value with non-zero probability if we get here due to roundoff. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++) 
							 | 
						||
| 
								 | 
							
								  { if (p[i]>0) return i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  abort(); 
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GENERATE RANDOM PERMUTATION OF INTEGERS FROM 1 TO N. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rand_permutation
							 | 
						||
| 
								 | 
							
								( int *perm,		/* Place to store permutation */
							 | 
						||
| 
								 | 
							
								  int n			/* Number of integers to permute */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int i, j, t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++) 
							 | 
						||
| 
								 | 
							
								  { perm[i] = i+1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { t = perm[i];
							 | 
						||
| 
								 | 
							
								    j = i + rand_int(n-i);
							 | 
						||
| 
								 | 
							
								    perm[i] = perm[j];
							 | 
						||
| 
								 | 
							
								    perm[j] = t;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* POISSON GENERATOR.  The method used is simple, but not very fast.  See
							 | 
						||
| 
								 | 
							
								   Devroye, p. 503.  Very large means are done using Gaussian approximation. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int rand_poisson 
							 | 
						||
| 
								 | 
							
								( double lambda
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ int v;
							 | 
						||
| 
								 | 
							
								  if (lambda>10000)
							 | 
						||
| 
								 | 
							
								  { v = (int) (lambda + rand_gaussian()*sqrt(lambda) + 0.5);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  { v = 0;
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								    { lambda -= rand_exp();
							 | 
						||
| 
								 | 
							
								      if (lambda<=0) break;
							 | 
						||
| 
								 | 
							
								      v += 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return v;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GAUSSIAN GENERATOR.  Done by using the Box-Muller method, but only one
							 | 
						||
| 
								 | 
							
								   of the variates is retained (using both would require saving more state).
							 | 
						||
| 
								 | 
							
								   See Devroye, p. 235. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   As written, should never deliver exactly zero, which may sometimes be
							 | 
						||
| 
								 | 
							
								   helpful. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_gaussian (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  double a, b;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  a = rand_uniform();
							 | 
						||
| 
								 | 
							
								  b = rand_uniopen();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return cos(2.0*M_PI*a) * sqrt(-2.0*log(b));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* EXPONENTIAL GENERATOR.  See Devroye, p. 29.  Written so as to never
							 | 
						||
| 
								 | 
							
								   return exactly zero. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_exp (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return -log(rand_uniopen());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* LOGISTIC GENERATOR.  Just inverts the CDF. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_logistic (void)
							 | 
						||
| 
								 | 
							
								{ double u;
							 | 
						||
| 
								 | 
							
								  u = rand_uniopen();
							 | 
						||
| 
								 | 
							
								  return log(u/(1-u));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* CAUCHY GENERATOR.  See Devroye, p. 29. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_cauchy (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return tan (M_PI * (rand_uniopen()-0.5));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GAMMA GENERATOR.  Generates a positive real number, r, with density
							 | 
						||
| 
								 | 
							
								   proportional to r^(a-1) * exp(-r).  See Devroye, p. 410 and p. 420. 
							 | 
						||
| 
								 | 
							
								   Things are fiddled to avoid ever returning a value that is very near 
							 | 
						||
| 
								 | 
							
								   zero. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_gamma
							 | 
						||
| 
								 | 
							
								( double a
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  double b, c, X, Y, Z, U, V, W;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (a<0.00001)
							 | 
						||
| 
								 | 
							
								  { X = a;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  else if (a<=1) 
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    U = rand_uniopen();
							 | 
						||
| 
								 | 
							
								    X = rand_gamma(1+a) * pow(U,1/a);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  else if (a<1.00001)
							 | 
						||
| 
								 | 
							
								  { X = rand_exp();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    b = a-1;
							 | 
						||
| 
								 | 
							
								    c = 3*a - 0.75;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								    for (;;)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      U = rand_uniopen();
							 | 
						||
| 
								 | 
							
								      V = rand_uniopen();
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								      W = U*(1-U);
							 | 
						||
| 
								 | 
							
								      Y = sqrt(c/W) * (U-0.5);
							 | 
						||
| 
								 | 
							
								      X = b+Y;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								      if (X>=0)
							 | 
						||
| 
								 | 
							
								      { 
							 | 
						||
| 
								 | 
							
								        Z = 64*W*W*W*V*V;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								        if (Z <= 1 - 2*Y*Y/X || log(Z) <= 2 * (b*log(X/b) - Y)) break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return X<1e-30 && X<a ? (a<1e-30 ? a : 1e-30) : X;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* BETA GENERATOR. Generates a real number, r, in (0,1), with density
							 | 
						||
| 
								 | 
							
								   proportional to r^(a-1) * (1-r)^(b-1).  Things are fiddled to avoid
							 | 
						||
| 
								 | 
							
								   the end-points, and to make the procedure symmetric between a and b. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double rand_beta 
							 | 
						||
| 
								 | 
							
								( double a, 
							 | 
						||
| 
								 | 
							
								  double b
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  double x, y, r;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  do
							 | 
						||
| 
								 | 
							
								  { x = rand_gamma(a);
							 | 
						||
| 
								 | 
							
								    y = rand_gamma(b);
							 | 
						||
| 
								 | 
							
								    r = 1.0 + x/(x+y);
							 | 
						||
| 
								 | 
							
								    r = r - 1.0;
							 | 
						||
| 
								 | 
							
								  } while (r<=0.0 || r>=1.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return r;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ROUTINES FROM THE GNU C LIBRARY.  These were modified to extract 
							 | 
						||
| 
								 | 
							
								   only the routines used here, and to allow them to be included in 
							 | 
						||
| 
								 | 
							
								   this module without any possible name conflict with other modules.
							 | 
						||
| 
								 | 
							
								   Inclusion here ensures that these routines are always available, and 
							 | 
						||
| 
								 | 
							
								   operate in exactly the same way on all systems.  The routines as copied
							 | 
						||
| 
								 | 
							
								   below are still easily useable by other programs by simply inserting 
							 | 
						||
| 
								 | 
							
								   this source code into an appropriate source file.
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   The following is the copyright notice for these routines:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
							 | 
						||
| 
								 | 
							
								     This file is part of the GNU C Library.
							 | 
						||
| 
								 | 
							
								     Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								     The GNU C Library is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								     modify it under the terms of the GNU Lesser General Public
							 | 
						||
| 
								 | 
							
								     License as published by the Free Software Foundation; either
							 | 
						||
| 
								 | 
							
								     version 2.1 of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								     The GNU C Library is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								     but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
							 | 
						||
| 
								 | 
							
								     Lesser General Public License for more details.
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								     You should have received a copy of the GNU Lesser General Public
							 | 
						||
| 
								 | 
							
								     License along with the GNU C Library; if not, write to the Free
							 | 
						||
| 
								 | 
							
								     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
							 | 
						||
| 
								 | 
							
								     02111-1307 USA.  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   The GNU Lesser General Public License is included with these source
							 | 
						||
| 
								 | 
							
								   files in the file LGPL. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <errno.h>
							 | 
						||
| 
								 | 
							
								#include <limits.h>
							 | 
						||
| 
								 | 
							
								#include <sys/types.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct this_drand48_data
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    unsigned short int x[3];	/* Current state.  */
							 | 
						||
| 
								 | 
							
								    unsigned short int old_x[3]; /* Old state.  */
							 | 
						||
| 
								 | 
							
								    unsigned short int c;	/* Additive const. in congruential formula.  */
							 | 
						||
| 
								 | 
							
								    unsigned short int init;	/* Flag for initializing.  */
							 | 
						||
| 
								 | 
							
								    unsigned long long int a;	/* Factor in congruential formula.  */
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Global state for non-reentrant functions.  */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct this_drand48_data libc_this_drand48_data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int this_nrand48_r (unsigned short int xsubi[3],
							 | 
						||
| 
								 | 
							
								                      struct this_drand48_data *buffer,
							 | 
						||
| 
								 | 
							
								                      long int *result);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Internal function to compute next state of the generator.  */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int this_drand48_iterate (unsigned short int xsubi[3],
							 | 
						||
| 
								 | 
							
								                            struct this_drand48_data *buffer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static long int this_nrand48 (xsubi)
							 | 
						||
| 
								 | 
							
								     unsigned short int xsubi[3];
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  long int result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  (void) this_nrand48_r (xsubi, &libc_this_drand48_data, &result);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int this_nrand48_r (xsubi, buffer, result)
							 | 
						||
| 
								 | 
							
								     unsigned short int xsubi[3];
							 | 
						||
| 
								 | 
							
								     struct this_drand48_data *buffer;
							 | 
						||
| 
								 | 
							
								     long int *result;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /* Compute next state.  */
							 | 
						||
| 
								 | 
							
								  if (this_drand48_iterate (xsubi, buffer) < 0)
							 | 
						||
| 
								 | 
							
								    return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Store the result.  */
							 | 
						||
| 
								 | 
							
								  if (sizeof (unsigned short int) == 2)
							 | 
						||
| 
								 | 
							
								    *result = xsubi[2] << 15 | xsubi[1] >> 1;
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    *result = xsubi[2] >> 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int this_drand48_iterate (xsubi, buffer)
							 | 
						||
| 
								 | 
							
								     unsigned short int xsubi[3];
							 | 
						||
| 
								 | 
							
								     struct this_drand48_data *buffer;
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  uint64_t X;
							 | 
						||
| 
								 | 
							
								  uint64_t result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Initialize buffer, if not yet done.  */
							 | 
						||
| 
								 | 
							
								  if (!buffer->init)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      buffer->a = 0x5deece66dull;
							 | 
						||
| 
								 | 
							
								      buffer->c = 0xb;
							 | 
						||
| 
								 | 
							
								      buffer->init = 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Do the real work.  We choose a data type which contains at least
							 | 
						||
| 
								 | 
							
								     48 bits.  Because we compute the modulus it does not care how
							 | 
						||
| 
								 | 
							
								     many bits really are computed.  */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  result = X * buffer->a + buffer->c;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  xsubi[0] = result & 0xffff;
							 | 
						||
| 
								 | 
							
								  xsubi[1] = (result >> 16) & 0xffff;
							 | 
						||
| 
								 | 
							
								  xsubi[2] = (result >> 32) & 0xffff;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 |