mardi 25 août 2020

uniform_int_distribution with zero range goes to infinite loop

For unit tests I implemented a mock random number generator. I believe that this is a valid implementation of UniformBitGenerator (the mock actually uses google mock to set the return of operator(), but it behaves the same).

struct RNG
{
    using result_type = size_t;
    static result_type min() { return 0; }
    static result_type max() { return std::numeric_limits<result_type>::max(); }
    result_type operator()() { return max(); }
};

Now I use this mock to sample from std::uniform_int_distribution in the range [a, b], a == b. I believe this is allowed, the only restriction I have found here on the parameters of the distribution is b >= a. So I would expect the following program to print 5.

int main()
{
    auto rng = RNG();
    auto dist = std::uniform_int_distribution<>(5, 5);
    printf("%d\n", dist(rng));
    return 0;
}

Instead it goes into an infinite loop inside the STL, repeatedly drawing numbers from the generator but failing to find a number within the specified range. I tested different (current) compilers (including clang, gcc, icc) in different versions. RNG::max can return other values (e.g. 42) as well, doesn't change anything.

The real code I'm testing draws a random index into a container which may contain only one element. It would be easy to check this condition but it's a rare case and I would like to avoid it.

Am I missing something in the specification of RNGs in the STL? I'd be surprised to find a bug in ALL compilers ...




Aucun commentaire:

Enregistrer un commentaire