• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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