// 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. Load more
// 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 this module are not designed to be cryptographically secure, and are therefore unsuitable for cryptographic or security-related purposes such as generating authentication tokens or network sequence numbers. For such needs, please use a reputable cryptographic library instead. The new-style generator objects hold their own state so they are immune of threading issues. The generators feature a number of well-known and well-documented methods of generating random numbers. An overall fast and reliable means to generate random numbers is 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 of 19937". In memory-constrained situations, $(LINK2 https://en.wikipedia.org/wiki/Linear_congruential_generator, linear congruential generators) such as `MinstdRand0` and `MinstdRand` might be useful. The standard library provides an alias $(D_PARAM Random) for whichever generator it considers the most fit for the target environment. In addition to random number generators, this module features distributions, which skew a generator's output statistical distribution in various ways. So far the uniform distribution for integers 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 })); ///ditto enum 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;