Molassembler  3.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Jsf.h
Go to the documentation of this file.
1 
8 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_JSF
9 #define INCLUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_JSF
10 
11 #include <cstdint>
12 #include <random>
13 #include <array>
14 
15 namespace Scine {
16 namespace Molassembler {
17 namespace Temple {
18 
19 /* Heavily modified from:
20  *
21  * A C++ implementation of a Bob Jenkins Small Fast (Noncryptographic) PRNGs
22  * Based on code published by Bob Jenkins in 2007, adapted for C++
23  *
24  * The MIT License (MIT)
25  *
26  * Copyright (c) 2018 Melissa E. O'Neill
27  *
28  * Permission is hereby granted, free of charge, to any person obtaining a
29  * copy of this software and associated documentation files (the "Software"),
30  * to deal in the Software without restriction, including without limitation
31  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32  * and/or sell copies of the Software, and to permit persons to whom the
33  * Software is furnished to do so, subject to the following conditions:
34  *
35  * The above copyright notice and this permission notice shall be included in
36  * all copies or substantial portions of the Software.
37  *
38  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
44  * IN THE SOFTWARE.
45  */
46 
58 template<
59  typename UnsignedType,
60  unsigned p,
61  unsigned q,
62  unsigned r
63 > class JSF {
64 public:
66  using result_type = UnsignedType;
67 
71  static constexpr result_type min() {
72  return 0;
73  }
74 
76  static constexpr result_type max() {
77  return ~result_type(0);
78  }
80 
84  constexpr explicit JSF() = default;
85 
87  constexpr explicit JSF(const std::array<UnsignedType, 4>& input) {
88  static_assert(
89  std::is_unsigned<UnsignedType>::value,
90  "The underlying type of the JSF generator must be unsigned!"
91  );
92 
93  seed_(input);
94  }
95 
97  explicit JSF(std::seed_seq& seedSeq) {
98  seed_(seedSeq);
99  }
100 
102  explicit JSF(int seedInt) {
103  seed(seedInt);
104  }
106 
110  constexpr void seed(const std::array<UnsignedType, 4>& input) {
111  seed_(input);
112  }
113 
115  void seed(std::seed_seq& seedSeq) {
116  seed_(seedSeq);
117  }
118 
120  void seed(int seed) {
121  std::seed_seq seedSeq {{seed}};
122  seed_(seedSeq);
123  }
125 
128 
132  constexpr UnsignedType operator() () {
133  advance_();
134 
135  return d_;
136  }
137 
142  constexpr bool operator == (const JSF& other) const {
143  return (
144  a_ == other.a_
145  && b_ == other.b_
146  && c_ == other.c_
147  && d_ == other.d_
148  );
149  }
150 
152  constexpr bool operator != (const JSF& other) const {
153  return !(*this == other);
154  }
156 
157 private:
160  UnsignedType a_, b_, c_, d_;
162 
165  static constexpr unsigned bits = 8 * sizeof(UnsignedType);
167 
170  static constexpr UnsignedType rotate_(UnsignedType x, unsigned k) {
171  return (x << k) | (x >> (bits - k));
172  }
173 
174  constexpr void advance_() {
175  UnsignedType e = a_ - rotate_(b_, p);
176  a_ = b_ ^ rotate_(c_, q);
177  b_ = c_ + ((r > 0) ? rotate_(d_, r) : d_);
178  c_ = d_ + e;
179  d_ = e + a_;
180  }
181 
182  constexpr void advance_(unsigned N) {
183  for(unsigned i = 0; i < N; ++i) {
184  advance_();
185  }
186  }
187 
188  constexpr void seed_(const std::array<UnsignedType, 4>& state) {
189  a_ = state[0];
190  b_ = state[1];
191  c_ = state[2];
192  d_ = state[3];
193  }
194 
195  void seed_(std::seed_seq& seedSeq) {
196  std::array<UnsignedType, 4> stateArray;
197 
198  seedSeq.generate(
199  std::begin(stateArray),
200  std::end(stateArray)
201  );
202 
203  /* You can safely ignore the warning that shift cout >= width of type for
204  * instantiations with uint32_t by clang. In those cases, stateArray is
205  * already adequately filled.
206  */
207  if constexpr(std::is_same<UnsignedType, std::uint64_t>::value) {
208  /* seed_seq only generates 32 bit unsigneds, so just combine 8 32-bit
209  * values into 4 64-bit values for the state array
210  */
211  std::array<UnsignedType, 4> topBits;
212 
213  seedSeq.generate(
214  std::begin(topBits),
215  std::end(topBits)
216  );
217 
218  // Shift the topBits values by 32 and XOR them onto stateArray
219  for(unsigned i = 0; i < 4; ++i) {
220  stateArray[i] ^= (topBits[i] << 32);
221  }
222  }
223 
224  seed_(stateArray);
225  }
227 };
228 
230 //
231 // Each size has variations corresponding to different parameter sets.
232 // Each variant will create a distinct (and hopefully statistically
233 // independent) sequence.
234 //
235 // The constants are all those suggested by Bob Jenkins. The n variants
236 // perform only two rotations, the r variants perform three.
237 // 128 state bits, uint32_t output
238 
239 using JSF32na = JSF<uint32_t, 27, 17, 0>;
240 using JSF32nb = JSF<uint32_t, 9, 16, 0>;
241 using JSF32nc = JSF<uint32_t, 9, 24, 0>;
242 using JSF32nd = JSF<uint32_t, 10, 16, 0>;
243 using JSF32ne = JSF<uint32_t, 10, 24, 0>;
244 using JSF32nf = JSF<uint32_t, 11, 16, 0>;
245 using JSF32ng = JSF<uint32_t, 11, 24, 0>;
246 using JSF32nh = JSF<uint32_t, 25, 8, 0>;
247 using JSF32ni = JSF<uint32_t, 25, 16, 0>;
248 using JSF32nj = JSF<uint32_t, 26, 8, 0>;
249 using JSF32nk = JSF<uint32_t, 26, 16, 0>;
250 using JSF32nl = JSF<uint32_t, 26, 17, 0>;
251 using JSF32nm = JSF<uint32_t, 27, 16, 0>;
252 
253 using JSF32ra = JSF<uint32_t, 3, 14, 24>;
254 using JSF32rb = JSF<uint32_t, 3, 25, 15>;
255 using JSF32rc = JSF<uint32_t, 4, 15, 24>;
256 using JSF32rd = JSF<uint32_t, 6, 16, 28>;
257 using JSF32re = JSF<uint32_t, 7, 16, 27>;
258 using JSF32rf = JSF<uint32_t, 8, 14, 3>;
259 using JSF32rg = JSF<uint32_t, 11, 16, 23>;
260 using JSF32rh = JSF<uint32_t, 12, 16, 22>;
261 using JSF32ri = JSF<uint32_t, 12, 17, 23>;
262 using JSF32rj = JSF<uint32_t, 13, 16, 22>;
263 using JSF32rk = JSF<uint32_t, 15, 25, 3>;
264 using JSF32rl = JSF<uint32_t, 16, 9, 3>;
265 using JSF32rm = JSF<uint32_t, 17, 9, 3>;
266 using JSF32rn = JSF<uint32_t, 17, 27, 7>;
267 using JSF32ro = JSF<uint32_t, 19, 7, 3>;
268 using JSF32rp = JSF<uint32_t, 23, 15, 11>;
269 using JSF32rq = JSF<uint32_t, 23, 16, 11>;
270 using JSF32rr = JSF<uint32_t, 23, 17, 11>;
271 using JSF32rs = JSF<uint32_t, 24, 3, 16>;
272 using JSF32rt = JSF<uint32_t, 24, 4, 16>;
273 using JSF32ru = JSF<uint32_t, 25, 14, 3>;
274 using JSF32rv = JSF<uint32_t, 27, 16, 6>;
275 using JSF32rw = JSF<uint32_t, 27, 16, 7>;
276 
277 using JSF32n = JSF32na;
278 using JSF32r = JSF32rq;
279 using JSF32 = JSF32n;
280 
281 // - 256 state bits, uint64_t output
282 
283 using JSF64na = JSF<uint64_t, 39, 11, 0>;
284 using JSF64ra = JSF<uint64_t, 7, 13, 37>;
285 
286 using JSF64n = JSF64na;
287 using JSF64r = JSF64ra;
288 using JSF64 = JSF64r;
289 
291 template<class Engine = JSF32>
292 struct Generator {
293  Engine engine;
294 
295  explicit Generator() {
296 #ifndef NDEBUG
297  engine.seed(272181374);
298 #else
299  std::random_device randomDevice;
300 
301  engine.seed(
302  std::array<typename Engine::result_type, 4> {
303  randomDevice(),
304  randomDevice(),
305  randomDevice(),
306  randomDevice()
307  }
308  );
309 #endif
310  }
311 };
312 
313 } // namespace Temple
314 } // namespace Molassembler
315 } // namespace Scine
316 
317 #endif
JSF(std::seed_seq &seedSeq)
Construct from a seed sequence.
Definition: Jsf.h:97
static constexpr result_type max()
Maximum value of result_type.
Definition: Jsf.h:76
constexpr UnsignedType operator()()
Advance the state and return the current value.
Definition: Jsf.h:132
constexpr bool operator==(const JSF &other) const
Compares the underlying state of two instances.
Definition: Jsf.h:142
constexpr JSF()=default
Default constructor.
JSF(int seedInt)
Construct from a single integer seed value.
Definition: Jsf.h:102
Provides a seeded engine instance.
Definition: Jsf.h:292
void seed(int seed)
Seed the underlying state with a single integer value.
Definition: Jsf.h:120
constexpr JSF(const std::array< UnsignedType, 4 > &input)
Construct from four seed values.
Definition: Jsf.h:87
constexpr void seed(const std::array< UnsignedType, 4 > &input)
Seed the underlying state with four values.
Definition: Jsf.h:110
static constexpr result_type min()
Minimum value of result_type.
Definition: Jsf.h:71
UnsignedType result_type
When used as a functor, this is the return type of operator ()
Definition: Jsf.h:66
General class enabling the construction of a pattern of PRNGs by Bob Jenkins.
Definition: Jsf.h:63
void seed(std::seed_seq &seedSeq)
Seed the underlying state with a seed sequence.
Definition: Jsf.h:115
constexpr bool operator!=(const JSF &other) const
Compares the underlying state of two instances.
Definition: Jsf.h:152