/*
 *  =================================================================
 *  The purposes of this computer program are to:
 *
 *     -- Generate a family of 1000 random numbers that are uniformly
 *        distributed within the interval [0,1].
 *     -- Scale the distribution so that the numbers range [10,30].
 *     -- Compute the average and standard deviation of the scaled
 *        distribution.
 *     -- Output histogram of random numbers.
 *
 *  Note : We use our own function "Random()" to generate uniformly
 *         distributed random numbers. This functions ONLY WORKS on
 *         computers having a 32-bit word architecture.
 *
 *  Copyright (C) 1998 by Mark Austin and David Chancogne.
 *                                                                     
 *  This software is provided "as is" without express or implied warranty.
 *  Permission is granted to use this software on any computer system,
 *  and to redistribute it freely, subject to the following restrictions:
 * 
 *  1. The authors are not responsible for the consequences of use of
 *     this software, even if they arise from defects in the software.
 *  2. The origin of this software must not be misrepresented, either
 *     by explicit claim or by omission.
 *  3. Altered versions must be plainly marked as such, and must not
 *     be misrepresented as being the original software.
 *  4. This notice is to remain intact.
 * 
 *  Written by : Mark Austin 
 *  =================================================================
 */

#include <stdio.h>
#include <math.h>

void   InitRandom( long int );
double Random();

enum { SampleSize = 1000, HistogramSize = 20 };

int main( void ) {
int iaHistogram [ HistogramSize ];
int iCount, iInterval;
float fRandomNo, fAverage, fVariance;
float fSum        = 0.0;
float fSumSquares = 0.0;

   /* [a] : Zero-out elements of histogram array */

   for(iCount = 0; iCount < HistogramSize; iCount = iCount + 1) 
       iaHistogram [ iCount ] = 0;

   /* [b] : Initialize Seed for Random Numbers */
 
   InitRandom((long) 12);

   /* [c] : Generate, scale, and catalogue random numbers */

   for(iCount = 1; iCount <= SampleSize; iCount = iCount + 1) {

      fRandomNo = 20*Random() + 10;
      fSum += fRandomNo;
      fSumSquares += fRandomNo*fRandomNo;

      iInterval = (int) floor( fRandomNo ) - 10;
      iaHistogram [ iInterval ] += 1;
   }

   /* [d] : Compute standard deviation and average of scaled */
   /*       random numbers                                   */

   fAverage  = fSum/SampleSize;
   fVariance = fSumSquares/SampleSize - fAverage*fAverage;

   printf("** Random No. -- Average            = %8.5f\n", fAverage );
   printf("**            -- Variance           = %8.5f\n", fVariance );
   printf("**            -- Standard Deviation = %8.5f\n",
          sqrt(fVariance) );

   /* [e] : Output histogram of random numbers */

   printf("\n");
   for(iCount = 10; iCount < 30; iCount = iCount + 1)
       printf(" %5.1f  %5d \n", (iCount + 0.5),
              iaHistogram[ iCount-10 ] );

}

/* 
 *  ========================================================
 *  Random() : Generate Uniformly Distributed Random Numbers
 *  ========================================================
 */ 

static unsigned long int uliSeed = 1;

void InitRandom( long int iMySeed ) {
     uliSeed = iMySeed;
}

double Random() {
long int liA = 16807;
long int liM = 2147483647;
long int liQ = 127773;
long int liR = 2836;
long int liTempSeed;

    liTempSeed = liA*( uliSeed%liQ ) - liR*( uliSeed/liQ );
    if( liTempSeed >= 0 )
        uliSeed = liTempSeed;
    else
        uliSeed = liTempSeed + liM;

    return( ((double) uliSeed)/liM );
}
