/*============================================================================= 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_DETAIL_SEED_IMPL_HPP #define SPROUT_RANDOM_DETAIL_SEED_IMPL_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace random { namespace detail { template struct seed_log : public std::conditional< m == 0, std::integral_constant::digits>, std::integral_constant::value> >::type {}; template struct seed_k : public std::integral_constant< int, (log + ((~(IntType(2) << (log - 1)) & m)? 32 : 31)) / 32 > {}; template inline SPROUT_CONSTEXPR IntType seed_one_int_impl(Array const& arr, IntType s, int j) { return j < k ? sprout::random::detail::seed_one_int_impl( arr, sprout::random::detail::const_mod::mult_add( IntType(1) << 32 * j, sprout::random::detail::const_mod::apply(IntType(arr[j + 3])), s ), j + 1 ) : s ; } template inline SPROUT_CONSTEXPR IntType seed_one_int(Sseq const& seq) { typedef typename sprout::random::detail::seed_log::type log_t; typedef typename sprout::random::detail::seed_k::type k_t; return sprout::random::detail::seed_one_int_impl( seq.generate(sprout::pit >()), 0, 0 ); } template inline SPROUT_CXX14_CONSTEXPR IntType seed_one_int(Sseq& seq) { typedef typename sprout::random::detail::seed_log::type log_t; typedef typename sprout::random::detail::seed_k::type k_t; sprout::array arr{{}}; seq.generate(arr.begin(), arr.begin() + (k_t::value + 3)); IntType s = 0; for (int j = 0; j < k_t::value; ++j) { IntType digit = sprout::random::detail::const_mod::apply(IntType(arr[j + 3])); IntType mult = IntType(1) << 32 * j; s = sprout::random::detail::const_mod::mult_add(mult, digit, s); } return s; } template inline SPROUT_CONSTEXPR IntType get_one_int_impl(InputIterator first, InputIterator last, IntType s, int j) { return j < k ? first != last ? sprout::random::detail::get_one_int_impl( sprout::next(first), last, sprout::random::detail::const_mod::mult_add( IntType(1) << 32 * j, sprout::random::detail::const_mod::apply(IntType(*first)), s ), j + 1 ) : throw std::invalid_argument("Not enough elements in call to seed.") : s ; } template inline SPROUT_CONSTEXPR IntType get_one_int(InputIterator first, InputIterator last) { typedef typename sprout::random::detail::seed_log::type log_t; typedef typename sprout::random::detail::seed_k::type k_t; return sprout::random::detail::get_one_int_impl( first, last, 0, 0 ); } } // namespace detail } // namespace random } // namespace sprout #endif // #ifndef SPROUT_RANDOM_DETAIL_SEED_IMPL_HPP