OpenRAND  0.9
OpenRAND: A C++ Library for Reproducible Random Number Generation in Parallel Computing Environments
tyche.h
1 // @HEADER
2 // *******************************************************************************
3 // OpenRAND *
4 // A Performance Portable, Reproducible Random Number Generation Library *
5 // *
6 // Copyright (c) 2023, Michigan State University *
7 // *
8 // Permission is hereby granted, free of charge, to any person obtaining a copy *
9 // of this software and associated documentation files (the "Software"), to deal *
10 // in the Software without restriction, including without limitation the rights *
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
12 // copies of the Software, and to permit persons to whom the Software is *
13 // furnished to do so, subject to the following conditions: *
14 // *
15 // The above copyright notice and this permission notice shall be included in *
16 // all copies or substantial portions of the Software. *
17 // *
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
24 // SOFTWARE. *
25 //********************************************************************************
26 // @HEADER
27 
28 #ifndef OPENRAND_TYCHE_H_
29 #define OPENRAND_TYCHE_H_
30 
31 #include <openrand/base_state.h>
32 
33 #include <cstdint>
34 #include <iostream>
35 #include <limits>
36 
37 namespace {
38 inline OPENRAND_DEVICE uint32_t rotl(uint32_t value, unsigned int x) {
39  return (value << x) | (value >> (32 - x));
40 }
41 } // namespace
42 
43 namespace openrand {
44 
45 class Tyche : public BaseRNG<Tyche> {
46  public:
47  OPENRAND_DEVICE Tyche(uint64_t seed, uint32_t ctr,
48  uint32_t global_seed = openrand::DEFAULT_GLOBAL_SEED) {
49  seed = seed ^ global_seed;
50  a = static_cast<uint32_t>(seed >> 32);
51  b = static_cast<uint32_t>(seed & 0xFFFFFFFFULL);
52  d = d ^ ctr;
53 
54  for (int i = 0; i < 20; i++) {
55  mix();
56  }
57  }
58 
59  template <typename T = uint32_t>
60  OPENRAND_DEVICE T draw() {
61  mix();
62  if constexpr (std::is_same_v<T, uint32_t>)
63  return a;
64 
65  else {
66  uint32_t tmp = a;
67  mix();
68  uint64_t res = (static_cast<uint64_t>(tmp) << 32) | a;
69  return static_cast<T>(res);
70  }
71  }
72 
73  private:
74  // inline OPENRAND_DEVICE void mix() {
75  // a += b;
76  // d = rotl(d ^ a, 16);
77  // c += d;
78  // b = rotl(b ^ c, 12);
79  // a += b;
80  // d = rotl(d ^ a, 8);
81  // c += d;
82  // b = rotl(b ^ c, 7);
83  // }
84 
85  inline OPENRAND_DEVICE void mix() {
86  b = rotl(b, 7) ^ c;
87  c -= d;
88  d = rotl(d, 8) ^ a;
89  a -= b;
90  b = rotl(b, 12) ^ c;
91  c -= d;
92  d = rotl(d, 16) ^ a;
93  a -= b;
94  }
95 
96  uint32_t a, b;
97  uint32_t c = 2654435769;
98  uint32_t d = 1367130551;
99 }; // class Tyche
100 
101 } // namespace openrand
102 
103 #endif // OPENRAND_TYCHE_H_
Base class for random number generators.
Definition: base_state.h:50
Definition: tyche.h:45