Skip to content

Commit 5d42d69

Browse files
[libc] Change rand implementation so all tests pass in both 32- and 64-bit systems (#98692)
This patch makes rand select different algorithms depending on the arch. This is needed to avoid a test failure in 32-bit systems where the LSB of rand was not uniform enough when the 64-bit constants are used in 32-bit systems.
1 parent a56e009 commit 5d42d69

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

libc/src/stdlib/rand.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,39 @@
1414

1515
namespace LIBC_NAMESPACE_DECL {
1616

17-
// An implementation of the xorshift64star pseudo random number generator. This
18-
// is a good general purpose generator for most non-cryptographics applications.
1917
LLVM_LIBC_FUNCTION(int, rand, (void)) {
2018
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
21-
for (;;) {
22-
unsigned long x = orig;
23-
x ^= x >> 12;
24-
x ^= x << 25;
25-
x ^= x >> 27;
26-
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
27-
cpp::MemoryOrder::RELAXED))
28-
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
29-
sleep_briefly();
19+
20+
// An implementation of the xorshift64star pseudo random number generator.
21+
// This is a good general purpose generator for most non-cryptographics
22+
// applications.
23+
if constexpr (sizeof(void *) == sizeof(uint64_t)) {
24+
for (;;) {
25+
unsigned long x = orig;
26+
x ^= x >> 12;
27+
x ^= x << 25;
28+
x ^= x >> 27;
29+
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
30+
cpp::MemoryOrder::RELAXED))
31+
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
32+
sleep_briefly();
33+
}
34+
} else {
35+
// This is the xorshift32 pseudo random number generator, slightly different
36+
// from the 64-bit star version above, as the previous version fails to
37+
// generate uniform enough LSB in 32-bit systems.
38+
for (;;) {
39+
unsigned long x = orig;
40+
x ^= x >> 13;
41+
x ^= x << 27;
42+
x ^= x >> 5;
43+
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
44+
cpp::MemoryOrder::RELAXED))
45+
return static_cast<int>(x * 1597334677ul) & RAND_MAX;
46+
sleep_briefly();
47+
}
3048
}
49+
__builtin_unreachable();
3150
}
3251

3352
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)