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 17 #ifndef BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP 18 #define BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP 19 20 #include <boost/config/no_tr1/cmath.hpp> 21 #include <iosfwd> 22 #include <ios> 23 #include <istream> 24 #include <boost/assert.hpp> 25 #include <boost/random/detail/config.hpp> 26 #include <boost/random/detail/operators.hpp> 27 #include <boost/random/uniform_01.hpp> 28 29 namespace boost { 30 namespace random { 31 32 /** 33 * Instantiations of @c triangle_distribution model a \random_distribution. 34 * A @c triangle_distribution has three parameters, @c a, @c b, and @c c, 35 * which are the smallest, the most probable and the largest values of 36 * the distribution respectively. 37 */ 38 template<class RealType = double> 39 class triangle_distribution 40 { 41 public: 42 typedef RealType input_type; 43 typedef RealType result_type; 44 45 class param_type 46 { 47 public: 48 49 typedef triangle_distribution distribution_type; 50 51 /** Constructs the parameters of a @c triangle_distribution. */ param_type(RealType a_arg=RealType (0.0),RealType b_arg=RealType (0.5),RealType c_arg=RealType (1.0))52 explicit param_type(RealType a_arg = RealType(0.0), 53 RealType b_arg = RealType(0.5), 54 RealType c_arg = RealType(1.0)) 55 : _a(a_arg), _b(b_arg), _c(c_arg) 56 { 57 BOOST_ASSERT(_a <= _b && _b <= _c); 58 } 59 60 /** Returns the minimum value of the distribution. */ a() const61 RealType a() const { return _a; } 62 /** Returns the mode of the distribution. */ b() const63 RealType b() const { return _b; } 64 /** Returns the maximum value of the distribution. */ c() const65 RealType c() const { return _c; } 66 67 /** Writes the parameters to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,param_type,parm)68 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) 69 { 70 os << parm._a << " " << parm._b << " " << parm._c; 71 return os; 72 } 73 74 /** Reads the parameters from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,param_type,parm)75 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) 76 { 77 double a_in, b_in, c_in; 78 if(is >> a_in >> std::ws >> b_in >> std::ws >> c_in) { 79 if(a_in <= b_in && b_in <= c_in) { 80 parm._a = a_in; 81 parm._b = b_in; 82 parm._c = c_in; 83 } else { 84 is.setstate(std::ios_base::failbit); 85 } 86 } 87 return is; 88 } 89 90 /** Returns true if the two sets of parameters are equal. */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type,lhs,rhs)91 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) 92 { return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; } 93 94 /** Returns true if the two sets of parameters are different. */ 95 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) 96 97 private: 98 RealType _a; 99 RealType _b; 100 RealType _c; 101 }; 102 103 /** 104 * Constructs a @c triangle_distribution with the parameters 105 * @c a, @c b, and @c c. 106 * 107 * Preconditions: a <= b <= c. 108 */ triangle_distribution(RealType a_arg=RealType (0.0),RealType b_arg=RealType (0.5),RealType c_arg=RealType (1.0))109 explicit triangle_distribution(RealType a_arg = RealType(0.0), 110 RealType b_arg = RealType(0.5), 111 RealType c_arg = RealType(1.0)) 112 : _a(a_arg), _b(b_arg), _c(c_arg) 113 { 114 BOOST_ASSERT(_a <= _b && _b <= _c); 115 init(); 116 } 117 118 /** Constructs a @c triangle_distribution from its parameters. */ triangle_distribution(const param_type & parm)119 explicit triangle_distribution(const param_type& parm) 120 : _a(parm.a()), _b(parm.b()), _c(parm.c()) 121 { 122 init(); 123 } 124 125 // compiler-generated copy ctor and assignment operator are fine 126 127 /** Returns the @c a parameter of the distribution */ a() const128 result_type a() const { return _a; } 129 /** Returns the @c b parameter of the distribution */ b() const130 result_type b() const { return _b; } 131 /** Returns the @c c parameter of the distribution */ c() const132 result_type c() const { return _c; } 133 134 /** Returns the smallest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const135 RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _a; } 136 /** Returns the largest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const137 RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c; } 138 139 /** Returns the parameters of the distribution. */ param() const140 param_type param() const { return param_type(_a, _b, _c); } 141 /** Sets the parameters of the distribution. */ param(const param_type & parm)142 void param(const param_type& parm) 143 { 144 _a = parm.a(); 145 _b = parm.b(); 146 _c = parm.c(); 147 init(); 148 } 149 150 /** 151 * Effects: Subsequent uses of the distribution do not depend 152 * on values produced by any engine prior to invoking reset. 153 */ reset()154 void reset() { } 155 156 /** 157 * Returns a random variate distributed according to the 158 * triangle distribution. 159 */ 160 template<class Engine> operator ()(Engine & eng)161 result_type operator()(Engine& eng) 162 { 163 using std::sqrt; 164 result_type u = uniform_01<result_type>()(eng); 165 if( u <= q1 ) 166 return _a + p1*sqrt(u); 167 else 168 return _c - d3*sqrt(d2*u-d1); 169 } 170 171 /** 172 * Returns a random variate distributed according to the 173 * triangle distribution with parameters specified by param. 174 */ 175 template<class Engine> operator ()(Engine & eng,const param_type & parm)176 result_type operator()(Engine& eng, const param_type& parm) 177 { return triangle_distribution(parm)(eng); } 178 179 /** Writes the distribution to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,triangle_distribution,td)180 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, triangle_distribution, td) 181 { 182 os << td.param(); 183 return os; 184 } 185 186 /** Reads the distribution from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,triangle_distribution,td)187 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, triangle_distribution, td) 188 { 189 param_type parm; 190 if(is >> parm) { 191 td.param(parm); 192 } 193 return is; 194 } 195 196 /** 197 * Returns true if the two distributions will produce identical 198 * sequences of values given equal generators. 199 */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(triangle_distribution,lhs,rhs)200 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(triangle_distribution, lhs, rhs) 201 { return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; } 202 203 /** 204 * Returns true if the two distributions may produce different 205 * sequences of values given equal generators. 206 */ 207 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(triangle_distribution) 208 209 private: 210 /// \cond show_private init()211 void init() 212 { 213 using std::sqrt; 214 d1 = _b - _a; 215 d2 = _c - _a; 216 d3 = sqrt(_c - _b); 217 q1 = d1 / d2; 218 p1 = sqrt(d1 * d2); 219 } 220 /// \endcond 221 222 RealType _a, _b, _c; 223 RealType d1, d2, d3, q1, p1; 224 }; 225 226 } // namespace random 227 228 using random::triangle_distribution; 229 230 } // namespace boost 231 232 #endif // BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP 233