Skip to content

Commit 22f4ff4

Browse files
N-R-Ksfan5
authored andcommitted
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.
1 parent b968dec commit 22f4ff4

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

common/playlist.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ void playlist_shuffle(struct playlist *pl)
172172
pl->entries[n]->original_index = n;
173173
mp_rand_state s = mp_rand_seed(0);
174174
for (int n = 0; n < pl->num_entries - 1; n++) {
175-
size_t j = (size_t)((pl->num_entries - n) * mp_rand_next_double(&s));
176-
MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]);
175+
size_t j = mp_rand_in_range32(&s, n, pl->num_entries);
176+
MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[j]);
177177
}
178178
playlist_update_indexes(pl, 0, -1);
179179
}

misc/random.c

+16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include <libavutil/random_seed.h>
2424

25+
#include "common/common.h"
26+
#include "misc/mp_assert.h"
2527
#include "osdep/timer.h"
2628
#include "random.h"
2729

@@ -84,3 +86,17 @@ double mp_rand_next_double(mp_rand_state *s)
8486
{
8587
return (mp_rand_next(s) >> 11) * 0x1.0p-53;
8688
}
89+
90+
// <https://web.archive.org/web/20250321082025/
91+
// https://www.pcg-random.org/posts/bounded-rands.html#bitmask-with-rejection-unbiased-apples-method>
92+
uint32_t mp_rand_in_range32(mp_rand_state *s, uint32_t min, uint32_t max)
93+
{
94+
mp_assert(min < max);
95+
uint32_t range = max - min;
96+
uint32_t mask = mp_round_next_power_of_2(range) - 1;
97+
uint32_t ret;
98+
do {
99+
ret = mp_rand_next(s) & mask;
100+
} while (ret >= range);
101+
return min + ret;
102+
}

misc/random.h

+6
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,9 @@ uint64_t mp_rand_next(mp_rand_state *s);
4646
* distribution, and update the state accordingly.
4747
*/
4848
double mp_rand_next_double(mp_rand_state *s);
49+
50+
/*
51+
* Return a 32 bit integer in the range [min, max) with uniform distribution.
52+
* Caller should ensure `min < max`.
53+
*/
54+
uint32_t mp_rand_in_range32(mp_rand_state *s, uint32_t min, uint32_t max);

0 commit comments

Comments
 (0)