triangle_distribution.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* boost random/triangle_distribution.hpp header file
  2. *
  3. * Copyright Jens Maurer 2000-2001
  4. * Copyright Steven Watanabe 2011
  5. * Distributed under the Boost Software License, Version 1.0. (See
  6. * accompanying file LICENSE_1_0.txt or copy at
  7. * http://www.boost.org/LICENSE_1_0.txt)
  8. *
  9. * See http://www.boost.org for most recent version including documentation.
  10. *
  11. * $Id$
  12. *
  13. * Revision history
  14. * 2001-02-18 moved to individual header files
  15. */
  16. #ifndef BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP
  17. #define BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP
  18. #include <boost/config/no_tr1/cmath.hpp>
  19. #include <iosfwd>
  20. #include <ios>
  21. #include <istream>
  22. #include <boost/assert.hpp>
  23. #include <boost/random/detail/config.hpp>
  24. #include <boost/random/detail/operators.hpp>
  25. #include <boost/random/uniform_01.hpp>
  26. namespace boost {
  27. namespace random {
  28. /**
  29. * Instantiations of @c triangle_distribution model a \random_distribution.
  30. * A @c triangle_distribution has three parameters, @c a, @c b, and @c c,
  31. * which are the smallest, the most probable and the largest values of
  32. * the distribution respectively.
  33. */
  34. template<class RealType = double>
  35. class triangle_distribution
  36. {
  37. public:
  38. typedef RealType input_type;
  39. typedef RealType result_type;
  40. class param_type
  41. {
  42. public:
  43. typedef triangle_distribution distribution_type;
  44. /** Constructs the parameters of a @c triangle_distribution. */
  45. explicit param_type(RealType a_arg = RealType(0.0),
  46. RealType b_arg = RealType(0.5),
  47. RealType c_arg = RealType(1.0))
  48. : _a(a_arg), _b(b_arg), _c(c_arg)
  49. {
  50. BOOST_ASSERT(_a <= _b && _b <= _c);
  51. }
  52. /** Returns the minimum value of the distribution. */
  53. RealType a() const { return _a; }
  54. /** Returns the mode of the distribution. */
  55. RealType b() const { return _b; }
  56. /** Returns the maximum value of the distribution. */
  57. RealType c() const { return _c; }
  58. /** Writes the parameters to a @c std::ostream. */
  59. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
  60. {
  61. os << parm._a << " " << parm._b << " " << parm._c;
  62. return os;
  63. }
  64. /** Reads the parameters from a @c std::istream. */
  65. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
  66. {
  67. double a_in, b_in, c_in;
  68. if(is >> a_in >> std::ws >> b_in >> std::ws >> c_in) {
  69. if(a_in <= b_in && b_in <= c_in) {
  70. parm._a = a_in;
  71. parm._b = b_in;
  72. parm._c = c_in;
  73. } else {
  74. is.setstate(std::ios_base::failbit);
  75. }
  76. }
  77. return is;
  78. }
  79. /** Returns true if the two sets of parameters are equal. */
  80. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
  81. { return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; }
  82. /** Returns true if the two sets of parameters are different. */
  83. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
  84. private:
  85. RealType _a;
  86. RealType _b;
  87. RealType _c;
  88. };
  89. /**
  90. * Constructs a @c triangle_distribution with the parameters
  91. * @c a, @c b, and @c c.
  92. *
  93. * Preconditions: a <= b <= c.
  94. */
  95. explicit triangle_distribution(RealType a_arg = RealType(0.0),
  96. RealType b_arg = RealType(0.5),
  97. RealType c_arg = RealType(1.0))
  98. : _a(a_arg), _b(b_arg), _c(c_arg)
  99. {
  100. BOOST_ASSERT(_a <= _b && _b <= _c);
  101. init();
  102. }
  103. /** Constructs a @c triangle_distribution from its parameters. */
  104. explicit triangle_distribution(const param_type& parm)
  105. : _a(parm.a()), _b(parm.b()), _c(parm.c())
  106. {
  107. init();
  108. }
  109. // compiler-generated copy ctor and assignment operator are fine
  110. /** Returns the @c a parameter of the distribution */
  111. result_type a() const { return _a; }
  112. /** Returns the @c b parameter of the distribution */
  113. result_type b() const { return _b; }
  114. /** Returns the @c c parameter of the distribution */
  115. result_type c() const { return _c; }
  116. /** Returns the smallest value that the distribution can produce. */
  117. RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _a; }
  118. /** Returns the largest value that the distribution can produce. */
  119. RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c; }
  120. /** Returns the parameters of the distribution. */
  121. param_type param() const { return param_type(_a, _b, _c); }
  122. /** Sets the parameters of the distribution. */
  123. void param(const param_type& parm)
  124. {
  125. _a = parm.a();
  126. _b = parm.b();
  127. _c = parm.c();
  128. init();
  129. }
  130. /**
  131. * Effects: Subsequent uses of the distribution do not depend
  132. * on values produced by any engine prior to invoking reset.
  133. */
  134. void reset() { }
  135. /**
  136. * Returns a random variate distributed according to the
  137. * triangle distribution.
  138. */
  139. template<class Engine>
  140. result_type operator()(Engine& eng)
  141. {
  142. using std::sqrt;
  143. result_type u = uniform_01<result_type>()(eng);
  144. if( u <= q1 )
  145. return _a + p1*sqrt(u);
  146. else
  147. return _c - d3*sqrt(d2*u-d1);
  148. }
  149. /**
  150. * Returns a random variate distributed according to the
  151. * triangle distribution with parameters specified by param.
  152. */
  153. template<class Engine>
  154. result_type operator()(Engine& eng, const param_type& parm)
  155. { return triangle_distribution(parm)(eng); }
  156. /** Writes the distribution to a @c std::ostream. */
  157. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, triangle_distribution, td)
  158. {
  159. os << td.param();
  160. return os;
  161. }
  162. /** Reads the distribution from a @c std::istream. */
  163. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, triangle_distribution, td)
  164. {
  165. param_type parm;
  166. if(is >> parm) {
  167. td.param(parm);
  168. }
  169. return is;
  170. }
  171. /**
  172. * Returns true if the two distributions will produce identical
  173. * sequences of values given equal generators.
  174. */
  175. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(triangle_distribution, lhs, rhs)
  176. { return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; }
  177. /**
  178. * Returns true if the two distributions may produce different
  179. * sequences of values given equal generators.
  180. */
  181. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(triangle_distribution)
  182. private:
  183. /// \cond show_private
  184. void init()
  185. {
  186. using std::sqrt;
  187. d1 = _b - _a;
  188. d2 = _c - _a;
  189. d3 = sqrt(_c - _b);
  190. q1 = d1 / d2;
  191. p1 = sqrt(d1 * d2);
  192. }
  193. /// \endcond
  194. RealType _a, _b, _c;
  195. RealType d1, d2, d3, q1, p1;
  196. };
  197. } // namespace random
  198. using random::triangle_distribution;
  199. } // namespace boost
  200. #endif // BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP