-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bugfix random_shuffle is removed in C++17 - replace with std::shuffle (…
- Loading branch information
Showing
1 changed file
with
3 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the original
random_shuffle()
was seeded by the implementation-dependantsrand()
which is called at least once inofSeedRandom()
withinof::priv::initutils()
. this replacement uses astd::default_random_engine
with a constant seed of0
, so the shuffle will be predictable (which is probably not the vernacular expectation of a "random" process). calling astd::random_device
in lieu of the seed is typically how unpredictable randomness is obtained:std::random_device rd; std::shuffle(values.begin(), values.end(), std::default_random_engine(rd()));
as as stop-gap measure the code above will correctly replace the
srand
-seededrandom_shuffle
, albeit not optimally as it generates a new seed at everyofRandomize()
call, which is wasteful as thedefault_random_engine
only needs 1 seed. perhapsofSeedRandom()
should instantiate a random device and store a staticof::utils::seed
value that gets re-used? and if a value is passed, it set theof::utils::seed
, in parallel so what happens withsrand()
?(and as a matter of fact having a function called
ofRandomize()
is not ideal... perhaps it should be deprecated in favour ofofShuffle()
, like thestd::shuffle
dropped therandom_
part, as the randomness is managed elsewhere...)cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly 0 means use time as the seed, so it is random and not a single seed.
Trying to find a reference for that - I'll see if I can dig it up ( but if that's not correct we should fix )
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i double-checked and the (0) version produces predictable results:
gives the same
re-thinking about it, it should definitely be fixed not by generating a seed within ofRandomize() like I did above but by augmenting ofSeedRandom with a random device, as we will probably want to update other OF random utils with modern random stuff, which will need such a seed instead of depending on srand. (and it is important to keep the current model of being able to choose between "unpredictable randomness" and "reproducible randomness" by passing a desired seed)
while we're at it,
ofSeedRandom()
is a confusing name (the "seed" part is probably thought as the verb), especially as it radically changes behaviour between the no-argument ("random" random seed) and the argument version.proposal to deprecate ofSeedRandom and ride as close as possible to the std approach and separating the seed store/recall from the gen with something like:
generating a default random seed in
of::priv::initutils()
then meansofSetRandomSeed(ofAdvanceRandomDevice())
and users wishing for a specific seed will simply overwrite it with a call toofSetRandomSeed(12212)
. functions relying on the seed will retrieve it withofGetRandomSeed()
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in order to facilitate transitioning
could call
ofSetRandomSeed(ofAdvanceRandomDevice())
, but should be deprecated-at-birth as it's a bad shortcutcce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!
Thanks @artificiel.
I think deprecate makes sense (but we'll need it for a while).
Want to do a PR with your above proposal?
Could
ofAdvanceRandomDevice()
beofGetNewRandomSeed()
Advance reads a bit like expert instead of new / increment
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case it helps something take a look at this PR @artificiel
#7572
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dimitre mt19937 is meaningful when used directly as a generator, but in the case of providing a single seed to the app instance, I don't think the distribution matters so much. (but perhaps we want to offer different random generators within ofUtils, in which case the 19937 might be relevant). but in any case we don't want a new seed at every ofRandomize() call.
@ofTheo I can wrap a PR but not immediately. I will also take a look at other random stuff to make sure we don't paint ourselves in a corner by moving too fast. as far as the naming, "advance" refers to the principle of the generator which literally increments its state each time it's called. perhaps it's more logical to offer an interface to a generic ofRandomDevice, and call it directly? so
then
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i've opened a discussion #7579
cce8428
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've appended some concrete code to #7579