diff --git a/sprout/operation/fit.hpp b/sprout/operation/fit.hpp index 80af77b8..9f720730 100644 --- a/sprout/operation/fit.hpp +++ b/sprout/operation/fit.hpp @@ -21,5 +21,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_OPERATION_FIT_HPP diff --git a/sprout/operation/fit/set.hpp b/sprout/operation/fit/set.hpp new file mode 100644 index 00000000..15ea704e --- /dev/null +++ b/sprout/operation/fit/set.hpp @@ -0,0 +1,63 @@ +#ifndef SPROUT_OPERATION_FIT_SET_HPP +#define SPROUT_OPERATION_FIT_SET_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace fit { + namespace result_of { + // + // set + // + template + struct set { + public: + typedef sprout::sub_array< + typename sprout::fixed_container_traits< + typename sprout::fixed::result_of::set::type + >::internal_type + > type; + }; + } // namespace result_of + + // + // set + // + template + SPROUT_CONSTEXPR inline typename sprout::fit::result_of::set::type set( + Container const& cont, + typename sprout::fixed_container_traits::const_iterator pos, + T const& v + ) + { + return sprout::sub_copy( + sprout::get_fixed(sprout::fixed::set(cont, pos, v)), + sprout::fixed_begin_offset(cont), + sprout::fixed_end_offset(cont) + ); + } + // + // set + // + template + SPROUT_CONSTEXPR inline typename sprout::fit::result_of::set::type set( + Container const& cont, + typename sprout::fixed_container_traits::difference_type pos, + T const& v + ) + { + return sprout::sub_copy( + sprout::get_fixed(sprout::fixed::set(cont, pos, v)), + sprout::fixed_begin_offset(cont), + sprout::fixed_end_offset(cont) + ); + } + } // namespace fit +} // namespace sprout + +#endif // #ifndef SPROUT_OPERATION_FIT_SET_HPP diff --git a/sprout/operation/fixed.hpp b/sprout/operation/fixed.hpp index 89c5888d..2475257d 100644 --- a/sprout/operation/fixed.hpp +++ b/sprout/operation/fixed.hpp @@ -21,5 +21,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_OPERATION_FIXED_HPP diff --git a/sprout/operation/fixed/realign.hpp b/sprout/operation/fixed/realign.hpp index d4927dbb..a4b59b69 100644 --- a/sprout/operation/fixed/realign.hpp +++ b/sprout/operation/fixed/realign.hpp @@ -17,7 +17,7 @@ namespace sprout { template struct realign { public: - typedef Container type; + typedef typename sprout::fixed_container_traits::clone_type type; }; } // namespace result_of diff --git a/sprout/operation/fixed/set.hpp b/sprout/operation/fixed/set.hpp new file mode 100644 index 00000000..5857a284 --- /dev/null +++ b/sprout/operation/fixed/set.hpp @@ -0,0 +1,87 @@ +#ifndef SPROUT_OPERATION_FIXED_SET_HPP +#define SPROUT_OPERATION_FIXED_SET_HPP + +#include +#include +#include +#include +#include +#include +#include HDR_ITERATOR_SSCRISK_CEL_OR_SPROUT_DETAIL + +namespace sprout { + namespace fixed { + namespace result_of { + // + // set + // + template + struct set { + public: + typedef typename sprout::fixed_container_traits::clone_type type; + }; + } // namespace result_of + + namespace detail { + template + SPROUT_CONSTEXPR inline Result set_impl( + Container const& cont, + sprout::index_tuple, + typename sprout::fixed_container_traits::difference_type pos, + T const& v + ) + { + return sprout::remake_clone( + cont, + sprout::size(cont), + (Indexes != pos + ? *sprout::next(sprout::fixed_begin(cont), Indexes) + : v + )... + ); + } + } // namespace detail + // + // set + // + template + SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::set::type set( + Container const& cont, + typename sprout::fixed_container_traits::const_iterator pos, + T const& v + ) + { + return sprout::fixed::detail::set_impl::type>( + cont, + typename sprout::index_range<0, sprout::fixed_container_traits::type>::fixed_size>::type(), + NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::fixed_begin(cont), pos), + v + ); + } + // + // set + // + template + SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::set::type set( + Container const& cont, + typename sprout::fixed_container_traits::difference_type pos, + T const& v + ) + { + return sprout::fixed::detail::set_impl::type>( + cont, + typename sprout::index_range<0, sprout::fixed_container_traits::type>::fixed_size>::type(), + NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::fixed_begin(cont), sprout::next(sprout::begin(cont), pos)), + v + ); + } + } // namespace fixed + + namespace result_of { + using sprout::fixed::result_of::set; + } // namespace result_of + + using sprout::fixed::set; +} // namespace sprout + +#endif // #ifndef SPROUT_OPERATION_FIXED_SET_HPP diff --git a/sprout/operation/set.hpp b/sprout/operation/set.hpp new file mode 100644 index 00000000..89440912 --- /dev/null +++ b/sprout/operation/set.hpp @@ -0,0 +1,8 @@ +#ifndef SPROUT_OPERATION_SET_HPP +#define SPROUT_OPERATION_SET_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_OPERATION_SET_HPP diff --git a/sprout/random.hpp b/sprout/random.hpp index 9f8f0bd1..8baba2e5 100644 --- a/sprout/random.hpp +++ b/sprout/random.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/sprout/random/linear_congruential.hpp b/sprout/random/linear_congruential.hpp index 861dd59e..1b9cdb9a 100644 --- a/sprout/random/linear_congruential.hpp +++ b/sprout/random/linear_congruential.hpp @@ -95,7 +95,7 @@ namespace sprout { ) { IntType x; - if(lhs >> x) { + if (lhs >> x) { if(arg_check_nothrow(x)) { rhs.x_ = x; } else { diff --git a/sprout/random/shuffle_order.hpp b/sprout/random/shuffle_order.hpp new file mode 100644 index 00000000..331a2fc5 --- /dev/null +++ b/sprout/random/shuffle_order.hpp @@ -0,0 +1,193 @@ +#ifndef SPROUT_RANDOM_SHUFFLE_ORDER_HPP +#define SPROUT_RANDOM_SHUFFLE_ORDER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace random { + namespace detail { + template + class shuffle_order_engine_member { + protected: + typedef UniformRandomNumberGenerator base_type; + typedef typename base_type::result_type result_type; + public: + base_type rng_; + sprout::array v_; + result_type y_; + }; + } // namespace detail + // + // shuffle_order_engine + // + template + class shuffle_order_engine + : private sprout::random::detail::shuffle_order_engine_member + { + private: + typedef sprout::random::detail::shuffle_order_engine_member member_type; + public: + typedef UniformRandomNumberGenerator base_type; + typedef typename base_type::result_type result_type; + private: + struct private_constructor_tag {}; + public: + SPROUT_STATIC_CONSTEXPR std::size_t buffer_size = k; + SPROUT_STATIC_CONSTEXPR std::size_t table_size = k; + public: + static_assert(std::numeric_limits::is_integer, "std::numeric_limits::is_integer"); + static_assert(k > 0, "k > 0"); + private: + template + static SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) == k, + member_type + >::type init_member_1(Random const& rnd, Args const&... args) { + return member_type{ + rnd.engine(), + sprout::array{{args...}}, + rnd.result() + }; + } + template + static SPROUT_CONSTEXPR typename std::enable_if< + sizeof...(Args) < k, + member_type + >::type init_member_1(Random const& rnd, Args const&... args) { + return init_member_1(rnd(), args..., rnd.result()); + } + static SPROUT_CONSTEXPR member_type init_member(base_type const& rng) { + return init_member_1(rng()); + } + private: + using member_type::rng_; + using member_type::v_; + using member_type::y_; + private: + SPROUT_CONSTEXPR shuffle_order_engine( + base_type const& rng, + sprout::array const& v, + result_type const& y, + private_constructor_tag + ) + : member_type{rng, v, y} + {} + template + SPROUT_CONSTEXPR sprout::random::random_result generate_1(Random const& rnd, BaseUnsigned j) const { + return sprout::random::random_result( + v_[j], + shuffle_order_engine( + rnd.engine(), + sprout::fixed::set(v_, j, rnd.result()), + v_[j], + private_constructor_tag() + ) + ); + } + template + SPROUT_CONSTEXPR sprout::random::random_result generate(BaseUnsigned brange, BaseUnsigned off) const { + return generate_1( + rng_(), + k == 1 ? BaseUnsigned(0) + : brange < std::numeric_limits::max() / k ? BaseUnsigned(k * off / (brange + 1)) + : brange < std::numeric_limits::max() / k ? static_cast(static_cast(off) * k / (static_cast(brange) + 1)) + : /*static_cast(sprout::random::detail::muldiv(off, k, static_cast(brange) + 1))*/throw "Sorry, not implemented." + ); + } + public: + SPROUT_CONSTEXPR shuffle_order_engine() + : member_type(init_member(base_type())) + {} + SPROUT_CONSTEXPR explicit shuffle_order_engine(result_type const& s) + : member_type(init_member(base_type(s))) + {} + SPROUT_CONSTEXPR explicit shuffle_order_engine(base_type const& rng) + : member_type(init_member(rng)) + {} + SPROUT_CONSTEXPR result_type min() const { + return rng_.min(); + } + SPROUT_CONSTEXPR result_type max() const { + return rng_.max(); + } + SPROUT_CONSTEXPR sprout::random::random_result operator()() const { + typedef typename std::make_unsigned::type base_unsigned; + return generate( + base_unsigned(sprout::random::detail::subtract()(max(), min())), + base_unsigned(sprout::random::detail::subtract()(y_, min())) + ); + } + friend SPROUT_CONSTEXPR bool operator==(shuffle_order_engine const& lhs, shuffle_order_engine const& rhs) { + return lhs.rng_ == rhs.rng_ && lhs.y_ == rhs.y_ && lhs.v_ == rhs.v_; + } + friend SPROUT_CONSTEXPR bool operator!=(shuffle_order_engine const& lhs, shuffle_order_engine const& rhs) { + return !(lhs == rhs); + } + template + friend std::basic_istream& operator>>( + std::basic_istream& lhs, + shuffle_order_engine& rhs + ) + { + using std::swap; + base_type rng; + sprout::array v; + result_type y; + lhs >> rng; + for (std::size_t i = 0; i < k; ++i) { + lhs >> std::ws >> v[i]; + } + lhs >> std::ws >> y; + if (lhs) { + swap(rhs.rng_, rng); + swap(rhs.v_, v); + swap(rhs.y_, y); + } + return lhs; + } + template + friend std::basic_ostream& operator<<( + std::basic_ostream& lhs, + shuffle_order_engine const& rhs + ) + { + lhs << rhs.rng_; + for (std::size_t i = 0; i < k; ++i) { + lhs << ' ' << rhs.v_[i]; + } + lhs << ' ' << rhs.y_; + return lhs; + } + }; + template + SPROUT_CONSTEXPR std::size_t sprout::random::shuffle_order_engine::buffer_size; + template + SPROUT_CONSTEXPR std::size_t sprout::random::shuffle_order_engine::table_size; + + // + // knuth_b + // + typedef shuffle_order_engine knuth_b; + // + // kreutzer1986 + // + typedef sprout::random::shuffle_order_engine, 97> kreutzer1986; + } // namespace random + + using sprout::random::knuth_b; + using sprout::random::kreutzer1986; +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_SHUFFLE_ORDER_HPP