0001 """Wichman-Hill random number generator. 0002 0003 Wichmann, B. A. & Hill, I. D. (1982) 0004 Algorithm AS 183: 0005 An efficient and portable pseudo-random number generator 0006 Applied Statistics 31 (1982) 188-190 0007 0008 see also: 0009 Correction to Algorithm AS 183 0010 Applied Statistics 33 (1984) 123 0011 0012 McLeod, A. I. (1985) 0013 A remark on Algorithm AS 183 0014 Applied Statistics 34 (1985),198-200 0015 0016 0017 USE: 0018 whrandom.random() yields double precision random numbers 0019 uniformly distributed between 0 and 1. 0020 0021 whrandom.seed(x, y, z) must be called before whrandom.random() 0022 to seed the generator 0023 0024 There is also an interface to create multiple independent 0025 random generators, and to choose from other ranges. 0026 0027 0028 0029 Multi-threading note: the random number generator used here is not 0030 thread-safe; it is possible that nearly simultaneous calls in 0031 different theads return the same random value. To avoid this, you 0032 have to use a lock around all calls. (I didn't want to slow this 0033 down in the serial case by using a lock here.) 0034 """ 0035 0036 import warnings 0037 warnings.warn("the whrandom module is deprecated; please use the random module", 0038 DeprecationWarning) 0039 0040 # Translated by Guido van Rossum from C source provided by 0041 # Adrian Baddeley. 0042 0043 0044 class whrandom: 0045 def __init__(self, x = 0, y = 0, z = 0): 0046 """Initialize an instance. 0047 Without arguments, initialize from current time. 0048 With arguments (x, y, z), initialize from them.""" 0049 self.seed(x, y, z) 0050 0051 def seed(self, x = 0, y = 0, z = 0): 0052 """Set the seed from (x, y, z). 0053 These must be integers in the range [0, 256).""" 0054 if not type(x) == type(y) == type(z) == type(0): 0055 raise TypeError, 'seeds must be integers' 0056 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): 0057 raise ValueError, 'seeds must be in range(0, 256)' 0058 if 0 == x == y == z: 0059 # Initialize from current time 0060 import time 0061 t = long(time.time() * 256) 0062 t = int((t&0xffffff) ^ (t>>24)) 0063 t, x = divmod(t, 256) 0064 t, y = divmod(t, 256) 0065 t, z = divmod(t, 256) 0066 # Zero is a poor seed, so substitute 1 0067 self._seed = (x or 1, y or 1, z or 1) 0068 0069 def random(self): 0070 """Get the next random number in the range [0.0, 1.0).""" 0071 # This part is thread-unsafe: 0072 # BEGIN CRITICAL SECTION 0073 x, y, z = self._seed 0074 # 0075 x = (171 * x) % 30269 0076 y = (172 * y) % 30307 0077 z = (170 * z) % 30323 0078 # 0079 self._seed = x, y, z 0080 # END CRITICAL SECTION 0081 # 0082 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0 0083 0084 def uniform(self, a, b): 0085 """Get a random number in the range [a, b).""" 0086 return a + (b-a) * self.random() 0087 0088 def randint(self, a, b): 0089 """Get a random integer in the range [a, b] including 0090 both end points. 0091 0092 (Deprecated; use randrange below.)""" 0093 return self.randrange(a, b+1) 0094 0095 def choice(self, seq): 0096 """Choose a random element from a non-empty sequence.""" 0097 return seq[int(self.random() * len(seq))] 0098 0099 def randrange(self, start, stop=None, step=1, int=int, default=None): 0100 """Choose a random item from range(start, stop[, step]). 0101 0102 This fixes the problem with randint() which includes the 0103 endpoint; in Python this is usually not what you want. 0104 Do not supply the 'int' and 'default' arguments.""" 0105 # This code is a bit messy to make it fast for the 0106 # common case while still doing adequate error checking 0107 istart = int(start) 0108 if istart != start: 0109 raise ValueError, "non-integer arg 1 for randrange()" 0110 if stop is default: 0111 if istart > 0: 0112 return int(self.random() * istart) 0113 raise ValueError, "empty range for randrange()" 0114 istop = int(stop) 0115 if istop != stop: 0116 raise ValueError, "non-integer stop for randrange()" 0117 if step == 1: 0118 if istart < istop: 0119 return istart + int(self.random() * 0120 (istop - istart)) 0121 raise ValueError, "empty range for randrange()" 0122 istep = int(step) 0123 if istep != step: 0124 raise ValueError, "non-integer step for randrange()" 0125 if istep > 0: 0126 n = (istop - istart + istep - 1) / istep 0127 elif istep < 0: 0128 n = (istop - istart + istep + 1) / istep 0129 else: 0130 raise ValueError, "zero step for randrange()" 0131 0132 if n <= 0: 0133 raise ValueError, "empty range for randrange()" 0134 return istart + istep*int(self.random() * n) 0135 0136 0137 # Initialize from the current time 0138 _inst = whrandom() 0139 seed = _inst.seed 0140 random = _inst.random 0141 uniform = _inst.uniform 0142 randint = _inst.randint 0143 choice = _inst.choice 0144 randrange = _inst.randrange 0145
Generated by PyXR 0.9.4