Fix bugs introduced by rewrite (in particular, time-based initialization
got broken).  Also added new method .jumpahead(N).  This finally gives us
a semi-decent answer to how Python's RNGs can be used safely and efficiently
in multithreaded programs (although it requires the user to use the new
machinery!).
diff --git a/Lib/random.py b/Lib/random.py
index a818f73..1b91886 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -72,8 +72,8 @@
         self.gauss_next = None
 
     # Specific to Wichmann-Hill generator.  Subclasses wishing to use a
-    # different core generator should override seed(), random(),  getstate()
-    # and setstate().
+    # different core generator should override the seed(), random(),
+    # getstate(), setstate(), and jumpahead() methods.
 
     def __whseed(self, x=0, y=0, z=0):
         """Set the Wichmann-Hill seed from (x, y, z).
@@ -104,6 +104,7 @@
 
         if a is None:
             self.__whseed()
+            return
         a = hash(a)
         a, x = divmod(a, 256)
         a, y = divmod(a, 256)
@@ -115,11 +116,10 @@
 
     def getstate(self):
         """Return internal state; can be passed to setstate() later."""
-
         return self.VERSION, self._seed, self.gauss_next
 
     def __getstate__(self): # for pickle
-        self.getstate()
+        return self.getstate()
 
     def setstate(self, state):
         """Restore internal state from object returned by getstate()."""
@@ -134,6 +134,28 @@
     def __setstate__(self, state):  # for pickle
         self.setstate(state)
 
+    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 random(self):
         """Get the next random number in the range [0.0, 1.0)."""
 
@@ -471,6 +493,17 @@
     print 'avg %g, stddev %g, min %g, max %g' % \
               (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
     print 'LOG4          =', LOG4
@@ -515,6 +548,7 @@
 weibullvariate = _inst.weibullvariate
 getstate = _inst.getstate
 setstate = _inst.setstate
+jumpahead = _inst.jumpahead
 
 if __name__ == '__main__':
     _test()