diff --git a/common/playlist.c b/common/playlist.c index fa834254e5..6d03c030c2 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -172,8 +172,8 @@ void playlist_shuffle(struct playlist *pl) pl->entries[n]->original_index = n; mp_rand_state s = mp_rand_seed(0); for (int n = 0; n < pl->num_entries - 1; n++) { - size_t j = (size_t)((pl->num_entries - n) * mp_rand_next_double(&s)); - MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]); + size_t j = mp_rand_in_range32(&s, n, pl->num_entries); + MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[j]); } playlist_update_indexes(pl, 0, -1); } diff --git a/misc/random.c b/misc/random.c index d3b2a62da4..30e43118a1 100644 --- a/misc/random.c +++ b/misc/random.c @@ -22,6 +22,8 @@ #include +#include "common/common.h" +#include "misc/mp_assert.h" #include "osdep/timer.h" #include "random.h" @@ -84,3 +86,17 @@ double mp_rand_next_double(mp_rand_state *s) { return (mp_rand_next(s) >> 11) * 0x1.0p-53; } + +// +uint32_t mp_rand_in_range32(mp_rand_state *s, uint32_t min, uint32_t max) +{ + mp_assert(min < max); + uint32_t range = max - min; + uint32_t mask = mp_round_next_power_of_2(range) - 1; + uint32_t ret; + do { + ret = mp_rand_next(s) & mask; + } while (ret >= range); + return min + ret; +} diff --git a/misc/random.h b/misc/random.h index c5300a599b..451d514b9c 100644 --- a/misc/random.h +++ b/misc/random.h @@ -46,3 +46,9 @@ uint64_t mp_rand_next(mp_rand_state *s); * distribution, and update the state accordingly. */ double mp_rand_next_double(mp_rand_state *s); + +/* + * Return a 32 bit integer in the range [min, max) with uniform distribution. + * Caller should ensure `min < max`. + */ +uint32_t mp_rand_in_range32(mp_rand_state *s, uint32_t min, uint32_t max);