1 """Wichman-Hill random number generator.
3 Wichmann, B. A. & Hill, I. D. (1982)
5 An efficient and portable pseudo-random number generator
6 Applied Statistics 31 (1982) 188-190
9 Correction to Algorithm AS 183
10 Applied Statistics 33 (1984) 123
13 A remark on Algorithm AS 183
14 Applied Statistics 34 (1985),198-200
18 whrandom.random() yields double precision random numbers
19 uniformly distributed between 0 and 1.
21 whrandom.seed(x, y, z) must be called before whrandom.random()
24 There is also an interface to create multiple independent
25 random generators, and to choose from other ranges.
29 Multi-threading note: the random number generator used here is not
30 thread-safe; it is possible that nearly simultaneous calls in
31 different theads return the same random value. To avoid this, you
32 have to use a lock around all calls. (I didn't want to slow this
33 down in the serial case by using a lock here.)
42 """Initialize an instance.
43 Without arguments, initialize from current time.
44 With arguments (x, y, z), initialize from them."""
47 def seed(self, x = 0, y = 0, z = 0):
48 """Set the seed from (x, y, z).
49 These must be integers in the range [0, 256)."""
50 if not type(x) == type(y) == type(z) == type(0):
51 raise TypeError,
'seeds must be integers'
52 if not (0 <= x < 256
and 0 <= y < 256
and 0 <= z < 256):
53 raise ValueError,
'seeds must be in range(0, 256)'
57 t = long(time.time() * 256)
58 t = int((t&0xffffff) ^ (t>>24))
63 self.
_seed = (x
or 1, y
or 1, z
or 1)
66 """Get the next random number in the range [0.0, 1.0)."""
78 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
81 """Get a random number in the range [a, b)."""
82 return a + (b-a) * self.
random()
85 """Get a random integer in the range [a, b] including
88 (Deprecated; use randrange below.)"""
92 """Choose a random element from a non-empty sequence."""
93 return seq[int(self.
random() * len(seq))]
95 def randrange(self, start, stop=None, step=1, int=int, default=None):
96 """Choose a random item from range(start, stop[, step]).
98 This fixes the problem with randint() which includes the
99 endpoint; in Python this is usually not what you want.
100 Do not supply the 'int' and 'default' arguments."""
105 raise ValueError,
"non-integer arg 1 for randrange()"
108 return int(self.
random() * istart)
109 raise ValueError,
"empty range for randrange()"
112 raise ValueError,
"non-integer stop for randrange()"
115 return istart + int(self.
random() *
117 raise ValueError,
"empty range for randrange()"
120 raise ValueError,
"non-integer step for randrange()"
122 n = (istop - istart + istep - 1) / istep
124 n = (istop - istart + istep + 1) / istep
126 raise ValueError,
"zero step for randrange()"
129 raise ValueError,
"empty range for randrange()"
130 return istart + istep*int(self.
random() * n)
136 random = _inst.random
137 uniform = _inst.uniform
138 randint = _inst.randint
139 choice = _inst.choice
140 randrange = _inst.randrange