Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v9 / lib / python2.4 / whrandom.py
CommitLineData
920dae64
AT
1"""Wichman-Hill random number generator.
2
3Wichmann, B. A. & Hill, I. D. (1982)
4Algorithm AS 183:
5An efficient and portable pseudo-random number generator
6Applied Statistics 31 (1982) 188-190
7
8see also:
9 Correction to Algorithm AS 183
10 Applied Statistics 33 (1984) 123
11
12 McLeod, A. I. (1985)
13 A remark on Algorithm AS 183
14 Applied Statistics 34 (1985),198-200
15
16
17USE:
18whrandom.random() yields double precision random numbers
19 uniformly distributed between 0 and 1.
20
21whrandom.seed(x, y, z) must be called before whrandom.random()
22 to seed the generator
23
24There is also an interface to create multiple independent
25random generators, and to choose from other ranges.
26
27
28
29Multi-threading note: the random number generator used here is not
30thread-safe; it is possible that nearly simultaneous calls in
31different theads return the same random value. To avoid this, you
32have to use a lock around all calls. (I didn't want to slow this
33down in the serial case by using a lock here.)
34"""
35
36import warnings
37warnings.warn("the whrandom module is deprecated; please use the random module",
38 DeprecationWarning)
39
40# Translated by Guido van Rossum from C source provided by
41# Adrian Baddeley.
42
43
44class whrandom:
45 def __init__(self, x = 0, y = 0, z = 0):
46 """Initialize an instance.
47 Without arguments, initialize from current time.
48 With arguments (x, y, z), initialize from them."""
49 self.seed(x, y, z)
50
51 def seed(self, x = 0, y = 0, z = 0):
52 """Set the seed from (x, y, z).
53 These must be integers in the range [0, 256)."""
54 if not type(x) == type(y) == type(z) == type(0):
55 raise TypeError, 'seeds must be integers'
56 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
57 raise ValueError, 'seeds must be in range(0, 256)'
58 if 0 == x == y == z:
59 # Initialize from current time
60 import time
61 t = long(time.time() * 256)
62 t = int((t&0xffffff) ^ (t>>24))
63 t, x = divmod(t, 256)
64 t, y = divmod(t, 256)
65 t, z = divmod(t, 256)
66 # Zero is a poor seed, so substitute 1
67 self._seed = (x or 1, y or 1, z or 1)
68
69 def random(self):
70 """Get the next random number in the range [0.0, 1.0)."""
71 # This part is thread-unsafe:
72 # BEGIN CRITICAL SECTION
73 x, y, z = self._seed
74 #
75 x = (171 * x) % 30269
76 y = (172 * y) % 30307
77 z = (170 * z) % 30323
78 #
79 self._seed = x, y, z
80 # END CRITICAL SECTION
81 #
82 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
83
84 def uniform(self, a, b):
85 """Get a random number in the range [a, b)."""
86 return a + (b-a) * self.random()
87
88 def randint(self, a, b):
89 """Get a random integer in the range [a, b] including
90 both end points.
91
92 (Deprecated; use randrange below.)"""
93 return self.randrange(a, b+1)
94
95 def choice(self, seq):
96 """Choose a random element from a non-empty sequence."""
97 return seq[int(self.random() * len(seq))]
98
99 def randrange(self, start, stop=None, step=1, int=int, default=None):
100 """Choose a random item from range(start, stop[, step]).
101
102 This fixes the problem with randint() which includes the
103 endpoint; in Python this is usually not what you want.
104 Do not supply the 'int' and 'default' arguments."""
105 # This code is a bit messy to make it fast for the
106 # common case while still doing adequate error checking
107 istart = int(start)
108 if istart != start:
109 raise ValueError, "non-integer arg 1 for randrange()"
110 if stop is default:
111 if istart > 0:
112 return int(self.random() * istart)
113 raise ValueError, "empty range for randrange()"
114 istop = int(stop)
115 if istop != stop:
116 raise ValueError, "non-integer stop for randrange()"
117 if step == 1:
118 if istart < istop:
119 return istart + int(self.random() *
120 (istop - istart))
121 raise ValueError, "empty range for randrange()"
122 istep = int(step)
123 if istep != step:
124 raise ValueError, "non-integer step for randrange()"
125 if istep > 0:
126 n = (istop - istart + istep - 1) / istep
127 elif istep < 0:
128 n = (istop - istart + istep + 1) / istep
129 else:
130 raise ValueError, "zero step for randrange()"
131
132 if n <= 0:
133 raise ValueError, "empty range for randrange()"
134 return istart + istep*int(self.random() * n)
135
136
137# Initialize from the current time
138_inst = whrandom()
139seed = _inst.seed
140random = _inst.random
141uniform = _inst.uniform
142randint = _inst.randint
143choice = _inst.choice
144randrange = _inst.randrange