From 8ebe6ea878099495b4651d6b5b56d09260131036 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Wed, 19 Oct 2011 00:18:58 +0900 Subject: [PATCH] =?UTF-8?q?sprout/random/taus88.hpp=20=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sprout/random.hpp | 3 + sprout/random/linear_congruential.hpp | 2 +- sprout/random/linear_feedback_shift.hpp | 112 ++++++++++++++++++++++++ sprout/random/taus88.hpp | 30 +++++++ sprout/random/xor_combine.hpp | 90 +++++++++++++++++++ 5 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 sprout/random/linear_feedback_shift.hpp create mode 100644 sprout/random/taus88.hpp create mode 100644 sprout/random/xor_combine.hpp diff --git a/sprout/random.hpp b/sprout/random.hpp index f24457d6..f288c9f7 100644 --- a/sprout/random.hpp +++ b/sprout/random.hpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include #include #include diff --git a/sprout/random/linear_congruential.hpp b/sprout/random/linear_congruential.hpp index 96dc7bcc..eb875f13 100644 --- a/sprout/random/linear_congruential.hpp +++ b/sprout/random/linear_congruential.hpp @@ -144,7 +144,7 @@ namespace sprout { 0xB, std::uint64_t(1) << 48 > lcf_type; - public: + private: static SPROUT_CONSTEXPR result_type static_min() { return 0; } diff --git a/sprout/random/linear_feedback_shift.hpp b/sprout/random/linear_feedback_shift.hpp new file mode 100644 index 00000000..962202ef --- /dev/null +++ b/sprout/random/linear_feedback_shift.hpp @@ -0,0 +1,112 @@ +#ifndef SPROUT_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP +#define SPROUT_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace random { + // + // linear_feedback_shift_engine + // + template + class linear_feedback_shift_engine { + public: + typedef UIntType result_type; + private: + struct private_constructor_tag {}; + public: + SPROUT_STATIC_CONSTEXPR int word_size = w; + SPROUT_STATIC_CONSTEXPR int exponent1 = k; + SPROUT_STATIC_CONSTEXPR int exponent2 = q; + SPROUT_STATIC_CONSTEXPR int step_size = s; + SPROUT_STATIC_CONSTEXPR UIntType default_seed = 341; + public: + static_assert(w > 0, "w > 0"); + static_assert(q > 0, "q > 0"); + static_assert(k < w, "k < w"); + static_assert(0 < 2 * q && 2 * q < k, "0 < 2 * q && 2 * q < k"); + static_assert(0 < s && s <= k - q, "0 < s && s <= k - q"); + private: + static SPROUT_CONSTEXPR UIntType wordmask() { + return sprout::detail::low_bits_mask_t::sig_bits; + } + static SPROUT_CONSTEXPR result_type static_min() { + return 0; + } + static SPROUT_CONSTEXPR result_type static_max() { + return wordmask(); + } + static SPROUT_CONSTEXPR UIntType init_seed_1(UIntType const& x0) { + return x0 < (1 << (w - k)) ? x0 + (1 << (w - k)) : x0; + } + static SPROUT_CONSTEXPR UIntType init_seed(UIntType const& x0) { + return init_seed_1(x0 & wordmask()); + } + private: + UIntType x_; + private: + SPROUT_CONSTEXPR linear_feedback_shift_engine(UIntType const& x, private_constructor_tag) + : x_(x) + {} + SPROUT_CONSTEXPR sprout::random::random_result generate(result_type result) const { + return sprout::random::random_result( + result, + linear_feedback_shift_engine(result, private_constructor_tag()) + ); + } + public: + SPROUT_CONSTEXPR linear_feedback_shift_engine() + : x_(init_seed(default_seed)) + {} + SPROUT_CONSTEXPR explicit linear_feedback_shift_engine(UIntType const& x0) + : x_(init_seed(x0)) + {} + SPROUT_CONSTEXPR result_type min() const { + return static_min(); + } + SPROUT_CONSTEXPR result_type max() const { + return static_max(); + } + SPROUT_CONSTEXPR sprout::random::random_result operator()() const { + return generate(((x_ & ((wordmask() << (w - k)) & wordmask())) << s) ^ ((((x_ << q) ^ x_) & wordmask()) >> (k - s))); + } + friend SPROUT_CONSTEXPR bool operator==(linear_feedback_shift_engine const& lhs, linear_feedback_shift_engine const& rhs) { + return lhs.x_ == rhs.x_; + } + friend SPROUT_CONSTEXPR bool operator!=(linear_feedback_shift_engine const& lhs, linear_feedback_shift_engine const& rhs) { + return !(lhs == rhs); + } + template + friend std::basic_istream& operator>>( + std::basic_istream& lhs, + linear_feedback_shift_engine& rhs + ) + { + return lhs >> rhs.x_; + } + template + friend std::basic_ostream& operator<<( + std::basic_ostream& lhs, + linear_feedback_shift_engine const& rhs + ) + { + return lhs << rhs.x_; + } + }; + template + SPROUT_CONSTEXPR int sprout::random::linear_feedback_shift_engine::word_size; + template + SPROUT_CONSTEXPR int sprout::random::linear_feedback_shift_engine::exponent1; + template + SPROUT_CONSTEXPR int sprout::random::linear_feedback_shift_engine::exponent2; + template + SPROUT_CONSTEXPR int sprout::random::linear_feedback_shift_engine::step_size; + template + SPROUT_CONSTEXPR UIntType sprout::random::linear_feedback_shift_engine::default_seed; + } // namespace random +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP diff --git a/sprout/random/taus88.hpp b/sprout/random/taus88.hpp new file mode 100644 index 00000000..ef8e8b1d --- /dev/null +++ b/sprout/random/taus88.hpp @@ -0,0 +1,30 @@ +#ifndef SPROUT_RANDOM_TAUS88_HPP +#define SPROUT_RANDOM_TAUS88_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace random { + // + // taus88 + // + typedef sprout::random::xor_combine_engine< + sprout::random::xor_combine_engine< + sprout::random::linear_feedback_shift_engine, + 0, + sprout::random::linear_feedback_shift_engine, + 0 + >, + 0, + sprout::random::linear_feedback_shift_engine, + 0 + > taus88; + } // namespace random + + using sprout::random::taus88; +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_TAUS88_HPP diff --git a/sprout/random/xor_combine.hpp b/sprout/random/xor_combine.hpp new file mode 100644 index 00000000..afa1e973 --- /dev/null +++ b/sprout/random/xor_combine.hpp @@ -0,0 +1,90 @@ +#ifndef SPROUT_RANDOM_XOR_COMBINE_HPP +#define SPROUT_RANDOM_XOR_COMBINE_HPP + +#include +#include +#include +#include +#include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL + +namespace sprout { + namespace random { + // + // xor_combine_engine + // + template + class xor_combine_engine { + public: + typedef URNG1 base1_type; + typedef URNG2 base2_type; + typedef typename base1_type::result_type result_type; + public: + SPROUT_STATIC_CONSTEXPR int shift1 = s1; + SPROUT_STATIC_CONSTEXPR int shift2 = s2; + private: + base1_type rng1_; + base2_type rng2_; + private: + template + SPROUT_CONSTEXPR sprout::random::random_result generate(Random1 const& rnd1, Random2 const& rnd2) const { + return sprout::random::random_result( + (rnd1.result() << s1) ^ (rnd2.result() << s2), + xor_combine_engine( + rnd1.engine(), + rnd2.engine() + ) + ); + } + public: + SPROUT_CONSTEXPR xor_combine_engine() + : rng1_() + , rng2_() + {} + SPROUT_CONSTEXPR explicit xor_combine_engine(result_type const& seed) + : rng1_(seed) + , rng2_(seed) + {} + SPROUT_CONSTEXPR xor_combine_engine(base1_type const& rng1, base2_type const& rng2) + : rng1_(rng1) + , rng2_(rng2) + {} + SPROUT_CONSTEXPR result_type min() const { + return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::min(rng1_.min(), rng2_.min()); + } + SPROUT_CONSTEXPR result_type max() const { + return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::max(rng1_.max(), rng2_.max()); + } + SPROUT_CONSTEXPR sprout::random::random_result operator()() const { + return generate(rng1_(), rng2_()); + } + friend SPROUT_CONSTEXPR bool operator==(xor_combine_engine const& lhs, xor_combine_engine const& rhs) { + return lhs.rng1_ == rhs.rng1_ && lhs.rng2_ == rhs.rng2_; + } + friend SPROUT_CONSTEXPR bool operator!=(xor_combine_engine const& lhs, xor_combine_engine const& rhs) { + return !(lhs == rhs); + } + template + friend std::basic_istream& operator>>( + std::basic_istream& lhs, + xor_combine_engine& rhs + ) + { + return lhs >> rhs.rng1_ >> std::ws >> rhs.rng2_; + } + template + friend std::basic_ostream& operator<<( + std::basic_ostream& lhs, + xor_combine_engine const& rhs + ) + { + return lhs << rhs.rng1_ << ' ' << rhs.rng2_; + } + }; + template + SPROUT_CONSTEXPR int sprout::random::xor_combine_engine::shift1; + template + SPROUT_CONSTEXPR int sprout::random::xor_combine_engine::shift2; + } // namespace random +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_XOR_COMBINE_HPP