1 double precision function randlc(x, a)
3 c---------------------------------------------------------------------
5 c This routine returns a uniform pseudorandom double precision number in the
6 c range (0, 1) by using the linear congruential generator
8 c x_{k+1} = a x_k (mod 2^46)
10 c where 0 < x_k < 2^46 and 0 < a < 2^46. This scheme generates 2^44 numbers
11 c before repeating. The argument A is the same as 'a' in the above formula,
12 c and X is the same as x_0. A and X must be odd double precision integers
13 c in the range (1, 2^46). The returned value RANDLC is normalized to be
14 c between 0 and 1, i.e. RANDLC = 2^(-46) * x_1. X is updated to contain
15 c the new seed x_1, so that subsequent calls to RANDLC using the same
16 c arguments will generate a continuous sequence.
20 integer*8 i246m1, Lx, La
21 double precision d2m46
23 parameter(d2m46=0.5d0**46)
26 data i246m1/X'00003FFFFFFFFFFF'/
31 Lx = iand(Lx*La,i246m1)
32 randlc = d2m46*dble(Lx)
38 c---------------------------------------------------------------------
39 c---------------------------------------------------------------------
42 SUBROUTINE VRANLC (N, X, A, Y)
45 double precision x, a, y(*)
46 integer*8 i246m1, Lx, La
47 double precision d2m46
49 c This doesn't work, because the compiler does the calculation in 32
50 c bits and overflows. No standard way (without f90 stuff) to specify
51 c that the rhs should be done in 64 bit arithmetic.
52 c parameter(i246m1=2**46-1)
54 parameter(d2m46=0.5d0**46)
57 data i246m1/X'00003FFFFFFFFFFF'/
59 c Note that the v6 compiler on an R8000 does something stupid with
60 c the above. Using the following instead (or various other things)
61 c makes the calculation run almost 10 times as fast.
65 c if (d2m46 .eq. 0.0d0) then
72 Lx = iand(Lx*La,i246m1)