[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.