From:	CSBVAX::MRGATE!RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP 18-AUG-1988 20:09
To:	ARISIA::EVERHART
Subj:	Random number generator


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Thu, 18 AUG 88 15:23:49 PDT
Received: from circus.llnl.gov by KL.SRI.COM with TCP; Thu, 18 Aug 88 15:24:07 PDT
Date: Thu, 18 Aug 88 15:17 PDT
From: "Vladimir Ivanovic, x3-7786" <IVANOVIC%VAXR@circus.llnl.gov>
Subject: Random number generator
To: info-vax@kl.sri.COM
X-VMS-To: INFO-VAX,IVANOVIC

PROGRAM Uniform_Driver (input, output);

{ *************************************************************************** }
{                                                                             }
{ Uniform_Driver is a program that demonstrates the use of the function       }
{ Uniform, a portable random number generator for 32-bit computers.           }
{                                                                             }
{ This program may be freely distributed for commercial use or otherwise.     }
{ Many thanks to THINK Technologies for their marvelous Lightspeed Pascal     }
{ development environment.                                                    }
{                                                                             }
{ Vladimir G. Ivanovic                                                        }
{ Lawrence Livermore National Laboratory                                      }
{ P.O. Box 808, L-445                                                         }
{ Livermore, CA 94550                                                         }
{ (415) 423-7786                                                              }
{ CompuServe: 75176,2321                                                      }
{ ARPAnet: ivanovic%vaxr@circus.llnl.gov                                      }
{                                                                             }
{ *************************************************************************** }

    VAR
        Seed_1, Seed_2 : longint; { signed 32-bit integers }

        i : integer;


    FUNCTION Uniform (VAR Seed_1, Seed_2 : longint) : real;

{ *************************************************************************** }
{                                                                             }
{ Uniform is a portable random number generator for 32-bit computers that     }
{ implements an efficient way to combine two Multiplicative Linear            }
{ Congruential Generators (MLCGs) so that (1) it satisfies stringent          }
{ theoretical criteria for the quality of the sequence it produces            }
{ and (2) is easy to implement in a portable way, i.e. it produces the same   }
{ results on any machine with sufficient word length.                         }
{                                                                             }
{ This version works for computers which can represent all integers in the    }
{ range [ -2**31 + 85, 2**31 - 85 ].  Another version for 16-bit computers    }
{ is given in [1].                                                            }
{                                                                             }
{ L'Ecuyer reports in [1] that a comprehensive battery of 21 different tests  }
{ were performed on the generators that involved billions of psuedo-random    }
{ numbers and over 200 hours of VAX-11/780 CPU time.  The empirical behavior  }
{ of the generators is highly satisfactory.                                   }
{                                                                             }
{ Much additional material is given in [1] and in the references cited in [1].}
{                                                                             }
{ Portions copyright 1988 by the Association for Computing Machinery, Inc.    }
{ Permission to copy without fee all or part of this material is granted      }
{ provided that the copies are not made or distributed for direct commercial  }
{ advantage, the ACM copyright notice and the title of the publication and    }
{ its date appear, and notice is given that copying is by permission of the   }
{ Association for Computing Machinery.                                        }
{                                                                             }
{ 1. L'Ecuyer, Pierre, Efficient and Portable Combined Random Number          }
{   Generators. Communications of the ACM, 31, 6 (June 1988), 742-749, 774    }
{                                                                             }
{ *************************************************************************** }

        VAR
            z, k : longint;

    BEGIN

        k := Seed_1 DIV 53668;
        Seed_1 := 40014 * (Seed_1 - k * 53668) - k * 12211;
        IF Seed_1 < 0 THEN
            Seed_1 := Seed_1 + 2147483563;

        k := Seed_2 DIV 52774;
        Seed_2 := 40692 * (Seed_2 - k * 52774) - k * 3791;
        IF Seed_2 < 0 THEN
            Seed_2 := Seed_2 + 2147483399;

        z := Seed_1 - Seed_2;

        IF z < 1 THEN
            z := z + 2147483562;

        Uniform := z * 4.65661E-10;

    END;


    PROCEDURE Create_Text_Window;
{ Create_Text_Window is not needed for environments which have a default       }
{ output device.  In Lightspeed Pascal, one must make sure that the window     }
{ is visible.                                                                  }
    VAR
            WindRect : Rect;
    BEGIN
        WindRect.top := 40;
        WindRect.left := 100;
        WindRect.bottom := 300;
        WindRect.right := 412;
        SetTextRect(WindRect);
        ShowText;
    END;


    PROCEDURE Initialize_Seeds (VAR Seed_1, Seed_2 : longint);

{ This version of Initialize_Seeds is Macintosh dependent.  The theoretical   }
{ requirement is that Seed_1 be in the range [1, 2_147_483_562] and Seed_2    }
{ be in [1, 2_147_483_398] ( [ -2**31 + 85, 2**31 - 85 ]). Here, Seed_1 and   }
{ Seed_2 are in [0, 32_737].  See reference [1] cited in the comments of      }
{ Uniform for more information on generating seeds.                           }

    BEGIN
        GetDateTime(randSeed);
        Seed_1 := abs(Random);
        Seed_2 := abs(Random);
    END;


BEGIN

    Initialize_Seeds(Seed_1, Seed_2);
    Create_Text_Window;

    writeln('20 random numbers in the range [0,1]:');

    FOR i := 1 TO 20 DO
        writeln(Uniform(Seed_1, Seed_2) : 25 : 19);

    write('Press RETURN to exit. ');
    readln;

END.

