Update random module to cpython 3.10

This commit is contained in:
snowapril
2021-11-30 00:00:16 +09:00
parent 30fe670d75
commit e009f12e3f

85
Lib/random.py vendored
View File

@@ -48,7 +48,7 @@ General notes on the underlying Mersenne Twister core generator:
from warnings import warn as _warn
from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
from math import tau as TWOPI, floor as _floor
from math import tau as TWOPI, floor as _floor, isfinite as _isfinite
try:
from os import urandom as _urandom
except ImportError:
@@ -59,6 +59,7 @@ except ImportError:
raise NotImplementedError("urandom")
_os = None
from _collections_abc import Set as _Set, Sequence as _Sequence
from operator import index as _index
from itertools import accumulate as _accumulate, repeat as _repeat
from bisect import bisect as _bisect
try:
@@ -109,6 +110,7 @@ LOG4 = _log(4.0)
SG_MAGICCONST = 1.0 + _log(4.5)
BPF = 53 # Number of bits in a float
RECIP_BPF = 2 ** -BPF
_ONE = 1
class Random(_random.Random):
@@ -300,7 +302,7 @@ class Random(_random.Random):
## -------------------- integer methods -------------------
def randrange(self, start, stop=None, step=1):
def randrange(self, start, stop=None, step=_ONE):
"""Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
@@ -310,38 +312,68 @@ class Random(_random.Random):
# This code is a bit messy to make it fast for the
# common case while still doing adequate error checking.
istart = int(start)
if istart != start:
raise ValueError("non-integer arg 1 for randrange()")
try:
istart = _index(start)
except TypeError:
istart = int(start)
if istart != start:
_warn('randrange() will raise TypeError in the future',
DeprecationWarning, 2)
raise ValueError("non-integer arg 1 for randrange()")
_warn('non-integer arguments to randrange() have been deprecated '
'since Python 3.10 and will be removed in a subsequent '
'version',
DeprecationWarning, 2)
if stop is None:
# We don't check for "step != 1" because it hasn't been
# type checked and converted to an integer yet.
if step is not _ONE:
raise TypeError('Missing a non-None stop argument')
if istart > 0:
return self._randbelow(istart)
raise ValueError("empty range for randrange()")
# stop argument supplied.
istop = int(stop)
if istop != stop:
raise ValueError("non-integer stop for randrange()")
try:
istop = _index(stop)
except TypeError:
istop = int(stop)
if istop != stop:
_warn('randrange() will raise TypeError in the future',
DeprecationWarning, 2)
raise ValueError("non-integer stop for randrange()")
_warn('non-integer arguments to randrange() have been deprecated '
'since Python 3.10 and will be removed in a subsequent '
'version',
DeprecationWarning, 2)
width = istop - istart
if step == 1 and width > 0:
return istart + self._randbelow(width)
if step == 1:
try:
istep = _index(step)
except TypeError:
istep = int(step)
if istep != step:
_warn('randrange() will raise TypeError in the future',
DeprecationWarning, 2)
raise ValueError("non-integer step for randrange()")
_warn('non-integer arguments to randrange() have been deprecated '
'since Python 3.10 and will be removed in a subsequent '
'version',
DeprecationWarning, 2)
# Fast path.
if istep == 1:
if width > 0:
return istart + self._randbelow(width)
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
# Non-unit step argument supplied.
istep = int(step)
if istep != step:
raise ValueError("non-integer step for randrange()")
if istep > 0:
n = (width + istep - 1) // istep
elif istep < 0:
n = (width + istep + 1) // istep
else:
raise ValueError("zero step for randrange()")
if n <= 0:
raise ValueError("empty range for randrange()")
return istart + istep * self._randbelow(n)
def randint(self, a, b):
@@ -437,13 +469,14 @@ class Random(_random.Random):
# too many calls to _randbelow(), making them slower and
# causing them to eat more entropy than necessary.
if isinstance(population, _Set):
_warn('Sampling from a set deprecated\n'
'since Python 3.9 and will be removed in a subsequent version.',
DeprecationWarning, 2)
population = tuple(population)
if not isinstance(population, _Sequence):
raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
if isinstance(population, _Set):
_warn('Sampling from a set deprecated\n'
'since Python 3.9 and will be removed in a subsequent version.',
DeprecationWarning, 2)
population = tuple(population)
else:
raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).")
n = len(population)
if counts is not None:
cum_counts = list(_accumulate(counts))
@@ -513,6 +546,8 @@ class Random(_random.Random):
total = cum_weights[-1] + 0.0 # convert to float
if total <= 0.0:
raise ValueError('Total of weights must be greater than zero')
if not _isfinite(total):
raise ValueError('Total of weights must be finite')
bisect = _bisect
hi = n - 1
return [population[bisect(cum_weights, random() * total, 0, hi)]
@@ -703,7 +738,7 @@ class Random(_random.Random):
bbb = alpha - LOG4
ccc = alpha + ainv
while 1:
while True:
u1 = random()
if not 1e-7 < u1 < 0.9999999:
continue
@@ -770,7 +805,7 @@ class Random(_random.Random):
# Jain, pg. 495
u = 1.0 - self.random()
return 1.0 / u ** (1.0 / alpha)
return u ** (-1.0 / alpha)
def weibullvariate(self, alpha, beta):
"""Weibull distribution.
@@ -866,7 +901,7 @@ def _test_generator(n, func, args):
from time import perf_counter
t0 = perf_counter()
data = [func(*args) for i in range(n)]
data = [func(*args) for i in _repeat(None, n)]
t1 = perf_counter()
xbar = mean(data)