267 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			267 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* RAND-TEST.C - Program to test random number generators. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* 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.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Usage:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     rand-test seed generator { parameters } / sample-size [ low high bins ]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Using the seed given, tests the random number generator identified by
							 | 
						||
| 
								 | 
							
								the second argument, for the parameter values specified.  The possible
							 | 
						||
| 
								 | 
							
								generators and required parameters are as follows:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    uniform                  Uniform from [0,1)
							 | 
						||
| 
								 | 
							
								    uniopen                  Uniform from (0,1)
							 | 
						||
| 
								 | 
							
								    int n                    Uniform from the set { 0, 1, ..., (n-1) }
							 | 
						||
| 
								 | 
							
								    gaussian                 From Gaussian with mean zero and unit variance
							 | 
						||
| 
								 | 
							
								    exp                      From exponential with mean one
							 | 
						||
| 
								 | 
							
								    cauchy                   From Cauchy centred at zero with unit width
							 | 
						||
| 
								 | 
							
								    gamma alpha              From Gamma with shape parameter (and mean) alpha
							 | 
						||
| 
								 | 
							
								    beta a b                 From Beta with parameters a and b
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The size of the sample to use is also specified.  The program reports
							 | 
						||
| 
								 | 
							
								the mean and variance of the sample.  A histogram is also printed if a
							 | 
						||
| 
								 | 
							
								low and high range and number of bins are for it are specified.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								These tests are not really adequate to detect subtle forms of bias due
							 | 
						||
| 
								 | 
							
								to use of pseudo-random numbers, but are hopefully good enough to find
							 | 
						||
| 
								 | 
							
								most programming errors. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include <math.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "rand.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define Max_bins 1000		/* Maximum number of histogram bins */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void usage (void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* MAIN PROGRAM. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								main
							 | 
						||
| 
								 | 
							
								( int argc,
							 | 
						||
| 
								 | 
							
								  char **argv
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int seed, sample_size, bins, np;
							 | 
						||
| 
								 | 
							
								  double low, high;
							 | 
						||
| 
								 | 
							
								  char *generator;
							 | 
						||
| 
								 | 
							
								  double p1, p2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  double mean, variance;
							 | 
						||
| 
								 | 
							
								  double tmean, tvariance;
							 | 
						||
| 
								 | 
							
								  int undef_mean, undef_variance;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int count[Max_bins];
							 | 
						||
| 
								 | 
							
								  int under, over;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  char **ap;
							 | 
						||
| 
								 | 
							
								  double x;
							 | 
						||
| 
								 | 
							
								  int i, n;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bins = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (argc<5) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ((seed = atoi(argv[1]))==0 && strcmp(argv[1],"0")!=0) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  generator = argv[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if      (strcmp(generator,"uniform")==0)  np = 0;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"uniopen")==0)  np = 0;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"int")==0)      np = 1;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"poisson")==0)  np = 1;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"gaussian")==0) np = 0;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"exp")==0)      np = 0;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"cauchy")==0)   np = 0;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"gamma")==0)    np = 1;
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"beta")==0)     np = 2;
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"Unknown generator: %s\n",generator);
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ap = argv+3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (np>0) 
							 | 
						||
| 
								 | 
							
								  { if (*ap==0 || (p1 = atof(*ap++))<=0) usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (np>1) 
							 | 
						||
| 
								 | 
							
								  { if (*ap==0 || (p2 = atof(*ap++))<=0) usage();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (*ap==0 || strcmp(*ap++,"/")!=0) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (*ap==0 || (sample_size = atoi(*ap++))<=0) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (*ap!=0)
							 | 
						||
| 
								 | 
							
								  { low = atof(*ap++);
							 | 
						||
| 
								 | 
							
								    if (*ap==0) usage();
							 | 
						||
| 
								 | 
							
								    high = atof(*ap++);
							 | 
						||
| 
								 | 
							
								    if (high<=low) usage();
							 | 
						||
| 
								 | 
							
								    if (*ap==0 || (bins = atoi(*ap++))<=0) usage();
							 | 
						||
| 
								 | 
							
								    if (bins>Max_bins) 
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"Too many histogram bins\n");
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (*ap!=0) usage();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  printf("\nTest of %s(",generator);
							 | 
						||
| 
								 | 
							
								  if (np>0) printf("%.4f",p1);
							 | 
						||
| 
								 | 
							
								  if (np>1) printf(",%.4f",p2);
							 | 
						||
| 
								 | 
							
								  printf(") generator using sample of size %d with seed %d\n\n",
							 | 
						||
| 
								 | 
							
								   sample_size, seed);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  undef_mean = undef_variance = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (strcmp(generator,"uniform")==0)  
							 | 
						||
| 
								 | 
							
								  { tmean = 0.5;
							 | 
						||
| 
								 | 
							
								    tvariance = 1.0/12.0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"uniopen")==0)  
							 | 
						||
| 
								 | 
							
								  { tmean = 0.5;
							 | 
						||
| 
								 | 
							
								    tvariance = 1.0/12.0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"int")==0)      
							 | 
						||
