diff --git a/sprout/generator.hpp b/sprout/generator.hpp index 1eeb60b7..4ad56834 100644 --- a/sprout/generator.hpp +++ b/sprout/generator.hpp @@ -9,6 +9,7 @@ #define SPROUT_GENERATOR_HPP #include +#include #include #endif // #ifndef SPROUT_GENERATOR_HPP diff --git a/sprout/generator/results.hpp b/sprout/generator/results.hpp new file mode 100644 index 00000000..166a98c9 --- /dev/null +++ b/sprout/generator/results.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_GENERATOR_RESULTS_HPP +#define SPROUT_GENERATOR_RESULTS_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace generators { + namespace results { + // + // generated_value + // + template + struct generated_value + : public std::decay()()))> + {}; + + // + // next_generator + // + template + struct next_generator + : public std::decay()()))> + {}; + } // namespace results + } // namespace generators + + namespace results { + using sprout::generators::generated_value; + using sprout::generators::next_generator; + } // namespace results +} // namespace sprout + +#endif // #ifndef SPROUT_GENERATOR_RESULTS_HPP diff --git a/sprout/random/generate_array.hpp b/sprout/random/generate_array.hpp index 63aa79a1..b42216fe 100644 --- a/sprout/random/generate_array.hpp +++ b/sprout/random/generate_array.hpp @@ -12,16 +12,18 @@ #include #include #include +#include +#include namespace sprout { namespace random { // // generate_array // - template - inline SPROUT_CXX14_CONSTEXPR sprout::array - generate_array(URNG& rng) { - sprout::array result{{}}; + template + inline SPROUT_CXX14_CONSTEXPR sprout::array + generate_array(RandomNumberGenerator& rng) { + sprout::array result{{}}; for (std::size_t i = 0; i != N; ++i) { result[i] = rng(); } @@ -29,32 +31,47 @@ namespace sprout { } namespace detail { - template + template static SPROUT_CONSTEXPR typename std::enable_if< (sizeof...(Args) + 1 == N), - sprout::pair, URNG> const + sprout::pair< + sprout::array::type, N>, + typename sprout::generators::results::next_generator::type + > const >::type generate_array_impl(Random const& rnd, Args const&... args) { - typedef sprout::pair, URNG> const pair_type; + typedef sprout::pair< + sprout::array::type, N>, + typename sprout::generators::results::next_generator::type + > const pair_type; return pair_type{ - sprout::array{{args..., rnd.result()}}, - rnd.engine() + sprout::array{{args..., sprout::generators::generated_value(rnd)}}, + sprout::generators::next_generator(rnd) }; } - template + template static SPROUT_CONSTEXPR typename std::enable_if< (sizeof...(Args) + 1 < N), - sprout::pair, URNG> const + sprout::pair< + sprout::array::type, N>, + typename sprout::generators::results::next_generator::type + > const >::type generate_array_impl(Random const& rnd, Args const&... args) { - return sprout::random::detail::generate_array_impl(rnd(), args..., rnd.result()); + return sprout::random::detail::generate_array_impl( + sprout::generators::next_generator(rnd)(), + args..., sprout::generators::generated_value(rnd) + ); } } // namespace detail // // generate_array // - template - inline SPROUT_CONSTEXPR sprout::pair, URNG> const - generate_array(URNG const& rng) { - return sprout::random::detail::generate_array_impl(rng()); + template + inline SPROUT_CONSTEXPR sprout::pair< + sprout::array::type, N>, + typename sprout::generators::results::next_generator::type + > const + generate_array(RandomNumberGenerator const& rng) { + return sprout::random::detail::generate_array_impl(rng()); } } // namespace random } // namespace sprout diff --git a/sprout/random/generate_canonical.hpp b/sprout/random/generate_canonical.hpp index 9ce07359..404fdce5 100644 --- a/sprout/random/generate_canonical.hpp +++ b/sprout/random/generate_canonical.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include HDR_ALGORITHM_MIN_MAX_SSCRISK_CEL_OR_SPROUT @@ -89,13 +90,23 @@ namespace sprout { typedef sprout::pair const pair_type; return mult * r < limit ? sprout::random::detail::generate_canonical_impl_1_1( r, limit, - s + RealType(sprout::random::detail::subtract()(rnd.result(), rnd.engine().min())) * mult, + s + RealType( + sprout::random::detail::subtract()( + sprout::generators::generated_value(rnd), + sprout::generators::next_generator(rnd).min() + ) + ) * mult, mult * r, rnd() ) : pair_type( - (s + RealType(sprout::random::detail::subtract()(rnd.result(), rnd.engine().min())) * mult) / (mult * r), - rnd.engine() + (s + RealType( + sprout::random::detail::subtract()( + sprout::generators::generated_value(rnd), + sprout::generators::next_generator(rnd).min() + ) + ) * mult) / (mult * r), + sprout::generators::next_generator(rnd) ) ; } @@ -106,13 +117,23 @@ namespace sprout { typedef sprout::pair const pair_type; return r < limit ? sprout::random::detail::generate_canonical_impl_1_1( r, limit, - RealType(sprout::random::detail::subtract()(rnd.result(), rnd.engine().min())), + RealType( + sprout::random::detail::subtract()( + sprout::generators::generated_value(rnd), + sprout::generators::next_generator(rnd).min() + ) + ), r, rnd() ) : pair_type( - RealType(sprout::random::detail::subtract()(rnd.result(), rnd.engine().min())) / r, - rnd.engine() + RealType( + sprout::random::detail::subtract()( + sprout::generators::generated_value(rnd), + sprout::generators::next_generator(rnd).min() + ) + ) / r, + sprout::generators::next_generator(rnd) ) ; } @@ -135,13 +156,17 @@ namespace sprout { typedef sprout::pair const pair_type; return mult * r < limit ? sprout::random::detail::generate_canonical_impl_0_1( r, limit, - s + sprout::math::floor((RealType(rnd.result()) - RealType(rnd.engine().min())) * r) * mult, + s + sprout::math::floor( + (RealType(sprout::generators::generated_value(rnd)) - RealType(sprout::generators::next_generator(rnd).min())) * r + ) * mult, mult * r, rnd() ) : pair_type( - (s + sprout::math::floor((RealType(rnd.result()) - RealType(rnd.engine().min())) * r) * mult) / (mult * r), - rnd.engine() + (s + sprout::math::floor( + (RealType(sprout::generators::generated_value(rnd)) - RealType(sprout::generators::next_generator(rnd).min())) * r + ) * mult) / (mult * r), + sprout::generators::next_generator(rnd) ) ; } @@ -151,13 +176,13 @@ namespace sprout { typedef sprout::pair const pair_type; return r < limit ? sprout::random::detail::generate_canonical_impl_0_1( r, limit, - RealType(rnd.result() - rnd.engine().min()), + RealType(sprout::generators::generated_value(rnd) - sprout::generators::next_generator(rnd).min()), r, rnd() ) : pair_type( - RealType(rnd.result() - rnd.engine().min()) / r, - rnd.engine() + RealType(sprout::generators::generated_value(rnd) - sprout::generators::next_generator(rnd).min()) / r, + sprout::generators::next_generator(rnd) ) ; } diff --git a/sprout/random/random_result.hpp b/sprout/random/random_result.hpp index 4e44e424..8b678d2b 100644 --- a/sprout/random/random_result.hpp +++ b/sprout/random/random_result.hpp @@ -15,7 +15,9 @@ #include #include #include -#include +#include +#include +#include #include #include #include @@ -25,9 +27,6 @@ namespace sprout { // // random_result // - template - class random_result; - template class random_result< Engine, @@ -46,6 +45,7 @@ namespace sprout { typedef Engine engine_type; typedef Distribution distribution_type; typedef typename distribution_type::result_type result_type; + typedef sprout::random::variate_generator generator_type; private: typedef std::iterator< std::input_iterator_tag, @@ -62,31 +62,23 @@ namespace sprout { typedef typename base_type::reference reference; private: result_type result_; - engine_type engine_; - distribution_type distribution_; + generator_type generator_; public: SPROUT_CONSTEXPR random_result() : result_() - , engine_() - , distribution_() + , generator_() {} + random_result(random_result const&) = default; SPROUT_CONSTEXPR random_result( result_type result, engine_type const& engine, distribution_type const& distribution ) : result_(result) - , engine_(engine) - , distribution_(distribution) + , generator_(engine, distribution) {} SPROUT_CONSTEXPR random_result operator()() const { - return distribution_(engine_); - } - SPROUT_CXX14_CONSTEXPR result_type& result() SPROUT_NOEXCEPT { - return result_; - } - SPROUT_CONSTEXPR result_type const& result() const SPROUT_NOEXCEPT { - return result_; + return generator_(); } SPROUT_CXX14_CONSTEXPR result_type& generated_value() SPROUT_NOEXCEPT { return result_; @@ -94,51 +86,54 @@ namespace sprout { SPROUT_CONSTEXPR result_type const& generated_value() const SPROUT_NOEXCEPT { return result_; } + SPROUT_CXX14_CONSTEXPR generator_type& next_generator() SPROUT_NOEXCEPT { + return generator_; + } + SPROUT_CONSTEXPR generator_type const& next_generator() const SPROUT_NOEXCEPT { + return generator_; + } + SPROUT_CXX14_CONSTEXPR result_type& result() SPROUT_NOEXCEPT { + return result_; + } + SPROUT_CONSTEXPR result_type const& result() const SPROUT_NOEXCEPT { + return result_; + } SPROUT_CXX14_CONSTEXPR engine_type& engine() SPROUT_NOEXCEPT { - return engine_; + return generator_.engine(); } SPROUT_CONSTEXPR engine_type const& engine() const SPROUT_NOEXCEPT { - return engine_; - } - SPROUT_CXX14_CONSTEXPR random_result& next_generator() SPROUT_NOEXCEPT { - return *this; - } - SPROUT_CONSTEXPR random_result const& next_generator() const SPROUT_NOEXCEPT { - return *this; + return generator_.engine(); } SPROUT_CXX14_CONSTEXPR distribution_type& distribution() SPROUT_NOEXCEPT { - return distribution_; + return generator_.distribution(); } SPROUT_CONSTEXPR distribution_type const& distribution() const SPROUT_NOEXCEPT { - return distribution_; + return generator_.distribution(); } SPROUT_CXX14_CONSTEXPR operator result_type&() SPROUT_NOEXCEPT { - return generated_value(); + return result_; } SPROUT_CONSTEXPR operator result_type const&() const SPROUT_NOEXCEPT { - return generated_value(); + return result_; } SPROUT_CONSTEXPR result_type min() const SPROUT_NOEXCEPT { - return distribution_.min(); + return distribution().min(); } SPROUT_CONSTEXPR result_type max() const SPROUT_NOEXCEPT { - return distribution_.max(); + return distribution().max(); } SPROUT_CXX14_CONSTEXPR void swap(random_result& other) SPROUT_NOEXCEPT_EXPR( SPROUT_NOEXCEPT_EXPR(sprout::swap(result_, other.result_)) - && SPROUT_NOEXCEPT_EXPR(sprout::swap(engine_, other.engine_)) - && SPROUT_NOEXCEPT_EXPR(sprout::swap(distribution_, other.distribution_)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(generator_, other.generator_)) ) { sprout::swap(result_, other.result_); - sprout::swap(engine_, other.engine_); - sprout::swap(distribution_, other.distribution_); + sprout::swap(generator_, other.generator_); } friend SPROUT_CONSTEXPR bool operator==(random_result const& lhs, random_result const& rhs) SPROUT_NOEXCEPT { return lhs.result_ == rhs.result_ - && lhs.engine_ == rhs.engine_ - && lhs.distribution_ == rhs.distribution_ + && lhs.generator_ == rhs.generator_ ; } friend SPROUT_CONSTEXPR bool operator!=(random_result const& lhs, random_result const& rhs) SPROUT_NOEXCEPT { @@ -178,6 +173,7 @@ namespace sprout { public: typedef Engine engine_type; typedef typename engine_type::result_type result_type; + typedef engine_type generator_type; private: typedef std::iterator< std::input_iterator_tag, @@ -194,27 +190,22 @@ namespace sprout { typedef typename base_type::reference reference; private: result_type result_; - engine_type engine_; + generator_type generator_; public: SPROUT_CONSTEXPR random_result() : result_() - , engine_() + , generator_() {} + random_result(random_result const&) = default; SPROUT_CONSTEXPR random_result( result_type result, engine_type const& engine ) : result_(result) - , engine_(engine) + , generator_(engine) {} SPROUT_CONSTEXPR random_result operator()() const { - return engine_(); - } - SPROUT_CXX14_CONSTEXPR result_type& result() SPROUT_NOEXCEPT { - return result_; - } - SPROUT_CONSTEXPR result_type const& result() const SPROUT_NOEXCEPT { - return result_; + return generator_(); } SPROUT_CXX14_CONSTEXPR result_type& generated_value() SPROUT_NOEXCEPT { return result_; @@ -222,33 +213,39 @@ namespace sprout { SPROUT_CONSTEXPR result_type const& generated_value() const SPROUT_NOEXCEPT { return result_; } + SPROUT_CXX14_CONSTEXPR generator_type& next_generator() SPROUT_NOEXCEPT { + return generator_; + } + SPROUT_CONSTEXPR generator_type const& next_generator() const SPROUT_NOEXCEPT { + return generator_; + } + SPROUT_CXX14_CONSTEXPR result_type& result() SPROUT_NOEXCEPT { + return result_; + } + SPROUT_CONSTEXPR result_type const& result() const SPROUT_NOEXCEPT { + return result_; + } SPROUT_CXX14_CONSTEXPR engine_type& engine() SPROUT_NOEXCEPT { - return engine_; + return generator_; } SPROUT_CONSTEXPR engine_type const& engine() const SPROUT_NOEXCEPT { - return engine_; - } - SPROUT_CXX14_CONSTEXPR random_result& next_generator() SPROUT_NOEXCEPT { - return *this; - } - SPROUT_CONSTEXPR random_result const& next_generator() const SPROUT_NOEXCEPT { - return *this; + return generator_; } SPROUT_CXX14_CONSTEXPR operator result_type&() SPROUT_NOEXCEPT { - return generated_value(); + return result_; } SPROUT_CONSTEXPR operator result_type const&() const SPROUT_NOEXCEPT { - return generated_value(); + return result_; } SPROUT_CONSTEXPR result_type min() const SPROUT_NOEXCEPT { - return engine_.min(); + return engine().min(); } SPROUT_CONSTEXPR result_type max() const SPROUT_NOEXCEPT { - return engine_.max(); + return engine().max(); } friend SPROUT_CONSTEXPR bool operator==(random_result const& lhs, random_result const& rhs) SPROUT_NOEXCEPT { return lhs.result_ == rhs.result_ - && lhs.engine_ == rhs.engine_ + && lhs.generator_ == rhs.generator_ ; } friend SPROUT_CONSTEXPR bool operator!=(random_result const& lhs, random_result const& rhs) SPROUT_NOEXCEPT { @@ -257,11 +254,11 @@ namespace sprout { SPROUT_CXX14_CONSTEXPR void swap(random_result& other) SPROUT_NOEXCEPT_EXPR( SPROUT_NOEXCEPT_EXPR(sprout::swap(result_, other.result_)) - && SPROUT_NOEXCEPT_EXPR(sprout::swap(engine_, other.engine_)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(generator_, other.generator_)) ) { sprout::swap(result_, other.result_); - sprout::swap(engine_, other.engine_); + sprout::swap(generator_, other.generator_); } SPROUT_CONSTEXPR reference operator*() const SPROUT_NOEXCEPT { return result_; @@ -303,8 +300,6 @@ namespace sprout { } } // namespace random - using sprout::random::random_result; - namespace tuples { namespace detail { template @@ -317,7 +312,7 @@ namespace sprout { template struct tuple_element_impl<1, sprout::random::random_result > { public: - typedef sprout::random::random_result type; + typedef typename sprout::random::random_result::generator_type type; }; template @@ -337,11 +332,11 @@ namespace sprout { template struct get_impl<1, sprout::random::random_result > { public: - SPROUT_CONSTEXPR sprout::random::random_result& + SPROUT_CONSTEXPR typename sprout::random::random_result::generator_type& operator()(sprout::random::random_result& t) const { return t.next_generator(); } - SPROUT_CONSTEXPR sprout::random::random_result const& + SPROUT_CONSTEXPR typename sprout::random::random_result::generator_type const& operator()(sprout::random::random_result const& t) const { return t.next_generator(); } diff --git a/sprout/random/random_result_fwd.hpp b/sprout/random/random_result_fwd.hpp new file mode 100644 index 00000000..f925bc7d --- /dev/null +++ b/sprout/random/random_result_fwd.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2011-2014 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_RANDOM_RESULT_FWD_HPP +#define SPROUT_RANDOM_RANDOM_RESULT_FWD_HPP + +#include + +namespace sprout { + namespace random { + // + // random_result + // + template + class random_result; + } // namespace random + + using sprout::random::random_result; +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_RANDOM_RESULT_FWD_HPP diff --git a/sprout/random/utility.hpp b/sprout/random/utility.hpp index 1261e58d..fa414aab 100644 --- a/sprout/random/utility.hpp +++ b/sprout/random/utility.hpp @@ -9,10 +9,11 @@ #define SPROUT_RANDOM_UTILITY_HPP #include +#include #include +#include #include #include -#include #include #include diff --git a/sprout/random/variate_generator.hpp b/sprout/random/variate_generator.hpp index e297a79d..2c6442d0 100644 --- a/sprout/random/variate_generator.hpp +++ b/sprout/random/variate_generator.hpp @@ -11,7 +11,8 @@ #include #include #include -#include +#include +#include namespace sprout { namespace random { @@ -41,6 +42,11 @@ namespace sprout { engine_type engine_; distribution_type distribution_; public: + SPROUT_CONSTEXPR variate_generator() + : engine_() + , distribution_() + {} + variate_generator(variate_generator const&) = default; SPROUT_CONSTEXPR variate_generator( engine_param_type engine, distribution_param_type distribution @@ -48,7 +54,7 @@ namespace sprout { : engine_(engine) , distribution_(distribution) {} - SPROUT_CONSTEXPR random_result_type operator()() const { + SPROUT_CONSTEXPR random_result_type const operator()() const { return distribution_(engine_); } engine_reference_type engine() SPROUT_NOEXCEPT { @@ -69,8 +75,36 @@ namespace sprout { SPROUT_CONSTEXPR result_type max() const SPROUT_NOEXCEPT { return distribution_.max(); } + SPROUT_CXX14_CONSTEXPR void swap(variate_generator& other) + SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(sprout::swap(engine_, other.engine_)) + && SPROUT_NOEXCEPT_EXPR(sprout::swap(distribution_, other.distribution_)) + ) + { + sprout::swap(engine_, other.engine_); + sprout::swap(distribution_, other.distribution_); + } + friend SPROUT_CONSTEXPR bool operator==(variate_generator const& lhs, variate_generator const& rhs) SPROUT_NOEXCEPT { + return lhs.engine_ == rhs.engine_ + && lhs.distribution_ == rhs.distribution_ + ; + } + friend SPROUT_CONSTEXPR bool operator!=(variate_generator const& lhs, variate_generator const& rhs) SPROUT_NOEXCEPT { + return !(lhs == rhs); + } }; + // + // swap + // + template + inline SPROUT_CXX14_CONSTEXPR void + swap(sprout::random::variate_generator& lhs, sprout::random::variate_generator& rhs) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + // // combine // @@ -93,4 +127,6 @@ namespace sprout { using sprout::random::variate_generator; } // namespace sprout +#include + #endif // #ifndef SPROUT_RANDOM_VARIATE_GENERATOR_HPP