dlang / phobos

The standard library of the D programming language
https://dlang.org
Boost Software License 1.0
1.18k stars 703 forks source link

std.random.uniform return value depends on integer size #10144

Open dlangBugzillaToGithub opened 9 years ago

dlangBugzillaToGithub commented 9 years ago

dlang-bugzilla (@CyberShadow) reported this on 2015-10-03T18:25:09Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=15147

CC List

Description

With an RNG seeded with a constant value, uniform(0, 100) and uniform(0, 100L) will return different values.

Demonstration:

////////////////// test.d //////////////////
import std.random;
import std.stdio;

void test(T)()
{
    Mt19937 rng;
    foreach (n; 0..10)
        write(uniform(0, T(100), rng), " ");
    writeln();
}

void main()
{
    test!int();
    test!uint();
    test!long();
    test!ulong();
}
////////////////////////////////////////////

This will print:

12 2 34 85 4 91 29 85 98 3
12 2 34 85 4 91 29 85 98 3
54 49 75 69 11 25 66 64 28 18
54 49 75 69 11 25 66 64 28 18

This can be a problem for applications that expect seeded RNGs to behave predictably on all platforms (e.g. to generate something procedurally than must be in sync), and pass a size_t to uniform. E.g.:

string sample = arr[uniform(0, $, rng)];
dlangBugzillaToGithub commented 6 years ago

greensunny12 commented on 2018-03-31T18:09:58Z

I just ran into this when trying to add more/better public examples for std.random (https://github.com/dlang/phobos/pull/6393).

Normally, examples can be done by seeding the RNG and thus _knowing_ the sequence of the PRNG.
The current behavior is really nasty.
dlangBugzillaToGithub commented 6 years ago

jrdemail2000-dlang commented on 2018-10-10T05:55:50Z

I'm interested in this, as I use these properties extensively for unit tests in randomization routines. Is it also a capability intended to be supported by some of my tools.

The formulation of the unit tests added as part of https://github.com/dlang/phobos/pull/6393 raised a couple questions for me. Those unit tests are qualified as follows:

version(X86_64) // Issue 15147
assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));

My questions:
* Is the lack of consistency strictly related to integer size (e.g. 32-bit vs 64-bit), or can these differences surface between different platforms even with the same integer size?
* For routines like std.random.randomShuffle and std.random.randomCover, is the issue that these are passing the range length, normally size_t, to std.random.uniform et.al. The issue being that the size of size_t is platform specific?