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 |