Wolfgang Thallergcc16 merge934c3885 months agoHistory
4378 lines · 135.2 KB · D
RawDownload
// Written in the D programming language. /**Facilities for random number generation. $(SCRIPT inhibitQuickIndex = 1;)$(DIVC quickindex,$(BOOKTABLE,$(TR $(TH Category) $(TH Functions))$(TR $(TD Uniform sampling) $(TD    $(LREF uniform)    $(LREF uniform01)    $(LREF uniformDistribution)))$(TR $(TD Element sampling) $(TD    $(LREF choice)    $(LREF dice)))$(TR $(TD Range sampling) $(TD    $(LREF randomCover)    $(LREF randomSample)))$(TR $(TD Default Random Engines) $(TD    $(LREF rndGen)    $(LREF Random)    $(LREF unpredictableSeed)))$(TR $(TD Linear Congruential Engines) $(TD    $(LREF MinstdRand)    $(LREF MinstdRand0)    $(LREF LinearCongruentialEngine)))$(TR $(TD Mersenne Twister Engines) $(TD    $(LREF Mt19937)    $(LREF Mt19937_64)    $(LREF MersenneTwisterEngine)))$(TR $(TD Xorshift Engines) $(TD    $(LREF Xorshift)    $(LREF XorshiftEngine)    $(LREF Xorshift32)    $(LREF Xorshift64)    $(LREF Xorshift96)    $(LREF Xorshift128)    $(LREF Xorshift160)    $(LREF Xorshift192)))$(TR $(TD Shuffle) $(TD    $(LREF partialShuffle)    $(LREF randomShuffle)))$(TR $(TD Traits) $(TD    $(LREF isSeedable)    $(LREF isUniformRNG))))) $(RED Disclaimer:) The random number generators and API provided in thismodule are not designed to be cryptographically secure, and are thereforeunsuitable for cryptographic or security-related purposes such as generatingauthentication tokens or network sequence numbers. For such needs, please use areputable cryptographic library instead. The new-style generator objects hold their own state so they areimmune of threading issues. The generators feature a number ofwell-known and well-documented methods of generating randomnumbers. An overall fast and reliable means to generate random numbersis the $(D_PARAM Mt19937) generator, which derives its name from"$(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister)with a period of 2 to the power of19937". In memory-constrained situations,$(LINK2 https://en.wikipedia.org/wiki/Linear_congruential_generator,linear congruential generators) such as `MinstdRand0` and `MinstdRand` might beuseful. The standard library provides an alias $(D_PARAM Random) forwhichever generator it considers the most fit for the targetenvironment. In addition to random number generators, this module featuresdistributions, which skew a generator's output statisticaldistribution in various ways. So far the uniform distribution forintegers and real numbers have been implemented. Source:    $(PHOBOSSRC std/random.d) Macros: Copyright: Copyright Andrei Alexandrescu 2008 - 2009, Joseph Rushton Wakeling 2012.License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).Authors:   $(HTTP erdani.org, Andrei Alexandrescu)           Masahiro Nakagawa (Xorshift random generator)           $(HTTP braingam.es, Joseph Rushton Wakeling) (Algorithm D for random sampling)           Ilya Yaroshenko (Mersenne Twister implementation, adapted from $(HTTPS github.com/libmir/mir-random, mir-random))Credits:   The entire random number library architecture is derived from the           excellent $(HTTP open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf, C++0X)           random number facility proposed by Jens Maurer and contributed to by           researchers at the Fermi laboratory (excluding Xorshift).*//*         Copyright Andrei Alexandrescu 2008 - 2009.Distributed under the Boost Software License, Version 1.0.   (See accompanying file LICENSE_1_0.txt or copy at         http://www.boost.org/LICENSE_1_0.txt)*/module std.random;  import std.range.primitives;import std.traits; ///@safe unittest{    import std.algorithm.comparison : among, equal;    import std.range : iota;     // seed a random generator with a constant    auto rnd = Random(42);     // Generate a uniformly-distributed integer in the range [0, 14]    // If no random generator is passed, the global `rndGen` would be used    auto i = uniform(0, 15, rnd);    assert(i >= 0 && i < 15);     // Generate a uniformly-distributed real in the range [0, 100)    auto r = uniform(0.0L, 100.0L, rnd);    assert(r >= 0 && r < 100);     // Sample from a custom type    enum Fruit { apple, mango, pear }    auto f = rnd.uniform!Fruit;    with(Fruit)    assert(f.among(apple, mango, pear));     // Generate a 32-bit random number    auto u = uniform!uint(rnd);    static assert(is(typeof(u) == uint));     // Generate a random number in the range in the range [0, 1)    auto u2 = uniform01(rnd);    assert(u2 >= 0 && u2 < 1);     // Select an element randomly    auto el = 10.iota.choice(rnd);    assert(0 <= el && el < 10);     // Throw a dice with custom proportions    // 0: 20%, 1: 10%, 2: 60%    auto val = rnd.dice(0.2, 0.1, 0.6);    assert(0 <= val && val <= 2);     auto rnd2 = MinstdRand0(42);     // Select a random subsample from a range    assert(10.iota.randomSample(3, rnd2).equal([7, 8, 9]));     // Cover all elements in an array in random order    version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147        assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));    else        assert(10.iota.randomCover(rnd2).equal([4, 8, 7, 3, 5, 9, 2, 6, 0, 1]));     // Shuffle an array    version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147        assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));    else        assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([4, 2, 5, 0, 1]));} version (OSX)    version = Darwin;else version (iOS)    version = Darwin;else version (TVOS)    version = Darwin;else version (WatchOS)    version = Darwin; version (D_InlineAsm_X86) version = InlineAsm_X86_Any;version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any; version (StdUnittest){    static import std.meta;    package alias Xorshift64_64 = XorshiftEngine!(ulong, 64, -12, 25, -27);    package alias Xorshift128_64 = XorshiftEngine!(ulong, 128, 23, -18, -5);    package alias PseudoRngTypes = std.meta.AliasSeq!(MinstdRand0, MinstdRand, Mt19937, Xorshift32, Xorshift64,                                                      Xorshift96, Xorshift128, Xorshift160, Xorshift192,                                                      Xorshift64_64, Xorshift128_64);} // Segments of the code in this file Copyright (c) 1997 by Rick Booth// From "Inner Loops" by Rick Booth, Addison-Wesley // Work derived from: /*   A C-program for MT19937, with initialization improved 2002/1/26.   Coded by Takuji Nishimura and Makoto Matsumoto.    Before using, initialize the state by using init_genrand(seed)   or init_by_array(init_key, key_length).    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,   All rights reserved.    Redistribution and use in source and binary forms, with or without   modification, are permitted provided that the following conditions   are met:      1. Redistributions of source code must retain the above copyright        notice, this list of conditions and the following disclaimer.      2. Redistributions in binary form must reproduce the above copyright        notice, this list of conditions and the following disclaimer in the        documentation and/or other materials provided with the distribution.      3. The names of its contributors may not be used to endorse or promote        products derived from this software without specific prior written        permission.    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     Any feedback is very welcome.   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)*/ /** * Test if Rng is a random-number generator. The overload * taking a ElementType also makes sure that the Rng generates * values of that type. * * A random-number generator has at least the following features: * $(UL *   $(LI it's an InputRange) *   $(LI it has a 'bool isUniformRandom' field readable in CTFE) * ) */enum isUniformRNG(Rng, ElementType) = .isUniformRNG!Rng &&	is(std.range.primitives.ElementType!Rng == ElementType); /** * ditto */enum isUniformRNG(Rng) = isInputRange!Rng &&	is(typeof(	{        static assert(Rng.isUniformRandom); //tag    })); ///@safe unittest{    struct NoRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}    }    static assert(!isUniformRNG!(NoRng));     struct validRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}         enum isUniformRandom = true;    }    static assert(isUniformRNG!(validRng, uint));    static assert(isUniformRNG!(validRng));} @safe unittest{    // two-argument predicate should not require @property on `front`    // https://issues.dlang.org/show_bug.cgi?id=19837    struct Rng    {        float front() {return 0;}        void popFront() {}        enum empty = false;        enum isUniformRandom = true;    }    static assert(isUniformRNG!(Rng, float));} /** * Test if Rng is seedable. The overload * taking a SeedType also makes sure that the Rng can be seeded with SeedType. * * A seedable random-number generator has the following additional features: * $(UL *   $(LI it has a 'seed(ElementType)' function) * ) */enum isSeedable(Rng, SeedType) = isUniformRNG!(Rng) &&	is(typeof(    {        Rng r = void;              ///< can define a Rng object        SeedType s = void; ///< Dummy doc to silence D-scanner.        r.seed(s); // can seed a Rng    })); ///dittoenum isSeedable(Rng) = isUniformRNG!Rng &&	is(typeof(    {        Rng r = void;                     ///< can define a Rng object        alias SeedType = typeof(r.front);        SeedType s = void; ///< Dummy doc to silence D-scanner.        r.seed(s); // can seed a Rng    })); ///@safe unittest{    struct validRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}         enum isUniformRandom = true;    }    static assert(!isSeedable!(validRng, uint));    static assert(!isSeedable!(validRng));     struct seedRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}        void seed(uint val){}        enum isUniformRandom = true;    }    static assert(isSeedable!(seedRng, uint));    static assert(!isSeedable!(seedRng, ulong));    static assert(isSeedable!(seedRng));} @safe @nogc pure nothrow unittest{    struct NoRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}    }    static assert(!isUniformRNG!(NoRng, uint));    static assert(!isUniformRNG!(NoRng));    static assert(!isSeedable!(NoRng, uint));    static assert(!isSeedable!(NoRng));     struct NoRng2    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}         enum isUniformRandom = false;    }    static assert(!isUniformRNG!(NoRng2, uint));    static assert(!isUniformRNG!(NoRng2));    static assert(!isSeedable!(NoRng2, uint));    static assert(!isSeedable!(NoRng2));     struct NoRng3    {        @property bool empty() {return false;}        void popFront() {}         enum isUniformRandom = true;    }    static assert(!isUniformRNG!(NoRng3, uint));    static assert(!isUniformRNG!(NoRng3));    static assert(!isSeedable!(NoRng3, uint));    static assert(!isSeedable!(NoRng3));     struct validRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}         enum isUniformRandom = true;    }    static assert(isUniformRNG!(validRng, uint));    static assert(isUniformRNG!(validRng));    static assert(!isSeedable!(validRng, uint));    static assert(!isSeedable!(validRng));     struct seedRng    {        @property uint front() {return 0;}        @property bool empty() {return false;}        void popFront() {}        void seed(uint val){}        enum isUniformRandom = true;    }    static assert(isUniformRNG!(seedRng, uint));    static assert(isUniformRNG!(seedRng));    static assert(isSeedable!(seedRng, uint));    static assert(!isSeedable!(seedRng, ulong));    static assert(isSeedable!(seedRng));} /**Linear Congruential generator. When m = 0, no modulus is used. */struct LinearCongruentialEngine(UIntType, UIntType a, UIntType c, UIntType m)if (isUnsigned!UIntType){    ///Mark this as a Rng    enum bool isUniformRandom = true;    /// Does this generator have a fixed range? ($(D_PARAM true)).    enum bool hasFixedRange = true;    /// Lowest generated value (`1` if $(D c == 0), `0` otherwise).    enum UIntType min = ( c == 0 ? 1 : 0 );    /// Highest generated value ($(D modulus - 1)).    enum UIntType max = m - 1;/**The parameters of this distribution. The random number is $(D_PARAM x= (x * multipler + increment) % modulus). */    enum UIntType multiplier = a;    ///ditto    enum UIntType increment = c;    ///ditto    enum UIntType modulus = m;     static assert(isIntegral!(UIntType));    static assert(m == 0 || a < m);    static assert(m == 0 || c < m);    static assert(m == 0 ||            (cast(ulong) a * (m-1) + c) % m == (c < a ? c - a + m : c - a));     // Check for maximum range    private static ulong gcd(ulong a, ulong b) @safe pure nothrow @nogc    {        while (b)        {            auto t = b;            b = a % b;            a = t;        }        return a;    }     private static ulong primeFactorsOnly(ulong n) @safe pure nothrow @nogc    {        ulong result = 1;        ulong iter = 2;        for (; n >= iter * iter; iter += 2 - (iter == 2))        {            if (n % iter) continue;            result *= iter;            do            {                n /= iter;            } while (n % iter == 0);        }        return result * n;    }     @safe pure nothrow unittest    {        static assert(primeFactorsOnly(100) == 10);        //writeln(primeFactorsOnly(11));        static assert(primeFactorsOnly(11) == 11);        static assert(primeFactorsOnly(7 * 7 * 7 * 11 * 15 * 11) == 7 * 11 * 15);        static assert(primeFactorsOnly(129 * 2) == 129 * 2);        // enum x = primeFactorsOnly(7 * 7 * 7 * 11 * 15);        // static assert(x == 7 * 11 * 15);    }     private static bool properLinearCongruentialParameters(ulong m,            ulong a, ulong c) @safe pure nothrow @nogc    {        if (m == 0)        {            static if (is(UIntType == uint))            {                // Assume m is uint.max + 1                m = (1uL << 32);            }            else            {                return false;

Lines 1–500 of 4378.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t