From f2a900a60d88004f9adc7bcc2151eb54497570e6 Mon Sep 17 00:00:00 2001 From: Marcos De La Torre <35145332+Marcos-D@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:23:40 -0800 Subject: [PATCH] [rcore] Fix modulo bias in `GetRandomValue()` (#5392) * Fix modulo bias in GetRandomValue(); implement rejection sampling for uniformity * Replace do-while with for-loop in GetRandomValue rejection sampling --- src/rcore.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index 5a630b99e..04f419eee 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1743,7 +1743,30 @@ int GetRandomValue(int min, int max) TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX); } - value = (rand()%(abs(max - min) + 1) + min); + int range = (max - min) + 1; + + // Degenerate/overflow case: fall back to min (same behavior as "always min" instead of UB) + if (range <= 0) + { + value = min; + } + else + { + // Rejection sampling to get a uniform integer in [min, max] + unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results + unsigned long m = (unsigned long)range; // size of the target interval + unsigned long t = c - (c % m); // largest multiple of m <= c + unsigned long r; + + for (;;) + { + r = (unsigned long)rand(); + if (r < t) break; // Only accept values within the fair region + } + + + value = min + (int)(r % m); + } #endif return value; }