10 #if !defined(RANDOMLIB_RANDOMENGINE_HPP)
11 #define RANDOMLIB_RANDOMENGINE_HPP 1
19 #if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64)
23 #if !defined(RANDOMLIB_BUILDING_LIBRARY) && \
24 defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION
25 #include <boost/serialization/nvp.hpp>
26 #include <boost/serialization/split_member.hpp>
27 #include <boost/serialization/vector.hpp>
80 template<
class Algorithm,
class Mixer>
86 typedef typename Algorithm::engine_t result_t;
90 typedef typename Mixer::mixer_t mixer_t;
94 typedef typename Algorithm::internal_type engine_type;
100 width = result_t::width
132 static const u64::type version = 0x52616e644c696230ULL;
136 static const unsigned UNINIT = 0xffffffffU;
145 NU = (N * width + mixer_t::width - 1) / mixer_t::width,
166 typename mixer_t::type _stateu[NU];
170 engine_type _statev[NV];
199 template<
typename IntType>
210 template<
typename InputIterator>
249 return Algorithm::Generate(y);
259 return u32::cast(Ran());
268 const u64::type x = Ran();
269 return width > 32 ? x : u64::cast(Ran()) << (64 - width) | x;
281 #if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64)
285 void*
operator new(
size_t n) {
287 if (p == 0)
throw std::bad_alloc();
294 void operator delete(
void* p) { _aligned_free(p); }
299 void*
operator new[](
size_t n) {
300 void* p = _aligned_malloc(n, __alignof(RandomEngine));
301 if (p == 0)
throw std::bad_alloc();
308 void operator delete[](
void* p) { _aligned_free(p); }
331 {
return Count() == r.Count() && _seed == r._seed &&
332 _stride == r._stride; }
340 {
return !operator==(r); }
357 std::swap_ranges(_state, _state + N, t._state);
388 void Save(std::ostream& os,
bool bin =
true)
const;
400 void Load(std::istream& is,
bool bin =
true) {
403 _seed.reserve(t.
_seed.size());
451 {
return _ptr == UNINIT ? 0 : _rounds * N + _ptr; }
458 void SetCount(
long long n)
throw() { StepCount(n - Count()); }
464 void StepCount(
long long n)
throw();
470 void Reset() throw() { _ptr = UNINIT; _stride = 1; }
498 if (n == 0 || n > UNINIT/2)
499 throw RandomErr(
"RandomEngine: Invalid stride");
501 throw RandomErr(
"RandomEngine: Invalid offset");
518 static void SelfTest();
527 return "RandomEngine<" + Algorithm::Name() +
"," + Mixer::Name() +
">";
538 void Next() throw() {
542 Algorithm::Transition(_ptr/N, _statev);
546 u32::type Check(u64::type v, u32::type e, u32::type m)
const;
548 static result_type SelfTestResult(
unsigned) throw() {
return 0; }
555 explicit RandomEngine(std::istream& is,
bool bin);
557 #if !defined(RANDOMLIB_BUILDING_LIBRARY) && \
558 defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION
559 friend class boost::serialization::access;
566 template<
class Archive>
void save(Archive& ar,
const unsigned int)
const {
567 u64::type _version = version;
568 u32::type _eversion = Algorithm::version,
569 _mversion = Mixer::version,
570 _checksum = Check(_version, _eversion, _mversion);
571 ar & boost::serialization::make_nvp(
"version" , _version )
572 & boost::serialization::make_nvp(
"eversion", _eversion)
573 & boost::serialization::make_nvp(
"mversion", _mversion)
574 & boost::serialization::make_nvp(
"seed" , _seed )
575 & boost::serialization::make_nvp(
"ptr" , _ptr )
576 & boost::serialization::make_nvp(
"stride" , _stride );
578 ar & boost::serialization::make_nvp(
"rounds", _rounds )
579 & boost::serialization::make_nvp(
"state" , _state );
580 ar & boost::serialization::make_nvp(
"checksum", _checksum);
586 template<
class Archive>
void load(Archive& ar,
const unsigned int) {
588 u32::type _eversion, _mversion, _checksum;
589 ar & boost::serialization::make_nvp(
"version" , _version )
590 & boost::serialization::make_nvp(
"eversion", _eversion )
591 & boost::serialization::make_nvp(
"mversion", _mversion );
592 RandomEngine<Algorithm, Mixer> t(std::vector<seed_type>(0));
593 ar & boost::serialization::make_nvp(
"seed" , t._seed )
594 & boost::serialization::make_nvp(
"ptr" , t._ptr )
595 & boost::serialization::make_nvp(
"stride" , t._stride );
596 if (t._ptr != UNINIT)
597 ar & boost::serialization::make_nvp(
"rounds", t._rounds )
598 & boost::serialization::make_nvp(
"state" , t._state );
599 ar & boost::serialization::make_nvp(
"checksum", _checksum );
600 if (t.Check(_version, _eversion, _mversion) != _checksum)
601 throw RandomErr(
"RandomEngine: Checksum failure");
602 _seed.reserve(t._seed.size());
609 template<
class Archive>
610 void serialize(Archive &ar,
const unsigned int file_version)
611 { boost::serialization::split_member(ar, *
this, file_version); }
612 #endif // HAVE_BOOST_SERIALIZATION
632 template<
class Algorithm,
class Mixer>
640 #endif // RANDOMLIB_RANDOMENGINE_HPP
bool operator!=(const RandomEngine &r) const
result_t::type result_type
RandomEngine(seed_type n)
void Save(std::ostream &os, bool bin=true) const
friend std::istream & operator>>(std::istream &is, RandomEngine &r)
bool operator==(const RandomEngine &r) const
RandomEngine< SFMT19937< Random_u64 >, MixerSFMT > SRandomGenerator64
RandomEngine< MT19937< Random_u64 >, MixerSFMT > MRandomGenerator64
void SetStride(unsigned n=1, unsigned k=0)
A base class for random generators.
void Load(std::istream &is, bool bin=true)
Exception handling for RandomLib.
void swap(RandomEngine &t)
The SFMT mixing functionality.
std::vector< seed_type > _seed
void SetCount(long long n)
RandomEngine(const std::vector< IntType > &v)
void swap(RandomLib::RandomCanonical< Generator > &r, RandomLib::RandomCanonical< Generator > &s)
static std::string Name()
RandomEngine< MT19937< Random_u32 >, MixerSFMT > MRandomGenerator32
void swap(RandomLib::RandomEngine< Algorithm, Mixer > &r, RandomLib::RandomEngine< Algorithm, Mixer > &s)
Header for MT19937 and SFMT19937.
Uniform random number generator.
RandomEngine< SFMT19937< Random_u32 >, MixerSFMT > SRandomGenerator32
Header for Mixer classes.
friend std::ostream & operator<<(std::ostream &os, const RandomEngine &r)
RandomEngine(const std::string &s)
unsigned GetStride() const
RandomEngine(InputIterator a, InputIterator b)