Skip to content

Commit 3681378

Browse files
[libc] Change rand implementation so all tests pass in both 32- and 64-bit systems
The current xorshift star algorithm fails to produce uniform enough values in 32-bit systems, so this patch changes the algorithm so the tests now pass in both 32- and 64-bit systems. The multiplifier used in the algorithm was obtained from "The Art of Computer Programming" book. It is also used by musl and newlib.
1 parent dd44003 commit 3681378

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

libc/src/stdlib/rand.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@
1313

1414
namespace LIBC_NAMESPACE {
1515

16-
// An implementation of the xorshift64star pseudo random number generator. This
17-
// is a good general purpose generator for most non-cryptographics applications.
16+
// This multiplier was obtained from Knuth, D.E., "The Art of
17+
// Computer Programming," Vol 2, Seminumerical Algorithms, Third
18+
// Edition, Addison-Wesley, 1998, p. 106 (line 26) & p. 108 */
1819
LLVM_LIBC_FUNCTION(int, rand, (void)) {
1920
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
2021
for (;;) {
21-
unsigned long x = orig;
22-
x ^= x >> 12;
23-
x ^= x << 25;
24-
x ^= x >> 27;
25-
if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
22+
uint64_t x = orig;
23+
x = static_cast<unsigned long>(6364136223846793005ULL) * x;
24+
if (rand_next.compare_exchange_strong(orig, static_cast<unsigned long>(x),
25+
cpp::MemoryOrder::ACQUIRE,
2626
cpp::MemoryOrder::RELAXED))
27-
return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
27+
return static_cast<int>(x >> 32) & RAND_MAX;
2828
sleep_briefly();
2929
}
3030
}

0 commit comments

Comments
 (0)