467 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			467 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/* boost random/piecewise_constant_distribution.hpp header file
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright Steven Watanabe 2011
							 | 
						||
| 
								 | 
							
								 * 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$
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_HPP_INCLUDED
							 | 
						||
| 
								 | 
							
								#define BOOST_RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_HPP_INCLUDED
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <vector>
							 | 
						||
| 
								 | 
							
								#include <numeric>
							 | 
						||
| 
								 | 
							
								#include <boost/assert.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/uniform_real.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/discrete_distribution.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/config.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/operators.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/vector_io.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
							 | 
						||
| 
								 | 
							
								#include <initializer_list>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/range/begin.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/range/end.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								namespace random {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * The class @c piecewise_constant_distribution models a \random_distribution.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								template<class RealType = double, class WeightType = double>
							 | 
						||
| 
								 | 
							
								class piecewise_constant_distribution {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    typedef std::size_t input_type;
							 | 
						||
| 
								 | 
							
								    typedef RealType result_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    class param_type {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        typedef piecewise_constant_distribution distribution_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs a @c param_type object, representing a distribution
							 | 
						||
| 
								 | 
							
								         * that produces values uniformly distributed in the range [0, 1).
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        param_type()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            _weights.push_back(WeightType(1));
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs a @c param_type object from two iterator ranges
							 | 
						||
| 
								 | 
							
								         * containing the interval boundaries and the interval weights.
							 | 
						||
| 
								 | 
							
								         * If there are less than two boundaries, then this is equivalent to
							 | 
						||
| 
								 | 
							
								         * the default constructor and creates a single interval, [0, 1).
							 | 
						||
| 
								 | 
							
								         *
							 | 
						||
| 
								 | 
							
								         * The values of the interval boundaries must be strictly
							 | 
						||
| 
								 | 
							
								         * increasing, and the number of weights must be one less than
							 | 
						||
| 
								 | 
							
								         * the number of interval boundaries.  If there are extra
							 | 
						||
| 
								 | 
							
								         * weights, they are ignored.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        template<class IntervalIter, class WeightIter>
							 | 
						||
| 
								 | 
							
								        param_type(IntervalIter intervals_first, IntervalIter intervals_last,
							 | 
						||
| 
								 | 
							
								                   WeightIter weight_first)
							 | 
						||
| 
								 | 
							
								          : _intervals(intervals_first, intervals_last)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								                _intervals.clear();
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								                _weights.push_back(WeightType(1));
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                _weights.reserve(_intervals.size() - 1);
							 | 
						||
| 
								 | 
							
								                for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
							 | 
						||
| 
								 | 
							
								                    _weights.push_back(*weight_first++);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs a @c param_type object from an
							 | 
						||
| 
								 | 
							
								         * initializer_list containing the interval boundaries
							 | 
						||
| 
								 | 
							
								         * and a unary function specifying the weights.  Each
							 | 
						||
| 
								 | 
							
								         * weight is determined by calling the function at the
							 | 
						||
| 
								 | 
							
								         * midpoint of the corresponding interval.
							 | 
						||
| 
								 | 
							
								         *
							 | 
						||
| 
								 | 
							
								         * If the initializer_list contains less than two elements,
							 | 
						||
| 
								 | 
							
								         * this is equivalent to the default constructor and the
							 | 
						||
| 
								 | 
							
								         * distribution will produce values uniformly distributed
							 | 
						||
| 
								 | 
							
								         * in the range [0, 1).
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        template<class T, class F>
							 | 
						||
| 
								 | 
							
								        param_type(const std::initializer_list<T>& il, F f)
							 | 
						||
| 
								 | 
							
								          : _intervals(il.begin(), il.end())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								                _intervals.clear();
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								                _weights.push_back(WeightType(1));
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                _weights.reserve(_intervals.size() - 1);
							 | 
						||
| 
								 | 
							
								                for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
							 | 
						||
| 
								 | 
							
								                    RealType midpoint = (_intervals[i] + _intervals[i + 1]) / 2;
							 | 
						||
| 
								 | 
							
								                    _weights.push_back(f(midpoint));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs a @c param_type object from Boost.Range
							 | 
						||
| 
								 | 
							
								         * ranges holding the interval boundaries and the weights.  If
							 | 
						||
| 
								 | 
							
								         * there are less than two interval boundaries, this is equivalent
							 | 
						||
| 
								 | 
							
								         * to the default constructor and the distribution will produce
							 | 
						||
| 
								 | 
							
								         * values uniformly distributed in the range [0, 1).  The
							 | 
						||
| 
								 | 
							
								         * number of weights must be one less than the number of
							 | 
						||
| 
								 | 
							
								         * interval boundaries.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        template<class IntervalRange, class WeightRange>
							 | 
						||
| 
								 | 
							
								        param_type(const IntervalRange& intervals_arg,
							 | 
						||
| 
								 | 
							
								                   const WeightRange& weights_arg)
							 | 
						||
| 
								 | 
							
								          : _intervals(boost::begin(intervals_arg), boost::end(intervals_arg)),
							 | 
						||
| 
								 | 
							
								            _weights(boost::begin(weights_arg), boost::end(weights_arg))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								                _intervals.clear();
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								                _weights.push_back(WeightType(1));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs the parameters for a distribution that approximates a
							 | 
						||
| 
								 | 
							
								         * function.  The range of the distribution is [xmin, xmax).  This
							 | 
						||
| 
								 | 
							
								         * range is divided into nw equally sized intervals and the weights
							 | 
						||
| 
								 | 
							
								         * are found by calling the unary function f on the midpoints of the
							 | 
						||
| 
								 | 
							
								         * intervals.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        template<class F>
							 | 
						||
| 
								 | 
							
								        param_type(std::size_t nw, RealType xmin, RealType xmax, F f)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            std::size_t n = (nw == 0) ? 1 : nw;
							 | 
						||
| 
								 | 
							
								            double delta = (xmax - xmin) / n;
							 | 
						||
| 
								 | 
							
								            BOOST_ASSERT(delta > 0);
							 | 
						||
| 
								 | 
							
								            for(std::size_t k = 0; k < n; ++k) {
							 | 
						||
| 
								 | 
							
								                _weights.push_back(f(xmin + k*delta + delta/2));
							 | 
						||
| 
								 | 
							
								                _intervals.push_back(xmin + k*delta);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(xmax);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**  Returns a vector containing the interval boundaries. */
							 | 
						||
