From ab0731c4fced50f84fae82c4c4df9b5260d4cb48 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Fri, 8 Nov 2013 23:20:43 +0900 Subject: [PATCH] [sprout.random] add seed_array --- sprout/algorithm/fixed/transform.hpp | 4 +- sprout/functional/bind/bind.hpp | 2 +- sprout/functional/modulus.hpp | 2 +- sprout/math/remainder.hpp | 2 +- sprout/pit/pit.hpp | 10 +- sprout/random.hpp | 2 +- sprout/random/seed.hpp | 15 ++ sprout/random/seed_array.hpp | 370 +++++++++++++++++++++++++++ 8 files changed, 399 insertions(+), 8 deletions(-) create mode 100644 sprout/random/seed.hpp create mode 100644 sprout/random/seed_array.hpp diff --git a/sprout/algorithm/fixed/transform.hpp b/sprout/algorithm/fixed/transform.hpp index e04738af..4eea74b8 100644 --- a/sprout/algorithm/fixed/transform.hpp +++ b/sprout/algorithm/fixed/transform.hpp @@ -41,7 +41,7 @@ namespace sprout { return sprout::remake( result, sprout::size(result), (Indexes >= offset && Indexes < offset + size && Indexes < offset + input_size - ? op(first[Indexes - offset]) + ? op(*sprout::next(first, Indexes - offset)) : *sprout::next(sprout::internal_begin(result), Indexes) )... ); @@ -159,7 +159,7 @@ namespace sprout { return sprout::remake( result, sprout::size(result), (Indexes >= offset && Indexes < offset + size && Indexes < offset + input_size - ? op(first1[Indexes - offset], first2[Indexes - offset]) + ? op(*sprout::next(first1, Indexes - offset), *sprout::next(first2, Indexes - offset)) : *sprout::next(sprout::internal_begin(result), Indexes) )... ); diff --git a/sprout/functional/bind/bind.hpp b/sprout/functional/bind/bind.hpp index df1f6205..a4dc77ac 100644 --- a/sprout/functional/bind/bind.hpp +++ b/sprout/functional/bind/bind.hpp @@ -241,7 +241,7 @@ namespace sprout { {}; template struct bounds_size_impl< - I, Bounds, ArgSize, + I, Bounds, ArgSize, typename std::enable_if<(I < sprout::tuples::tuple_size::value)>::type > : public std::integral_constant< diff --git a/sprout/functional/modulus.hpp b/sprout/functional/modulus.hpp index 12de5898..f30a1945 100644 --- a/sprout/functional/modulus.hpp +++ b/sprout/functional/modulus.hpp @@ -24,7 +24,7 @@ namespace sprout { typedef T result_type; public: SPROUT_CONSTEXPR T operator()(T const& x, T const& y) const { - return x % y; + return x % y; } }; diff --git a/sprout/math/remainder.hpp b/sprout/math/remainder.hpp index 7b00300d..a65df1a8 100644 --- a/sprout/math/remainder.hpp +++ b/sprout/math/remainder.hpp @@ -30,7 +30,7 @@ namespace sprout { builtin_remainder(double x, double y) { return __builtin_remainder(x, y); } - inline SPROUT_CONSTEXPR long double + inline SPROUT_CONSTEXPR long double builtin_remainder(long double x, long double y) { return __builtin_remainderl(x, y); } diff --git a/sprout/pit/pit.hpp b/sprout/pit/pit.hpp index 2afb51f8..b1ba31c3 100644 --- a/sprout/pit/pit.hpp +++ b/sprout/pit/pit.hpp @@ -43,10 +43,16 @@ namespace sprout { typedef typename sprout::reverse_iterator const_reverse_iterator; public: SPROUT_STATIC_CONSTEXPR size_type enumerable_size = sprout::detail::static_size_or_zero::value; - public: + private: value_type elem; public: - pit() = default; + SPROUT_CONSTEXPR pit() + : elem() + {} + pit(pit const&) = default; + explicit SPROUT_CONSTEXPR pit(value_type const& t) + : elem(t) + {} SPROUT_CXX14_CONSTEXPR void swap(pit& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(elem, other.elem))) { diff --git a/sprout/random.hpp b/sprout/random.hpp index 467a015b..8165b9a3 100644 --- a/sprout/random.hpp +++ b/sprout/random.hpp @@ -15,6 +15,6 @@ #include #include #include -#include +#include #endif // #ifndef SPROUT_RANDOM_HPP diff --git a/sprout/random/seed.hpp b/sprout/random/seed.hpp new file mode 100644 index 00000000..67496135 --- /dev/null +++ b/sprout/random/seed.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + 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_SEED_HPP +#define SPROUT_RANDOM_SEED_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_RANDOM_SEED_HPP diff --git a/sprout/random/seed_array.hpp b/sprout/random/seed_array.hpp new file mode 100644 index 00000000..43b4e7d4 --- /dev/null +++ b/sprout/random/seed_array.hpp @@ -0,0 +1,370 @@ +/*============================================================================= + 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_SEED_ARRAY_HPP +#define SPROUT_RANDOM_SEED_ARRAY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace random { + namespace detail { + template + class seed_array_init { + public: + template + SPROUT_CONSTEXPR UIntType operator()(IntType const& x) const { + return static_cast(x % (std::uint_least64_t(2) << 32)); + } + }; + + template + class seed_array_impl { + public: + typedef std::uint_least32_t result_type; + protected: + typedef sprout::array array_type; + protected: + array_type v; + public: + SPROUT_CONSTEXPR seed_array_impl() SPROUT_NOEXCEPT + : v{{}} + {} + template + SPROUT_CONSTEXPR seed_array_impl(InputIterator begin, InputIterator end) + : v(sprout::fixed::transform(begin, end, sprout::random::detail::seed_array_init())) + {} + }; + } // namespace detail + // + // seed_array + // + template + class seed_array + : public sprout::random::detail::seed_array_impl + { + private: + typedef sprout::random::detail::seed_array_impl impl_type; + public: + typedef typename impl_type::result_type result_type; + typedef result_type value_type; + typedef std::size_t size_type; + private: + using impl_type::v; + private: + static SPROUT_CONSTEXPR result_type tp(result_type x) { + return x ^ (x >> 27); + } + static SPROUT_CONSTEXPR size_type tval(size_type n) { + return (n >= 623) ? 11 + : (n >= 68) ? 7 + : (n >= 39) ? 5 + : (n >= 7) ? 3 + : (n - 1) / 2 + ; + } + template + static SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type set2_impl( + Result const& result, + size_type kpn, size_type kqn, size_type kn, + typename sprout::container_traits::value_type r3, + typename sprout::container_traits::value_type r4, + sprout::index_tuple + ) + { + return sprout::remake( + result, + sprout::size(result), + (Indexes == kn ? r4 + : (result[Indexes] + ^ (Indexes == kpn ? r3 : typename sprout::container_traits::value_type()) + ^ (Indexes == kqn ? r4 : typename sprout::container_traits::value_type()) + ) + )... + ); + } + template + static SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type set2( + Result const& result, + size_type kpn, size_type kqn, size_type kn, + typename sprout::container_traits::value_type r3, + typename sprout::container_traits::value_type r4_3 + ) + { + return set2_impl(result, kpn, kqn, kn, r3, r3 - r4_3, sprout::container_indexes::make()); + } + template + static SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type set1_impl( + Result const& result, + size_type kpn, size_type kqn, size_type kn, + typename sprout::container_traits::value_type r1, + typename sprout::container_traits::value_type r2, + sprout::index_tuple + ) + { + return sprout::remake( + result, + sprout::size(result), + (Indexes == kn ? r2 + : (result[Indexes] + + (Indexes == kpn ? r1 : typename sprout::container_traits::value_type()) + + (Indexes == kqn ? r2 : typename sprout::container_traits::value_type()) + ) + )... + ); + } + template + static SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type set1( + Result const& result, + size_type kpn, size_type kqn, size_type kn, + typename sprout::container_traits::value_type r1, + typename sprout::container_traits::value_type r2_1 + ) + { + return set1_impl(result, kpn, kqn, kn, r1, r1 + r2_1, sprout::container_indexes::make()); + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen2( + Result const& result, + size_type n, size_type s, size_type m, size_type t, size_type p, size_type q, + size_type k + ) const + { + return k < m + n ? gen2( + set2( + result, (k + p) % n, (k + q) % n, k % n, + 1566083941 * tp(result[k % n] + result[(k + p) % n] + result[(k + n - 1) % n]), + k % n + ), + n, s, m, t, p, q, + k + 1 + ) + : sprout::deep_copy(result) + ; + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen1_2( + Result const& result, + size_type n, size_type s, size_type m, size_type t, size_type p, size_type q, + size_type k + ) const + { + return k < m ? gen1_2( + set1( + result, (k + p) % n, (k + q) % n, k % n, + 1664525 * tp(result[k % n] ^ result[(k + p) % n] ^ result[(k - 1) % n]), + k % n + ), + n, s, m, t, p, q, + k + 1 + ) + : sprout::deep_copy(result) + ; + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen1_1( + Result const& result, + size_type n, size_type s, size_type m, size_type t, size_type p, size_type q, + size_type k + ) const + { + return k <= s ? gen1_1( + set1( + result, (k + p) % n, (k + q) % n, k % n, + 1664525 * tp(result[k % n] ^ result[(k + p) % n] ^ result[(k - 1) % n]), + k % n + v[k - 1] + ), + n, s, m, t, p, q, + k + 1 + ) + : sprout::deep_copy(result) + ; + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen1_0( + Result const& result, + size_type n, size_type s, size_type m, size_type t, size_type p, size_type q + ) const + { + return set1( + result, p, q, size_type(0), + 1664525 * tp(result[0] ^ result[p] ^ result[n - 1]), + s + ); + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen_impl( + Result const& result, + size_type n, size_type s, size_type m, size_type t, size_type p, size_type q + ) const + { + return gen2( + gen1_2( + gen1_1( + gen1_0( + result, + n, s, m, t, p, q + ), + n, s, m, t, p, q, + 1 + ), + n, s, m, t, p, q, + s + 1 + ), + n, s, m, t, p, q, + m + ); + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type gen( + Result const& result, TempResult const& temp_result, + size_type n, size_type s, size_type m, size_type t + ) const + { + return sprout::range::fixed::copy( + gen_impl(temp_result, n, s, m, t, (n - t) / 2, (n - t) / 2 + t), + result + ); + } + public: + SPROUT_CONSTEXPR seed_array() SPROUT_NOEXCEPT + : impl_type() + {} + seed_array(seed_array const&) = default; + template + SPROUT_INITIALIZER_LIST_CONSTEXPR seed_array(std::initializer_list il) + : impl_type(il.begin(), il.end()) + {} + template + SPROUT_CONSTEXPR seed_array(InputIterator begin, InputIterator end) + : impl_type(begin, end) + {} + template + explicit SPROUT_CONSTEXPR seed_array(InputRange const& rng) + : impl_type(sprout::begin(rng), sprout::end(rng)) + {} + template + SPROUT_CXX14_CONSTEXPR void generate(RandomAccessIterator begin, RandomAccessIterator end) const { + typedef typename std::iterator_traits::value_type value_type; + if (begin == end) { + return; + } + sprout::fill(begin, end, static_cast(0x8b8b8b8bu)); + size_type n = end - begin; + size_type s = size(); + size_type m = sprout::max(s + 1, n); + size_type t = tval(n); + size_type p = (n - t) / 2; + size_type q = p + t; + for (size_type k = 0; k < m; ++k) { + size_type kn = k % n; + size_type kpn = (k + p) % n; + size_type kqn = (k + q) % n; + size_type k1n = (k + n - 1) % n; + value_type r1 = 1664525 * tp(begin[kn] ^ begin[kpn] ^ begin[k1n]); + value_type r2 = r1 + ( + k == 0 ? s + : k <= s ? (kn + v[k - 1]) + : kn + ); + begin[kpn] += r1; + begin[kqn] += r2; + begin[kn] = r2; + } + for (size_type k = m; k < m + n; ++k) { + size_type kn = k % n; + size_type kpn = (k + p) % n; + size_type kqn = (k + q) % n; + size_type k1n = (k + n - 1) % n; + value_type r3 = 1566083941 * tp(begin[kn] + begin[kpn] + begin[k1n]); + value_type r4 = r3 - kn; + begin[kpn] ^= r3; + begin[kqn] ^= r4; + begin[kn] = r4; + } + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type generate(Result const& result) const { + typedef typename sprout::container_traits::value_type value_type; + typedef sprout::array::static_size> temp_type; + return !sprout::empty(result) ? gen( + result, sprout::pit(static_cast(0x8b8b8b8bu)), + sprout::size(result), size(), sprout::max(size() + 1, sprout::size(result)), + tval(sprout::size(result)) + ) + : sprout::detail::container_complate(result) + ; + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type generate() const { + return generate(sprout::pit()); + } + SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { + return v.size(); + } + template< + typename OutputIterator, + typename sprout::enabler_if::value>::type = sprout::enabler + > + SPROUT_CXX14_CONSTEXPR void param(OutputIterator dest) const { + sprout::copy(v.begin(), v.end(), dest); + } + SPROUT_CONSTEXPR sprout::array const& param() const { + return v; + } + template< + typename Result, + typename sprout::enabler_if::value>::type = sprout::enabler + > + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type param(Result const& result) const { + return sprout::fixed::copy(v.begin(), v.end(), result); + } + template + SPROUT_CONSTEXPR typename sprout::fixed::result_of::algorithm::type param() const { + return sprout::fixed::copy(v.begin(), v.end()); + } + }; + + // + // make_seed_array + // + template + inline SPROUT_CONSTEXPR sprout::random::seed_array + make_seed_array(Args&&... args) { + return sprout::random::seed_array( + sprout::make_common_array(sprout::forward(args)...) + ); + } + } // namespace random + + using sprout::random::seed_array; + using sprout::random::make_seed_array; +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_SEED_ARRAY_HPP