Skylark (Sketching Library)
0.1
|
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