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