222 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			222 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/* boost random/non_central_chi_squared_distribution.hpp header file
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright Thijs van den Berg 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 for most recent version including documentation.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * $Id$
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_RANDOM_NON_CENTRAL_CHI_SQUARED_DISTRIBUTION_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_RANDOM_NON_CENTRAL_CHI_SQUARED_DISTRIBUTION_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/config/no_tr1/cmath.hpp>
							 | 
						||
| 
								 | 
							
								#include <iosfwd>
							 | 
						||
| 
								 | 
							
								#include <istream>
							 | 
						||
| 
								 | 
							
								#include <boost/limits.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/config.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/operators.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/uniform_real_distribution.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/normal_distribution.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/chi_squared_distribution.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/random/poisson_distribution.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								namespace random {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * The noncentral chi-squared distribution is a real valued distribution with
							 | 
						||
| 
								 | 
							
								 * two parameter, @c k and @c lambda.  The distribution produces values > 0.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This is the distribution of the sum of squares of k Normal distributed
							 | 
						||
| 
								 | 
							
								 * variates each with variance one and \f$\lambda\f$ the sum of squares of the
							 | 
						||
| 
								 | 
							
								 * normal means.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The distribution function is
							 | 
						||
| 
								 | 
							
								 * \f$\displaystyle P(x) = \frac{1}{2} e^{-(x+\lambda)/2} \left( \frac{x}{\lambda} \right)^{k/4-1/2} I_{k/2-1}( \sqrt{\lambda x} )\f$.
							 | 
						||
| 
								 | 
							
								 *  where  \f$\displaystyle I_\nu(z)\f$ is a modified Bessel function of the
							 | 
						||
| 
								 | 
							
								 * first kind.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The algorithm is taken from
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *  @blockquote
							 | 
						||
| 
								 | 
							
								 *  "Monte Carlo Methods in Financial Engineering", Paul Glasserman,
							 | 
						||
| 
								 | 
							
								 *  2003, XIII, 596 p, Stochastic Modelling and Applied Probability, Vol. 53,
							 | 
						||
| 
								 | 
							
								 *  ISBN 978-0-387-21617-1, p 124, Fig. 3.5.
							 | 
						||
| 
								 | 
							
								 *  @endblockquote
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								template <typename RealType = double>
							 | 
						||
| 
								 | 
							
								class non_central_chi_squared_distribution {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    typedef RealType result_type;
							 | 
						||
| 
								 | 
							
								    typedef RealType input_type;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    class param_type {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        typedef non_central_chi_squared_distribution distribution_type;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Constructs the parameters of a non_central_chi_squared_distribution.
							 | 
						||
| 
								 | 
							
								         * @c k and @c lambda are the parameter of the distribution.
							 | 
						||
| 
								 | 
							
								         *
							 | 
						||
| 
								 | 
							
								         * Requires: k > 0 && lambda > 0
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        explicit
							 | 
						||
| 
								 | 
							
								        param_type(RealType k_arg = RealType(1), RealType lambda_arg = RealType(1))
							 | 
						||
| 
								 | 
							
								        : _k(k_arg), _lambda(lambda_arg)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            BOOST_ASSERT(k_arg > RealType(0));
							 | 
						||
| 
								 | 
							
								            BOOST_ASSERT(lambda_arg > RealType(0));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /** Returns the @c k parameter of the distribution */
							 | 
						||
| 
								 | 
							
								        RealType k() const { return _k; }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /** Returns the @c lambda parameter of the distribution */
							 | 
						||
