138b6f58eSMichael Jones //===-- Implementation of rand --------------------------------------------===// 238b6f58eSMichael Jones // 338b6f58eSMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 438b6f58eSMichael Jones // See https://llvm.org/LICENSE.txt for license information. 538b6f58eSMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 638b6f58eSMichael Jones // 738b6f58eSMichael Jones //===----------------------------------------------------------------------===// 838b6f58eSMichael Jones 938b6f58eSMichael Jones #include "src/stdlib/rand.h" 1038b6f58eSMichael Jones #include "src/__support/common.h" 115ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1286860be2SJoseph Huber #include "src/__support/threads/sleep.h" 1338b6f58eSMichael Jones #include "src/stdlib/rand_util.h" 1438b6f58eSMichael Jones 155ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 1638b6f58eSMichael Jones 17ef169f57SJoseph Huber LLVM_LIBC_FUNCTION(int, rand, (void)) { 1886860be2SJoseph Huber unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED); 19*5d42d69dSMikhail R. Gadelha 20*5d42d69dSMikhail R. Gadelha // An implementation of the xorshift64star pseudo random number generator. 21*5d42d69dSMikhail R. Gadelha // This is a good general purpose generator for most non-cryptographics 22*5d42d69dSMikhail R. Gadelha // applications. 23*5d42d69dSMikhail R. Gadelha if constexpr (sizeof(void *) == sizeof(uint64_t)) { 2486860be2SJoseph Huber for (;;) { 2586860be2SJoseph Huber unsigned long x = orig; 26630037edSJoseph Huber x ^= x >> 12; 27630037edSJoseph Huber x ^= x << 25; 28630037edSJoseph Huber x ^= x >> 27; 2986860be2SJoseph Huber if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE, 3086860be2SJoseph Huber cpp::MemoryOrder::RELAXED)) 31630037edSJoseph Huber return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX; 3286860be2SJoseph Huber sleep_briefly(); 3386860be2SJoseph Huber } 34*5d42d69dSMikhail R. Gadelha } else { 35*5d42d69dSMikhail R. Gadelha // This is the xorshift32 pseudo random number generator, slightly different 36*5d42d69dSMikhail R. Gadelha // from the 64-bit star version above, as the previous version fails to 37*5d42d69dSMikhail R. Gadelha // generate uniform enough LSB in 32-bit systems. 38*5d42d69dSMikhail R. Gadelha for (;;) { 39*5d42d69dSMikhail R. Gadelha unsigned long x = orig; 40*5d42d69dSMikhail R. Gadelha x ^= x >> 13; 41*5d42d69dSMikhail R. Gadelha x ^= x << 27; 42*5d42d69dSMikhail R. Gadelha x ^= x >> 5; 43*5d42d69dSMikhail R. Gadelha if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE, 44*5d42d69dSMikhail R. Gadelha cpp::MemoryOrder::RELAXED)) 45*5d42d69dSMikhail R. Gadelha return static_cast<int>(x * 1597334677ul) & RAND_MAX; 46*5d42d69dSMikhail R. Gadelha sleep_briefly(); 47*5d42d69dSMikhail R. Gadelha } 48*5d42d69dSMikhail R. Gadelha } 49*5d42d69dSMikhail R. Gadelha __builtin_unreachable(); 5038b6f58eSMichael Jones } 5138b6f58eSMichael Jones 525ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 53