[Python-checkins] CVS: python/dist/src/Lib random.py,1.17,1.18
Tim Peters
tim_one@users.sourceforge.net
Thu, 25 Jan 2001 12:25:59 -0800
Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv29278/python/dist/src/lib
Modified Files:
random.py
Log Message:
Cosmetic changes after some sleep; no change in semantics.
Index: random.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/random.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -r1.17 -r1.18
*** random.py 2001/01/25 06:23:18 1.17
--- random.py 2001/01/25 20:25:57 1.18
***************
*** 28,32 ****
Multi-threading note: the random number generator used here is not
thread-safe; it is possible that two calls return the same random
! value.
"""
# XXX The docstring sucks.
--- 28,35 ----
Multi-threading note: the random number generator used here is not
thread-safe; it is possible that two calls return the same random
! value. But you can instantiate a different instance of Random() in
! each thread to get generators that don't share state, then use
! .setstate() and .jumpahead() to move the generators to disjoint
! segments of the full period.
"""
# XXX The docstring sucks.
***************
*** 72,78 ****
self.gauss_next = None
# Specific to Wichmann-Hill generator. Subclasses wishing to use a
# different core generator should override the seed(), random(),
! # getstate(), setstate(), and jumpahead() methods.
def __whseed(self, x=0, y=0, z=0):
--- 75,83 ----
self.gauss_next = None
+ ## -------------------- core generator -------------------
+
# Specific to Wichmann-Hill generator. Subclasses wishing to use a
# different core generator should override the seed(), random(),
! # getstate(), setstate() and jumpahead() methods.
def __whseed(self, x=0, y=0, z=0):
***************
*** 97,104 ****
self._seed = (x or 1, y or 1, z or 1)
def seed(self, a=None):
! """Seed from hashable value
! None or no argument seeds from current time.
"""
--- 102,142 ----
self._seed = (x or 1, y or 1, z or 1)
+ def random(self):
+ """Get the next random number in the range [0.0, 1.0)."""
+
+ # Wichman-Hill random number generator.
+ #
+ # Wichmann, B. A. & Hill, I. D. (1982)
+ # Algorithm AS 183:
+ # An efficient and portable pseudo-random number generator
+ # Applied Statistics 31 (1982) 188-190
+ #
+ # see also:
+ # Correction to Algorithm AS 183
+ # Applied Statistics 33 (1984) 123
+ #
+ # McLeod, A. I. (1985)
+ # A remark on Algorithm AS 183
+ # Applied Statistics 34 (1985),198-200
+
+ # This part is thread-unsafe:
+ # BEGIN CRITICAL SECTION
+ x, y, z = self._seed
+ x = (171 * x) % 30269
+ y = (172 * y) % 30307
+ z = (170 * z) % 30323
+ self._seed = x, y, z
+ # END CRITICAL SECTION
+
+ # Note: on a platform using IEEE-754 double arithmetic, this can
+ # never return 0.0 (asserted by Tim; proof too long for a comment).
+ return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
+
def seed(self, a=None):
! """Seed from hashable object's hash code.
! None or no argument seeds from current time. It is not guaranteed
! that objects with distinct hash codes lead to distinct internal
! states.
"""
***************
*** 119,125 ****
return self.VERSION, self._seed, self.gauss_next
- def __getstate__(self): # for pickle
- return self.getstate()
-
def setstate(self, state):
"""Restore internal state from object returned by getstate()."""
--- 157,160 ----
***************
*** 132,138 ****
(version, self.VERSION))
- def __setstate__(self, state): # for pickle
- self.setstate(state)
-
def jumpahead(self, n):
"""Act as if n calls to random() were made, but quickly.
--- 167,170 ----
***************
*** 157,190 ****
self._seed = x, y, z
! def random(self):
! """Get the next random number in the range [0.0, 1.0)."""
! # Wichman-Hill random number generator.
! #
! # Wichmann, B. A. & Hill, I. D. (1982)
! # Algorithm AS 183:
! # An efficient and portable pseudo-random number generator
! # Applied Statistics 31 (1982) 188-190
! #
! # see also:
! # Correction to Algorithm AS 183
! # Applied Statistics 33 (1984) 123
! #
! # McLeod, A. I. (1985)
! # A remark on Algorithm AS 183
! # Applied Statistics 34 (1985),198-200
! # This part is thread-unsafe:
! # BEGIN CRITICAL SECTION
! x, y, z = self._seed
! x = (171 * x) % 30269
! y = (172 * y) % 30307
! z = (170 * z) % 30323
! self._seed = x, y, z
! # END CRITICAL SECTION
! # Note: on a platform using IEEE-754 double arithmetic, this can
! # never return 0.0 (asserted by Tim; proof too long for a comment).
! return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
def randrange(self, start, stop=None, step=1, int=int, default=None):
--- 189,204 ----
self._seed = x, y, z
! ## ---- Methods below this point do not need to be overridden when
! ## ---- subclassing for the purpose of using a different core generator.
! ## -------------------- pickle support -------------------
! def __getstate__(self): # for pickle
! return self.getstate()
! def __setstate__(self, state): # for pickle
! self.setstate(state)
!
! ## -------------------- integer methods -------------------
def randrange(self, start, stop=None, step=1, int=int, default=None):
***************
*** 228,239 ****
def randint(self, a, b):
! """Get a random integer in the range [a, b] including
! both end points.
! (Deprecated; use randrange below.)
"""
return self.randrange(a, b+1)
def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
--- 242,254 ----
def randint(self, a, b):
! """Return random integer in range [a, b], including both end points.
! (Deprecated; use randrange(a, b+1).)
"""
return self.randrange(a, b+1)
+ ## -------------------- sequence methods -------------------
+
def choice(self, seq):
"""Choose a random element from a non-empty sequence."""
***************
*** 255,269 ****
random = self.random
for i in xrange(len(x)-1, 0, -1):
! # pick an element in x[:i+1] with which to exchange x[i]
j = int(random() * (i+1))
x[i], x[j] = x[j], x[i]
! # -------------------- uniform distribution -------------------
def uniform(self, a, b):
"""Get a random number in the range [a, b)."""
return a + (b-a) * self.random()
! # -------------------- normal distribution --------------------
def normalvariate(self, mu, sigma):
--- 270,286 ----
random = self.random
for i in xrange(len(x)-1, 0, -1):
! # pick an element in x[:i+1] with which to exchange x[i]
j = int(random() * (i+1))
x[i], x[j] = x[j], x[i]
! ## -------------------- real-valued distributions -------------------
+ ## -------------------- uniform distribution -------------------
+
def uniform(self, a, b):
"""Get a random number in the range [a, b)."""
return a + (b-a) * self.random()
! ## -------------------- normal distribution --------------------
def normalvariate(self, mu, sigma):
***************
*** 285,294 ****
return mu + z*sigma
! # -------------------- lognormal distribution --------------------
def lognormvariate(self, mu, sigma):
return _exp(self.normalvariate(mu, sigma))
! # -------------------- circular uniform --------------------
def cunifvariate(self, mean, arc):
--- 302,311 ----
return mu + z*sigma
! ## -------------------- lognormal distribution --------------------
def lognormvariate(self, mu, sigma):
return _exp(self.normalvariate(mu, sigma))
! ## -------------------- circular uniform --------------------
def cunifvariate(self, mean, arc):
***************
*** 298,302 ****
return (mean + arc * (self.random() - 0.5)) % _pi
! # -------------------- exponential distribution --------------------
def expovariate(self, lambd):
--- 315,319 ----
return (mean + arc * (self.random() - 0.5)) % _pi
! ## -------------------- exponential distribution --------------------
def expovariate(self, lambd):
***************
*** 310,314 ****
return -_log(u)/lambd
! # -------------------- von Mises distribution --------------------
def vonmisesvariate(self, mu, kappa):
--- 327,331 ----
return -_log(u)/lambd
! ## -------------------- von Mises distribution --------------------
def vonmisesvariate(self, mu, kappa):
***************
*** 352,356 ****
return theta
! # -------------------- gamma distribution --------------------
def gammavariate(self, alpha, beta):
--- 369,373 ----
return theta
! ## -------------------- gamma distribution --------------------
def gammavariate(self, alpha, beta):
***************
*** 411,415 ****
! # -------------------- Gauss (faster alternative) --------------------
def gauss(self, mu, sigma):
--- 428,432 ----
! ## -------------------- Gauss (faster alternative) --------------------
def gauss(self, mu, sigma):
***************
*** 444,448 ****
return mu + z*sigma
! # -------------------- beta --------------------
def betavariate(self, alpha, beta):
--- 461,465 ----
return mu + z*sigma
! ## -------------------- beta --------------------
def betavariate(self, alpha, beta):
***************
*** 454,458 ****
return z/(y+z)
! # -------------------- Pareto --------------------
def paretovariate(self, alpha):
--- 471,475 ----
return z/(y+z)
! ## -------------------- Pareto --------------------
def paretovariate(self, alpha):
***************
*** 462,466 ****
return 1.0 / pow(u, 1.0/alpha)
! # -------------------- Weibull --------------------
def weibullvariate(self, alpha, beta):
--- 479,483 ----
return 1.0 / pow(u, 1.0/alpha)
! ## -------------------- Weibull --------------------
def weibullvariate(self, alpha, beta):
***************
*** 470,474 ****
return alpha * pow(-_log(u), 1.0/beta)
! # -------------------- test program --------------------
def _test_generator(n, funccall):
--- 487,491 ----
return alpha * pow(-_log(u), 1.0/beta)
! ## -------------------- test program --------------------
def _test_generator(n, funccall):
***************
*** 494,508 ****
(avg, stddev, smallest, largest)
- s = getstate()
- N = 1019
- jumpahead(N)
- r1 = random()
- setstate(s)
- for i in range(N): # now do it the slow way
- random()
- r2 = random()
- if r1 != r2:
- raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
-
def _test(N=200):
print 'TWOPI =', TWOPI
--- 511,514 ----
***************
*** 526,529 ****
--- 532,547 ----
_test_generator(N, 'paretovariate(1.0)')
_test_generator(N, 'weibullvariate(1.0, 1.0)')
+
+ # Test jumpahead.
+ s = getstate()
+ jumpahead(N)
+ r1 = random()
+ # now do it the slow way
+ setstate(s)
+ for i in range(N):
+ random()
+ r2 = random()
+ if r1 != r2:
+ raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
# Initialize from current time.