diff options
Diffstat (limited to 'boost/random/non_central_chi_squared_distribution.hpp')
-rw-r--r-- | boost/random/non_central_chi_squared_distribution.hpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/boost/random/non_central_chi_squared_distribution.hpp b/boost/random/non_central_chi_squared_distribution.hpp new file mode 100644 index 0000000000..28c9ff6d9a --- /dev/null +++ b/boost/random/non_central_chi_squared_distribution.hpp @@ -0,0 +1,221 @@ +/* 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 |