/*============================================================================= Copyright (c) 2011-2013 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_RANDOM_ADDITIVE_COMBINE_HPP #define SPROUT_RANDOM_ADDITIVE_COMBINE_HPP #include #include #include #include #include #include namespace sprout { namespace random { // // additive_combine_engine // template class additive_combine_engine { public: typedef MLCG1 base1_type; typedef MLCG2 base2_type; typedef base1_type first_base; typedef base2_type second_base; typedef typename base1_type::result_type result_type; private: static SPROUT_CONSTEXPR result_type static_min() SPROUT_NOEXCEPT { return 1; } static SPROUT_CONSTEXPR result_type static_max() SPROUT_NOEXCEPT { return base1_type::modulus - 1; } public: struct private_constructor_tag {}; private: base1_type mlcg1_; base2_type mlcg2_; private: SPROUT_CONSTEXPR additive_combine_engine( base1_type const& mlcg1, base2_type const& mlcg2, private_constructor_tag ) : mlcg1_(mlcg1) , mlcg2_(mlcg2) {} template SPROUT_CONSTEXPR sprout::random::random_result generate(Random1 const& rnd1, Random2 const& rnd2) const { return sprout::random::random_result( rnd2.result() < rnd1.result() ? rnd1.result() - rnd2.result() : rnd1.result() - rnd2.result() + base1_type::modulus - 1 , additive_combine_engine( rnd1.engine(), rnd2.engine(), private_constructor_tag() ) ); } public: SPROUT_CONSTEXPR additive_combine_engine() : mlcg1_() , mlcg2_() {} explicit SPROUT_CONSTEXPR additive_combine_engine(result_type const& seed) : mlcg1_(seed) , mlcg2_(seed) {} SPROUT_CONSTEXPR additive_combine_engine(typename MLCG1::result_type seed1, typename MLCG2::result_type seed2) : mlcg1_(seed1) , mlcg2_(seed2) {} SPROUT_CONSTEXPR result_type min() const SPROUT_NOEXCEPT { return 1; } SPROUT_CONSTEXPR result_type max() const SPROUT_NOEXCEPT { return base1_type::modulus - 1; } SPROUT_CONSTEXPR sprout::random::random_result operator()() const { return generate(mlcg1_(), mlcg2_()); } SPROUT_CONSTEXPR base1_type const& base1() const SPROUT_NOEXCEPT { return mlcg1_; } SPROUT_CONSTEXPR base2_type const& base2() const SPROUT_NOEXCEPT { return mlcg2_; } friend SPROUT_CONSTEXPR bool operator==(additive_combine_engine const& lhs, additive_combine_engine const& rhs) SPROUT_NOEXCEPT { return lhs.mlcg1_ == rhs.mlcg1_ && lhs.mlcg2_ == rhs.mlcg2_; } friend SPROUT_CONSTEXPR bool operator!=(additive_combine_engine const& lhs, additive_combine_engine const& rhs) SPROUT_NOEXCEPT { return !(lhs == rhs); } template friend std::basic_istream& operator>>( std::basic_istream& lhs, additive_combine_engine& rhs ) { return lhs >> rhs.mlcg1_ >> std::ws >> rhs.mlcg2_; } template friend std::basic_ostream& operator<<( std::basic_ostream& lhs, additive_combine_engine const& rhs ) { return lhs << rhs.mlcg1_ << ' ' << rhs.mlcg2_; } }; // // ecuyer1988 // typedef sprout::random::additive_combine_engine< sprout::random::linear_congruential_engine, sprout::random::linear_congruential_engine > ecuyer1988; } // namespace random using sprout::random::additive_combine_engine; using sprout::random::ecuyer1988; } // namespace sprout #endif // #ifndef SPROUT_RANDOM_ADDITIVE_COMBINE_HPP