(root)/
Python-3.11.7/
Lib/
random.py
       1  """Random variable generators.
       2  
       3      bytes
       4      -----
       5             uniform bytes (values between 0 and 255)
       6  
       7      integers
       8      --------
       9             uniform within range
      10  
      11      sequences
      12      ---------
      13             pick random element
      14             pick random sample
      15             pick weighted random sample
      16             generate random permutation
      17  
      18      distributions on the real line:
      19      ------------------------------
      20             uniform
      21             triangular
      22             normal (Gaussian)
      23             lognormal
      24             negative exponential
      25             gamma
      26             beta
      27             pareto
      28             Weibull
      29  
      30      distributions on the circle (angles 0 to 2pi)
      31      ---------------------------------------------
      32             circular uniform
      33             von Mises
      34  
      35  General notes on the underlying Mersenne Twister core generator:
      36  
      37  * The period is 2**19937-1.
      38  * It is one of the most extensively tested generators in existence.
      39  * The random() method is implemented in C, executes in a single Python step,
      40    and is, therefore, threadsafe.
      41  
      42  """
      43  
      44  # Translated by Guido van Rossum from C source provided by
      45  # Adrian Baddeley.  Adapted by Raymond Hettinger for use with
      46  # the Mersenne Twister  and os.urandom() core generators.
      47  
      48  from warnings import warn as _warn
      49  from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
      50  from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
      51  from math import tau as TWOPI, floor as _floor, isfinite as _isfinite
      52  from os import urandom as _urandom
      53  from _collections_abc import Set as _Set, Sequence as _Sequence
      54  from operator import index as _index
      55  from itertools import accumulate as _accumulate, repeat as _repeat
      56  from bisect import bisect as _bisect
      57  import os as _os
      58  import _random
      59  
      60  try:
      61      # hashlib is pretty heavy to load, try lean internal module first
      62      from _sha512 import sha512 as _sha512
      63  except ImportError:
      64      # fallback to official implementation
      65      from hashlib import sha512 as _sha512
      66  
      67  __all__ = [
      68      "Random",
      69      "SystemRandom",
      70      "betavariate",
      71      "choice",
      72      "choices",
      73      "expovariate",
      74      "gammavariate",
      75      "gauss",
      76      "getrandbits",
      77      "getstate",
      78      "lognormvariate",
      79      "normalvariate",
      80      "paretovariate",
      81      "randbytes",
      82      "randint",
      83      "random",
      84      "randrange",
      85      "sample",
      86      "seed",
      87      "setstate",
      88      "shuffle",
      89      "triangular",
      90      "uniform",
      91      "vonmisesvariate",
      92      "weibullvariate",
      93  ]
      94  
      95  NV_MAGICCONST = 4 * _exp(-0.5) / _sqrt(2.0)
      96  LOG4 = _log(4.0)
      97  SG_MAGICCONST = 1.0 + _log(4.5)
      98  BPF = 53        # Number of bits in a float
      99  RECIP_BPF = 2 ** -BPF
     100  _ONE = 1
     101  
     102  
     103  class ESC[4;38;5;81mRandom(ESC[4;38;5;149m_randomESC[4;38;5;149m.ESC[4;38;5;149mRandom):
     104      """Random number generator base class used by bound module functions.
     105  
     106      Used to instantiate instances of Random to get generators that don't
     107      share state.
     108  
     109      Class Random can also be subclassed if you want to use a different basic
     110      generator of your own devising: in that case, override the following
     111      methods:  random(), seed(), getstate(), and setstate().
     112      Optionally, implement a getrandbits() method so that randrange()
     113      can cover arbitrarily large ranges.
     114  
     115      """
     116  
     117      VERSION = 3     # used by getstate/setstate
     118  
     119      def __init__(self, x=None):
     120          """Initialize an instance.
     121  
     122          Optional argument x controls seeding, as for Random.seed().
     123          """
     124  
     125          self.seed(x)
     126          self.gauss_next = None
     127  
     128      def seed(self, a=None, version=2):
     129          """Initialize internal state from a seed.
     130  
     131          The only supported seed types are None, int, float,
     132          str, bytes, and bytearray.
     133  
     134          None or no argument seeds from current time or from an operating
     135          system specific randomness source if available.
     136  
     137          If *a* is an int, all bits are used.
     138  
     139          For version 2 (the default), all of the bits are used if *a* is a str,
     140          bytes, or bytearray.  For version 1 (provided for reproducing random
     141          sequences from older versions of Python), the algorithm for str and
     142          bytes generates a narrower range of seeds.
     143  
     144          """
     145  
     146          if version == 1 and isinstance(a, (str, bytes)):
     147              a = a.decode('latin-1') if isinstance(a, bytes) else a
     148              x = ord(a[0]) << 7 if a else 0
     149              for c in map(ord, a):
     150                  x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF
     151              x ^= len(a)
     152              a = -2 if x == -1 else x
     153  
     154          elif version == 2 and isinstance(a, (str, bytes, bytearray)):
     155              if isinstance(a, str):
     156                  a = a.encode()
     157              a = int.from_bytes(a + _sha512(a).digest())
     158  
     159          elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)):
     160              raise TypeError('The only supported seed types are: None,\n'
     161                              'int, float, str, bytes, and bytearray.')
     162  
     163          super().seed(a)
     164          self.gauss_next = None
     165  
     166      def getstate(self):
     167          """Return internal state; can be passed to setstate() later."""
     168          return self.VERSION, super().getstate(), self.gauss_next
     169  
     170      def setstate(self, state):
     171          """Restore internal state from object returned by getstate()."""
     172          version = state[0]
     173          if version == 3:
     174              version, internalstate, self.gauss_next = state
     175              super().setstate(internalstate)
     176          elif version == 2:
     177              version, internalstate, self.gauss_next = state
     178              # In version 2, the state was saved as signed ints, which causes
     179              #   inconsistencies between 32/64-bit systems. The state is
     180              #   really unsigned 32-bit ints, so we convert negative ints from
     181              #   version 2 to positive longs for version 3.
     182              try:
     183                  internalstate = tuple(x % (2 ** 32) for x in internalstate)
     184              except ValueError as e:
     185                  raise TypeError from e
     186              super().setstate(internalstate)
     187          else:
     188              raise ValueError("state with version %s passed to "
     189                               "Random.setstate() of version %s" %
     190                               (version, self.VERSION))
     191  
     192  
     193      ## -------------------------------------------------------
     194      ## ---- Methods below this point do not need to be overridden or extended
     195      ## ---- when subclassing for the purpose of using a different core generator.
     196  
     197  
     198      ## -------------------- pickle support  -------------------
     199  
     200      # Issue 17489: Since __reduce__ was defined to fix #759889 this is no
     201      # longer called; we leave it here because it has been here since random was
     202      # rewritten back in 2001 and why risk breaking something.
     203      def __getstate__(self):  # for pickle
     204          return self.getstate()
     205  
     206      def __setstate__(self, state):  # for pickle
     207          self.setstate(state)
     208  
     209      def __reduce__(self):
     210          return self.__class__, (), self.getstate()
     211  
     212  
     213      ## ---- internal support method for evenly distributed integers ----
     214  
     215      def __init_subclass__(cls, /, **kwargs):
     216          """Control how subclasses generate random integers.
     217  
     218          The algorithm a subclass can use depends on the random() and/or
     219          getrandbits() implementation available to it and determines
     220          whether it can generate random integers from arbitrarily large
     221          ranges.
     222          """
     223  
     224          for c in cls.__mro__:
     225              if '_randbelow' in c.__dict__:
     226                  # just inherit it
     227                  break
     228              if 'getrandbits' in c.__dict__:
     229                  cls._randbelow = cls._randbelow_with_getrandbits
     230                  break
     231              if 'random' in c.__dict__:
     232                  cls._randbelow = cls._randbelow_without_getrandbits
     233                  break
     234  
     235      def _randbelow_with_getrandbits(self, n):
     236          "Return a random int in the range [0,n).  Defined for n > 0."
     237  
     238          getrandbits = self.getrandbits
     239          k = n.bit_length()  # don't use (n-1) here because n can be 1
     240          r = getrandbits(k)  # 0 <= r < 2**k
     241          while r >= n:
     242              r = getrandbits(k)
     243          return r
     244  
     245      def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
     246          """Return a random int in the range [0,n).  Defined for n > 0.
     247  
     248          The implementation does not use getrandbits, but only random.
     249          """
     250  
     251          random = self.random
     252          if n >= maxsize:
     253              _warn("Underlying random() generator does not supply \n"
     254                  "enough bits to choose from a population range this large.\n"
     255                  "To remove the range limitation, add a getrandbits() method.")
     256              return _floor(random() * n)
     257          rem = maxsize % n
     258          limit = (maxsize - rem) / maxsize   # int(limit * maxsize) % n == 0
     259          r = random()
     260          while r >= limit:
     261              r = random()
     262          return _floor(r * maxsize) % n
     263  
     264      _randbelow = _randbelow_with_getrandbits
     265  
     266  
     267      ## --------------------------------------------------------
     268      ## ---- Methods below this point generate custom distributions
     269      ## ---- based on the methods defined above.  They do not
     270      ## ---- directly touch the underlying generator and only
     271      ## ---- access randomness through the methods:  random(),
     272      ## ---- getrandbits(), or _randbelow().
     273  
     274  
     275      ## -------------------- bytes methods ---------------------
     276  
     277      def randbytes(self, n):
     278          """Generate n random bytes."""
     279          return self.getrandbits(n * 8).to_bytes(n, 'little')
     280  
     281  
     282      ## -------------------- integer methods  -------------------
     283  
     284      def randrange(self, start, stop=None, step=_ONE):
     285          """Choose a random item from range(stop) or range(start, stop[, step]).
     286  
     287          Roughly equivalent to ``choice(range(start, stop, step))`` but
     288          supports arbitrarily large ranges and is optimized for common cases.
     289  
     290          """
     291  
     292          # This code is a bit messy to make it fast for the
     293          # common case while still doing adequate error checking.
     294          try:
     295              istart = _index(start)
     296          except TypeError:
     297              istart = int(start)
     298              if istart != start:
     299                  _warn('randrange() will raise TypeError in the future',
     300                        DeprecationWarning, 2)
     301                  raise ValueError("non-integer arg 1 for randrange()")
     302              _warn('non-integer arguments to randrange() have been deprecated '
     303                    'since Python 3.10 and will be removed in a subsequent '
     304                    'version',
     305                    DeprecationWarning, 2)
     306          if stop is None:
     307              # We don't check for "step != 1" because it hasn't been
     308              # type checked and converted to an integer yet.
     309              if step is not _ONE:
     310                  raise TypeError('Missing a non-None stop argument')
     311              if istart > 0:
     312                  return self._randbelow(istart)
     313              raise ValueError("empty range for randrange()")
     314  
     315          # stop argument supplied.
     316          try:
     317              istop = _index(stop)
     318          except TypeError:
     319              istop = int(stop)
     320              if istop != stop:
     321                  _warn('randrange() will raise TypeError in the future',
     322                        DeprecationWarning, 2)
     323                  raise ValueError("non-integer stop for randrange()")
     324              _warn('non-integer arguments to randrange() have been deprecated '
     325                    'since Python 3.10 and will be removed in a subsequent '
     326                    'version',
     327                    DeprecationWarning, 2)
     328          width = istop - istart
     329          try:
     330              istep = _index(step)
     331          except TypeError:
     332              istep = int(step)
     333              if istep != step:
     334                  _warn('randrange() will raise TypeError in the future',
     335                        DeprecationWarning, 2)
     336                  raise ValueError("non-integer step for randrange()")
     337              _warn('non-integer arguments to randrange() have been deprecated '
     338                    'since Python 3.10 and will be removed in a subsequent '
     339                    'version',
     340                    DeprecationWarning, 2)
     341          # Fast path.
     342          if istep == 1:
     343              if width > 0:
     344                  return istart + self._randbelow(width)
     345              raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
     346  
     347          # Non-unit step argument supplied.
     348          if istep > 0:
     349              n = (width + istep - 1) // istep
     350          elif istep < 0:
     351              n = (width + istep + 1) // istep
     352          else:
     353              raise ValueError("zero step for randrange()")
     354          if n <= 0:
     355              raise ValueError("empty range for randrange()")
     356          return istart + istep * self._randbelow(n)
     357  
     358      def randint(self, a, b):
     359          """Return random integer in range [a, b], including both end points.
     360          """
     361  
     362          return self.randrange(a, b+1)
     363  
     364  
     365      ## -------------------- sequence methods  -------------------
     366  
     367      def choice(self, seq):
     368          """Choose a random element from a non-empty sequence."""
     369  
     370          # As an accommodation for NumPy, we don't use "if not seq"
     371          # because bool(numpy.array()) raises a ValueError.
     372          if not len(seq):
     373              raise IndexError('Cannot choose from an empty sequence')
     374          return seq[self._randbelow(len(seq))]
     375  
     376      def shuffle(self, x):
     377          """Shuffle list x in place, and return None."""
     378  
     379          randbelow = self._randbelow
     380          for i in reversed(range(1, len(x))):
     381              # pick an element in x[:i+1] with which to exchange x[i]
     382              j = randbelow(i + 1)
     383              x[i], x[j] = x[j], x[i]
     384  
     385      def sample(self, population, k, *, counts=None):
     386          """Chooses k unique random elements from a population sequence.
     387  
     388          Returns a new list containing elements from the population while
     389          leaving the original population unchanged.  The resulting list is
     390          in selection order so that all sub-slices will also be valid random
     391          samples.  This allows raffle winners (the sample) to be partitioned
     392          into grand prize and second place winners (the subslices).
     393  
     394          Members of the population need not be hashable or unique.  If the
     395          population contains repeats, then each occurrence is a possible
     396          selection in the sample.
     397  
     398          Repeated elements can be specified one at a time or with the optional
     399          counts parameter.  For example:
     400  
     401              sample(['red', 'blue'], counts=[4, 2], k=5)
     402  
     403          is equivalent to:
     404  
     405              sample(['red', 'red', 'red', 'red', 'blue', 'blue'], k=5)
     406  
     407          To choose a sample from a range of integers, use range() for the
     408          population argument.  This is especially fast and space efficient
     409          for sampling from a large population:
     410  
     411              sample(range(10000000), 60)
     412  
     413          """
     414  
     415          # Sampling without replacement entails tracking either potential
     416          # selections (the pool) in a list or previous selections in a set.
     417  
     418          # When the number of selections is small compared to the
     419          # population, then tracking selections is efficient, requiring
     420          # only a small set and an occasional reselection.  For
     421          # a larger number of selections, the pool tracking method is
     422          # preferred since the list takes less space than the
     423          # set and it doesn't suffer from frequent reselections.
     424  
     425          # The number of calls to _randbelow() is kept at or near k, the
     426          # theoretical minimum.  This is important because running time
     427          # is dominated by _randbelow() and because it extracts the
     428          # least entropy from the underlying random number generators.
     429  
     430          # Memory requirements are kept to the smaller of a k-length
     431          # set or an n-length list.
     432  
     433          # There are other sampling algorithms that do not require
     434          # auxiliary memory, but they were rejected because they made
     435          # too many calls to _randbelow(), making them slower and
     436          # causing them to eat more entropy than necessary.
     437  
     438          if not isinstance(population, _Sequence):
     439              raise TypeError("Population must be a sequence.  "
     440                              "For dicts or sets, use sorted(d).")
     441          n = len(population)
     442          if counts is not None:
     443              cum_counts = list(_accumulate(counts))
     444              if len(cum_counts) != n:
     445                  raise ValueError('The number of counts does not match the population')
     446              total = cum_counts.pop()
     447              if not isinstance(total, int):
     448                  raise TypeError('Counts must be integers')
     449              if total <= 0:
     450                  raise ValueError('Total of counts must be greater than zero')
     451              selections = self.sample(range(total), k=k)
     452              bisect = _bisect
     453              return [population[bisect(cum_counts, s)] for s in selections]
     454          randbelow = self._randbelow
     455          if not 0 <= k <= n:
     456              raise ValueError("Sample larger than population or is negative")
     457          result = [None] * k
     458          setsize = 21        # size of a small set minus size of an empty list
     459          if k > 5:
     460              setsize += 4 ** _ceil(_log(k * 3, 4))  # table size for big sets
     461          if n <= setsize:
     462              # An n-length list is smaller than a k-length set.
     463              # Invariant:  non-selected at pool[0 : n-i]
     464              pool = list(population)
     465              for i in range(k):
     466                  j = randbelow(n - i)
     467                  result[i] = pool[j]
     468                  pool[j] = pool[n - i - 1]  # move non-selected item into vacancy
     469          else:
     470              selected = set()
     471              selected_add = selected.add
     472              for i in range(k):
     473                  j = randbelow(n)
     474                  while j in selected:
     475                      j = randbelow(n)
     476                  selected_add(j)
     477                  result[i] = population[j]
     478          return result
     479  
     480      def choices(self, population, weights=None, *, cum_weights=None, k=1):
     481          """Return a k sized list of population elements chosen with replacement.
     482  
     483          If the relative weights or cumulative weights are not specified,
     484          the selections are made with equal probability.
     485  
     486          """
     487          random = self.random
     488          n = len(population)
     489          if cum_weights is None:
     490              if weights is None:
     491                  floor = _floor
     492                  n += 0.0    # convert to float for a small speed improvement
     493                  return [population[floor(random() * n)] for i in _repeat(None, k)]
     494              try:
     495                  cum_weights = list(_accumulate(weights))
     496              except TypeError:
     497                  if not isinstance(weights, int):
     498                      raise
     499                  k = weights
     500                  raise TypeError(
     501                      f'The number of choices must be a keyword argument: {k=}'
     502                  ) from None
     503          elif weights is not None:
     504              raise TypeError('Cannot specify both weights and cumulative weights')
     505          if len(cum_weights) != n:
     506              raise ValueError('The number of weights does not match the population')
     507          total = cum_weights[-1] + 0.0   # convert to float
     508          if total <= 0.0:
     509              raise ValueError('Total of weights must be greater than zero')
     510          if not _isfinite(total):
     511              raise ValueError('Total of weights must be finite')
     512          bisect = _bisect
     513          hi = n - 1
     514          return [population[bisect(cum_weights, random() * total, 0, hi)]
     515                  for i in _repeat(None, k)]
     516  
     517  
     518      ## -------------------- real-valued distributions  -------------------
     519  
     520      def uniform(self, a, b):
     521          "Get a random number in the range [a, b) or [a, b] depending on rounding."
     522          return a + (b - a) * self.random()
     523  
     524      def triangular(self, low=0.0, high=1.0, mode=None):
     525          """Triangular distribution.
     526  
     527          Continuous distribution bounded by given lower and upper limits,
     528          and having a given mode value in-between.
     529  
     530          http://en.wikipedia.org/wiki/Triangular_distribution
     531  
     532          """
     533          u = self.random()
     534          try:
     535              c = 0.5 if mode is None else (mode - low) / (high - low)
     536          except ZeroDivisionError:
     537              return low
     538          if u > c:
     539              u = 1.0 - u
     540              c = 1.0 - c
     541              low, high = high, low
     542          return low + (high - low) * _sqrt(u * c)
     543  
     544      def normalvariate(self, mu=0.0, sigma=1.0):
     545          """Normal distribution.
     546  
     547          mu is the mean, and sigma is the standard deviation.
     548  
     549          """
     550          # Uses Kinderman and Monahan method. Reference: Kinderman,
     551          # A.J. and Monahan, J.F., "Computer generation of random
     552          # variables using the ratio of uniform deviates", ACM Trans
     553          # Math Software, 3, (1977), pp257-260.
     554  
     555          random = self.random
     556          while True:
     557              u1 = random()
     558              u2 = 1.0 - random()
     559              z = NV_MAGICCONST * (u1 - 0.5) / u2
     560              zz = z * z / 4.0
     561              if zz <= -_log(u2):
     562                  break
     563          return mu + z * sigma
     564  
     565      def gauss(self, mu=0.0, sigma=1.0):
     566          """Gaussian distribution.
     567  
     568          mu is the mean, and sigma is the standard deviation.  This is
     569          slightly faster than the normalvariate() function.
     570  
     571          Not thread-safe without a lock around calls.
     572  
     573          """
     574          # When x and y are two variables from [0, 1), uniformly
     575          # distributed, then
     576          #
     577          #    cos(2*pi*x)*sqrt(-2*log(1-y))
     578          #    sin(2*pi*x)*sqrt(-2*log(1-y))
     579          #
     580          # are two *independent* variables with normal distribution
     581          # (mu = 0, sigma = 1).
     582          # (Lambert Meertens)
     583          # (corrected version; bug discovered by Mike Miller, fixed by LM)
     584  
     585          # Multithreading note: When two threads call this function
     586          # simultaneously, it is possible that they will receive the
     587          # same return value.  The window is very small though.  To
     588          # avoid this, you have to use a lock around all calls.  (I
     589          # didn't want to slow this down in the serial case by using a
     590          # lock here.)
     591  
     592          random = self.random
     593          z = self.gauss_next
     594          self.gauss_next = None
     595          if z is None:
     596              x2pi = random() * TWOPI
     597              g2rad = _sqrt(-2.0 * _log(1.0 - random()))
     598              z = _cos(x2pi) * g2rad
     599              self.gauss_next = _sin(x2pi) * g2rad
     600  
     601          return mu + z * sigma
     602  
     603      def lognormvariate(self, mu, sigma):
     604          """Log normal distribution.
     605  
     606          If you take the natural logarithm of this distribution, you'll get a
     607          normal distribution with mean mu and standard deviation sigma.
     608          mu can have any value, and sigma must be greater than zero.
     609  
     610          """
     611          return _exp(self.normalvariate(mu, sigma))
     612  
     613      def expovariate(self, lambd):
     614          """Exponential distribution.
     615  
     616          lambd is 1.0 divided by the desired mean.  It should be
     617          nonzero.  (The parameter would be called "lambda", but that is
     618          a reserved word in Python.)  Returned values range from 0 to
     619          positive infinity if lambd is positive, and from negative
     620          infinity to 0 if lambd is negative.
     621  
     622          """
     623          # lambd: rate lambd = 1/mean
     624          # ('lambda' is a Python reserved word)
     625  
     626          # we use 1-random() instead of random() to preclude the
     627          # possibility of taking the log of zero.
     628          return -_log(1.0 - self.random()) / lambd
     629  
     630      def vonmisesvariate(self, mu, kappa):
     631          """Circular data distribution.
     632  
     633          mu is the mean angle, expressed in radians between 0 and 2*pi, and
     634          kappa is the concentration parameter, which must be greater than or
     635          equal to zero.  If kappa is equal to zero, this distribution reduces
     636          to a uniform random angle over the range 0 to 2*pi.
     637  
     638          """
     639          # Based upon an algorithm published in: Fisher, N.I.,
     640          # "Statistical Analysis of Circular Data", Cambridge
     641          # University Press, 1993.
     642  
     643          # Thanks to Magnus Kessler for a correction to the
     644          # implementation of step 4.
     645  
     646          random = self.random
     647          if kappa <= 1e-6:
     648              return TWOPI * random()
     649  
     650          s = 0.5 / kappa
     651          r = s + _sqrt(1.0 + s * s)
     652  
     653          while True:
     654              u1 = random()
     655              z = _cos(_pi * u1)
     656  
     657              d = z / (r + z)
     658              u2 = random()
     659              if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
     660                  break
     661  
     662          q = 1.0 / r
     663          f = (q + z) / (1.0 + q * z)
     664          u3 = random()
     665          if u3 > 0.5:
     666              theta = (mu + _acos(f)) % TWOPI
     667          else:
     668              theta = (mu - _acos(f)) % TWOPI
     669  
     670          return theta
     671  
     672      def gammavariate(self, alpha, beta):
     673          """Gamma distribution.  Not the gamma function!
     674  
     675          Conditions on the parameters are alpha > 0 and beta > 0.
     676  
     677          The probability distribution function is:
     678  
     679                      x ** (alpha - 1) * math.exp(-x / beta)
     680            pdf(x) =  --------------------------------------
     681                        math.gamma(alpha) * beta ** alpha
     682  
     683          """
     684          # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
     685  
     686          # Warning: a few older sources define the gamma distribution in terms
     687          # of alpha > -1.0
     688          if alpha <= 0.0 or beta <= 0.0:
     689              raise ValueError('gammavariate: alpha and beta must be > 0.0')
     690  
     691          random = self.random
     692          if alpha > 1.0:
     693  
     694              # Uses R.C.H. Cheng, "The generation of Gamma
     695              # variables with non-integral shape parameters",
     696              # Applied Statistics, (1977), 26, No. 1, p71-74
     697  
     698              ainv = _sqrt(2.0 * alpha - 1.0)
     699              bbb = alpha - LOG4
     700              ccc = alpha + ainv
     701  
     702              while True:
     703                  u1 = random()
     704                  if not 1e-7 < u1 < 0.9999999:
     705                      continue
     706                  u2 = 1.0 - random()
     707                  v = _log(u1 / (1.0 - u1)) / ainv
     708                  x = alpha * _exp(v)
     709                  z = u1 * u1 * u2
     710                  r = bbb + ccc * v - x
     711                  if r + SG_MAGICCONST - 4.5 * z >= 0.0 or r >= _log(z):
     712                      return x * beta
     713  
     714          elif alpha == 1.0:
     715              # expovariate(1/beta)
     716              return -_log(1.0 - random()) * beta
     717  
     718          else:
     719              # alpha is between 0 and 1 (exclusive)
     720              # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
     721              while True:
     722                  u = random()
     723                  b = (_e + alpha) / _e
     724                  p = b * u
     725                  if p <= 1.0:
     726                      x = p ** (1.0 / alpha)
     727                  else:
     728                      x = -_log((b - p) / alpha)
     729                  u1 = random()
     730                  if p > 1.0:
     731                      if u1 <= x ** (alpha - 1.0):
     732                          break
     733                  elif u1 <= _exp(-x):
     734                      break
     735              return x * beta
     736  
     737      def betavariate(self, alpha, beta):
     738          """Beta distribution.
     739  
     740          Conditions on the parameters are alpha > 0 and beta > 0.
     741          Returned values range between 0 and 1.
     742  
     743          """
     744          ## See
     745          ## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
     746          ## for Ivan Frohne's insightful analysis of why the original implementation:
     747          ##
     748          ##    def betavariate(self, alpha, beta):
     749          ##        # Discrete Event Simulation in C, pp 87-88.
     750          ##
     751          ##        y = self.expovariate(alpha)
     752          ##        z = self.expovariate(1.0/beta)
     753          ##        return z/(y+z)
     754          ##
     755          ## was dead wrong, and how it probably got that way.
     756  
     757          # This version due to Janne Sinkkonen, and matches all the std
     758          # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
     759          y = self.gammavariate(alpha, 1.0)
     760          if y:
     761              return y / (y + self.gammavariate(beta, 1.0))
     762          return 0.0
     763  
     764      def paretovariate(self, alpha):
     765          """Pareto distribution.  alpha is the shape parameter."""
     766          # Jain, pg. 495
     767  
     768          u = 1.0 - self.random()
     769          return u ** (-1.0 / alpha)
     770  
     771      def weibullvariate(self, alpha, beta):
     772          """Weibull distribution.
     773  
     774          alpha is the scale parameter and beta is the shape parameter.
     775  
     776          """
     777          # Jain, pg. 499; bug fix courtesy Bill Arms
     778  
     779          u = 1.0 - self.random()
     780          return alpha * (-_log(u)) ** (1.0 / beta)
     781  
     782  
     783  ## ------------------------------------------------------------------
     784  ## --------------- Operating System Random Source  ------------------
     785  
     786  
     787  class ESC[4;38;5;81mSystemRandom(ESC[4;38;5;149mRandom):
     788      """Alternate random number generator using sources provided
     789      by the operating system (such as /dev/urandom on Unix or
     790      CryptGenRandom on Windows).
     791  
     792       Not available on all systems (see os.urandom() for details).
     793  
     794      """
     795  
     796      def random(self):
     797          """Get the next random number in the range 0.0 <= X < 1.0."""
     798          return (int.from_bytes(_urandom(7)) >> 3) * RECIP_BPF
     799  
     800      def getrandbits(self, k):
     801          """getrandbits(k) -> x.  Generates an int with k random bits."""
     802          if k < 0:
     803              raise ValueError('number of bits must be non-negative')
     804          numbytes = (k + 7) // 8                       # bits / 8 and rounded up
     805          x = int.from_bytes(_urandom(numbytes))
     806          return x >> (numbytes * 8 - k)                # trim excess bits
     807  
     808      def randbytes(self, n):
     809          """Generate n random bytes."""
     810          # os.urandom(n) fails with ValueError for n < 0
     811          # and returns an empty bytes string for n == 0.
     812          return _urandom(n)
     813  
     814      def seed(self, *args, **kwds):
     815          "Stub method.  Not used for a system random number generator."
     816          return None
     817  
     818      def _notimplemented(self, *args, **kwds):
     819          "Method should not be called for a system random number generator."
     820          raise NotImplementedError('System entropy source does not have state.')
     821      getstate = setstate = _notimplemented
     822  
     823  
     824  # ----------------------------------------------------------------------
     825  # Create one instance, seeded from current time, and export its methods
     826  # as module-level functions.  The functions share state across all uses
     827  # (both in the user's code and in the Python libraries), but that's fine
     828  # for most programs and is easier for the casual user than making them
     829  # instantiate their own Random() instance.
     830  
     831  _inst = Random()
     832  seed = _inst.seed
     833  random = _inst.random
     834  uniform = _inst.uniform
     835  triangular = _inst.triangular
     836  randint = _inst.randint
     837  choice = _inst.choice
     838  randrange = _inst.randrange
     839  sample = _inst.sample
     840  shuffle = _inst.shuffle
     841  choices = _inst.choices
     842  normalvariate = _inst.normalvariate
     843  lognormvariate = _inst.lognormvariate
     844  expovariate = _inst.expovariate
     845  vonmisesvariate = _inst.vonmisesvariate
     846  gammavariate = _inst.gammavariate
     847  gauss = _inst.gauss
     848  betavariate = _inst.betavariate
     849  paretovariate = _inst.paretovariate
     850  weibullvariate = _inst.weibullvariate
     851  getstate = _inst.getstate
     852  setstate = _inst.setstate
     853  getrandbits = _inst.getrandbits
     854  randbytes = _inst.randbytes
     855  
     856  
     857  ## ------------------------------------------------------
     858  ## ----------------- test program -----------------------
     859  
     860  def _test_generator(n, func, args):
     861      from statistics import stdev, fmean as mean
     862      from time import perf_counter
     863  
     864      t0 = perf_counter()
     865      data = [func(*args) for i in _repeat(None, n)]
     866      t1 = perf_counter()
     867  
     868      xbar = mean(data)
     869      sigma = stdev(data, xbar)
     870      low = min(data)
     871      high = max(data)
     872  
     873      print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}')
     874      print('avg %g, stddev %g, min %g, max %g\n' % (xbar, sigma, low, high))
     875  
     876  
     877  def _test(N=2000):
     878      _test_generator(N, random, ())
     879      _test_generator(N, normalvariate, (0.0, 1.0))
     880      _test_generator(N, lognormvariate, (0.0, 1.0))
     881      _test_generator(N, vonmisesvariate, (0.0, 1.0))
     882      _test_generator(N, gammavariate, (0.01, 1.0))
     883      _test_generator(N, gammavariate, (0.1, 1.0))
     884      _test_generator(N, gammavariate, (0.1, 2.0))
     885      _test_generator(N, gammavariate, (0.5, 1.0))
     886      _test_generator(N, gammavariate, (0.9, 1.0))
     887      _test_generator(N, gammavariate, (1.0, 1.0))
     888      _test_generator(N, gammavariate, (2.0, 1.0))
     889      _test_generator(N, gammavariate, (20.0, 1.0))
     890      _test_generator(N, gammavariate, (200.0, 1.0))
     891      _test_generator(N, gauss, (0.0, 1.0))
     892      _test_generator(N, betavariate, (3.0, 3.0))
     893      _test_generator(N, triangular, (0.0, 1.0, 1.0 / 3.0))
     894  
     895  
     896  ## ------------------------------------------------------
     897  ## ------------------ fork support  ---------------------
     898  
     899  if hasattr(_os, "fork"):
     900      _os.register_at_fork(after_in_child=_inst.seed)
     901  
     902  
     903  if __name__ == '__main__':
     904      _test()