www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 21381] New: std.random.uniform!T(urng) when T is long or

https://issues.dlang.org/show_bug.cgi?id=21381

          Issue ID: 21381
           Summary: std.random.uniform!T(urng) when T is long or ulong and
                    urng.front is signed int will be biased in its high
                    bits
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: phobos
          Assignee: nobody puremagic.com
          Reporter: n8sh.secondary hotmail.com

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.
}
---

--
Nov 12 2020