Blame view

fvn_fnlib/rand.f 4.45 KB
38581db0c   daniau   git-svn-id: https...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
        function rand (r)
  c
  c      this pseudo-random number generator is portable amoung a wide
  c variety of computers.  rand(r) undoubtedly is not as good as many
  c readily available installation dependent versions, and so this
  c routine is not recommended for widespread usage.  its redeeming
  c feature is that the exact same random numbers (to within final round-
  c off error) can be generated from machine to machine.  thus, programs
  c that make use of random numbers can be easily transported to and
  c checked in a new environment.
  c      the random numbers are generated by the linear congruential
  c method described, e.g., by knuth in seminumerical methods (p.9),
  c addison-wesley, 1969.  given the i-th number of a pseudo-random
  c sequence, the i+1 -st number is generated from
  c             x(i+1) = (a*x(i) + c) mod m,
  c where here m = 2**22 = 4194304, c = 1731 and several suitable values
  c of the multiplier a are discussed below.  both the multiplier a and
  c random number x are represented in double precision as two 11-bit
  c words.  the constants are chosen so that the period is the maximum
  c possible, 4194304.
  c      in order that the same numbers be generated from machine to
  c machine, it is necessary that 23-bit integers be reducible modulo
  c 2**11 exactly, that 23-bit integers be added exactly, and that 11-bit
  c integers be multiplied exactly.  furthermore, if the restart option
  c is used (where r is between 0 and 1), then the product r*2**22 =
  c r*4194304 must be correct to the nearest integer.
  c      the first four random numbers should be .0004127026,
  c .6750836372, .1614754200, and .9086198807.  the tenth random number
  c is .5527787209, and the hundredth is .3600893021 .  the thousandth
  c number should be .2176990509 .
  c      in order to generate several effectively independent sequences
  c with the same generator, it is necessary to know the random number
  c for several widely spaced calls.  the i-th random number times 2**22,
  c where i=k*p/8 and p is the period of the sequence (p = 2**22), is
  c still of the form l*p/8.  in particular we find the i-th random
  c number multiplied by 2**22 is given by
  c i   =  0  1*p/8  2*p/8  3*p/8  4*p/8  5*p/8  6*p/8  7*p/8  8*p/8
  c rand=  0  5*p/8  2*p/8  7*p/8  4*p/8  1*p/8  6*p/8  3*p/8  0
  c thus the 4*p/8 = 2097152 random number is 2097152/2**22.
  c      several multipliers have been subjected to the spectral test
  c (see knuth, p. 82).  four suitable multipliers roughly in order of
  c goodness according to the spectral test are
  c    3146757 = 1536*2048 + 1029 = 2**21 + 2**20 + 2**10 + 5
  c    2098181 = 1024*2048 + 1029 = 2**21 + 2**10 + 5
  c    3146245 = 1536*2048 +  517 = 2**21 + 2**20 + 2**9 + 5
  c    2776669 = 1355*2048 + 1629 = 5**9 + 7**7 + 1
  c
  c      in the table below log10(nu(i)) gives roughly the number of
  c random decimal digits in the random numbers considered i at a time.
  c c is the primary measure of goodness.  in both cases bigger is better.
  c
  c                   log10 nu(i)              c(i)
  c       a       i=2  i=3  i=4  i=5    i=2  i=3  i=4  i=5
  c
  c    3146757    3.3  2.0  1.6  1.3    3.1  1.3  4.6  2.6
  c    2098181    3.3  2.0  1.6  1.2    3.2  1.3  4.6  1.7
  c    3146245    3.3  2.2  1.5  1.1    3.2  4.2  1.1  0.4
  c    2776669    3.3  2.1  1.6  1.3    2.5  2.0  1.9  2.6
  c   best
  c    possible   3.3  2.3  1.7  1.4    3.6  5.9  9.7  14.9
  c
  c             input argument --
  c r      if r=0., the next random number of the sequence is generated.
  c        if r.lt.0., the last generated number will be returned for
  c          possible use in a restart procedure.
  c        if r.gt.0., the sequence of random numbers will start with the
  c          seed r mod 1.  this seed is also returned as the value of
  c          rand provided the arithmetic is done exactly.
  c
  c             output value --
  c rand   a pseudo-random number between 0. and 1.
  c
  c ia1 and ia0 are the hi and lo parts of a.  ia1ma0 = ia1 - ia0.
        data ia1, ia0, ia1ma0 /1536, 1029, 507/
        data ic /1731/
        data ix1, ix0 /0, 0/
  c
        if (r.lt.0.) go to 10
        if (r.gt.0.) go to 20
  c
  c           a*x = 2**22*ia1*ix1 + 2**11*(ia1*ix1 + (ia1-ia0)*(ix0-ix1)
  c                   + ia0*ix0) + ia0*ix0
  c
        iy0 = ia0*ix0
        iy1 = ia1*ix1 + ia1ma0*(ix0-ix1) + iy0
        iy0 = iy0 + ic
        ix0 = mod (iy0, 2048)
        iy1 = iy1 + (iy0-ix0)/2048
        ix1 = mod (iy1, 2048)
  c
   10   rand = ix1*2048 + ix0
        rand = rand / 4194304.
        return
  c
   20   ix1 = amod(r,1.)*4194304. + 0.5
        ix0 = mod (ix1, 2048)
        ix1 = (ix1-ix0)/2048
        go to 10
  c
        end