| 
								 | 
							
								        RealType lambda() const { return _lambda; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /** Writes the parameters of the distribution to a @c std::ostream. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            os << parm._k << ' ' << parm._lambda;
							 | 
						||
| 
								 | 
							
								            return os;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /** Reads the parameters of the distribution from a @c std::istream. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            is >> parm._k >> std::ws >> parm._lambda;
							 | 
						||
| 
								 | 
							
								            return is;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /** Returns true if the parameters have the same values. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
							 | 
						||
| 
								 | 
							
								        { return lhs._k == rhs._k && lhs._lambda == rhs._lambda; }
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        /** Returns true if the parameters have different values. */
							 | 
						||
| 
								 | 
							
								        BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								    private:
							 | 
						||
| 
								 | 
							
								        RealType _k;
							 | 
						||
| 
								 | 
							
								        RealType _lambda;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Construct a @c non_central_chi_squared_distribution object. @c k and
							 | 
						||
| 
								 | 
							
								     * @c lambda are the parameter of the distribution.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * Requires: k > 0 && lambda > 0
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    explicit
							 | 
						||
| 
								 | 
							
								    non_central_chi_squared_distribution(RealType k_arg = RealType(1), RealType lambda_arg = RealType(1))
							 | 
						||
| 
								 | 
							
								      : _param(k_arg, lambda_arg)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        BOOST_ASSERT(k_arg > RealType(0));
							 | 
						||
| 
								 | 
							
								        BOOST_ASSERT(lambda_arg > RealType(0));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Construct a @c non_central_chi_squared_distribution object from the parameter.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    explicit
							 | 
						||
| 
								 | 
							
								    non_central_chi_squared_distribution(const param_type& parm)
							 | 
						||
| 
								 | 
							
								      : _param( parm )
							 | 
						||
| 
								 | 
							
								    { }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns a random variate distributed according to the
							 | 
						||
| 
								 | 
							
								     * non central chi squared distribution specified by @c param.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<typename URNG>
							 | 
						||
| 
								 | 
							
								    RealType operator()(URNG& eng, const param_type& parm) const
							 | 
						||
| 
								 | 
							
								    { return non_central_chi_squared_distribution(parm)(eng); }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Returns a random variate distributed according to the
							 | 
						||
| 
								 | 
							
								     * non central chi squared distribution.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    template<typename URNG> 
							 | 
						||
| 
								 | 
							
								    RealType operator()(URNG& eng) 
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        using std::sqrt;
							 | 
						||
| 
								 | 
							
								        if (_param.k() > 1) {
							 | 
						||
| 
								 | 
							
								            boost::random::normal_distribution<RealType> n_dist;
							 | 
						||
| 
								 | 
							
								            boost::random::chi_squared_distribution<RealType> c_dist(_param.k() - RealType(1));
							 | 
						||
| 
								 | 
							
								            RealType _z = n_dist(eng);
							 | 
						||
| 
								 | 
							
								            RealType _x = c_dist(eng);
							 | 
						||
| 
								 | 
							
								            RealType term1 = _z + sqrt(_param.lambda());
							 | 
						||
| 
								 | 
							
								            return term1*term1 + _x;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else {
							 | 
						||
| 
								 | 
							
								            boost::random::poisson_distribution<> p_dist(_param.lambda()/RealType(2));
							 | 
						||
| 
								 | 
							
								            boost::random::poisson_distribution<>::result_type _p = p_dist(eng);
							 | 
						||
| 
								 | 
							
								            boost::random::chi_squared_distribution<RealType> c_dist(_param.k() + RealType(2)*_p);
							 | 
						||
| 
								 | 
							
								            return c_dist(eng);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Returns the @c k parameter of the distribution. */
							 | 
						||
| 
								 | 
							
								    RealType k() const { return _param.k(); }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns the @c lambda parameter of the distribution. */
							 | 
						||
| 
								 | 
							
								    RealType lambda() const { return _param.lambda(); }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns the parameters of the distribution. */
							 | 
						||
| 
								 | 
							
								    param_type param() const { return _param; }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Sets parameters of the distribution. */
							 | 
						||
| 
								 | 
							
								    void param(const param_type& parm) { _param = parm; }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Resets the distribution, so that subsequent uses does not depend on values already produced by it.*/
							 | 
						||
| 
								 | 
							
								    void reset() {}
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns the smallest value that the distribution can produce. */
							 | 
						||
| 
								 | 
							
								    RealType min BOOST_PREVENT_MACRO_SUBSTITUTION() const
							 | 
						||
| 
								 | 
							
								    { return RealType(0); }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns the largest value that the distribution can produce. */
							 | 
						||
| 
								 | 
							
								    RealType max BOOST_PREVENT_MACRO_SUBSTITUTION() const
							 | 
						||
| 
								 | 
							
								    { return (std::numeric_limits<RealType>::infinity)(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Writes the parameters of the distribution to a @c std::ostream. */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, non_central_chi_squared_distribution, dist)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        os << dist.param();
							 | 
						||
| 
								 | 
							
								        return os;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** reads the parameters of the distribution from a @c std::istream. */
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, non_central_chi_squared_distribution, dist)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        param_type parm;
							 | 
						||
| 
								 | 
							
								        if(is >> parm) {
							 | 
						||
| 
								 | 
							
								            dist.param(parm);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return is;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /** Returns true if two distributions have the same parameters and produce 
							 | 
						||
| 
								 | 
							
								        the same sequence of random numbers given equal generators.*/
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(non_central_chi_squared_distribution, lhs, rhs)
							 | 
						||
| 
								 | 
							
								    { return lhs.param() == rhs.param(); }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    /** Returns true if two distributions have different parameters and/or can produce 
							 | 
						||
| 
								 | 
							
								       different sequences of random numbers given equal generators.*/
							 | 
						||
| 
								 | 
							
								    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(non_central_chi_squared_distribution)
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// @cond show_private
							 | 
						||
| 
								 | 
							
								    param_type  _param;
							 | 
						||
| 
								 | 
							
								    /// @endcond
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace random
							 | 
						||
| 
								 | 
							
								} // namespace boost
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |