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:
parent
b968dec77d
commit
22f4ff44c5
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user