Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef __Engine_dot_hpp_
00033 #define __Engine_dot_hpp_
00034
00035 #include "../features/compilerfeatures.h"
00036 #include "../array.h"
00037 #include <limits>
00038 #include <stdexcept>
00039 #include <sstream>
00040 #include <algorithm>
00041 #include <vector>
00042 #if R123_USE_CXX11_TYPE_TRAITS
00043 #include <type_traits>
00044 #endif
00045
00046 namespace r123{
00067 template<typename CBRNG>
00068 struct Engine {
00069 typedef CBRNG cbrng_type;
00070 typedef typename CBRNG::ctr_type ctr_type;
00071 typedef typename CBRNG::key_type key_type;
00072 typedef typename CBRNG::ukey_type ukey_type;
00073 typedef typename ctr_type::value_type result_type;
00074 typedef size_t elem_type;
00075
00076 protected:
00077 cbrng_type b;
00078 key_type key;
00079 ukey_type ukey;
00080 ctr_type c;
00081 elem_type elem;
00082 ctr_type v;
00083
00084 void fix_invariant(){
00085 if( elem != 0 ) {
00086 v = b(c, key);
00087 }
00088 }
00089 public:
00090 explicit Engine() : b(), c(), elem() {
00091 ukey_type x = {{}};
00092 ukey = x;
00093 key = ukey;
00094 }
00095 explicit Engine(result_type r) : b(), c(), elem() {
00096 ukey_type x = {{typename ukey_type::value_type(r)}};
00097 ukey = x;
00098 key = ukey;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 Engine(Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
00113 key = ukey;
00114 fix_invariant();
00115 }
00116 Engine(const Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
00117 key = ukey;
00118 fix_invariant();
00119 }
00120
00121 template <typename SeedSeq>
00122 explicit Engine(SeedSeq &s
00123 #if R123_USE_CXX11_TYPE_TRAITS
00124 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
00125 #endif
00126 )
00127 : b(), c(), elem() {
00128 ukey = ukey_type::seed(s);
00129 key = ukey;
00130 }
00131 void seed(result_type r){
00132 *this = Engine(r);
00133 }
00134 template <typename SeedSeq>
00135 void seed(SeedSeq &s
00136 #if R123_USE_CXX11_TYPE_TRAITS
00137 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* =0
00138 #endif
00139 ){
00140 *this = Engine(s);
00141 }
00142 void seed(){
00143 *this = Engine();
00144 }
00145 friend bool operator==(const Engine& lhs, const Engine& rhs){
00146 return lhs.c==rhs.c && lhs.elem == rhs.elem && lhs.ukey == rhs.ukey;
00147 }
00148 friend bool operator!=(const Engine& lhs, const Engine& rhs){
00149 return lhs.c!=rhs.c || lhs.elem != rhs.elem || lhs.ukey!=rhs.ukey;
00150 }
00151
00152 friend std::ostream& operator<<(std::ostream& os, const Engine& be){
00153 return os << be.c << " " << be.ukey << " " << be.elem;
00154 }
00155
00156 friend std::istream& operator>>(std::istream& is, Engine& be){
00157 is >> be.c >> be.ukey >> be.elem;
00158 be.key = be.ukey;
00159 be.fix_invariant();
00160 return is;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 const static result_type _Min = 0;
00175 const static result_type _Max = ~((result_type)0);
00176
00177 static R123_CONSTEXPR result_type min R123_NO_MACRO_SUBST () { return _Min; }
00178 static R123_CONSTEXPR result_type max R123_NO_MACRO_SUBST () { return _Max; }
00179
00180 result_type operator()(){
00181 if( c.size() == 1 )
00182 return b(c.incr(), key)[0];
00183 if( elem == 0 ){
00184 v = b(c.incr(), key);
00185 elem = c.size();
00186 }
00187 return v[--elem];
00188 }
00189
00190 void discard(R123_ULONG_LONG skip){
00191
00192 size_t nelem = c.size();
00193 size_t sub = skip % nelem;
00194 skip /= nelem;
00195 if (elem < sub) {
00196 elem += nelem;
00197 skip++;
00198 }
00199 elem -= sub;
00200 c.incr(skip);
00201 fix_invariant();
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 explicit Engine(const ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
00211 explicit Engine(ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
00212 void seed(const ukey_type& uk){
00213 *this = Engine(uk);
00214 }
00215 void seed(ukey_type& uk){
00216 *this = Engine(uk);
00217 }
00218
00219
00220
00221 ctr_type operator()(const ctr_type& c) const{
00222 return b(c, key);
00223 }
00224
00225
00226
00227 ukey_type getseed() const{
00228 return ukey;
00229 }
00230
00231
00232
00233
00234 std::pair<ctr_type, elem_type> getcounter() const {
00235 return make_pair(c, elem);
00236 }
00237
00238
00239 void setcounter(const ctr_type& _c, elem_type _elem){
00240 static const size_t nelem = c.size();
00241 if( elem > nelem )
00242 throw std::range_error("Engine::setcounter called with elem out of range");
00243 c = _c;
00244 elem = _elem;
00245 fix_invariant();
00246 }
00247 };
00248 }
00249
00250 #endif