SUNphi  1.0
Sitmo2.hpp
1 #ifndef SITMO_HPP
2 #define SITMO_HPP
3 
4 /// \file Sitmo.hpp
5 ///
6 /// \brief Implements the SITMO random number generator
7 ///
8 /// Copyright (c) 2012-2016 M.A. (Thijs) van den Berg, http://sitmo.com/
9 ///
10 /// Use, modification and distribution are subject to the MIT Software License.
11 ///
12 /// The MIT License (MIT)
13 /// Permission is hereby granted, free of charge, to any person obtaining a copy
14 /// of this software and associated documentation files (the "Software"), to deal
15 /// in the Software without restriction, including without limitation the rights
16 /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 /// copies of the Software, and to permit persons to whom the Software is
18 /// furnished to do so, subject to the following conditions:
19 ///
20 /// The above copyright notice and this permission notice shall be included in
21 /// all copies or substantial portions of the Software.
22 ///
23 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 /// THE SOFTWARE.
30 
31 #include <random/Encrypter.hpp>
32 
33 namespace SUNphi
34 {
35  namespace Sitmo
36  {
37  /// Class encapsulating the Sitmo random generator
39  {
40  /// Default seed
41  static constexpr uint32_t DEFAULT_SEED=
42  3472291050;
43 
44  /// Holds the state of the generator
45  class State :
46  public Sitmo::Word
47  {
48 
49  public:
50 
51  /// Increment of a certain amount
52  State operator+(const uint64_t& z)
53  const
54  {
55  /// Result
56  State out=
57  (*this);
58 
59  // Increment
60  out[0]=
61  (*this)[0]+z;
62 
63  // Overflow check
64  if(out[0]<=(*this)[0])
65  {
66  /// Digit to check for overflow
67  int iDigit=
68  1;
69 
70  // Carry over
71  do out[iDigit]++;
72  while(out[iDigit++]==0 and iDigit<4);
73  }
74 
75  return
76  out;
77  }
78 
79  /// Self increment
80  State operator+=(const uint64_t& z)
81  {
82  return
83  (*this)=
84  (*this)+z;
85  }
86 
87  /// Unitary self-increment
89  {
90  return
91  (*this)+=
92  1;
93  }
94  };
95 
96 
97  /// Seed, used to encrypt
99 
100  /// State of the random number generator
102 
103  /// Number of reserved random number
105 
106  /// State whether the rng is locked or not
107  bool locked{false};
108 
109  /// Lock the generator
110  bool lock()
111  {
112  if(locked)
113  CRASH<<"Trying to lock an already locked generator!";
114 
115  locked=
116  true;
117 
118  return
119  locked;
120  }
121 
122  /// Unlock the generator
123  bool unLock()
124  {
125  if(not locked)
126  CRASH<<"Trying to unlock a non-locked generator!";
127 
128  locked=
129  false;
130 
131  return
132  locked;
133  }
134 
135  public:
136 
137  /// Type returned
138  using ResultType=
140 
142 
143  /// Draw a seed from a random generator
144  template <typename F>
145  void seed(F& f)
146  {
147  /// Result type of the callabale generator
148  using FRes=
149  typename F::ResultType;
150 
151  /// Number of calls to be issued to fill the state
152  constexpr int nCall=
153  sizeof(Word)/sizeof(FRes);
154 
155  union
156  {
157  /// Partial key
158  Word partKey;
159 
160  /// Access to the key in a way which allows to fill with the generator
161  FRes rawKey[nCall];
162  };
163 
164  /// Fill the key
165  for(int i=0;i<nCall;i++)
166  rawKey[i]=
167  f();
168 
169  key()=
170  buildKey(partKey);
171  }
172 
173  /// Seed from a seed
174  void seed(const uint32_t& s)
175  {
176  /// Partial word to be used
177  const Word& partKey=
178  {s};
179 
180  key()=
181  buildKey(partKey);
182  }
183 
184  /// Generate a number with a given offset w.r.t current state
186  {
187  // Check that this is in the range reserved
188  if(offset>=nReserved)
189  CRASH<<"Asking to generate "<<offset<<", beyond the reserved range: "<<nReserved;
190 
191  union
192  {
193  /// Temporary result of the encyipter
194  Word temp;
195 
196  /// Output to be returned
197  const ResultType out{};
198  };
199 
200  /// Shifted state
201  State shiftedState=
202  state+offset;
203 
204  temp=
205  encrypt(key,static_cast<Word>(shiftedState));
206 
207  return
208  out;
209  }
210 
211  /// Reserve a number of random number
212  bool reserve(const uint64_t& n)
213  {
214  nReserved=
215  n;
216 
217  return
218  lock();
219  }
220 
221  /// Release the reserved number of random number, increasing the state
222  bool release()
223  {
224  state+=
225  nReserved;
226 
227  nReserved=
228  0;
229 
230  return
231  unLock();
232  }
233 
234  /// Reserves, returning a scope-locker
235  ///
236  /// Automatically releases the lock and advances when the locker
237  /// goes out of scope
238  [[ nodiscard ]]
239  auto scopeReserve(const uint64_t& n)
240  {
241  return
242  ScopeDoer([this,n]()
243  {
244  return
245  this->reserve(n);
246  },
247  [this]()
248  {
249  return
250  this->release();
251  });
252  }
253 
254  /// Skip n numbers
255  void skip(const uint64_t& n)
256  {
257  auto s=
258  scopeReserve(n);
259  }
260 
261  /// Generate a number in the current stream and increase of 1
263  {
264  /// Holds the lock on the stream
265  auto hold=
266  scopeReserve(1);
267 
268  return
269  generateNth(0);
270  }
271 
272  /// Default constructor
273  explicit Rng(const uint32_t& s=DEFAULT_SEED)
274  {
275  seed(s);
276  }
277  };
278  }
279 }
280 
281 #endif
bool release()
Release the reserved number of random number, increasing the state.
Definition: Sitmo2.hpp:222
State operator+=(const uint64_t &z)
Self increment.
Definition: Sitmo2.hpp:80
State operator+(const uint64_t &z) const
Increment of a certain amount.
Definition: Sitmo2.hpp:52
#define DEFINE_SERIALIZABLE_CLASS(T)
Shortcut to define a serializable class.
Definition: Map.hpp:194
#define LIST_SERIALIZABLE_MEMBERS(...)
Defines a list of serializable members.
Definition: Map.hpp:203
#define CRASH
Initialize the crasher.
Definition: Crash.hpp:13
State operator++()
Unitary self-increment.
Definition: Sitmo2.hpp:88
Rng(const uint32_t &s=DEFAULT_SEED)
Default constructor.
Definition: Sitmo2.hpp:273
#define SERIALIZABLE_SEQUENCE(CONTAINER,NAME,...)
Create a serializable sequence.
Definition: Sequence.hpp:153
bool lock()
Lock the generator.
Definition: Sitmo2.hpp:110
#define SERIALIZABLE_SEQUENCE_WITH_TAG(CONTAINER,NAME,TAG,...)
Create a serializable sequence with a given tag.
Definition: Sequence.hpp:145
decltype(auto) operator+(T1 &&smet1, T2 &&smet2)
Implement smet1+smet2.
Definition: Add.hpp:87
bool unLock()
Unlock the generator.
Definition: Sitmo2.hpp:123
Holds the state of the generator.
Definition: Sitmo2.hpp:45
void seed(F &f)
Draw a seed from a random generator.
Definition: Sitmo2.hpp:145
ResultType generateNth(const uint64_t &offset)
Generate a number with a given offset w.r.t current state.
Definition: Sitmo2.hpp:185
bool reserve(const uint64_t &n)
Reserve a number of random number.
Definition: Sitmo2.hpp:212