PyXR

c:\python24\lib \ whrandom.py



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
SourceForge.net Logo