| 
								 | 
							
								        std::vector<RealType> intervals() const { return _intervals; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Returns a vector containing the probability densities
							 | 
						||
| 
								 | 
							
								         * over all the intervals of the distribution.
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        std::vector<RealType> densities() const
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            RealType sum = std::accumulate(_weights.begin(), _weights.end(),
							 | 
						||
| 
								 | 
							
								                                             static_cast<RealType>(0));
							 | 
						||
| 
								 | 
							
								            std::vector<RealType> result;
							 | 
						||
| 
								 | 
							
								            result.reserve(_weights.size());
							 | 
						||
| 
								 | 
							
								            for(std::size_t i = 0; i < _weights.size(); ++i) {
							 | 
						||
| 
								 | 
							
								                RealType width = _intervals[i + 1] - _intervals[i];
							 | 
						||
| 
								 | 
							
								                result.push_back(_weights[i] / (sum * width));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /** Writes the parameters to a @c std::ostream. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            detail::print_vector(os, parm._intervals);
							 | 
						||
| 
								 | 
							
								            detail::print_vector(os, parm._weights);
							 | 
						||
| 
								 | 
							
								            return os;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /** Reads the parameters from a @c std::istream. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            std::vector<RealType> new_intervals;
							 | 
						||
| 
								 | 
							
								            std::vector<WeightType> new_weights;
							 | 
						||
| 
								 | 
							
								            detail::read_vector(is, new_intervals);
							 | 
						||
| 
								 | 
							
								            detail::read_vector(is, new_weights);
							 | 
						||
| 
								 | 
							
								            if(is) {
							 | 
						||
| 
								 | 
							
								                parm._intervals.swap(new_intervals);
							 | 
						||
| 
								 | 
							
								                parm._weights.swap(new_weights);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return is;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /** Returns true if the two sets of parameters are the same. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            return lhs._intervals == rhs._intervals
							 | 
						||
| 
								 | 
							
								                && lhs._weights == rhs._weights;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        /** Returns true if the two sets of parameters are different. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        friend class piecewise_constant_distribution;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        std::vector<RealType> _intervals;
							 | 
						||
| 
								 | 
							
								        std::vector<WeightType> _weights;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Creates a new @c piecewise_constant_distribution with
							 | 
						||
| 
								 | 
							
								     * a single interval, [0, 1).
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    piecewise_constant_distribution()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								        _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructs a piecewise_constant_distribution from two iterator ranges
							 | 
						||
| 
								 | 
							
								     * containing the interval boundaries and the interval weights.
							 | 
						||
| 
								 | 
							
								     * If there are less than two boundaries, then this is equivalent to
							 | 
						||
| 
								 | 
							
								     * the default constructor and creates a single interval, [0, 1).
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * The values of the interval boundaries must be strictly
							 | 
						||
| 
								 | 
							
								     * increasing, and the number of weights must be one less than
							 | 
						||
| 
								 | 
							
								     * the number of interval boundaries.  If there are extra
							 | 
						||
| 
								 | 
							
								     * weights, they are ignored.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * For example,
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @code
							 | 
						||
| 
								 | 
							
								     * double intervals[] = { 0.0, 1.0, 4.0 };
							 | 
						||
| 
								 | 
							
								     * double weights[] = { 1.0, 1.0 };
							 | 
						||
| 
								 | 
							
								     * piecewise_constant_distribution<> dist(
							 | 
						||
| 
								 | 
							
								     *     &intervals[0], &intervals[0] + 3, &weights[0]);
							 | 
						||
| 
								 | 
							
								     * @endcode
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * The distribution has a 50% chance of producing a
							 | 
						||
| 
								 | 
							
								     * value between 0 and 1 and a 50% chance of producing
							 | 
						||
| 
								 | 
							
								     * a value between 1 and 4.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class IntervalIter, class WeightIter>
							 | 
						||
| 
								 | 
							
								    piecewise_constant_distribution(IntervalIter first_interval,
							 | 
						||
| 
								 | 
							
								                                    IntervalIter last_interval,
							 | 
						||
| 
								 | 
							
								                                    WeightIter first_weight)
							 | 
						||
| 
								 | 
							
								      : _intervals(first_interval, last_interval)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								            _intervals.clear();
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            std::vector<WeightType> actual_weights;
							 | 
						||
| 
								 | 
							
								            actual_weights.reserve(_intervals.size() - 1);
							 | 
						||
| 
								 | 
							
								            for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
							 | 
						||
| 
								 | 
							
								                actual_weights.push_back(*first_weight++);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            typedef discrete_distribution<std::size_t, WeightType> bins_type;
							 | 
						||
| 
								 | 
							
								            typename bins_type::param_type bins_param(actual_weights);
							 | 
						||
| 
								 | 
							
								            _bins.param(bins_param);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructs a piecewise_constant_distribution from an
							 | 
						||
| 
								 | 
							
								     * initializer_list containing the interval boundaries
							 | 
						||
| 
								 | 
							
								     * and a unary function specifying the weights.  Each
							 | 
						||
| 
								 | 
							
								     * weight is determined by calling the function at the
							 | 
						||
| 
								 | 
							
								     * midpoint of the corresponding interval.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * If the initializer_list contains less than two elements,
							 | 
						||
| 
								 | 
							
								     * this is equivalent to the default constructor and the
							 | 
						||
| 
								 | 
							
								     * distribution will produce values uniformly distributed
							 | 
						||
| 
								 | 
							
								     * in the range [0, 1).
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class T, class F>
							 | 
						||
| 
								 | 
							
								    piecewise_constant_distribution(std::initializer_list<T> il, F f)
							 | 
						||
| 
								 | 
							
								      : _intervals(il.begin(), il.end())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								            _intervals.clear();
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            std::vector<WeightType> actual_weights;
							 | 
						||
| 
								 | 
							
								            actual_weights.reserve(_intervals.size() - 1);
							 | 
						||
| 
								 | 
							
								            for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
							 | 
						||
| 
								 | 
							
								                RealType midpoint = (_intervals[i] + _intervals[i + 1]) / 2;
							 | 
						||
| 
								 | 
							
								                actual_weights.push_back(f(midpoint));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            typedef discrete_distribution<std::size_t, WeightType> bins_type;
							 | 
						||
| 
								 | 
							
								            typename bins_type::param_type bins_param(actual_weights);
							 | 
						||
| 
								 | 
							
								            _bins.param(bins_param);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructs a piecewise_constant_distribution from Boost.Range
							 | 
						||
| 
								 | 
							
								     * ranges holding the interval boundaries and the weights.  If
							 | 
						||
| 
								 | 
							
								     * there are less than two interval boundaries, this is equivalent
							 | 
						||
| 
								 | 
							
								     * to the default constructor and the distribution will produce
							 | 
						||
| 
								 | 
							
								     * values uniformly distributed in the range [0, 1).  The
							 | 
						||
| 
								 | 
							
								     * number of weights must be one less than the number of
							 | 
						||
| 
								 | 
							
								     * interval boundaries.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class IntervalsRange, class WeightsRange>
							 | 
						||
| 
								 | 
							
								    piecewise_constant_distribution(const IntervalsRange& intervals_arg,
							 | 
						||
| 
								 | 
							
								                                    const WeightsRange& weights_arg)
							 | 
						||
| 
								 | 
							
								      : _bins(weights_arg),
							 | 
						||
| 
								 | 
							
								        _intervals(boost::begin(intervals_arg), boost::end(intervals_arg))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(_intervals.size() < 2) {
							 | 
						||
| 
								 | 
							
								            _intervals.clear();
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(0));
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(RealType(1));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructs a piecewise_constant_distribution that approximates a
							 | 
						||
| 
								 | 
							
								     * function.  The range of the distribution is [xmin, xmax).  This
							 | 
						||
| 
								 | 
							
								     * range is divided into nw equally sized intervals and the weights
							 | 
						||
| 
								 | 
							
								     * are found by calling the unary function f on the midpoints of the
							 | 
						||
| 
								 | 
							
								     * intervals.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class F>
							 | 
						||
| 
								 | 
							
								    piecewise_constant_distribution(std::size_t nw,
							 | 
						||
| 
								 | 
							
								                                    RealType xmin,
							 | 
						||
| 
								 | 
							
								                                    RealType xmax,
							 | 
						||
| 
								 | 
							
								                                    F f)
							 | 
						||
| 
								 | 
							
								      : _bins(nw, xmin, xmax, f)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if(nw == 0) { nw = 1; }
							 | 
						||
| 
								 | 
							
								        RealType delta = (xmax - xmin) / nw;
							 | 
						||
| 
								 | 
							
								        _intervals.reserve(nw + 1);
							 | 
						||
| 
								 | 
							
								        for(std::size_t i = 0; i < nw; ++i) {
							 | 
						||
| 
								 | 
							
								            _intervals.push_back(xmin + i * delta);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        _intervals.push_back(xmax);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Constructs a piecewise_constant_distribution from its parameters.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    explicit piecewise_constant_distribution(const param_type& parm)
							 | 
						||
| 
								 | 
							
								      : _bins(parm._weights),
							 | 
						||
| 
								 | 
							
								        _intervals(parm._intervals)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns a value distributed according to the parameters of the
							 | 
						||
| 
								 | 
							
								     * piecewist_constant_distribution.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class URNG>
							 | 
						||
| 
								 | 
							
								    RealType operator()(URNG& urng) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::size_t i = _bins(urng);
							 | 
						||
| 
								 | 
							
								        return uniform_real<RealType>(_intervals[i], _intervals[i+1])(urng);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns a value distributed according to the parameters
							 | 
						||
| 
								 | 
							
								     * specified by param.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<class URNG>
							 | 
						||
| 
								 | 
							
								    RealType operator()(URNG& urng, const param_type& parm) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return piecewise_constant_distribution(parm)(urng);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns the smallest value that the distribution can produce. */
							 | 
						||
| 
								 | 
							
								    result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
							 | 
						||
| 
								 | 
							
								    { return _intervals.front(); }
							 | 
						||
| 
								 | 
							
								    /** Returns the largest value that the distribution can produce. */
							 | 
						||
| 
								 | 
							
								    result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
							 | 
						||
| 
								 | 
							
								    { return _intervals.back(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns a vector containing the probability density
							 | 
						||
| 
								 | 
							
								     * over each interval.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    std::vector<RealType> densities() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::vector<RealType> result(_bins.probabilities());
							 | 
						||
| 
								 | 
							
								        for(std::size_t i = 0; i < result.size(); ++i) {
							 | 
						||
| 
								 | 
							
								            result[i] /= (_intervals[i+1] - _intervals[i]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return(result);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**  Returns a vector containing the interval boundaries. */
							 | 
						||
| 
								 | 
							
								    std::vector<RealType> intervals() const { return _intervals; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Returns the parameters of the distribution. */
							 | 
						||
| 
								 | 
							
								    param_type param() const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return param_type(_intervals, _bins.probabilities());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /** Sets the parameters of the distribution. */
							 | 
						||
| 
								 | 
							
								    void param(const param_type& parm)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        std::vector<RealType> new_intervals(parm._intervals);
							 | 
						||
| 
								 | 
							
								        typedef discrete_distribution<std::size_t, WeightType> bins_type;
							 | 
						||
| 
								 | 
							
								        typename bins_type::param_type bins_param(parm._weights);
							 | 
						||
| 
								 | 
							
								        _bins.param(bins_param);
							 | 
						||
| 
								 | 
							
								        _intervals.swap(new_intervals);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Effects: Subsequent uses of the distribution do not depend
							 | 
						||
| 
								 | 
							
								     * on values produced by any engine prior to invoking reset.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    void reset() { _bins.reset(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Writes a distribution to a @c std::ostream. */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(
							 | 
						||
| 
								 | 
							
								        os, piecewise_constant_distribution, pcd)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        os << pcd.param();
							 | 
						||
| 
								 | 
							
								        return os;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Reads a distribution from a @c std::istream */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(
							 | 
						||
| 
								 | 
							
								        is, piecewise_constant_distribution, pcd)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        param_type parm;
							 | 
						||
| 
								 | 
							
								        if(is >> parm) {
							 | 
						||
| 
								 | 
							
								            pcd.param(parm);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return is;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns true if the two distributions will return the
							 | 
						||
| 
								 | 
							
								     * same sequence of values, when passed equal generators.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(
							 | 
						||
| 
								 | 
							
								        piecewise_constant_distribution, lhs,  rhs)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return lhs._bins == rhs._bins && lhs._intervals == rhs._intervals;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns true if the two distributions may return different
							 | 
						||
| 
								 | 
							
								     * sequences of values, when passed equal generators.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(piecewise_constant_distribution)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    discrete_distribution<std::size_t, WeightType> _bins;
							 | 
						||
| 
								 | 
							
								    std::vector<RealType> _intervals;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |