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