mirror of
https://github.com/mpv-player/mpv
synced 2025-04-22 15:17:43 +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;
|
pl->entries[n]->original_index = n;
|
||||||
mp_rand_state s = mp_rand_seed(0);
|
mp_rand_state s = mp_rand_seed(0);
|
||||||
for (int n = 0; n < pl->num_entries - 1; n++) {
|
for (int n = 0; n < pl->num_entries - 1; n++) {
|
||||||
size_t j = (size_t)((pl->num_entries - n) * mp_rand_next_double(&s));
|
size_t j = mp_rand_in_range32(&s, n, pl->num_entries);
|
||||||
MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]);
|
MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[j]);
|
||||||
}
|
}
|
||||||
playlist_update_indexes(pl, 0, -1);
|
playlist_update_indexes(pl, 0, -1);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <libavutil/random_seed.h>
|
#include <libavutil/random_seed.h>
|
||||||
|
|
||||||
|
#include "common/common.h"
|
||||||
|
#include "misc/mp_assert.h"
|
||||||
#include "osdep/timer.h"
|
#include "osdep/timer.h"
|
||||||
#include "random.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;
|
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.
|
* distribution, and update the state accordingly.
|
||||||
*/
|
*/
|
||||||
double mp_rand_next_double(mp_rand_state *s);
|
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