CORSIKA  @c8_version@
The framework to simulate particle cascades for astroparticle physics
Engine.hpp
1 /*
2  * (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu
3  *
4  * This software is distributed under the terms of the GNU General Public
5  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
6  * the license.
7  */
8 
9 /*
10  * Engine.hpp
11  *
12  * Created on: 22 de fev. de 2021
13  * Author: Antonio Augusto Alves Junior
14  */
15 
16 #pragma once
17 
18 #include <limits>
19 
20 #include "EngineTraits.hpp"
21 #include "SplitMix.hpp"
22 #include "Squares3_128.hpp"
23 #include "Squares4_128.hpp"
24 #include "Squares3_64.hpp"
25 #include "Squares4_64.hpp"
26 
27 namespace random_iterator {
28 
29  namespace detail {
30 
31  template <typename Engine123>
32  class Engine {
33 
34  typedef unsigned trigger_type;
35 
36  public:
37  typedef Engine123 engine_type;
38  typedef typename detail::random_traits<engine_type>::state_type state_type;
39  typedef typename detail::random_traits<engine_type>::seed_type seed_type;
40  typedef typename detail::random_traits<engine_type>::advance_type advance_type;
41  typedef typename detail::random_traits<engine_type>::init_type init_type;
42  typedef typename detail::random_traits<engine_type>::result_type result_type;
43 
44  static const unsigned arity = detail::random_traits<engine_type>::arity;
45 
46  Engine() = delete;
47 
48  Engine(result_type seed)
49  : engine_(engine_type{})
50  , cache_(state_type{})
51  , state_(state_type{})
52  , seed_(seed_type{})
53  , trigger_(arity) {
54  init_type temp{{}};
55 
56  for (unsigned i = 0; i < temp.size(); ++i) {
57  temp[i] = detail::splitmix<result_type>(seed);
58  }
59 
60  seed_ = temp;
61  }
62 
63  Engine(result_type seed, uint32_t stream)
64  : engine_(engine_type{})
65  , cache_(state_type{})
66  , state_(state_type{})
67  , seed_(seed_type{})
68  , trigger_(arity) {
69  init_type temp{{}};
70 
71  for (unsigned i = 0; i < temp.size(); ++i) {
72  temp[i] = detail::splitmix<result_type>(seed);
73  }
74 
75  state_[arity - 1] = stream;
76  state_[arity - 1] = state_[arity - 1] << 32;
77 
78  seed_ = temp;
79  }
80 
81  Engine(init_type seed)
82  : engine_(engine_type{})
83  , cache_(state_type{})
84  , state_(state_type{})
85  , seed_(seed)
86  , trigger_(arity) {}
87 
88  Engine(init_type seed, uint32_t stream)
89  : engine_(engine_type{})
90  , cache_(state_type{})
91  , state_(state_type{})
92  , seed_(seed)
93  , trigger_(arity) {
94  state_[arity - 1] = stream;
95  state_[arity - 1] << 32;
96  }
97 
98  Engine(Engine<Engine123> const& other)
99  : engine_(engine_type{})
100  , cache_(other.getCache())
101  , state_(other.getState())
102  , seed_(other.getSeed())
103  , trigger_(other.getTrigger()) {}
104 
105  inline Engine<Engine123>& operator=(Engine<Engine123> const& other) {
106 
107  if (this == &other) return *this;
108 
109  engine_ = engine_type{};
110  cache_ = other.getCache();
111  state_ = other.getState();
112  seed_ = other.getSeed();
113  trigger_ = other.getTrigger();
114  return *this;
115  }
116 
117  inline result_type operator()(void) {
118  result_type result = 0;
119 
120  if (trigger_ == arity) {
121 
122  trigger_ = 0;
123  cache_ = engine_(state_.incr(), seed_);
124  result = cache_[trigger_];
125  ++trigger_;
126  } else {
127  result = cache_[trigger_];
128  ++trigger_;
129  }
130 
131  return result;
132  }
133 
134  inline void discard(advance_type n) {
135 
136  state_.incr(n);
137  trigger_ = arity;
138  }
139 
140  inline void reset(void) {
141  trigger_ = arity;
142  state_ = state_type{};
143  cache_ = state_type{};
144  }
145 
146  inline const seed_type& getSeed() const { return seed_; }
147 
148  inline void setSeed(seed_type seed) { seed_ = seed; }
149 
150  inline void setSeed(result_type seed) {
151 
152  init_type temp{{}};
153  for (unsigned i = 0; i < temp.size(); ++i) {
154  temp[i] = detail::splitmix<result_type>(seed);
155  }
156  seed_ = temp;
157  }
158 
159  inline const state_type& getState() const { return state_; }
160 
161  inline void setState(const state_type& state) { state_ = state; }
162 
163  inline trigger_type getTrigger() const { return trigger_; }
164 
165  inline void setTrigger(trigger_type trigger) { trigger_ = trigger; }
166  static constexpr result_type min() { return 0; }
167 
168  static constexpr result_type max() {
169  return std::numeric_limits<result_type>::max();
170  }
171 
172  friend inline std::ostream& operator<<(std::ostream& os,
173  const Engine<Engine123>& be) {
174  return os << "state: " << be.getState() << " seed: " << be.getSeed()
175  << " trigger: " << be.getTrigger();
176  }
177 
178  private:
179  inline state_type getCache() const { return cache_; }
180 
181  engine_type engine_;
182  state_type cache_;
183  state_type state_;
184  seed_type seed_;
185  trigger_type trigger_;
186  };
187 
194 
195 #if RANDOM_ITERATOR_R123_USE_AES_NI
197 #endif
198 
199  } // namespace detail
200 
201 } // namespace random_iterator