/search.css" rel="stylesheet" type="text/css"/> /search.js">
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Engine.hpp
Go to the documentation of this file.
1 /*
2 Copyright 2010-2011, D. E. Shaw Research.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
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 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF 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 
46 namespace r123{
67 template<typename CBRNG>
68 struct 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 
75 protected:
80 
81  void fix_invariant(){
82  if( v.back() != 0 ) {
83  result_type vv = v.back();
84  v = b(c, key);
85  v.back() = vv;
86  }
87  }
88 public:
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++0x
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();
113  fix_invariant();
114  }
115  Engine(const Engine& e) : b(e.b), key(e.key), c(e.c){
116  v.back() = e.v.back();
117  fix_invariant();
118  }
119 
120  template <typename SeedSeq>
121  explicit Engine(SeedSeq &s
122 #if R123_USE_CXX11_TYPE_TRAITS
123  , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
124 #endif
125  )
126  : b(), c() {
127  ukey_type ukey = ukey_type::seed(s);
128  key = ukey;
129  v.back() = 0;
130  }
131  void seed(result_type r){
132  *this = Engine(r);
133  }
134  template <typename SeedSeq>
135  void seed(SeedSeq &s
136 #if R123_USE_CXX11_TYPE_TRAITS
137  , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
138 #endif
139  ){
140  *this = Engine(s);
141  }
142  void seed(){
143  *this = Engine();
144  }
145  friend bool operator==(const Engine& lhs, const Engine& rhs){
146  return lhs.c==rhs.c && lhs.v.back() == rhs.v.back() && lhs.key == rhs.key;
147  }
148  friend bool operator!=(const Engine& lhs, const Engine& rhs){
149  return lhs.c!=rhs.c || lhs.v.back()!=rhs.v.back() || lhs.key!=rhs.key;
150  }
151 
152  friend std::ostream& operator<<(std::ostream& os, const Engine& be){
153  return os << be.c << " " << be.key << " " << be.v.back();
154  }
155 
156  friend std::istream& operator>>(std::istream& is, Engine& be){
157  is >> be.c >> be.key >> be.v.back();
158  be.fix_invariant();
159  return is;
160  }
161 
162  // The <random> shipped with MacOS Xcode 4.5.2 imposes a
163  // non-standard requirement that URNGs also have static data
164  // members: _Min and _Max. Later versions of libc++ impose the
165  // requirement only when constexpr isn't supported. Although the
166  // Xcode 4.5.2 requirement is clearly non-standard, it is unlikely
167  // to be fixed and it is very easy work around. We certainly
168  // don't want to go to great lengths to accommodate every buggy
169  // library we come across, but in this particular case, the effort
170  // is low and the benefit is high, so it's worth doing. Thanks to
171  // Yan Zhou for pointing this out to us. See similar code in
172  // ../MicroURNG.hpp
173  const static result_type _Min = 0;
174  const static result_type _Max = ~((result_type)0);
175 
176  static R123_CONSTEXPR result_type min R123_NO_MACRO_SUBST () { return _Min; }
177  static R123_CONSTEXPR result_type max R123_NO_MACRO_SUBST () { return _Max; }
178 
180  if( c.size() == 1 ) // short-circuit the scalar case. Compilers aren't mind-readers.
181  return b(c.incr(), key)[0];
182  result_type& elem = v.back();
183  if( elem == 0 ){
184  v = b(c.incr(), key);
185  result_type ret = v.back();
186  elem = c.size()-1;
187  return ret;
188  }
189  return v[--elem];
190  }
191 
192  void discard(R123_ULONG_LONG skip){
193  // don't forget: elem counts down
194  size_t nelem = c.size();
195  size_t sub = skip % nelem;
196  result_type& elem = v.back();
197  skip /= nelem;
198  if (elem < sub) {
199  elem += nelem;
200  skip++;
201  }
202  elem -= sub;
203  c.incr(skip);
204  fix_invariant();
205  }
206 
207  //--------------------------
208  // Some bonus methods, not required for a Random Number
209  // Engine
210 
211  // Constructors and seed() method for ukey_type seem useful
212  // We need const and non-const to supersede the SeedSeq template.
213  explicit Engine(const ukey_type &uk) : key(uk), c(){ v.back() = 0; }
214  explicit Engine(ukey_type &uk) : key(uk), c(){ v.back() = 0; }
215  void seed(const ukey_type& uk){
216  *this = Engine(uk);
217  }
218  void seed(ukey_type& uk){
219  *this = Engine(uk);
220  }
221 
222 #if R123_USE_CXX11_TYPE_TRAITS
223  template <typename DUMMY=void>
224  explicit Engine(const key_type& k,
225  typename std::enable_if<!std::is_same<ukey_type, key_type>::value, DUMMY>::type* = 0)
226  : key(k), c(){ v.back() = 0; }
227 
228  template <typename DUMMY=void>
229  void seed(const key_type& k,
230  typename std::enable_if<!std::is_same<ukey_type, key_type>::value, DUMMY>::type* = 0){
231  *this = Engine(k);
232  }
233 #endif
234 
235  // Forward the e(counter) to the CBRNG we are templated
236  // on, using the current value of the key.
237  ctr_type operator()(const ctr_type& c) const{
238  return b(c, key);
239  }
240 
241  key_type getkey() const{
242  return key;
243  }
244 
245  // N.B. setkey(k) is different from seed(k) because seed(k) zeros
246  // the counter (per the C++11 requirements for an Engine), whereas
247  // setkey does not.
248  void setkey(const key_type& k){
249  key = k;
250  fix_invariant();
251  }
252 
253  // Maybe the caller want's to know the details of
254  // the internal state, e.g., so it can call a different
255  // bijection with the same counter.
256  std::pair<ctr_type, result_type> getcounter() const {
257  return std::make_pair(c, v.back());
258  }
259 
260  // And the inverse.
261  void setcounter(const ctr_type& _c, result_type _elem){
262  static const size_t nelem = c.size();
263  if( _elem >= nelem )
264  throw std::range_error("Engine::setcounter called with elem out of range");
265  c = _c;
266  v.back() = _elem;
267  fix_invariant();
268  }
269 
270  void setcounter(const std::pair<ctr_type, result_type>& ce){
271  setcounter(ce.first, ce.second);
272  }
273 };
274 } // namespace r123
275 
276 #endif
static R123_CONSTEXPR result_type min R123_NO_MACRO_SUBST()
Definition: Engine.hpp:176
CBRNG cbrng_type
Definition: Engine.hpp:69
Engine(result_type r)
Definition: Engine.hpp:94
ctr_type c
Definition: Engine.hpp:78
friend bool operator!=(const Engine &lhs, const Engine &rhs)
Definition: Engine.hpp:148
void setkey(const key_type &k)
Definition: Engine.hpp:248
Engine(SeedSeq &s)
Definition: Engine.hpp:121
Engine(ukey_type &uk)
Definition: Engine.hpp:214
key_type key
Definition: Engine.hpp:77
std::pair< ctr_type, result_type > getcounter() const
Definition: Engine.hpp:256
Engine(Engine &e)
Definition: Engine.hpp:111
Definition: Engine.hpp:68
CBRNG::ctr_type ctr_type
Definition: Engine.hpp:70
result_type operator()()
Definition: Engine.hpp:179
cbrng_type b
Definition: Engine.hpp:76
static const result_type _Min
Definition: Engine.hpp:173
ctr_type::value_type result_type
Definition: Engine.hpp:73
void setcounter(const std::pair< ctr_type, result_type > &ce)
Definition: Engine.hpp:270
Engine(const ukey_type &uk)
Definition: Engine.hpp:213
ctr_type operator()(const ctr_type &c) const
Definition: Engine.hpp:237
friend std::istream & operator>>(std::istream &is, Engine &be)
Definition: Engine.hpp:156
void setcounter(const ctr_type &_c, result_type _elem)
Definition: Engine.hpp:261
CBRNG::key_type key_type
Definition: Engine.hpp:71
void fix_invariant()
Definition: Engine.hpp:81
void seed(result_type r)
Definition: Engine.hpp:131
void seed(SeedSeq &s)
Definition: Engine.hpp:135
Engine()
Definition: Engine.hpp:89
void discard(R123_ULONG_LONG skip)
Definition: Engine.hpp:192
void seed(ukey_type &uk)
Definition: Engine.hpp:218
void seed()
Definition: Engine.hpp:142
void seed(const ukey_type &uk)
Definition: Engine.hpp:215
key_type getkey() const
Definition: Engine.hpp:241
friend std::ostream & operator<<(std::ostream &os, const Engine &be)
Definition: Engine.hpp:152
Engine(const Engine &e)
Definition: Engine.hpp:115
ctr_type v
Definition: Engine.hpp:79
friend bool operator==(const Engine &lhs, const Engine &rhs)
Definition: Engine.hpp:145
static R123_CONSTEXPR result_type max R123_NO_MACRO_SUBST()
Definition: Engine.hpp:177
CBRNG::ukey_type ukey_type
Definition: Engine.hpp:72
static const result_type _Max
Definition: Engine.hpp:174