Skip to content

Commit 6ea6bde

Browse files
[libc] Change rand implementation so all tests pass in both 32- and 64-bit systems
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 0309709 commit 6ea6bde

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

libc/src/stdlib/rand.cpp

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

1515
namespace LIBC_NAMESPACE_DECL {
1616

17-
// An implementation of the xorshift64star pseudo random number generator. This
17+
// An implementation of the xorshift pseudo random number generator. This
1818
// is a good general purpose generator for most non-cryptographics applications.
19-
LLVM_LIBC_FUNCTION(int, rand, (void)) {
19+
static unsigned long xorshift(unsigned long a, unsigned long b, unsigned long c,
20+
unsigned long d) {
2021
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
2122
for (;;) {
2223
unsigned long x = orig;
23-
x ^= x >> 12;
24-
x ^= x << 25;
25-
x ^= x >> 27;
24+
x ^= x >> a;
25+
x ^= x << b;
26+
x ^= x >> c;
2627
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
2728
cpp::MemoryOrder::RELAXED))
28-
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
29+
return x * d;
2930
sleep_briefly();
3031
}
3132
}
3233

34+
LLVM_LIBC_FUNCTION(int, rand, (void)) {
35+
int res;
36+
if constexpr (sizeof(void *) == sizeof(uint64_t))
37+
res = static_cast<int>(xorshift(12, 25, 27, 0x2545F4914F6CDD1Dul) >> 32);
38+
else
39+
res = static_cast<int>(xorshift(13, 17, 5, 1597334677ul));
40+
return res & RAND_MAX;
41+
}
42+
3343
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)