Skip to content

Commit f2a900a

Browse files
authored
[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
1 parent 3adfde4 commit f2a900a

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

src/rcore.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1743,7 +1743,30 @@ int GetRandomValue(int min, int max)
17431743
TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX);
17441744
}
17451745

1746-
value = (rand()%(abs(max - min) + 1) + min);
1746+
int range = (max - min) + 1;
1747+
1748+
// Degenerate/overflow case: fall back to min (same behavior as "always min" instead of UB)
1749+
if (range <= 0)
1750+
{
1751+
value = min;
1752+
}
1753+
else
1754+
{
1755+
// Rejection sampling to get a uniform integer in [min, max]
1756+
unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results
1757+
unsigned long m = (unsigned long)range; // size of the target interval
1758+
unsigned long t = c - (c % m); // largest multiple of m <= c
1759+
unsigned long r;
1760+
1761+
for (;;)
1762+
{
1763+
r = (unsigned long)rand();
1764+
if (r < t) break; // Only accept values within the fair region
1765+
}
1766+
1767+
1768+
value = min + (int)(r % m);
1769+
}
17471770
#endif
17481771
return value;
17491772
}

0 commit comments

Comments
 (0)