diff options
author | Mikhail R. Gadelha <mikhail@igalia.com> | 2024-07-17 17:01:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-17 12:01:26 -0300 |
commit | 5d42d69d936bc3f29e849aac33d331b198143145 (patch) | |
tree | 4cfe2b8662b8eb4e76099aadd933bb213b98fa67 /libc/src | |
parent | a56e009ef852926c8e77eb8e50739d2b5a389212 (diff) | |
download | llvm-5d42d69d936bc3f29e849aac33d331b198143145.zip llvm-5d42d69d936bc3f29e849aac33d331b198143145.tar.gz llvm-5d42d69d936bc3f29e849aac33d331b198143145.tar.bz2 |
[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.
Diffstat (limited to 'libc/src')
-rw-r--r-- | libc/src/stdlib/rand.cpp | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp index 1931727e..a8a4fab 100644 --- a/libc/src/stdlib/rand.cpp +++ b/libc/src/stdlib/rand.cpp @@ -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 |