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 #include <stdint.h>
00043 #if R123_USE_CXX0X
00044 #include <type_traits>
00045 #endif
00046
00047 namespace r123{
00068 template<typename CBRNG>
00069 struct Engine {
00070 typedef CBRNG cbrng_type;
00071 typedef typename CBRNG::ctr_type ctr_type;
00072 typedef typename CBRNG::key_type key_type;
00073 typedef typename CBRNG::ukey_type ukey_type;
00074 typedef typename ctr_type::value_type result_type;
00075 typedef size_t elem_type;
00076
00077 protected:
00078 cbrng_type b;
00079 key_type key;
00080 ukey_type ukey;
00081 ctr_type c;
00082 elem_type elem;
00083 ctr_type v;
00084
00085 void fix_invariant(){
00086 if( elem != 0 ) {
00087 v = b(c, key);
00088 }
00089 }
00090 public:
00091 explicit Engine() : b(), c(), elem() {
00092 ukey_type x = {{}};
00093 ukey = x;
00094 key = ukey;
00095 }
00096 explicit Engine(result_type r) : b(), c(), elem() {
00097 ukey_type x = {{typename ukey_type::value_type(r)}};
00098 ukey = x;
00099 key = ukey;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 Engine(Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
00114 key = ukey;
00115 fix_invariant();
00116 }
00117 Engine(const Engine& e) : b(e.b), ukey(e.ukey), c(e.c), elem(e.elem){
00118 key = ukey;
00119 fix_invariant();
00120 }
00121
00122 template <typename SeedSeq>
00123 explicit Engine(SeedSeq &s
00124 #if R123_USE_CXX0X
00125 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* dummy=0
00126 #endif
00127 )
00128 : b(), c(), elem() {
00129 ukey = ukey_type::seed(s);
00130 key = ukey;
00131 }
00132 void seed(result_type r){
00133 *this = Engine(r);
00134 }
00135 template <typename SeedSeq>
00136 void seed(SeedSeq &s
00137 #if R123_USE_CXX0X
00138 , typename std::enable_if<!std::is_convertible<SeedSeq, result_type>::value>::type* dummy=0
00139 #endif
00140 ){
00141 *this = Engine(s);
00142 }
00143 void seed(){
00144 *this = Engine();
00145 }
00146 friend bool operator==(const Engine& lhs, const Engine& rhs){
00147 return lhs.c==rhs.c && lhs.elem == rhs.elem && lhs.ukey == rhs.ukey;
00148 }
00149 friend bool operator!=(const Engine& lhs, const Engine& rhs){
00150 return lhs.c!=rhs.c || lhs.elem != rhs.elem || lhs.ukey!=rhs.ukey;
00151 }
00152
00153 friend std::ostream& operator<<(std::ostream& os, const Engine& be){
00154 return os << be.c << " " << be.ukey << " " << be.elem;
00155 }
00156
00157 friend std::istream& operator>>(std::istream& is, Engine& be){
00158 is >> be.c >> be.ukey >> be.elem;
00159 be.key = be.ukey;
00160 be.fix_invariant();
00161 return is;
00162 }
00163
00164 static result_type min() { return 0; }
00165 static result_type max() { return std::numeric_limits<result_type>::max(); }
00166
00167 result_type operator()(){
00168 if( c.size() == 1 )
00169 return b(c.incr(), key)[0];
00170 if( elem == 0 ){
00171 v = b(c.incr(), key);
00172 elem = c.size();
00173 }
00174 return v[--elem];
00175 }
00176
00177 void discard(R123_ULONG_LONG skip){
00178
00179 size_t nelem = c.size();
00180 size_t sub = skip % nelem;
00181 skip /= nelem;
00182 if (elem < sub) {
00183 elem += nelem;
00184 skip++;
00185 }
00186 elem -= sub;
00187 c.incr(skip);
00188 fix_invariant();
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 explicit Engine(const ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
00198 explicit Engine(ukey_type &uk) : key(uk), ukey(uk), c(), elem(){}
00199 void seed(const ukey_type& uk){
00200 *this = Engine(uk);
00201 }
00202 void seed(ukey_type& uk){
00203 *this = Engine(uk);
00204 }
00205
00206
00207
00208 ctr_type operator()(const ctr_type& c) const{
00209 return b(c, key);
00210 }
00211
00212
00213
00214 ukey_type getseed() const{
00215 return ukey;
00216 }
00217
00218
00219
00220
00221 std::pair<ctr_type, elem_type> getcounter() const {
00222 return make_pair(c, elem);
00223 }
00224
00225
00226 void setcounter(const ctr_type& _c, elem_type _elem){
00227 static const size_t nelem = c.size();
00228 if( elem > nelem )
00229 throw std::range_error("Engine::setcounter called with elem out of range");
00230 c = _c;
00231 elem = _elem;
00232 fix_invariant();
00233 }
00234 };
00235 }
00236
00237 #endif