Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/utility/randgen.hpp
Go to the documentation of this file.
00001 #ifndef RANDGEN_HPP
00002 #define RANDGEN_HPP
00003 
00004 #include <sstream>
00005 
00006 #include <Random123/threefry.h>
00007 #include <Random123/MicroURNG.hpp>
00008 
00009 namespace skylark { namespace utility {
00010 
00011 
00016 template <typename Distribution>
00017 struct random_samples_array_t {
00018 
00019 public:
00020 
00021     typedef typename Distribution::result_type value_type;
00022 
00026     typedef r123::Threefry4x64 RNG_t;
00027     typedef RNG_t::ctr_type ctr_t;
00028     typedef RNG_t::key_type key_t;
00029     typedef r123::MicroURNG<RNG_t> URNG_t;
00030 
00031     /*
00032      * Helper routine for handling array initializer in pre C++11 compilers
00033      */
00034     static key_t _seed_to_key(int seed) {
00035         key_t key;
00036         for(int i = 1; i < 4; i++)
00037             key.v[i] =  static_cast<key_t::value_type>(0);
00038         key.v[0] = static_cast<key_t::value_type>(seed);
00039         return key;
00040     }
00041 
00042     random_samples_array_t() :
00043         _base(0), _size(0), _key(_seed_to_key(0)), _distribution() {
00044 
00045     }
00046 
00059     random_samples_array_t(size_t base, size_t size, int seed,
00060         Distribution& distribution)
00061         : _base(base), _size(size),
00062           _key(_seed_to_key(seed)),
00063           _distribution(distribution) {
00064         if(std::numeric_limits<size_t>::max() - base < size - 1) {
00065             std::ostringstream msg;
00066             msg << "Unsupported operation:\n";
00067             msg << "The random number generator stream cannot supply the ";
00068             msg << "requested number of samples without being exhausted\n";
00069             SKYLARK_THROW_EXCEPTION (
00070                 base::random123_exception()
00071                 << base::error_msg(msg.str()) );
00072         }
00073         _distribution.reset();
00074     }
00075 
00076     random_samples_array_t(const random_samples_array_t& other) :
00077         _base(other._base), _size(other._size), _key(other._key),
00078         _distribution(other._distribution) {
00079 
00080     }
00081 
00082     random_samples_array_t& operator=(const random_samples_array_t& other) {
00083         _base = other._base;
00084         _size = other._size;
00085         _key = other._key;
00086         _distribution = other._distribution;
00087         return *this;
00088     }
00089 
00098     value_type operator[](size_t index) const {
00099         // Could be more specific exception std::out_of_range
00100         if( index >= _size ) {
00101             std::ostringstream msg;
00102             msg << "Index is out of bounds:\n";
00103             msg << "index = " << index << " not in expected ";
00104             msg << "[0, " << _size << ") range\n";
00105             SKYLARK_THROW_EXCEPTION (
00106                 base::random123_exception()
00107                 << base::error_msg(msg.str()) );
00108         }
00109         ctr_t ctr;
00110         for(int i = 1; i < 4; i++)
00111             ctr.v[i] = static_cast<ctr_t::value_type>(0);
00112         ctr.v[0] = static_cast<ctr_t::value_type>(_base + index);
00113         URNG_t urng(ctr, _key);
00114         Distribution cloned_distribution = _distribution;
00115         return cloned_distribution(urng);
00116     }
00117 
00118 private:
00119     size_t _base;
00120     size_t _size;
00121     key_t _key;
00122     Distribution _distribution;
00123 };
00124 
00125 
00129 struct random_array_t {
00130 
00131 public:
00135     typedef r123::Threefry4x64 RNG_t;
00136     typedef RNG_t::ctr_type ctr_t;
00137     typedef RNG_t::key_type key_t;
00138     typedef r123::MicroURNG<RNG_t> URNG_t;
00139 
00140     /*
00141      * Helper routine for handling array initializer in pre C++11 compilers
00142      */
00143     static key_t _seed_to_key(int seed) {
00144         key_t key;
00145         for(int i = 1; i < 4; i++)
00146             key.v[i] =  static_cast<key_t::value_type>(0);
00147         key.v[0] = static_cast<key_t::value_type>(seed);
00148         return key;
00149     }
00150 
00160     random_array_t(size_t base, size_t size, int seed)
00161         : _base(base), _size(size), _key(_seed_to_key(seed)) {
00162         if(std::numeric_limits<size_t>::max() - base + 1 < size) {
00163             std::ostringstream msg;
00164             msg << "Usupported operation:\n";
00165             msg << "The random number generator stream cannot supply the ";
00166             msg << "requested number of samples without being exhausted\n";
00167             SKYLARK_THROW_EXCEPTION (
00168                 base::random123_exception()
00169                 << base::error_msg(msg.str()) );
00170         }
00171     }
00172 
00173     int operator[](size_t index) const {
00174         // Could be more specific exception std::out_of_range
00175         if( index >= _size ) {
00176             std::ostringstream msg;
00177             msg << "Index is out of bounds:\n";
00178             msg << "index = " << index << " not in expected ";
00179             msg << "[0, " << _size << ") range\n";
00180             SKYLARK_THROW_EXCEPTION (
00181                 base::random123_exception()
00182                 << base::error_msg(msg.str()) );
00183         }
00184         ctr_t ctr;
00185         for(int i = 1; i < 4; i++)
00186             ctr.v[i] = static_cast<ctr_t::value_type>(0);
00187         ctr.v[0] = static_cast<ctr_t::value_type>(_base + index);
00188         URNG_t urng(ctr, _key);
00189         return urng();
00190     }
00191 
00192 private:
00193     const size_t _base;
00194     const size_t _size;
00195     const key_t _key;
00196 };
00197 
00198 } } 
00200 #endif // RANDGEN_HPP