1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-11 04:01:31 +00:00

misc/random: add mp_rand_in_range32()

removes awkward back-and-forth int -> double -> int conversion.
the last step also broke uniformity, though it likely doesn't
matter much in mpv's playlist shuffle context.
This commit is contained in:
NRK 2025-03-30 23:24:12 +00:00 committed by sfan5
parent b968dec77d
commit 22f4ff44c5
3 changed files with 24 additions and 2 deletions

View File

@ -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);
}

View File

@ -22,6 +22,8 @@
#include <libavutil/random_seed.h>
#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;
}
// <https://web.archive.org/web/20250321082025/
// https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method>
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;
}

View File

@ -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);