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 R123_NO_MACRO_SUBST () { return 0; }
00165     static result_type max R123_NO_MACRO_SUBST () { return std::numeric_limits<result_type>::max R123_NO_MACRO_SUBST (); }
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