summaryrefslogtreecommitdiff
path: root/boost/random/non_central_chi_squared_distribution.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/random/non_central_chi_squared_distribution.hpp')
-rw-r--r--boost/random/non_central_chi_squared_distribution.hpp221
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 0000000..28c9ff6
--- /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