From fd2e5ba03c2c1304dd516a32e2659c3ed01c1936 Mon Sep 17 00:00:00 2001 From: n8sh Date: Wed, 20 Sep 2017 14:56:52 -0400 Subject: [PATCH] =?UTF-8?q?Fix=20Issue=2017847=20-=20Properly=20sanitize?= =?UTF-8?q?=20seeds=20for=20Park=E2=80=93Miller=20engines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As in XorshiftEngine, sanitizing the seed is more useful than throwing an exception. The original check was broken because it checked the seed before taking the modulus. Making this change allows unpredictableSeed to be marked nothrow and @nogc. --- std/random.d | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/std/random.d b/std/random.d index d7f8a563c68..9e9a344691f 100644 --- a/std/random.d +++ b/std/random.d @@ -362,7 +362,7 @@ The parameters of this distribution. The random number is $(D_PARAM x Constructs a $(D_PARAM LinearCongruentialEngine) generator seeded with $(D x0). */ - this(UIntType x0) @safe pure + this(UIntType x0) @safe pure nothrow @nogc { seed(x0); } @@ -370,15 +370,15 @@ $(D x0). /** (Re)seeds the generator. */ - void seed(UIntType x0 = 1) @safe pure + void seed(UIntType x0 = 1) @safe pure nothrow @nogc { + _x = modulus ? (x0 % modulus) : x0; static if (c == 0) { - import std.exception : enforce; - enforce(x0, "Invalid (zero) seed for " - ~ LinearCongruentialEngine.stringof); + //Necessary to prevent generator from outputting an endless series of zeroes. + if (_x == 0) + _x = max; } - _x = modulus ? (x0 % modulus) : x0; popFront(); } @@ -537,6 +537,14 @@ alias MinstdRand = LinearCongruentialEngine!(uint, 48_271, 0, 2_147_483_647); } } +@safe unittest +{ + auto rnd0 = MinstdRand0(MinstdRand0.modulus); + auto n = rnd0.front; + rnd0.popFront(); + assert(n != rnd0.front); +} + /** The $(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister) generator. */ @@ -1291,7 +1299,7 @@ random number sequences every run. Returns: A single unsigned integer seed value, different on each successive call */ -@property uint unpredictableSeed() @trusted +@property uint unpredictableSeed() @trusted nothrow @nogc { import core.thread : Thread, getpid, MonoTime; static bool seeded;