;RANPACK.MAR Minimal Standard Pseudo-Random Number Generator ;> Extra additional hint: see Knuth, Donald E. "The Art of Computer ;> Programming: Volume 2 - Semi-Numerical Algorithms" on the subject. Damned ;> few pseudo random nubmer generators produce "good" sequences of random ;> numbers. As an example, the VAX C random number generator was criticized ;> here recently for alternately producing odd and even numbers. This was ;> explained as being "bug for bug" compatibility with Unix! ; ;Yep. The "standard" UNIX random number generator is worthless for anything ;but games. And I wouldn't even bet on that! ; ;> Another ;> generator has the interesting property that if successive "random" values ;> are plotted as points in 3D, they will fall in distinct planes. And so it ;> goes. ; ;The moral of the story is, if you need a real good one, use two fairly ;good generators (that hopefully use different techniques) and shuffle ;(the shuffling technique is described in Knuth) or hire a mathemetician! ; ;Here is an implementation in MACRO of a "Minimal Standard Pseudo-Random ;Number Generator" that was described in an article in the October 1988 ;issue of CACM. As I recall it was supposed to be better than your average ;maximal-length linear congruential generator (it is not a maximal-length ;generator, but generates a sequence that is nearly maximal length, and it ;is very fast as well). No warranties expressed or implied of course. HTH. .TITLE RANDPACK - Minimal Standard Pseudo-Random Number Generator .IDENT 'V00-000' ;++ ; FACILITY: ; ; VAX/VMS Minimal Standard Pseudo-Random Number Generator ; ; ABSTRACT: ; ; This package contains an efficient assembly-language implementation ; of the "minimal standard" random number generator similar to the ; one described in the article "Random: Number Generators: Good Ones ; are Hard to Find" by Stephen K. Park and Keith W. Miller, CACM ; vol. 31 no. 10 (Oct. 1988), pp 1192-1201. ; ; AUTHOR: ; ; 06-Feb-1989 James A. Harvey ; ; This program has been granted to the public domain by the author. ; ; Revision History: ; ; None (yet). ; ..SBTTL Symbolic Constants and Impure Data MODULUS=2147483647 ; The modulus, m. FMODULUS=^F2147483647.0 ; Ditto, as F-floating number. MINSEED=1 ; The minimum value for SEED. MAXSEED=2147483646 ; The maximum value for SEED. MULTIPLIER=16807 ; The multiplier, a. ..PSECT RWDATA,LONG,NOSHR,WRT ; Impure data. SEED: .LONG 1 ; The default seed. TIME: .BLKQ 1 ; For calls to RANDOMIZE(0) ..SBTTL RANDOMIZE - Initialize the Pseudo-Random Number Generator ;++ ; ; FUNCTIONAL DESCRIPTION: ; ; RANDOMIZE [seed] ; ; Initializes the pseudo-random number generator with the seed ; passed, if seed is in the range 1 to 2**31-2. If the seed ; argument is omitted or not in the valid range, the generator's ; seed is initialized based on the time of day as returned by the ; $GETTIM system service. ; ; CALLING SEQUENCE: ; ; Called with CALLS or CALLG to RANDOMIZE. The argument is ; optional. ; ; INPUT PARAMETERS: ; ; seed ; VMS Usage: longword_unsigned ; type: longword (unsigned) ; access: read only ; mechanism: by reference ; ; Seed is the initial seed for the random number generator. If ; the seed passed is not in the valid range of acceptable seeds ; (1 to 2**31-2) the generator's seed is initialized with a value ; based on the current system time as returned by the $GETTIM ; system service. ; ; RETURN VALUE: ; ; VMS Usage: longword_unsigned ; type: longword (unsigned) ; access: write only ; mechanism: by value ; ; RANDOMIZE returns the seed used to initialize the random number ; generator. This is always the same as the seed argument passed ; to RANDOMIZE if the argument was in the range 1 to 2**31-2. If ; the argument was omitted, or not in the required range, the ; returned value is the seed actually used to initialize the random ; number generator. ; ; SIDE EFFECTS: ; ; Updates SEED in impure data area. ; All registers except R0 and R1 are preserved. ; ..PSECT CODE,LONG,SHR,NOWRT NARGS=0 ; Offset to number of arguments. SEEDARG=4 ; Offset to optional seed argument. ..ENTRY RANDOMIZE,<0> TSTB NARGS(AP) ; Any argument? BEQLU 10$ ; No - randomize by time clock. MOVL SEEDARG(AP),R0 ; Move argument to R0. CMPL R0,#MINSEED ; Is argument less than 1? BLSS 10$ ; If so, it's out of range. CMPL R0,#MAXSEED ; Is argument greater than 2**31-2? BLEQ 30$ ; If not, use it. 10$: $GETTIM TIMADR=TIME ; Get the system time in TIME:TIME+7 MOVL TIME,R0 ; Get high order word in R0. XORL2 TIME+4,R0 ; Exclusive or in least sig. bits. BICL2 #^X80000000,R0 ; Clear the sign bit. CMPL R0,#MINSEED ; Is argument less than 1? BLSS 20$ ; If so, it's out of range, use 1. CMPL R0,#MAXSEED ; Is argument greater than 2**31-2? BLEQ 30$ ; If not, use it. 20$: MOVL #1,R0 ; Use 1 if $GETTIM result out of range. 30$: MOVL R0,SEED ; Store the initial seed. RET ; And return. ..SBTTL RANDOM - Return Next Pseudo-Random Uniform Variate on 0..1 ;++ ; ; FUNCTIONAL DESCRIPTION: ; ; RANDOM ; ; This routine returns an F_floating pseudo-random number uniformly ; distributed in the range 0..1. ; ; CALLING SEQUENCE: ; ; Called with CALLS or CALLG to RANDOM. No arguments are required. ; ; INPUT PARAMETERS: ; ; None. ; ; RETURNS: ; ; VMS Usage: floating_point ; type: F_floating ; access: write only ; mechanism: by value ; ; RANDOM routine returns an F_floating pseudo-random number uniformly ; distributed in the range 0..1. ; ; SIDE EFFECTS: ; ; Updates SEED in impure data area. ; All registers except R0 and R1 are preserved. ; ..PSECT CODE,LONG,SHR,NOWRT ..ENTRY RANDOM,<0> EMUL #MULTIPLIER,SEED,#0,R0 ; R0 = a * z EDIV #MODULUS,R0,SEED,SEED ; z = (a * z) mod m. CVTLF SEED,R0 ; R0 = float(z) DIVF2 #FMODULUS,R0 ; R0 = float(z) / float(m). RET ..ENTRY GETSEED,<0> MOVL SEED,R0 RET ..END