]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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. */ | |
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. */ | |
61 | RealType a() const { return _a; } | |
62 | /** Returns the mode of the distribution. */ | |
63 | RealType b() const { return _b; } | |
64 | /** Returns the maximum value of the distribution. */ | |
65 | RealType c() const { return _c; } | |
66 | ||
67 | /** Writes the parameters to a @c std::ostream. */ | |
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. */ | |
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. */ | |
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 | */ | |
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. */ | |
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 */ | |
128 | result_type a() const { return _a; } | |
129 | /** Returns the @c b parameter of the distribution */ | |
130 | result_type b() const { return _b; } | |
131 | /** Returns the @c c parameter of the distribution */ | |
132 | result_type c() const { return _c; } | |
133 | ||
134 | /** Returns the smallest value that the distribution can produce. */ | |
135 | RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _a; } | |
136 | /** Returns the largest value that the distribution can produce. */ | |
137 | RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c; } | |
138 | ||
139 | /** Returns the parameters of the distribution. */ | |
140 | param_type param() const { return param_type(_a, _b, _c); } | |
141 | /** Sets the parameters of the distribution. */ | |
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 | */ | |
154 | void reset() { } | |
155 | ||
156 | /** | |
157 | * Returns a random variate distributed according to the | |
158 | * triangle distribution. | |
159 | */ | |
160 | template<class Engine> | |
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> | |
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. */ | |
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. */ | |
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 | */ | |
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 | |
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 |