| 
								 | 
							
								  { tmean = (p1-1)/2;
							 | 
						||
| 
								 | 
							
								    tvariance = p1*p1/3.0 - p1/2.0 + 1/6.0 - tmean*tmean;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"poisson")==0) 
							 | 
						||
| 
								 | 
							
								  { tmean = p1;
							 | 
						||
| 
								 | 
							
								    tvariance = p1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"gaussian")==0) 
							 | 
						||
| 
								 | 
							
								  { tmean = 0;
							 | 
						||
| 
								 | 
							
								    tvariance = 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"exp")==0) 
							 | 
						||
| 
								 | 
							
								  { tmean = 1;
							 | 
						||
| 
								 | 
							
								    tvariance = 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"cauchy")==0)
							 | 
						||
| 
								 | 
							
								  { undef_mean = 1;
							 | 
						||
| 
								 | 
							
								    undef_variance = 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"gamma")==0)
							 | 
						||
| 
								 | 
							
								  { tmean = p1;
							 | 
						||
| 
								 | 
							
								    tvariance = p1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else if (strcmp(generator,"beta")==0)     
							 | 
						||
| 
								 | 
							
								  { tmean = p1 / (p1+p2);
							 | 
						||
| 
								 | 
							
								    tvariance = (p1*p2) / ((p1+p2)*(p1+p2)*(p1+p2+1));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else 
							 | 
						||
| 
								 | 
							
								  { abort();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mean = 0;
							 | 
						||
| 
								 | 
							
								  variance = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (bins>0)
							 | 
						||
| 
								 | 
							
								  { for (i = 0; i<bins; i++) count[i] = 0;
							 | 
						||
| 
								 | 
							
								    under = over = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rand_seed(seed);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (n = 0; n<sample_size; n++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if      (strcmp(generator,"uniform")==0)  x = rand_uniform();
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"uniopen")==0)  x = rand_uniopen();
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"int")==0)      x = rand_int((int)p1);
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"poisson")==0)  x = rand_poisson(p1);
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"gaussian")==0) x = rand_gaussian();
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"exp")==0)      x = rand_exp();
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"cauchy")==0)   x = rand_cauchy();
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"gamma")==0)    x = rand_gamma(p1);
							 | 
						||
| 
								 | 
							
								    else if (strcmp(generator,"beta")==0)     x = rand_beta(p1,p2);
							 | 
						||
| 
								 | 
							
								    else abort();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mean += x;
							 | 
						||
| 
								 | 
							
								    variance += x*x;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (bins>0)
							 | 
						||
| 
								 | 
							
								    { if (x<low) 
							 | 
						||
| 
								 | 
							
								      { under += 1;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								      { i = (int) ((x-low)/((high-low)/bins));
							 | 
						||
| 
								 | 
							
								        if (i>=bins) 
							 | 
						||
| 
								 | 
							
								        { over += 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else 
							 | 
						||
| 
								 | 
							
								        { count[i] += 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mean /= sample_size;
							 | 
						||
| 
								 | 
							
								  variance /= sample_size;
							 | 
						||
| 
								 | 
							
								  variance -= mean*mean;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  printf("Sample mean:     %.4f",mean);
							 | 
						||
| 
								 | 
							
								  if (undef_mean)
							 | 
						||
| 
								 | 
							
								  { printf(" (true value: undefined)\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  { printf(" (true value: %.4f)\n",tmean);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  printf("Sample variance: %.4f",variance);
							 | 
						||
| 
								 | 
							
								  if (undef_variance)
							 | 
						||
| 
								 | 
							
								  { printf(" (true value: undefined)\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								  { printf(" (true value: %.4f)\n",tvariance);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  printf("\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (bins!=0)
							 | 
						||
| 
								 | 
							
								  { printf("Histogram:\n");
							 | 
						||
| 
								 | 
							
								    printf("                    under : %8d  %.5f\n\n", 
							 | 
						||
| 
								 | 
							
								      under, (double)under / sample_size);
							 | 
						||
| 
								 | 
							
								    for (i = 0; i<bins; i++)
							 | 
						||
| 
								 | 
							
								    { printf("  %10.4f - %10.4f : %8d  %.5f\n", 
							 | 
						||
| 
								 | 
							
								        i*(high-low)/bins + low, (i+1)*(high-low)/bins + low, 
							 | 
						||
| 
								 | 
							
								        count[i], (double)count[i] / sample_size);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    printf("\n                     over : %8d  %.5f\n", 
							 | 
						||
| 
								 | 
							
								      over, (double)over / sample_size);
							 | 
						||
| 
								 | 
							
								    printf("\n");
							 | 
						||
| 
								 | 
							
								  }  
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  exit(0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* PRINT USAGE MESSAGE AND EXIT. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void usage (void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  fprintf(stderr,
							 | 
						||
| 
								 | 
							
								   "Usage: rand-test seed generator { parameters } / sample-size [ low high bins ]\n");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  exit(1);
							 | 
						||
| 
								 | 
							
								}
							 |