r/cpp • • Jul 21 '19

Fixing up <random>

I think everyone is excited after the report from Cologne. A lot of stuff is being added to the language, we'll get a ton of new features. Adding new features is more exciting than changing and tweaking the old stuff - that being said, there are some old parts of the language, that are sadly lacking or has some problems. One of them is <random> library.

Some of the problems this library has:
> `std::random_device` is not required to be non - deterministic
> no good way to initialize generators with big internal state
> `std::seed_seq` should be solution to ^, but isn't - `std::seed_seq` is not a bijection, does heap allocations without giving ability to provide own allocator, there is no nice way to initialize it from `std::random_device` properly
> `std::random_device` can't itself be used as a seed sequence,
> overall syntax is unnecessarily verbose (no, having a per-thread engine of type `std::default_random_engine` is NOT a good solution)

This is only one of the few libraries that could use improvements. Is there any chance that the committee will look back and change some of them or are they considered 'baked' and there will be no further changes to avoid API and ABI breaking?

Despite the "fixing" part, there are two additions I'd see in the <random> library:

1) std::random<std::uniform_random_bits_generator = std::default_random_engine> class:
> default constructor does anything it can that every time this class is called it is seeded differently - if there is no entropy source, uses a processor clock or a system clock (implementation defined)
> three methods: seed, next_int, next_real - for seeding and generating next integer/real number in given range

2) PCG http://www.pcg-random.org

What are the chances something like this would be proposed and adopted for, let's say, c++23 or c++26 standard? Is there any chance the problems mentioned in the first part of the post will get fixed somewhen?

46 Upvotes

68 comments sorted by

View all comments

7

u/HappyFruitTree Jul 21 '19 edited Jul 21 '19

I would like to have a portable way to serialize the state of the engines (preferably in a way that doesn't force me to use streams/strings but this is less important). It might seem like the << and >> operators should be able to do this, and I'm not sure if that was the intention, but in practice it doesn't work like that. GCC (libstdc++) and Clang (libc++) does not behave the same for std::mt19937.

2

u/degski Jul 22 '19

That's what they intend to do.

2

u/jwakely libstdc++ tamer, LWG chair Jul 22 '19

That's the intention, and the libstdc++ behaviour is a bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60441

If you care about this, please consider helping to fix the bug! It's not necessary to sign a copyright assignment form and contribute code, just describing where the bug is and suggesting (in English not code) how to fix it would be immensely valuable. Otherwise it will continue to wait for somebody to have the bandwidth to look into it.

1

u/TheThiefMaster C++latest fanatic (and game dev) Jul 22 '19

So GCC additionally serialises the state size after the state? That would seem unnecessary to me, and possibly against the standard.

That said, the standard doesn't require the stored state to be in the same order between compilers (let alone completely compatible) as far as I know, so if you need that we either need a stricter standard or you should implement it yourself.

5

u/HappyFruitTree Jul 22 '19

So GCC additionally serialises the state size after the state? That would seem unnecessary to me, and possibly against the standard.

I thought so too but after looking a bit closer I found out it's actually a counter.

GCC doesn't update the state each time a number is generated as described by the standard. Instead it increments a counter and when it reaches the size of the state it updates the whole state all at once.

If you generate a random number you'll see that GCC's state is totally different while Clang's state has just shifted one position and updated the last value.

This is probably an optimization, it doesn't change what numbers are generated, but it means that there is no longer a straight forward way to serialize the state as it is described by the standard.

That said, the standard doesn't require the stored state to be in the same order between compilers (let alone completely compatible) as far as I know, so if you need that we either need a stricter standard or you should implement it yourself.

The standard describes a transition algorithm (how to go from one state to the next) and a textual representation (what the output of << should be).

http://eel.is/c++draft/rand.eng.mers#5

"The textual representation of xᵢ consists of the values of Xᵢ₋ₙ , . . . , Xᵢ₋₁ , in that order."

When I thought the last number in GCC's output was simply the size of the state I was thinking that maybe "consists" is too weak and it was allowed to put additional values at the front or back of the sequence, but now I think it's pretty clear GCC's implementation is not conformant.