forked from Rust-related/RustPython
Update random module to cpython 3.10
This commit is contained in:
85
Lib/random.py
vendored
85
Lib/random.py
vendored
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user