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