Skip to content

Commit

Permalink
[libc] Change rand implementation so all tests pass in both 32- and 6…
Browse files Browse the repository at this point in the history
…4-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.
  • Loading branch information
mikhailramalho authored Jul 17, 2024
1 parent a56e009 commit 5d42d69
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions libc/src/stdlib/rand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,39 @@

namespace LIBC_NAMESPACE_DECL {

// An implementation of the xorshift64star pseudo random number generator. This
// is a good general purpose generator for most non-cryptographics applications.
LLVM_LIBC_FUNCTION(int, rand, (void)) {
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
for (;;) {
unsigned long x = orig;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
cpp::MemoryOrder::RELAXED))
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
sleep_briefly();

// An implementation of the xorshift64star pseudo random number generator.
// This is a good general purpose generator for most non-cryptographics
// applications.
if constexpr (sizeof(void *) == sizeof(uint64_t)) {
for (;;) {
unsigned long x = orig;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
cpp::MemoryOrder::RELAXED))
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
sleep_briefly();
}
} else {
// This is the xorshift32 pseudo random number generator, slightly different
// from the 64-bit star version above, as the previous version fails to
// generate uniform enough LSB in 32-bit systems.
for (;;) {
unsigned long x = orig;
x ^= x >> 13;
x ^= x << 27;
x ^= x >> 5;
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
cpp::MemoryOrder::RELAXED))
return static_cast<int>(x * 1597334677ul) & RAND_MAX;
sleep_briefly();
}
}
__builtin_unreachable();
}

} // namespace LIBC_NAMESPACE_DECL

0 comments on commit 5d42d69

Please sign in to comment.