Remove defunct parts of the random module
diff --git a/Lib/random.py b/Lib/random.py
index d8d2c1e..5e57203 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -30,9 +30,6 @@
* The period is 2**19937-1.
* It is one of the most extensively tested generators in existence.
-* Without a direct way to compute N steps forward, the semantics of
- jumpahead(n) are weakened to simply jump to another distant state and rely
- on the large period to avoid overlapping sequences.
* The random() method is implemented in C, executes in a single Python step,
and is, therefore, threadsafe.
@@ -49,7 +46,7 @@
"randrange","shuffle","normalvariate","lognormvariate",
"expovariate","vonmisesvariate","gammavariate",
"gauss","betavariate","paretovariate","weibullvariate",
- "getstate","setstate","jumpahead", "WichmannHill", "getrandbits",
+ "getstate","setstate", "getrandbits",
"SystemRandom"]
NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
@@ -70,14 +67,11 @@
"""Random number generator base class used by bound module functions.
Used to instantiate instances of Random to get generators that don't
- share state. Especially useful for multi-threaded programs, creating
- a different instance of Random for each thread, and using the jumpahead()
- method to ensure that the generated sequences seen by each thread don't
- overlap.
+ share state.
Class Random can also be subclassed if you want to use a different basic
generator of your own devising: in that case, override the following
- methods: random(), seed(), getstate(), setstate() and jumpahead().
+ methods: random(), seed(), getstate(), and setstate().
Optionally, implement a getrandombits() method so that randrange()
can cover arbitrarily large ranges.
@@ -615,156 +609,6 @@
u = 1.0 - self.random()
return alpha * pow(-_log(u), 1.0/beta)
-## -------------------- Wichmann-Hill -------------------
-
-class WichmannHill(Random):
-
- VERSION = 1 # used by getstate/setstate
-
- def seed(self, a=None):
- """Initialize internal state from hashable object.
-
- None or no argument seeds from current time or from an operating
- system specific randomness source if available.
-
- If a is not None or an int or long, hash(a) is used instead.
-
- If a is an int or long, a is used directly. Distinct values between
- 0 and 27814431486575L inclusive are guaranteed to yield distinct
- internal states (this guarantee is specific to the default
- Wichmann-Hill generator).
- """
-
- if a is None:
- try:
- a = int(_hexlify(_urandom(16)), 16)
- except NotImplementedError:
- import time
- a = int(time.time() * 256) # use fractional seconds
-
- if not isinstance(a, int):
- a = hash(a)
-
- a, x = divmod(a, 30268)
- a, y = divmod(a, 30306)
- a, z = divmod(a, 30322)
- self._seed = int(x)+1, int(y)+1, int(z)+1
-
- self.gauss_next = None
-
- 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 getstate(self):
- """Return internal state; can be passed to setstate() later."""
- return self.VERSION, self._seed, self.gauss_next
-
- def setstate(self, state):
- """Restore internal state from object returned by getstate()."""
- version = state[0]
- if version == 1:
- version, self._seed, self.gauss_next = state
- else:
- raise ValueError("state with version %s passed to "
- "Random.setstate() of version %s" %
- (version, self.VERSION))
-
- def jumpahead(self, n):
- """Act as if n calls to random() were made, but quickly.
-
- n is an int, greater than or equal to 0.
-
- Example use: If you have 2 threads and know that each will
- consume no more than a million random numbers, create two Random
- objects r1 and r2, then do
- r2.setstate(r1.getstate())
- r2.jumpahead(1000000)
- Then r1 and r2 will use guaranteed-disjoint segments of the full
- period.
- """
-
- if not n >= 0:
- raise ValueError("n must be >= 0")
- x, y, z = self._seed
- x = int(x * pow(171, n, 30269)) % 30269
- y = int(y * pow(172, n, 30307)) % 30307
- z = int(z * pow(170, n, 30323)) % 30323
- self._seed = x, y, z
-
- def __whseed(self, x=0, y=0, z=0):
- """Set the Wichmann-Hill seed from (x, y, z).
-
- These must be integers in the range [0, 256).
- """
-
- if not type(x) == type(y) == type(z) == int:
- raise TypeError('seeds must be integers')
- if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
- raise ValueError('seeds must be in range(0, 256)')
- if 0 == x == y == z:
- # Initialize from current time
- import time
- t = int(time.time() * 256)
- t = int((t&0xffffff) ^ (t>>24))
- t, x = divmod(t, 256)
- t, y = divmod(t, 256)
- t, z = divmod(t, 256)
- # Zero is a poor seed, so substitute 1
- self._seed = (x or 1, y or 1, z or 1)
-
- self.gauss_next = None
-
- def whseed(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.
-
- This is obsolete, provided for compatibility with the seed routine
- used prior to Python 2.1. Use the .seed() method instead.
- """
-
- if a is None:
- self.__whseed()
- return
- a = hash(a)
- a, x = divmod(a, 256)
- a, y = divmod(a, 256)
- a, z = divmod(a, 256)
- x = (x + a) % 256 or 1
- y = (y + a) % 256 or 1
- z = (z + a) % 256 or 1
- self.__whseed(x, y, z)
-
## --------------- Operating System Random Source ------------------
class SystemRandom(Random):
@@ -789,10 +633,9 @@
x = int(_hexlify(_urandom(bytes)), 16)
return x >> (bytes * 8 - k) # trim excess bits
- def _stub(self, *args, **kwds):
+ def seed(self, *args, **kwds):
"Stub method. Not used for a system random number generator."
return None
- seed = jumpahead = _stub
def _notimplemented(self, *args, **kwds):
"Method should not be called for a system random number generator."
@@ -866,7 +709,6 @@
weibullvariate = _inst.weibullvariate
getstate = _inst.getstate
setstate = _inst.setstate
-jumpahead = _inst.jumpahead
getrandbits = _inst.getrandbits
if __name__ == '__main__':
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index b6d2ec0..892535d 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -444,7 +444,7 @@
>>> roots = sets[:]
>>> import random
->>> gen = random.WichmannHill(42)
+>>> gen = random.Random(42)
>>> while 1:
... for s in sets:
... print(" %s->%s" % (s, s.find()), end='')
@@ -458,29 +458,29 @@
... else:
... break
A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->M
-merged D into G
- A->A B->B C->C D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
-merged C into F
- A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M
+merged I into A
+ A->A B->B C->C D->D E->E F->F G->G H->H I->A J->J K->K L->L M->M
+merged D into C
+ A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->K L->L M->M
+merged K into H
+ A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->H L->L M->M
merged L into A
- A->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->A M->M
-merged H into E
- A->A B->B C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
-merged B into E
- A->A B->E C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M
+ A->A B->B C->C D->C E->E F->F G->G H->H I->A J->J K->H L->A M->M
+merged E into A
+ A->A B->B C->C D->C E->A F->F G->G H->H I->A J->J K->H L->A M->M
+merged B into G
+ A->A B->G C->C D->C E->A F->F G->G H->H I->A J->J K->H L->A M->M
+merged A into F
+ A->F B->G C->C D->C E->F F->F G->G H->H I->F J->J K->H L->F M->M
+merged H into G
+ A->F B->G C->C D->C E->F F->F G->G H->G I->F J->J K->G L->F M->M
+merged F into J
+ A->J B->G C->C D->C E->J F->J G->G H->G I->J J->J K->G L->J M->M
+merged M into C
+ A->J B->G C->C D->C E->J F->J G->G H->G I->J J->J K->G L->J M->C
merged J into G
- A->A B->E C->F D->G E->E F->F G->G H->E I->I J->G K->K L->A M->M
-merged E into G
- A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->M
-merged M into G
- A->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->G
-merged I into K
- A->A B->G C->F D->G E->G F->F G->G H->G I->K J->G K->K L->A M->G
-merged K into A
- A->A B->G C->F D->G E->G F->F G->G H->G I->A J->G K->A L->A M->G
-merged F into A
- A->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G
-merged A into G
+ A->G B->G C->C D->C E->G F->G G->G H->G I->G J->G K->G L->G M->C
+merged C into G
A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G
"""
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index 6adcd06..a7fe605 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -42,21 +42,6 @@
self.assertRaises(TypeError, self.gen.seed, 1, 2)
self.assertRaises(TypeError, type(self.gen), [])
- def test_jumpahead(self):
- self.gen.seed()
- state1 = self.gen.getstate()
- self.gen.jumpahead(100)
- state2 = self.gen.getstate() # s/b distinct from state1
- self.assertNotEqual(state1, state2)
- self.gen.jumpahead(100)
- state3 = self.gen.getstate() # s/b distinct from state2
- self.assertNotEqual(state2, state3)
-
- self.assertRaises(TypeError, self.gen.jumpahead) # needs an arg
- self.assertRaises(TypeError, self.gen.jumpahead, "ick") # wrong type
- self.assertRaises(TypeError, self.gen.jumpahead, 2.3) # wrong type
- self.assertRaises(TypeError, self.gen.jumpahead, 2, 3) # too many
-
def test_sample(self):
# For the entire allowable range of 0 <= k <= N, validate that
# the sample is of the correct length and contains only unique items
@@ -157,48 +142,6 @@
f.close()
self.assertEqual(r.randrange(1000), value)
-class WichmannHill_TestBasicOps(TestBasicOps):
- gen = random.WichmannHill()
-
- def test_setstate_first_arg(self):
- self.assertRaises(ValueError, self.gen.setstate, (2, None, None))
-
- def test_strong_jumpahead(self):
- # tests that jumpahead(n) semantics correspond to n calls to random()
- N = 1000
- s = self.gen.getstate()
- self.gen.jumpahead(N)
- r1 = self.gen.random()
- # now do it the slow way
- self.gen.setstate(s)
- for i in range(N):
- self.gen.random()
- r2 = self.gen.random()
- self.assertEqual(r1, r2)
-
- def test_gauss_with_whseed(self):
- # Ensure that the seed() method initializes all the hidden state. In
- # particular, through 2.2.1 it failed to reset a piece of state used
- # by (and only by) the .gauss() method.
-
- for seed in 1, 12, 123, 1234, 12345, 123456, 654321:
- self.gen.whseed(seed)
- x1 = self.gen.random()
- y1 = self.gen.gauss(0, 1)
-
- self.gen.whseed(seed)
- x2 = self.gen.random()
- y2 = self.gen.gauss(0, 1)
-
- self.assertEqual(x1, x2)
- self.assertEqual(y1, y2)
-
- def test_bigrand(self):
- # Verify warnings are raised when randrange is too large for random()
- with test_support.catch_warning():
- warnings.filterwarnings("error", "Underlying random")
- self.assertRaises(UserWarning, self.gen.randrange, 2**60)
-
class SystemRandom_TestBasicOps(TestBasicOps):
gen = random.SystemRandom()
@@ -214,10 +157,6 @@
# Doesn't need to do anything except not fail
self.gen.seed(100)
- def test_jumpahead(self):
- # Doesn't need to do anything except not fail
- self.gen.jumpahead(100)
-
def test_gauss(self):
self.gen.gauss_next = None
self.gen.seed(100)
@@ -541,8 +480,7 @@
def test_main(verbose=None):
- testclasses = [WichmannHill_TestBasicOps,
- MersenneTwister_TestBasicOps,
+ testclasses = [MersenneTwister_TestBasicOps,
TestDistributions,
TestModule]