OpenRAND  0.9
OpenRAND: A C++ Library for Reproducible Random Number Generation in Parallel Computing Environments
threefry.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_THREEFRY_H_
29 #define OPENRAND_THREEFRY_H_
30 
31 #include <openrand/base_state.h>
32 
33 #include <array>
34 #include <cstdint>
35 #include <iostream>
36 #include <limits>
37 
38 namespace openrand {
39 
40 class Threefry : public BaseRNG<Threefry> {
41  public:
42  OPENRAND_DEVICE Threefry(uint64_t seed, uint32_t ctr,
43  uint32_t global_seed = openrand::DEFAULT_GLOBAL_SEED)
44  : seed(seed ^ global_seed), counter(ctr) {
45  }
46 
47  template <typename T = uint32_t>
48  OPENRAND_DEVICE T draw() {
49  uint32_t out[2];
50  round(static_cast<uint32_t>(seed >> 32), static_cast<uint32_t>(seed),
51  counter, _ctr++, out);
52 
53  static_assert(std::is_same_v<T, uint32_t> || std::is_same_v<T, uint64_t>);
54  if constexpr (std::is_same_v<T, uint32_t>)
55  return out[0];
56 
57  else {
58  uint64_t res =
59  (static_cast<uint64_t>(out[0]) << 32) | static_cast<uint64_t>(out[1]);
60  return static_cast<uint64_t>(res);
61  }
62  }
63 
64  private:
65  OPENRAND_DEVICE uint32_t rotl32(uint32_t x, uint32_t N) {
66  return (x << (N & 31)) | (x >> ((32 - N) & 31));
67  }
68 
69  OPENRAND_DEVICE void round(uint32_t ks0, uint32_t ks1, uint32_t counter,
70  uint32_t _ctr, uint32_t* out) {
71  uint32_t x0, x1;
72  uint32_t ks2 = 0x1BD11BDA;
73 
74  x0 = counter + ks0;
75  ks2 ^= ks0;
76 
77  x1 = _ctr + ks1;
78  ks2 ^= ks1;
79 
80  for (int i = 0; i < 20; i++) {
81  x0 += x1;
82  x1 = rotl32(x1, get_constant(i % 8));
83  x1 ^= x0;
84 
85  if (i == 3) {
86  x0 += ks1;
87  x1 += ks2;
88  x1 += 1;
89  }
90  if (i == 7) {
91  x0 += ks2;
92  x1 += ks0;
93  x1 += 2;
94  }
95  if (i == 11) {
96  x0 += ks0;
97  x1 += ks1;
98  x1 += 3;
99  }
100  if (i == 15) {
101  x0 += ks1;
102  x1 += ks2;
103  x1 += 4;
104  }
105  if (i == 19) {
106  x0 += ks2;
107  x1 += ks0;
108  x1 += 5;
109  }
110  }
111  out[0] = x0;
112  out[1] = x1;
113  }
114 
115  OPENRAND_DEVICE int get_constant(const int index) const {
116  switch (index) {
117  case 0:
118  return 13;
119  case 1:
120  return 15;
121  case 2:
122  return 26;
123  case 3:
124  return 6;
125  case 4:
126  return 17;
127  case 5:
128  return 29;
129  case 6:
130  return 16;
131  case 7:
132  return 24;
133  default:
134  return 24;
135  }
136  }
137 
138  const uint64_t seed;
139  const uint32_t counter;
140 
141  public:
142  uint32_t _ctr = 0;
143 }; // class Threefry
144 
145 } // namespace openrand
146 
147 #endif // OPENRAND_THREEFRY_H_
Base class for random number generators.
Definition: base_state.h:50
Definition: threefry.h:40