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