1 //===-- Implementation of rand --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/stdlib/rand.h" 10 #include "src/__support/common.h" 11 #include "src/__support/macros/config.h" 12 #include "src/__support/threads/sleep.h" 13 #include "src/stdlib/rand_util.h" 14 15 namespace LIBC_NAMESPACE_DECL { 16 17 LLVM_LIBC_FUNCTION(int, rand, (void)) { 18 unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED); 19 20 // An implementation of the xorshift64star pseudo random number generator. 21 // This is a good general purpose generator for most non-cryptographics 22 // applications. 23 if constexpr (sizeof(void *) == sizeof(uint64_t)) { 24 for (;;) { 25 unsigned long x = orig; 26 x ^= x >> 12; 27 x ^= x << 25; 28 x ^= x >> 27; 29 if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE, 30 cpp::MemoryOrder::RELAXED)) 31 return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX; 32 sleep_briefly(); 33 } 34 } else { 35 // This is the xorshift32 pseudo random number generator, slightly different 36 // from the 64-bit star version above, as the previous version fails to 37 // generate uniform enough LSB in 32-bit systems. 38 for (;;) { 39 unsigned long x = orig; 40 x ^= x >> 13; 41 x ^= x << 27; 42 x ^= x >> 5; 43 if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE, 44 cpp::MemoryOrder::RELAXED)) 45 return static_cast<int>(x * 1597334677ul) & RAND_MAX; 46 sleep_briefly(); 47 } 48 } 49 __builtin_unreachable(); 50 } 51 52 } // namespace LIBC_NAMESPACE_DECL 53