[libc-commits] [libc] 5d42d69 - [libc] Change rand implementation so all tests pass in both 32- and 64-bit systems (#98692)

via libc-commits libc-commits at lists.llvm.org
Wed Jul 17 08:01:29 PDT 2024


Author: Mikhail R. Gadelha
Date: 2024-07-17T12:01:26-03:00
New Revision: 5d42d69d936bc3f29e849aac33d331b198143145

URL: https://github.com/llvm/llvm-project/commit/5d42d69d936bc3f29e849aac33d331b198143145
DIFF: https://github.com/llvm/llvm-project/commit/5d42d69d936bc3f29e849aac33d331b198143145.diff

LOG: [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.

Added: 
    

Modified: 
    libc/src/stdlib/rand.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
index 1931727e2d9d1..a8a4fab3377cc 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 
diff erent
+    // 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


        


More information about the libc-commits mailing list