inverse_gaussian_distribution.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* boost random/inverse_gaussian_distribution.hpp header file
  2. *
  3. * Copyright Young Geun Kim 2025
  4. * Distributed under the Boost Software License, Version 1.0. (See
  5. * accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * See http://www.boost.org for most recent version including documentation.
  9. *
  10. * $Id$
  11. */
  12. #ifndef BOOST_RANDOM_INVERSE_GAUSSIAN_DISTRIBUTION_HPP
  13. #define BOOST_RANDOM_INVERSE_GAUSSIAN_DISTRIBUTION_HPP
  14. #include <boost/config/no_tr1/cmath.hpp>
  15. #include <istream>
  16. #include <iosfwd>
  17. #include <limits>
  18. #include <boost/assert.hpp>
  19. #include <boost/limits.hpp>
  20. #include <boost/random/detail/config.hpp>
  21. #include <boost/random/detail/operators.hpp>
  22. #include <boost/random/uniform_01.hpp>
  23. #include <boost/random/chi_squared_distribution.hpp>
  24. namespace boost {
  25. namespace random {
  26. /**
  27. * The inverse gaussian distribution is a real-valued distribution with
  28. * two parameters alpha (mean) and beta (shape). It produced values > 0.
  29. *
  30. * It has
  31. * \f$\displaystyle p(x) = \sqrt{\beta / (2 \pi x^3)} \exp(-\frac{\beta (x - \alpha)^2}{2 \alpha^2 x})$.
  32. *
  33. * The algorithm used is from
  34. *
  35. * @blockquote
  36. * "Generating Random Variates Using Transformations with Multiple Roots",
  37. * Michael, J. R., Schucany, W. R. and Haas, R. W.,
  38. * The American Statistician,
  39. * Volume 30, Issue 2, 1976, Pages 88 - 90
  40. * @endblockquote
  41. */
  42. template<class RealType = double>
  43. class inverse_gaussian_distribution
  44. {
  45. public:
  46. typedef RealType result_type;
  47. typedef RealType input_type;
  48. class param_type {
  49. public:
  50. typedef inverse_gaussian_distribution distribution_type;
  51. /**
  52. * Constructs a @c param_type object from the "alpha" and "beta"
  53. * parameters.
  54. *
  55. * Requires: alpha > 0 && beta > 0
  56. */
  57. explicit param_type(RealType alpha_arg = RealType(1.0),
  58. RealType beta_arg = RealType(1.0))
  59. : _alpha(alpha_arg), _beta(beta_arg)
  60. {
  61. BOOST_ASSERT(alpha_arg > 0);
  62. BOOST_ASSERT(beta_arg > 0);
  63. }
  64. /** Returns the "alpha" parameter of the distribution. */
  65. RealType alpha() const { return _alpha; }
  66. /** Returns the "beta" parameter of the distribution. */
  67. RealType beta() const { return _beta; }
  68. /** Writes a @c param_type to a @c std::ostream. */
  69. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
  70. { os << parm._alpha << ' ' << parm._beta; return os; }
  71. /** Reads a @c param_type from a @c std::istream. */
  72. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
  73. { is >> parm._alpha >> std::ws >> parm._beta; return is; }
  74. /** Returns true if the two sets of parameters are the same. */
  75. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
  76. { return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; }
  77. /** Returns true if the two sets fo parameters are different. */
  78. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
  79. private:
  80. RealType _alpha;
  81. RealType _beta;
  82. };
  83. #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
  84. BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
  85. #endif
  86. /**
  87. * Constructs an @c inverse_gaussian_distribution from its "alpha" and "beta" parameters.
  88. *
  89. * Requires: alpha > 0, beta > 0
  90. */
  91. explicit inverse_gaussian_distribution(RealType alpha_arg = RealType(1.0),
  92. RealType beta_arg = RealType(1.0))
  93. : _alpha(alpha_arg), _beta(beta_arg)
  94. {
  95. BOOST_ASSERT(alpha_arg > 0);
  96. BOOST_ASSERT(beta_arg > 0);
  97. init();
  98. }
  99. /** Constructs an @c inverse_gaussian_distribution from its parameters. */
  100. explicit inverse_gaussian_distribution(const param_type& parm)
  101. : _alpha(parm.alpha()), _beta(parm.beta())
  102. {
  103. init();
  104. }
  105. /**
  106. * Returns a random variate distributed according to the
  107. * inverse gaussian distribution.
  108. */
  109. template<class URNG>
  110. RealType operator()(URNG& urng) const
  111. {
  112. #ifndef BOOST_NO_STDC_NAMESPACE
  113. using std::sqrt;
  114. #endif
  115. RealType w = _alpha * chi_squared_distribution<RealType>(result_type(1))(urng);
  116. RealType cand = _alpha + _c * (w - sqrt(w * (result_type(4) * _beta + w)));
  117. RealType u = uniform_01<RealType>()(urng);
  118. if (u < _alpha / (_alpha + cand)) {
  119. return cand;
  120. }
  121. return _alpha * _alpha / cand;
  122. }
  123. /**
  124. * Returns a random variate distributed accordint to the beta
  125. * distribution with parameters specified by @c param.
  126. */
  127. template<class URNG>
  128. RealType operator()(URNG& urng, const param_type& parm) const
  129. {
  130. return inverse_gaussian_distribution(parm)(urng);
  131. }
  132. /** Returns the "alpha" parameter of the distribution. */
  133. RealType alpha() const { return _alpha; }
  134. /** Returns the "beta" parameter of the distribution. */
  135. RealType beta() const { return _beta; }
  136. /** Returns the smallest value that the distribution can produce. */
  137. RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
  138. { return RealType(0.0); }
  139. /** Returns the largest value that the distribution can produce. */
  140. RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
  141. { return (std::numeric_limits<RealType>::infinity)(); }
  142. /** Returns the parameters of the distribution. */
  143. param_type param() const { return param_type(_alpha, _beta); }
  144. /** Sets the parameters of the distribution. */
  145. void param(const param_type& parm)
  146. {
  147. _alpha = parm.alpha();
  148. _beta = parm.beta();
  149. init();
  150. }
  151. /**
  152. * Effects: Subsequent uses of the distribution do not depend
  153. * on values produced by any engine prior to invoking reset.
  154. */
  155. void reset() { }
  156. /** Writes an @c inverse_gaussian_distribution to a @c std::ostream. */
  157. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, inverse_gaussian_distribution, wd)
  158. {
  159. os << wd.param();
  160. return os;
  161. }
  162. /** Reads an @c inverse_gaussian_distribution from a @c std::istream. */
  163. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, inverse_gaussian_distribution, wd)
  164. {
  165. param_type parm;
  166. if(is >> parm) {
  167. wd.param(parm);
  168. }
  169. return is;
  170. }
  171. /**
  172. * Returns true if the two instances of @c inverse_gaussian_distribution will
  173. * return identical sequences of values given equal generators.
  174. */
  175. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(inverse_gaussian_distribution, lhs, rhs)
  176. { return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; }
  177. /**
  178. * Returns true if the two instances of @c inverse_gaussian_distribution will
  179. * return different sequences of values given equal generators.
  180. */
  181. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(inverse_gaussian_distribution)
  182. private:
  183. result_type _alpha;
  184. result_type _beta;
  185. // some data precomputed from the parameters
  186. result_type _c;
  187. void init()
  188. {
  189. _c = _alpha / (result_type(2) * _beta);
  190. }
  191. };
  192. } // namespace random
  193. using random::inverse_gaussian_distribution;
  194. } // namespace boost
  195. #endif // BOOST_RANDOM_INVERSE_GAUSSIAN_DISTRIBUTION_HPP