www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 21382] New: std.random.uniform!T(urng) when T is an integer

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

          Issue ID: 21382
           Summary: std.random.uniform!T(urng) when T is an integer type
                    and urng.front is floating point is completely broken
           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 an integer type and urng.front is floating
point is completely broken

std.random.uniform!T(urng) when T is an integer type and urng.front is floating
point is completely broken. No predefined generators in std.random have
floating point ElementType but user-defined generators might.

Demonstration:
---
void main()
{
    import std.random : isUniformRNG, uniform;

    static bool isEveryResultZero(T,RNG)(ref RNG rng, size_t numTrials)
    {
        foreach (_; 0 .. numTrials)
            if (uniform!T(rng) != 0)
                return false;
        return true;
    }

    static struct Double01PRNG
    {
        enum bool isUniformRandom = true;
        enum double min = 0.0;
        enum double max = (ulong.max >>> (64 - 53)) * 0x1p-53;
        enum bool empty = false;

        ulong state;
         property double front() const {
            auto result = (state >>> (64 - 53)) * 0x1p-53;
            assert(result >= 0 && result < 1);
            return result;
        }
        void popFront() { state = state * 2862933555777941757 + 1; }
    }
    static assert(isUniformRNG!Double01PRNG);

    // The following assertions pass but should not.
    auto double01PRNG = Double01PRNG(123456789);
    assert(isEveryResultZero!int(double01PRNG, 1_000_000));
    assert(isEveryResultZero!uint(double01PRNG, 1_000_000));
    assert(isEveryResultZero!long(double01PRNG, 1_000_000));
    assert(isEveryResultZero!ulong(double01PRNG, 1_000_000));
}
---

--
Nov 12 2020