| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 | /* boost random/poisson_distribution.hpp header file * * Copyright Jens Maurer 2002 * Copyright Steven Watanabe 2010 * 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_POISSON_DISTRIBUTION_HPP#define BOOST_RANDOM_POISSON_DISTRIBUTION_HPP#include <boost/config/no_tr1/cmath.hpp>#include <cstdlib>#include <iosfwd>#include <boost/assert.hpp>#include <boost/limits.hpp>#include <boost/random/uniform_01.hpp>#include <boost/random/detail/config.hpp>#include <boost/random/detail/disable_warnings.hpp>namespace boost {namespace random {namespace detail {template<class RealType>struct poisson_table {    static RealType value[10];};template<class RealType>RealType poisson_table<RealType>::value[10] = {    0.0,    0.0,    0.69314718055994529,    1.7917594692280550,    3.1780538303479458,    4.7874917427820458,    6.5792512120101012,    8.5251613610654147,    10.604602902745251,    12.801827480081469};}/** * An instantiation of the class template @c poisson_distribution is a * model of \random_distribution.  The poisson distribution has * \f$p(i) = \frac{e^{-\lambda}\lambda^i}{i!}\f$ * * This implementation is based on the PTRD algorithm described *  *  @blockquote *  "The transformed rejection method for generating Poisson random variables", *  Wolfgang Hormann, Insurance: Mathematics and Economics *  Volume 12, Issue 1, February 1993, Pages 39-45 *  @endblockquote */template<class IntType = int, class RealType = double>class poisson_distribution {public:    typedef IntType result_type;    typedef RealType input_type;    class param_type {    public:        typedef poisson_distribution distribution_type;        /**         * Construct a param_type object with the parameter "mean"         *         * Requires: mean > 0         */        explicit param_type(RealType mean_arg = RealType(1))          : _mean(mean_arg)        {            BOOST_ASSERT(_mean > 0);        }        /* Returns the "mean" parameter of the distribution. */        RealType mean() const { return _mean; }#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS        /** Writes the parameters of the distribution to a @c std::ostream. */        template<class CharT, class Traits>        friend std::basic_ostream<CharT, Traits>&        operator<<(std::basic_ostream<CharT, Traits>& os,                   const param_type& parm)        {            os << parm._mean;            return os;        }        /** Reads the parameters of the distribution from a @c std::istream. */        template<class CharT, class Traits>        friend std::basic_istream<CharT, Traits>&        operator>>(std::basic_istream<CharT, Traits>& is, param_type& parm)        {            is >> parm._mean;            return is;        }#endif        /** Returns true if the parameters have the same values. */        friend bool operator==(const param_type& lhs, const param_type& rhs)        {            return lhs._mean == rhs._mean;        }        /** Returns true if the parameters have different values. */        friend bool operator!=(const param_type& lhs, const param_type& rhs)        {            return !(lhs == rhs);        }    private:        RealType _mean;    };        /**     * Constructs a @c poisson_distribution with the parameter @c mean.     *     * Requires: mean > 0     */    explicit poisson_distribution(RealType mean_arg = RealType(1))      : _mean(mean_arg)    {        BOOST_ASSERT(_mean > 0);        init();    }        /**     * Construct an @c poisson_distribution object from the     * parameters.     */    explicit poisson_distribution(const param_type& parm)      : _mean(parm.mean())    {        init();    }        /**     * Returns a random variate distributed according to the     * poisson distribution.     */    template<class URNG>    IntType operator()(URNG& urng) const    {        if(use_inversion()) {            return invert(urng);        } else {            return generate(urng);        }    }    /**     * Returns a random variate distributed according to the     * poisson distribution with parameters specified by param.     */    template<class URNG>    IntType operator()(URNG& urng, const param_type& parm) const    {        return poisson_distribution(parm)(urng);    }    /** Returns the "mean" parameter of the distribution. */    RealType mean() const { return _mean; }        /** Returns the smallest value that the distribution can produce. */    IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }    /** Returns the largest value that the distribution can produce. */    IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const    { return (std::numeric_limits<IntType>::max)(); }    /** Returns the parameters of the distribution. */    param_type param() const { return param_type(_mean); }    /** Sets parameters of the distribution. */    void param(const param_type& parm)    {        _mean = parm.mean();        init();    }    /**     * Effects: Subsequent uses of the distribution do not depend     * on values produced by any engine prior to invoking reset.     */    void reset() { }#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS    /** Writes the parameters of the distribution to a @c std::ostream. */    template<class CharT, class Traits>    friend std::basic_ostream<CharT,Traits>&    operator<<(std::basic_ostream<CharT,Traits>& os,               const poisson_distribution& pd)    {        os << pd.param();        return os;    }        /** Reads the parameters of the distribution from a @c std::istream. */    template<class CharT, class Traits>    friend std::basic_istream<CharT,Traits>&    operator>>(std::basic_istream<CharT,Traits>& is, poisson_distribution& pd)    {        pd.read(is);        return is;    }#endif        /** Returns true if the two distributions will produce the same        sequence of values, given equal generators. */    friend bool operator==(const poisson_distribution& lhs,                           const poisson_distribution& rhs)    {        return lhs._mean == rhs._mean;    }    /** Returns true if the two distributions could produce different        sequences of values, given equal generators. */    friend bool operator!=(const poisson_distribution& lhs,                           const poisson_distribution& rhs)    {        return !(lhs == rhs);    }private:    /// @cond show_private    template<class CharT, class Traits>    void read(std::basic_istream<CharT, Traits>& is) {        param_type parm;        if(is >> parm) {            param(parm);        }    }    bool use_inversion() const    {        return _mean < 10;    }    static RealType log_factorial(IntType k)    {        BOOST_ASSERT(k >= 0);        BOOST_ASSERT(k < 10);        return detail::poisson_table<RealType>::value[k];    }    void init()    {        using std::sqrt;        using std::exp;        if(use_inversion()) {            _u._exp_mean = exp(-_mean);        } else {            _u._ptrd.smu = sqrt(_mean);            _u._ptrd.b = 0.931 + 2.53 * _u._ptrd.smu;            _u._ptrd.a = -0.059 + 0.02483 * _u._ptrd.b;            _u._ptrd.inv_alpha = 1.1239 + 1.1328 / (_u._ptrd.b - 3.4);            _u._ptrd.v_r = 0.9277 - 3.6224 / (_u._ptrd.b - 2);        }    }        template<class URNG>    IntType generate(URNG& urng) const    {        using std::floor;        using std::abs;        using std::log;        while(true) {            RealType u;            RealType v = uniform_01<RealType>()(urng);            if(v <= 0.86 * _u._ptrd.v_r) {                u = v / _u._ptrd.v_r - 0.43;                return static_cast<IntType>(floor(                    (2*_u._ptrd.a/(0.5-abs(u)) + _u._ptrd.b)*u + _mean + 0.445));            }            if(v >= _u._ptrd.v_r) {                u = uniform_01<RealType>()(urng) - 0.5;            } else {                u = v/_u._ptrd.v_r - 0.93;                u = ((u < 0)? -0.5 : 0.5) - u;                v = uniform_01<RealType>()(urng) * _u._ptrd.v_r;            }            RealType us = 0.5 - abs(u);            if(us < 0.013 && v > us) {                continue;            }            RealType k = floor((2*_u._ptrd.a/us + _u._ptrd.b)*u+_mean+0.445);            v = v*_u._ptrd.inv_alpha/(_u._ptrd.a/(us*us) + _u._ptrd.b);            RealType log_sqrt_2pi = 0.91893853320467267;            if(k >= 10) {                if(log(v*_u._ptrd.smu) <= (k + 0.5)*log(_mean/k)                               - _mean                               - log_sqrt_2pi                               + k                               - (1/12. - (1/360. - 1/(1260.*k*k))/(k*k))/k) {                    return static_cast<IntType>(k);                }            } else if(k >= 0) {                if(log(v) <= k*log(_mean)                           - _mean                           - log_factorial(static_cast<IntType>(k))) {                    return static_cast<IntType>(k);                }            }        }    }    template<class URNG>    IntType invert(URNG& urng) const    {        RealType p = _u._exp_mean;        IntType x = 0;        RealType u = uniform_01<RealType>()(urng);        while(u > p) {            u = u - p;            ++x;            p = _mean * p / x;        }        return x;    }    RealType _mean;    union {        // for ptrd        struct {            RealType v_r;            RealType a;            RealType b;            RealType smu;            RealType inv_alpha;        } _ptrd;        // for inversion        RealType _exp_mean;    } _u;    /// @endcond};} // namespace randomusing random::poisson_distribution;} // namespace boost#include <boost/random/detail/enable_warnings.hpp>#endif // BOOST_RANDOM_POISSON_DISTRIBUTION_HPP
 |