blob: 92c44e6ef6bdec5506680c118607852afd88de6b [file] [log] [blame]
/* boost random/variate_generator.hpp header file
*
* Copyright Jens Maurer 2002
* 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 for most recent version including documentation.
*
* $Id: variate_generator.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $
*
*/
#ifndef BOOST_RANDOM_RANDOM_GENERATOR_HPP
#define BOOST_RANDOM_RANDOM_GENERATOR_HPP
#include <boost/config.hpp>
// implementation details
#include <boost/detail/workaround.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/detail/pass_through_engine.hpp>
#include <boost/random/detail/uniform_int_float.hpp>
#include <boost/random/detail/ptr_helper.hpp>
// Borland C++ 5.6.0 has problems using its numeric_limits traits as
// template parameters
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
#include <boost/type_traits/is_integral.hpp>
#endif
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
/// \cond hide_private_members
namespace random {
namespace detail {
template<bool have_int, bool want_int>
struct engine_helper;
// for consistency, always have two levels of decorations
template<>
struct engine_helper<true, true>
{
template<class Engine, class DistInputType>
struct impl
{
typedef pass_through_engine<Engine> type;
};
};
template<>
struct engine_helper<false, false>
{
template<class Engine, class DistInputType>
struct impl
{
typedef uniform_01<Engine, DistInputType> type;
};
};
template<>
struct engine_helper<true, false>
{
template<class Engine, class DistInputType>
struct impl
{
typedef uniform_01<Engine, DistInputType> type;
};
};
template<>
struct engine_helper<false, true>
{
template<class Engine, class DistInputType>
struct impl
{
typedef uniform_int_float<Engine, unsigned long> type;
};
};
} // namespace detail
} // namespace random
///\endcond
/**
* A random variate generator is used to join a random number
* generator together with a random number distribution.
* Boost.Random provides a vast choice of \generators as well
* as \distributions.
*
* Instantations of class template @c variate_generator model
* a \number_generator.
*
* The argument for the template parameter Engine shall be of
* the form U, U&, or U*, where U models a
* \uniform_random_number_generator. Then, the member
* engine_value_type names U (not the pointer or reference to U).
*
* Specializations of @c variate_generator satisfy the
* requirements of CopyConstructible. They also satisfy the
* requirements of Assignable unless the template parameter
* Engine is of the form U&.
*
* The complexity of all functions specified in this section
* is constant. No function described in this section except
* the constructor throws an exception.
*/
template<class Engine, class Distribution>
class variate_generator
{
private:
typedef random::detail::pass_through_engine<Engine> decorated_engine;
public:
typedef typename decorated_engine::base_type engine_value_type;
typedef Engine engine_type;
typedef Distribution distribution_type;
typedef typename Distribution::result_type result_type;
/**
* Constructs a @c variate_generator object with the associated
* \uniform_random_number_generator eng and the associated
* \random_distribution d.
*
* Throws: If and what the copy constructor of Engine or
* Distribution throws.
*/
variate_generator(Engine e, Distribution d)
: _eng(decorated_engine(e)), _dist(d) { }
/**
* Returns: distribution()(e)
*
* Notes: The sequence of numbers produced by the
* \uniform_random_number_generator e, s<sub>e</sub>, is
* obtained from the sequence of numbers produced by the
* associated \uniform_random_number_generator eng, s<sub>eng</sub>,
* as follows: Consider the values of @c numeric_limits<T>::is_integer
* for @c T both @c Distribution::input_type and
* @c engine_value_type::result_type. If the values for both types are
* true, then se is identical to s<sub>eng</sub>. Otherwise, if the
* values for both types are false, then the numbers in s<sub>eng</sub>
* are divided by engine().max()-engine().min() to obtain the numbers
* in s<sub>e</sub>. Otherwise, if the value for
* @c engine_value_type::result_type is true and the value for
* @c Distribution::input_type is false, then the numbers in s<sub>eng</sub>
* are divided by engine().max()-engine().min()+1 to obtain the numbers in
* s<sub>e</sub>. Otherwise, the mapping from s<sub>eng</sub> to
* s<sub>e</sub> is implementation-defined. In all cases, an
* implicit conversion from @c engine_value_type::result_type to
* @c Distribution::input_type is performed. If such a conversion does
* not exist, the program is ill-formed.
*/
result_type operator()() { return _dist(_eng); }
/**
* Returns: distribution()(e, value).
* For the semantics of e, see the description of operator()().
*/
template<class T>
result_type operator()(T value) { return _dist(_eng, value); }
/**
* Returns: A reference to the associated uniform random number generator.
*/
engine_value_type& engine() { return _eng.base().base(); }
/**
* Returns: A reference to the associated uniform random number generator.
*/
const engine_value_type& engine() const { return _eng.base().base(); }
/**
* Returns: A reference to the associated random distribution.
*/
distribution_type& distribution() { return _dist; }
/**
* Returns: A reference to the associated random distribution.
*/
const distribution_type& distribution() const { return _dist; }
/**
* Precondition: distribution().min() is well-formed
*
* Returns: distribution().min()
*/
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().min)(); }
/**
* Precondition: distribution().max() is well-formed
*
* Returns: distribution().max()
*/
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().max)(); }
private:
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
typedef typename random::detail::engine_helper<
::boost::is_integral<typename decorated_engine::result_type>::value,
::boost::is_integral<typename Distribution::input_type>::value
>::BOOST_NESTED_TEMPLATE impl<decorated_engine, typename Distribution::input_type>::type internal_engine_type;
#else
enum {
have_int = std::numeric_limits<typename decorated_engine::result_type>::is_integer,
want_int = std::numeric_limits<typename Distribution::input_type>::is_integer
};
typedef typename random::detail::engine_helper<have_int, want_int>::BOOST_NESTED_TEMPLATE impl<decorated_engine, typename Distribution::input_type>::type internal_engine_type;
#endif
internal_engine_type _eng;
distribution_type _dist;
};
} // namespace boost
#include <boost/random/detail/disable_warnings.hpp>
#endif // BOOST_RANDOM_RANDOM_GENERATOR_HPP