Header file range/v3/utility/random.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/algorithm/copy.hpp>

#include <range/v3/algorithm/generate.hpp>

#include <range/v3/utility/concepts.hpp>

#include <range/v3/utility/iterator_concepts.hpp>

namespace ranges
{
    inline namespace v3
    {
        namespace concepts
        {
            struct UniformRandomNumberGenerator
            {
                template <typename Gen>
                using result_t = concepts::Function::result_t<Gen>;
                
                template <typename Gen, typename Result = result_t<Gen>>
                decltype(concepts::valid_expr(concepts::model_of<UnsignedIntegral, Result>(), concepts::has_type<Result>(uncvref_t<Gen>::min()), concepts::has_type<Result>(uncvref_t<Gen>::max()), concepts::is_true(meta::bool_<(uncvref_t<Gen>::min()<uncvref_t<Gen>::max())>()))) requires_(Gen&& gen);
            };
        }
        
        template <typename Gen>
        using UniformRandomNumberGenerator = concepts::models<concepts::UniformRandomNumberGenerator, Gen>;
        
        namespace detail
        {
            namespace randutils
            {
                template <typename T, int _concept_requires_127 = 42, typename std::enable_if<(_concept_requires_127==43)||(Integral<T>()), int>::type=0>
                constexpr std::uint32_t crushto32(T value);
                
                template <typename T>
                constexpr std::uint32_t hash(T&& value);
                
                constexpr std::uint32_t fnv(std::uint32_t hash, const char* pos);
                
                constexpr std::size_t seed_count = 19;
                
                template <typename = void>
                std::array<std::uint32_t, seed_count> local_entropy(std::uint32_t s1, std::uint32_t s2);
                
                template <typename I, int _concept_requires_221 = 42, typename std::enable_if<(_concept_requires_221==43)||(UnsignedIntegral<I>()), int>::type=0>
                constexpr I fast_exp(I x, I power, I result = I{1});
                
                template <std::size_t count = 4, typename IntRep = std::uint32_t, std::size_t mix_rounds = 1+(count<=2)>
                struct seed_seq_fe
                {
                    using result_type = IntRep;
                    
                    seed_seq_fe(const seed_seq_fe&) = delete;
                    
                    void operator=(const seed_seq_fe&) = delete;
                    
                    template <typename T, int _concept_requires_354 = 42, typename std::enable_if<(_concept_requires_354==43)||(ConvertibleTo<T const&, IntRep>()), int>::type=0>
                    seed_seq_fe(std::initializer_list<T> init);
                    
                    template <typename I, typename S, int _concept_requires_361 = 42, typename std::enable_if<(_concept_requires_361==43)||(InputIterator<I>()&&Sentinel<S, I>()&&ConvertibleTo<iterator_reference_t<I>, IntRep>()), int>::type=0>
                    seed_seq_fe(I begin, S end);
                    
                    template <typename I, typename S, int _concept_requires_370 = 42, typename std::enable_if<(_concept_requires_370==43)||(RandomAccessIterator<I>()&&Sentinel<S, I>()), int>::type=0>
                    void generate(I dest_begin, S dest_end) const;
                    
                    constexpr std::size_t size() const;
                    
                    template <typename O, int _concept_requires_395 = 42, typename std::enable_if<(_concept_requires_395==43)||(WeaklyIncrementable<O>()&&IndirectlyCopyable<decltype(mixer_.begin()), O>()), int>::type=0>
                    void param(O dest) const;
                    
                    template <typename I, typename S, int _concept_requires_436 = 42, typename std::enable_if<(_concept_requires_436==43)||(InputIterator<I>()&&Sentinel<S, I>()&&ConvertibleTo<iterator_reference_t<I>, IntRep>()), int>::type=0>
                    void seed(I begin, S end);
                    
                    seed_seq_fe& stir();
                };
                
                using seed_seq_fe128 = seed_seq_fe<4, std::uint32_t>;
                
                using seed_seq_fe256 = seed_seq_fe<8, std::uint32_t>;
                
                template <typename SeedSeq>
                struct auto_seeded
                : SeedSeq
                {
                    auto_seeded();
                    
                    template <std::size_t N>
                    auto_seeded(std::array<std::uint32_t, N>const& seeds);
                    
                    using SeedSeq::SeedSeq;
                    
                    const SeedSeq& base() const;
                    
                    SeedSeq& base();
                };
                
                using auto_seed_128 = auto_seeded<seed_seq_fe128>;
                
                using auto_seed_256 = auto_seeded<seed_seq_fe256>;
            }
            
            using default_URNG = meta::if_c<(sizeof(void*)>=8), std::mt19937_64, std::mt19937>;
            
            using default_random_engine = default_URNG;
            
            template <typename T = void>
            default_random_engine& get_random_engine();
        }
    }
}