Comment #0 by n8sh.secondary — 2020-11-13T02:43:48Z
std.random.uniform!T(urng) when T is long or ulong and urng.front is signed int will be biased in its high bits. No pseudorandom number generators defined in std.random produce signed integers but nothing in the function constraints or documentation advises library users against defining a custom PRNG that does.
Demonstration:
---
void main()
{
import std.random : isUniformRNG, uniform;
import std.stdio : writefln;
static struct SignedIntLCG
{
enum bool isUniformRandom = true;
enum int min = int.min;
enum int max = int.max;
enum bool empty = false;
int front;
void popFront() { front = front * 0xac564b05 + 1; }
}
static assert(isUniformRNG!SignedIntLCG);
// The higher bits of uniform!long(signedIntLCG) are biased towards
// non-zero with increasing probability. The highest bit of
// uniform!ulong(signedIntLCG) has a 75% chance of being non-zero.
auto signedIntLCG = SignedIntLCG(123456789);
size_t timesHighBitWas1 = 0;
foreach (_; 0 .. 1_000_000)
timesHighBitWas1 += uniform!ulong(signedIntLCG) >>> 63;
writefln("%,d", timesHighBitWas1); // Outputs 750,158.
}
---
Comment #1 by robert.schadek — 2024-12-01T16:37:52Z