v087mxgb@ubvmsa.cc.buffalo.edu (Shawn E Thompson) (10/18/90)
Anyone need an excellent random number generator???? In my graduate studies, I am writing an optimization program based on the relatively unexploited 'Genetic Algorithms' technique for the University of Buffalo. In my wanderings (and beggings), I was given a terrific random number generator, by ......um......oh......shoot - I forget (I will make sure he gets credit, but the name escapes me right now). Anyway I will pass it along (he said its ok), if anyone needs it. Again it is terriffic. It operates as follows; First a subroutine is called to initialize it, which requests 2 user seeds between 0 & 32000 (an enormity of seed combos!). Then it is called as a mere function every time you need a random number (between 0 & 1 but scalable) Apparently (again, I forget exactly) but I think it is capable of generating 10E6 random numbers from each pair of seeds!!!! Up for grabs.... Shawn Thompson V087MXGB@UBVMS.CC.BUFFALO.EDU (Grad School of Mechanical Engineering) Leica, Inc. PO Box 123 Buffalo, NY 14240-0123 (716) 891-3375
v087mxgb@ubvmsa.cc.buffalo.edu (Shawn E Thompson) (10/19/90)
************************************************************************** ************************************************************************** I lost part of the text header that accompanied this, when I received it, so here are some vitals (it came with no instructions, so those and the comments are mine); I received this from STUART@ADS.COM, and feel you should drop THAT person a note of thanks from yourself and me. Stuart's original, that he sent me said that this originally appeared in "Toward a Universal Random Number Generator" by George Marsaglia and Arif Zaman. Florida State University Report: FSU-SCRI-87-50 (1987). It was later modified by F. James and published in "A Review of Pseudo-random Number Generators" The highest recognition is due to these authors, who made this available. Stuart says this is the BEST KNOWN RANDOM NUMBER GENERATOR available. It passes all tests for a random number generator, and has a period of 2^144, and will give bit-identical results on all machines with at least 24-bit manitissas in the floating point representation. I have run it on a machine that I believe has a 16 bit mantissa in the floating point, and it was NOT identical results. But it still functioned perfectly for my applications! The algorithm is a combination of Fibonacci sequence (with lags of 97 and 33, and operation "subtraction plus one, modulo one") and an "arithmetic sequence" (using subtraction. There are three routines contained herein. I have separated them and the notes with double lines of asterisks (just delete all between them and the lines of asterisks). The first program, called TstRAN is a test for correct operation. The second part, RANMAR, is the function itself, which must be included in any program where you wish to call it from. The third part is the initialization routine, which asks for the number seeds. The first would actually be replaced by YOUR application (note the way the function is called, for anyone not familiar). The value returned by the RANMAR function is fully scalable (I use it between 0 & 100 % by saying x=100*RANMAR() Now, RMARIN and RANMAR share initialization variables in a common block, so they can be separated between subroutines, etc (again, for anyone unfamiliar, I call RMARIN as a subroutine from my main, and then include RANMAR as a function in some of my subroutines where I need to generate random numbers). ************************************************************************** ************************************************************************** PROGRAM TstRAN INTEGER IJ, KL, I C These are the seeds needed to produce the test case results IJ = 1802 KL = 9373 C Do the initialization call rmarin(ij,kl) C Generate 20000 random numbers do 10 I = 1, 20000 x = RANMAR() 10 continue C If the random number generator is working properly, the next six random C numbers should be: C 6533892.0 14220222.0 7275067.0 C 6172232.0 8354498.0 10633180.0 write(*,20) (4096.0*4096.0*RANMAR(), I=1,6) 20 format (3f12.1) end ************************************************************************** ************************************************************************** subroutine RMARIN(IJ,KL) C This is the initialization routine for the random number generator C RANMAR() C NOTE: The seed variables can have values between: 0 <= IJ <= 31328 C 0 <= KL <= 30081 real U(97), C, CD, CM integer I97, J97 logical TEST common /raset1/ U, C, CD, CM, I97, J97, TEST DATA TEST /.FALSE./ if( IJ .lt. 0 .or. IJ .gt. 31328 .or. * KL .lt. 0 .or. KL .gt. 30081 ) then print '(A)', ' The first random number seed must have a value *between 0 and 31328' print '(A)',' The second seed must have a value between 0 and *30081' stop endif i = mod(IJ/177, 177) + 2 j = mod(IJ , 177) + 2 k = mod(KL/169, 178) + 1 l = mod(KL, 169) do 2 ii = 1, 97 s = 0.0 t = 0.5 do 3 jj = 1, 24 m = mod(mod(i*j, 179)*k, 179) i = j j = k k = m l = mod(53*l+1, 169) if (mod(l*m, 64) .ge. 32) then s = s + t endif t = 0.5 * t 3 continue U(ii) = s 2 continue C = 362436.0 / 16777216.0 CD = 7654321.0 / 16777216.0 CM = 16777213.0 /16777216.0 I97 = 97 J97 = 33 TEST = .TRUE. return end ************************************************************************** ************************************************************************** function ranmar() real U(97), C, CD, CM integer I97, J97 logical TEST common /raset1/ U, C, CD, CM, I97, J97, TEST integer ivec if( .NOT. TEST ) then print '(A)',' Call the init routine (RMARIN) before calling RAN *MAR' stop endif uni = U(I97) - U(J97) if( uni .lt. 0.0 ) uni = uni + 1.0 U(I97) = uni I97 = I97 - 1 if(I97 .eq. 0) I97 = 97 J97 = J97 - 1 if(J97 .eq. 0) J97 = 97 C = C - CD if( C .lt. 0.0 ) C = C + CM uni = uni - C if( uni .lt. 0.0 ) uni = uni + 1.0 RANMAR = uni return END **************************************************************************