summaryrefslogtreecommitdiff
path: root/boost/test/data/monomorphic/generators/random.hpp
blob: a82eef103deecff2d2bae78e666e6d33f1bdf1c2 (plain)
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 2011-2014.
//  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 distrbution_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          data_type;
    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