Random123
Loading...
Searching...
No Matches
Engine.hpp
Go to the documentation of this file.
1/*
2Copyright 2010-2011, D. E. Shaw Research.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9* Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the following disclaimer.
11
12* Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16* Neither the name of D. E. Shaw Research nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32#ifndef __Engine_dot_hpp_
33#define __Engine_dot_hpp_
34
35#include "../features/compilerfeatures.h"
36#include "../array.h"
37#include <limits>
38#include <stdexcept>
39#include <sstream>
40#include <algorithm>
41#include <vector>
42#if R123_USE_CXX11_TYPE_TRAITS
43#include <type_traits>
44#endif
45
46namespace r123{
67template<typename CBRNG>
68struct Engine {
69 typedef CBRNG cbrng_type;
70 typedef typename CBRNG::ctr_type ctr_type;
71 typedef typename CBRNG::key_type key_type;
72 typedef typename CBRNG::ukey_type ukey_type;
73 typedef typename ctr_type::value_type result_type;
74
75protected:
80
82 if( v.back() != 0 ) {
83 result_type vv = v.back();
84 v = b(c, key);
85 v.back() = vv;
86 }
87 }
88public:
89 explicit Engine() : b(), c() {
90 ukey_type x = {{}};
91 v.back() = 0;
92 key = x;
93 }
94 explicit Engine(result_type r) : b(), c() {
95 ukey_type x = {{typename ukey_type::value_type(r)}};
96 v.back() = 0;
97 key = x;
98 }
99 // 26.5.3 says that the SeedSeq templates shouldn't particpate in
100 // overload resolution unless the type qualifies as a SeedSeq.
101 // How that is determined is unspecified, except that "as a
102 // minimum a type shall not qualify as a SeedSeq if it is
103 // implicitly convertible to a result_type."
104 //
105 // First, we make sure that even the non-const copy constructor
106 // works as expected. In addition, if we've got C++11
107 // type_traits, we use enable_if and is_convertible to implement
108 // the convertible-to-result_type restriction. Otherwise, the
109 // template is unconditional and will match in some surpirsing
110 // and undesirable situations.
111 Engine(Engine& e) : b(e.b), key(e.key), c(e.c){
112 v.back() = e.v.back();
114 }
115 Engine(const Engine& e) : b(e.b), key(e.key), c(e.c){
116 v.back() = e.v.back();
118 }
119#if __cplusplus >= 201103L
120 Engine& operator=(const Engine&) = default;
121 Engine& operator=(Engine&&) = default;
122#endif
123
124 template <typename SeedSeq>
125 explicit Engine(SeedSeq &s
127 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
128#endif
129 )
130 : b(), c() {
131 ukey_type ukey = ukey_type::seed(s);
132 key = ukey;
133 v.back() = 0;
134 }
136 *this = Engine(r);
137 }
138 template <typename SeedSeq>
141 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
142#endif
143 ){
144 *this = Engine(s);
145 }
146 void seed(){
147 *this = Engine();
148 }
149 friend bool operator==(const Engine& lhs, const Engine& rhs){
150 return lhs.c==rhs.c && lhs.v.back() == rhs.v.back() && lhs.key == rhs.key;
151 }
152 friend bool operator!=(const Engine& lhs, const Engine& rhs){
153 return lhs.c!=rhs.c || lhs.v.back()!=rhs.v.back() || lhs.key!=rhs.key;
154 }
155
156 friend std::ostream& operator<<(std::ostream& os, const Engine& be){
157 return os << be.c << " " << be.key << " " << be.v.back();
158 }
159
160 friend std::istream& operator>>(std::istream& is, Engine& be){
161 is >> be.c >> be.key >> be.v.back();
162 be.fix_invariant();
163 return is;
164 }
165
166 // The <random> shipped with MacOS Xcode 4.5.2 imposes a
167 // non-standard requirement that URNGs also have static data
168 // members: _Min and _Max. Later versions of libc++ impose the
169 // requirement only when constexpr isn't supported. Although the
170 // Xcode 4.5.2 requirement is clearly non-standard, it is unlikely
171 // to be fixed and it is very easy work around. We certainly
172 // don't want to go to great lengths to accommodate every buggy
173 // library we come across, but in this particular case, the effort
174 // is low and the benefit is high, so it's worth doing. Thanks to
175 // Yan Zhou for pointing this out to us. See similar code in
176 // ../MicroURNG.hpp
177 const static result_type _Min = 0;
178 const static result_type _Max = ~((result_type)0);
179
182
184 if( c.size() == 1 ) // short-circuit the scalar case. Compilers aren't mind-readers.
185 return b(c.incr(), key)[0];
186 result_type& elem = v.back();
187 if( elem == 0 ){
188 v = b(c.incr(), key);
189 result_type ret = v.back();
190 elem = c.size()-1;
191 return ret;
192 }
193 return v[--elem];
194 }
195
197 // don't forget: elem counts down
198 size_t nelem = c.size();
199 size_t sub = skip % nelem;
200 result_type& elem = v.back();
201 skip /= nelem;
202 if (elem < sub) {
203 elem += nelem;
204 skip++;
205 }
206 elem -= sub;
207 c.incr(skip);
209 }
210
211 //--------------------------
212 // Some bonus methods, not required for a Random Number
213 // Engine
214
215 // Constructors and seed() method for ukey_type seem useful
216 // We need const and non-const to supersede the SeedSeq template.
217 explicit Engine(const ukey_type &uk) : key(uk), c(){ v.back() = 0; }
218 explicit Engine(ukey_type &uk) : key(uk), c(){ v.back() = 0; }
219 void seed(const ukey_type& uk){
220 *this = Engine(uk);
221 }
223 *this = Engine(uk);
224 }
225
226#if R123_USE_CXX11_TYPE_TRAITS
227 template <typename DUMMY=void>
228 explicit Engine(const key_type& k,
229 typename std::enable_if<!std::is_same<ukey_type, key_type>::value, DUMMY>::type* = 0)
230 : key(k), c(){ v.back() = 0; }
231
232 template <typename DUMMY=void>
233 void seed(const key_type& k,
234 typename std::enable_if<!std::is_same<ukey_type, key_type>::value, DUMMY>::type* = 0){
235 *this = Engine(k);
236 }
237#endif
238
239 // Forward the e(counter) to the CBRNG we are templated
240 // on, using the current value of the key.
242 return b(c, key);
243 }
244
246 return key;
247 }
248
249 // N.B. setkey(k) is different from seed(k) because seed(k) zeros
250 // the counter (per the C++11 requirements for an Engine), whereas
251 // setkey does not.
252 void setkey(const key_type& k){
253 key = k;
255 }
256
257 // Maybe the caller want's to know the details of
258 // the internal state, e.g., so it can call a different
259 // bijection with the same counter.
260 std::pair<ctr_type, result_type> getcounter() const {
261 return std::make_pair(c, v.back());
262 }
263
264 // And the inverse.
266 static const size_t nelem = c.size();
267 if( _elem >= nelem )
268 throw std::range_error("Engine::setcounter called with elem out of range");
269 c = _c;
270 v.back() = _elem;
272 }
273
274 void setcounter(const std::pair<ctr_type, result_type>& ce){
275 setcounter(ce.first, ce.second);
276 }
277};
278} // namespace r123
279
280#endif
static Ftype uneg11(Itype in)
Return a signed value in [-1,1].
Definition uniform.hpp:206
Definition aes.h:242
Definition Engine.hpp:68
static R123_CONSTEXPR result_type max R123_NO_MACRO_SUBST()
Definition Engine.hpp:181
CBRNG::key_type key_type
Definition Engine.hpp:71
void discard(R123_ULONG_LONG skip)
Definition Engine.hpp:196
CBRNG::ukey_type ukey_type
Definition Engine.hpp:72
Engine(Engine &e)
Definition Engine.hpp:111
ctr_type::value_type result_type
Definition Engine.hpp:73
friend std::ostream & operator<<(std::ostream &os, const Engine &be)
Definition Engine.hpp:156
CBRNG cbrng_type
Definition Engine.hpp:69
Engine(const Engine &e)
Definition Engine.hpp:115
friend std::istream & operator>>(std::istream &is, Engine &be)
Definition Engine.hpp:160
ctr_type operator()(const ctr_type &c) const
Definition Engine.hpp:241
void seed(const ukey_type &uk)
Definition Engine.hpp:219
cbrng_type b
Definition Engine.hpp:76
friend bool operator==(const Engine &lhs, const Engine &rhs)
Definition Engine.hpp:149
ctr_type v
Definition Engine.hpp:79
void seed(ukey_type &uk)
Definition Engine.hpp:222
key_type getkey() const
Definition Engine.hpp:245
std::pair< ctr_type, result_type > getcounter() const
Definition Engine.hpp:260
void seed(result_type r)
Definition Engine.hpp:135
CBRNG::ctr_type ctr_type
Definition Engine.hpp:70
static const result_type _Min
Definition Engine.hpp:177
void fix_invariant()
Definition Engine.hpp:81
void seed(SeedSeq &s)
Definition Engine.hpp:139
Engine(const ukey_type &uk)
Definition Engine.hpp:217
void setcounter(const std::pair< ctr_type, result_type > &ce)
Definition Engine.hpp:274
Engine(SeedSeq &s)
Definition Engine.hpp:125
Engine()
Definition Engine.hpp:89
result_type operator()()
Definition Engine.hpp:183
void setkey(const key_type &k)
Definition Engine.hpp:252
key_type key
Definition Engine.hpp:77
Engine(result_type r)
Definition Engine.hpp:94
static const result_type _Max
Definition Engine.hpp:178
Engine(ukey_type &uk)
Definition Engine.hpp:218
void setcounter(const ctr_type &_c, result_type _elem)
Definition Engine.hpp:265
friend bool operator!=(const Engine &lhs, const Engine &rhs)
Definition Engine.hpp:152
static R123_CONSTEXPR result_type min R123_NO_MACRO_SUBST()
Definition Engine.hpp:180
ctr_type c
Definition Engine.hpp:78
void seed()
Definition Engine.hpp:146