1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
// (C) Copyright Gennadiy Rozental 2001.
// 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)
// See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief Random generator
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
// Boost.Test
#include <boost/test/data/config.hpp>
#if !defined(BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
#include <boost/test/data/monomorphic/generate.hpp>
#include <boost/test/data/monomorphic/generators/keywords.hpp>
// STL
#include <random>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace {
nfp::keyword<struct seed_t> seed;
nfp::keyword<struct distribution_t> distribution;
nfp::keyword<struct engine_t> engine;
} // local namespace
namespace monomorphic {
namespace ds_detail {
template<typename SampleType>
struct default_distribution {
typedef typename mpl::if_<std::is_integral<SampleType>,
std::uniform_int_distribution<SampleType>,
std::uniform_real_distribution<SampleType>>::type type;
};
} // namespace ds_detail
// ************************************************************************** //
// ************** random_t ************** //
// ************************************************************************** //
/*!@brief Generator for the random sequences
*
* This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing
* a random number generator.
*/
template<typename SampleType = double,
typename DistributionType = typename ds_detail::default_distribution<SampleType>::type,
typename EngineType = std::default_random_engine>
class random_t {
public:
typedef SampleType sample;
typedef DistributionType distr_type;
typedef EngineType engine_type;
random_t()
: m_distribution()
, m_engine( std::random_device()() )
{}
explicit random_t( distr_type&& d )
: m_distribution( std::forward<distr_type>(d) )
, m_engine( std::random_device()() ){}
random_t( engine_type&& e, distr_type&& d )
: m_distribution( std::forward<distr_type>(d) )
, m_engine( std::forward<engine_type>(e) ){}
// Generator interface
data::size_t capacity() const { return BOOST_TEST_DS_INFINITE_SIZE; }
SampleType next()
{
return m_distribution( m_engine );
}
void reset() {}
//! Sets the seed of the pseudo-random number engine.
template<typename SeedType>
void seed( SeedType&& seed ) { m_engine.seed( std::forward<SeedType>( seed ) ); }
private:
// Data members
DistributionType m_distribution;
EngineType m_engine;
};
//____________________________________________________________________________//
} // namespace monomorphic
//! @brief Returns an infinite sequence of random numbers.
//!
//! The following overloads are available:
//! @code
//! auto d = random();
//! auto d = random(begin, end);
//! auto d = random(params);
//! @endcode
//!
//!
//! - The first overload uses the default distribution, which is uniform and which elements
//! are @c double type (the values are in [0, 1) ).
//! - The second overload generates numbers in the given interval. The distribution is uniform (in [begin, end)
//! for real numbers, and in [begin, end] for integers). The type of the distribution is deduced from the type
//! of the @c begin and @c end parameters.
//! - The third overload generates numbers using the named parameter inside @c params , which are:
//! - @c distribution: the distribution used. In this overload, since the type of the samples cannot be deduced,
//! the samples are of type @c double and the distribution is uniform real in [0, 1).
//! - @c seed: the seed for generating the values
//! - @c engine: the random number generator engine
//!
//! The function returns an object that implements the dataset API.
//! @note This function is available only for C++11 capable compilers.
inline monomorphic::generated_by< monomorphic::random_t<>> random()
{
return monomorphic::generated_by<monomorphic::random_t<>>( monomorphic::random_t<>() );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::random()
template<typename SampleType>
inline monomorphic::generated_by< monomorphic::random_t<SampleType>>
random( SampleType begin, SampleType end )
{
typedef monomorphic::random_t<SampleType> Gen;
typedef typename Gen::distr_type distr_type;
return monomorphic::generated_by<Gen>( Gen( distr_type(begin,end) ) );
}
//____________________________________________________________________________//
namespace ds_detail {
template<typename Params>
struct random_gen_type {
typedef typename nfp::param_type<Params,decltype(distribution),std::uniform_real_distribution<>>::type distr_type;
typedef typename nfp::param_type<Params,decltype(engine),std::default_random_engine>::type engine_type;
typedef typename distr_type::result_type sample_type;
typedef monomorphic::random_t<sample_type,distr_type,engine_type> type;
};
}
/// @overload boost::unit_test::data::random()
template<typename Params>
inline monomorphic::generated_by<typename ds_detail::random_gen_type<Params>::type>
random( Params const& params )
{
typedef typename ds_detail::random_gen_type<Params>::type Gen;
typedef typename Gen::distr_type distr_type;
typedef typename Gen::engine_type engine_type;
std::random_device rd;
engine_type E;
// engine_type E( rd );
if( params.has(engine) )
E = params[engine];
distr_type D;
if( params.has(distribution) )
D = params[distribution];
Gen G( std::move(E), std::move(D) );
if( params.has(seed) )
G.seed( params[seed] );
return monomorphic::generated_by<Gen>( std::move(G) );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
|