Chris@16
|
1 // Copyright John Maddock 2006, 2007.
|
Chris@16
|
2 // Copyright Paul A. Bristow 2006, 2007.
|
Chris@16
|
3 // Use, modification and distribution are subject to the
|
Chris@16
|
4 // Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 #ifndef BOOST_STATS_TRIANGULAR_HPP
|
Chris@16
|
8 #define BOOST_STATS_TRIANGULAR_HPP
|
Chris@16
|
9
|
Chris@16
|
10 // http://mathworld.wolfram.com/TriangularDistribution.html
|
Chris@16
|
11 // http://en.wikipedia.org/wiki/Triangular_distribution
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/math/distributions/fwd.hpp>
|
Chris@16
|
14 #include <boost/math/special_functions/expm1.hpp>
|
Chris@16
|
15 #include <boost/math/distributions/detail/common_error_handling.hpp>
|
Chris@16
|
16 #include <boost/math/distributions/complement.hpp>
|
Chris@16
|
17 #include <boost/math/constants/constants.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 #include <utility>
|
Chris@16
|
20
|
Chris@16
|
21 namespace boost{ namespace math
|
Chris@16
|
22 {
|
Chris@16
|
23 namespace detail
|
Chris@16
|
24 {
|
Chris@16
|
25 template <class RealType, class Policy>
|
Chris@16
|
26 inline bool check_triangular_lower(
|
Chris@16
|
27 const char* function,
|
Chris@16
|
28 RealType lower,
|
Chris@16
|
29 RealType* result, const Policy& pol)
|
Chris@16
|
30 {
|
Chris@16
|
31 if((boost::math::isfinite)(lower))
|
Chris@16
|
32 { // Any finite value is OK.
|
Chris@16
|
33 return true;
|
Chris@16
|
34 }
|
Chris@16
|
35 else
|
Chris@16
|
36 { // Not finite: infinity or NaN.
|
Chris@16
|
37 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
38 function,
|
Chris@16
|
39 "Lower parameter is %1%, but must be finite!", lower, pol);
|
Chris@16
|
40 return false;
|
Chris@16
|
41 }
|
Chris@16
|
42 } // bool check_triangular_lower(
|
Chris@16
|
43
|
Chris@16
|
44 template <class RealType, class Policy>
|
Chris@16
|
45 inline bool check_triangular_mode(
|
Chris@16
|
46 const char* function,
|
Chris@16
|
47 RealType mode,
|
Chris@16
|
48 RealType* result, const Policy& pol)
|
Chris@16
|
49 {
|
Chris@16
|
50 if((boost::math::isfinite)(mode))
|
Chris@16
|
51 { // any finite value is OK.
|
Chris@16
|
52 return true;
|
Chris@16
|
53 }
|
Chris@16
|
54 else
|
Chris@16
|
55 { // Not finite: infinity or NaN.
|
Chris@16
|
56 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
57 function,
|
Chris@16
|
58 "Mode parameter is %1%, but must be finite!", mode, pol);
|
Chris@16
|
59 return false;
|
Chris@16
|
60 }
|
Chris@16
|
61 } // bool check_triangular_mode(
|
Chris@16
|
62
|
Chris@16
|
63 template <class RealType, class Policy>
|
Chris@16
|
64 inline bool check_triangular_upper(
|
Chris@16
|
65 const char* function,
|
Chris@16
|
66 RealType upper,
|
Chris@16
|
67 RealType* result, const Policy& pol)
|
Chris@16
|
68 {
|
Chris@16
|
69 if((boost::math::isfinite)(upper))
|
Chris@16
|
70 { // any finite value is OK.
|
Chris@16
|
71 return true;
|
Chris@16
|
72 }
|
Chris@16
|
73 else
|
Chris@16
|
74 { // Not finite: infinity or NaN.
|
Chris@16
|
75 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
76 function,
|
Chris@16
|
77 "Upper parameter is %1%, but must be finite!", upper, pol);
|
Chris@16
|
78 return false;
|
Chris@16
|
79 }
|
Chris@16
|
80 } // bool check_triangular_upper(
|
Chris@16
|
81
|
Chris@16
|
82 template <class RealType, class Policy>
|
Chris@16
|
83 inline bool check_triangular_x(
|
Chris@16
|
84 const char* function,
|
Chris@16
|
85 RealType const& x,
|
Chris@16
|
86 RealType* result, const Policy& pol)
|
Chris@16
|
87 {
|
Chris@16
|
88 if((boost::math::isfinite)(x))
|
Chris@16
|
89 { // Any finite value is OK
|
Chris@16
|
90 return true;
|
Chris@16
|
91 }
|
Chris@16
|
92 else
|
Chris@16
|
93 { // Not finite: infinity or NaN.
|
Chris@16
|
94 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
95 function,
|
Chris@16
|
96 "x parameter is %1%, but must be finite!", x, pol);
|
Chris@16
|
97 return false;
|
Chris@16
|
98 }
|
Chris@16
|
99 } // bool check_triangular_x
|
Chris@16
|
100
|
Chris@16
|
101 template <class RealType, class Policy>
|
Chris@16
|
102 inline bool check_triangular(
|
Chris@16
|
103 const char* function,
|
Chris@16
|
104 RealType lower,
|
Chris@16
|
105 RealType mode,
|
Chris@16
|
106 RealType upper,
|
Chris@16
|
107 RealType* result, const Policy& pol)
|
Chris@16
|
108 {
|
Chris@16
|
109 if ((check_triangular_lower(function, lower, result, pol) == false)
|
Chris@16
|
110 || (check_triangular_mode(function, mode, result, pol) == false)
|
Chris@16
|
111 || (check_triangular_upper(function, upper, result, pol) == false))
|
Chris@16
|
112 { // Some parameter not finite.
|
Chris@16
|
113 return false;
|
Chris@16
|
114 }
|
Chris@16
|
115 else if (lower >= upper) // lower == upper NOT useful.
|
Chris@16
|
116 { // lower >= upper.
|
Chris@16
|
117 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
118 function,
|
Chris@16
|
119 "lower parameter is %1%, but must be less than upper!", lower, pol);
|
Chris@16
|
120 return false;
|
Chris@16
|
121 }
|
Chris@16
|
122 else
|
Chris@16
|
123 { // Check lower <= mode <= upper.
|
Chris@16
|
124 if (mode < lower)
|
Chris@16
|
125 {
|
Chris@16
|
126 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
127 function,
|
Chris@16
|
128 "mode parameter is %1%, but must be >= than lower!", lower, pol);
|
Chris@16
|
129 return false;
|
Chris@16
|
130 }
|
Chris@16
|
131 if (mode > upper)
|
Chris@16
|
132 {
|
Chris@16
|
133 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
134 function,
|
Chris@16
|
135 "mode parameter is %1%, but must be <= than upper!", upper, pol);
|
Chris@16
|
136 return false;
|
Chris@16
|
137 }
|
Chris@16
|
138 return true; // All OK.
|
Chris@16
|
139 }
|
Chris@16
|
140 } // bool check_triangular
|
Chris@16
|
141 } // namespace detail
|
Chris@16
|
142
|
Chris@16
|
143 template <class RealType = double, class Policy = policies::policy<> >
|
Chris@16
|
144 class triangular_distribution
|
Chris@16
|
145 {
|
Chris@16
|
146 public:
|
Chris@16
|
147 typedef RealType value_type;
|
Chris@16
|
148 typedef Policy policy_type;
|
Chris@16
|
149
|
Chris@16
|
150 triangular_distribution(RealType l_lower = -1, RealType l_mode = 0, RealType l_upper = 1)
|
Chris@16
|
151 : m_lower(l_lower), m_mode(l_mode), m_upper(l_upper) // Constructor.
|
Chris@16
|
152 { // Evans says 'standard triangular' is lower 0, mode 1/2, upper 1,
|
Chris@16
|
153 // has median sqrt(c/2) for c <=1/2 and 1 - sqrt(1-c)/2 for c >= 1/2
|
Chris@16
|
154 // But this -1, 0, 1 is more useful in most applications to approximate normal distribution,
|
Chris@16
|
155 // where the central value is the most likely and deviations either side equally likely.
|
Chris@16
|
156 RealType result;
|
Chris@16
|
157 detail::check_triangular("boost::math::triangular_distribution<%1%>::triangular_distribution",l_lower, l_mode, l_upper, &result, Policy());
|
Chris@16
|
158 }
|
Chris@16
|
159 // Accessor functions.
|
Chris@16
|
160 RealType lower()const
|
Chris@16
|
161 {
|
Chris@16
|
162 return m_lower;
|
Chris@16
|
163 }
|
Chris@16
|
164 RealType mode()const
|
Chris@16
|
165 {
|
Chris@16
|
166 return m_mode;
|
Chris@16
|
167 }
|
Chris@16
|
168 RealType upper()const
|
Chris@16
|
169 {
|
Chris@16
|
170 return m_upper;
|
Chris@16
|
171 }
|
Chris@16
|
172 private:
|
Chris@16
|
173 // Data members:
|
Chris@16
|
174 RealType m_lower; // distribution lower aka a
|
Chris@16
|
175 RealType m_mode; // distribution mode aka c
|
Chris@16
|
176 RealType m_upper; // distribution upper aka b
|
Chris@16
|
177 }; // class triangular_distribution
|
Chris@16
|
178
|
Chris@16
|
179 typedef triangular_distribution<double> triangular;
|
Chris@16
|
180
|
Chris@16
|
181 template <class RealType, class Policy>
|
Chris@16
|
182 inline const std::pair<RealType, RealType> range(const triangular_distribution<RealType, Policy>& /* dist */)
|
Chris@16
|
183 { // Range of permissible values for random variable x.
|
Chris@16
|
184 using boost::math::tools::max_value;
|
Chris@16
|
185 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 template <class RealType, class Policy>
|
Chris@16
|
189 inline const std::pair<RealType, RealType> support(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
190 { // Range of supported values for random variable x.
|
Chris@16
|
191 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
Chris@16
|
192 return std::pair<RealType, RealType>(dist.lower(), dist.upper());
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 template <class RealType, class Policy>
|
Chris@16
|
196 RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
197 {
|
Chris@16
|
198 static const char* function = "boost::math::pdf(const triangular_distribution<%1%>&, %1%)";
|
Chris@16
|
199 RealType lower = dist.lower();
|
Chris@16
|
200 RealType mode = dist.mode();
|
Chris@16
|
201 RealType upper = dist.upper();
|
Chris@16
|
202 RealType result = 0; // of checks.
|
Chris@16
|
203 if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
|
Chris@16
|
204 {
|
Chris@16
|
205 return result;
|
Chris@16
|
206 }
|
Chris@16
|
207 if(false == detail::check_triangular_x(function, x, &result, Policy()))
|
Chris@16
|
208 {
|
Chris@16
|
209 return result;
|
Chris@16
|
210 }
|
Chris@16
|
211 if((x < lower) || (x > upper))
|
Chris@16
|
212 {
|
Chris@16
|
213 return 0;
|
Chris@16
|
214 }
|
Chris@16
|
215 if (x == lower)
|
Chris@16
|
216 { // (mode - lower) == 0 which would lead to divide by zero!
|
Chris@16
|
217 return (mode == lower) ? 2 / (upper - lower) : RealType(0);
|
Chris@16
|
218 }
|
Chris@16
|
219 else if (x == upper)
|
Chris@16
|
220 {
|
Chris@16
|
221 return (mode == upper) ? 2 / (upper - lower) : RealType(0);
|
Chris@16
|
222 }
|
Chris@16
|
223 else if (x <= mode)
|
Chris@16
|
224 {
|
Chris@16
|
225 return 2 * (x - lower) / ((upper - lower) * (mode - lower));
|
Chris@16
|
226 }
|
Chris@16
|
227 else
|
Chris@16
|
228 { // (x > mode)
|
Chris@16
|
229 return 2 * (upper - x) / ((upper - lower) * (upper - mode));
|
Chris@16
|
230 }
|
Chris@16
|
231 } // RealType pdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
232
|
Chris@16
|
233 template <class RealType, class Policy>
|
Chris@16
|
234 inline RealType cdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
235 {
|
Chris@16
|
236 static const char* function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)";
|
Chris@16
|
237 RealType lower = dist.lower();
|
Chris@16
|
238 RealType mode = dist.mode();
|
Chris@16
|
239 RealType upper = dist.upper();
|
Chris@16
|
240 RealType result = 0; // of checks.
|
Chris@16
|
241 if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
|
Chris@16
|
242 {
|
Chris@16
|
243 return result;
|
Chris@16
|
244 }
|
Chris@16
|
245 if(false == detail::check_triangular_x(function, x, &result, Policy()))
|
Chris@16
|
246 {
|
Chris@16
|
247 return result;
|
Chris@16
|
248 }
|
Chris@16
|
249 if((x <= lower))
|
Chris@16
|
250 {
|
Chris@16
|
251 return 0;
|
Chris@16
|
252 }
|
Chris@16
|
253 if (x >= upper)
|
Chris@16
|
254 {
|
Chris@16
|
255 return 1;
|
Chris@16
|
256 }
|
Chris@16
|
257 // else lower < x < upper
|
Chris@16
|
258 if (x <= mode)
|
Chris@16
|
259 {
|
Chris@16
|
260 return ((x - lower) * (x - lower)) / ((upper - lower) * (mode - lower));
|
Chris@16
|
261 }
|
Chris@16
|
262 else
|
Chris@16
|
263 {
|
Chris@16
|
264 return 1 - (upper - x) * (upper - x) / ((upper - lower) * (upper - mode));
|
Chris@16
|
265 }
|
Chris@16
|
266 } // RealType cdf(const triangular_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
267
|
Chris@16
|
268 template <class RealType, class Policy>
|
Chris@16
|
269 RealType quantile(const triangular_distribution<RealType, Policy>& dist, const RealType& p)
|
Chris@16
|
270 {
|
Chris@16
|
271 BOOST_MATH_STD_USING // for ADL of std functions (sqrt).
|
Chris@16
|
272 static const char* function = "boost::math::quantile(const triangular_distribution<%1%>&, %1%)";
|
Chris@16
|
273 RealType lower = dist.lower();
|
Chris@16
|
274 RealType mode = dist.mode();
|
Chris@16
|
275 RealType upper = dist.upper();
|
Chris@16
|
276 RealType result = 0; // of checks
|
Chris@16
|
277 if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
|
Chris@16
|
278 {
|
Chris@16
|
279 return result;
|
Chris@16
|
280 }
|
Chris@16
|
281 if(false == detail::check_probability(function, p, &result, Policy()))
|
Chris@16
|
282 {
|
Chris@16
|
283 return result;
|
Chris@16
|
284 }
|
Chris@16
|
285 if(p == 0)
|
Chris@16
|
286 {
|
Chris@16
|
287 return lower;
|
Chris@16
|
288 }
|
Chris@16
|
289 if(p == 1)
|
Chris@16
|
290 {
|
Chris@16
|
291 return upper;
|
Chris@16
|
292 }
|
Chris@16
|
293 RealType p0 = (mode - lower) / (upper - lower);
|
Chris@16
|
294 RealType q = 1 - p;
|
Chris@16
|
295 if (p < p0)
|
Chris@16
|
296 {
|
Chris@16
|
297 result = sqrt((upper - lower) * (mode - lower) * p) + lower;
|
Chris@16
|
298 }
|
Chris@16
|
299 else if (p == p0)
|
Chris@16
|
300 {
|
Chris@16
|
301 result = mode;
|
Chris@16
|
302 }
|
Chris@16
|
303 else // p > p0
|
Chris@16
|
304 {
|
Chris@16
|
305 result = upper - sqrt((upper - lower) * (upper - mode) * q);
|
Chris@16
|
306 }
|
Chris@16
|
307 return result;
|
Chris@16
|
308
|
Chris@16
|
309 } // RealType quantile(const triangular_distribution<RealType, Policy>& dist, const RealType& q)
|
Chris@16
|
310
|
Chris@16
|
311 template <class RealType, class Policy>
|
Chris@16
|
312 RealType cdf(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
313 {
|
Chris@16
|
314 static const char* function = "boost::math::cdf(const triangular_distribution<%1%>&, %1%)";
|
Chris@16
|
315 RealType lower = c.dist.lower();
|
Chris@16
|
316 RealType mode = c.dist.mode();
|
Chris@16
|
317 RealType upper = c.dist.upper();
|
Chris@16
|
318 RealType x = c.param;
|
Chris@16
|
319 RealType result = 0; // of checks.
|
Chris@16
|
320 if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
|
Chris@16
|
321 {
|
Chris@16
|
322 return result;
|
Chris@16
|
323 }
|
Chris@16
|
324 if(false == detail::check_triangular_x(function, x, &result, Policy()))
|
Chris@16
|
325 {
|
Chris@16
|
326 return result;
|
Chris@16
|
327 }
|
Chris@16
|
328 if (x <= lower)
|
Chris@16
|
329 {
|
Chris@16
|
330 return 1;
|
Chris@16
|
331 }
|
Chris@16
|
332 if (x >= upper)
|
Chris@16
|
333 {
|
Chris@16
|
334 return 0;
|
Chris@16
|
335 }
|
Chris@16
|
336 if (x <= mode)
|
Chris@16
|
337 {
|
Chris@16
|
338 return 1 - ((x - lower) * (x - lower)) / ((upper - lower) * (mode - lower));
|
Chris@16
|
339 }
|
Chris@16
|
340 else
|
Chris@16
|
341 {
|
Chris@16
|
342 return (upper - x) * (upper - x) / ((upper - lower) * (upper - mode));
|
Chris@16
|
343 }
|
Chris@16
|
344 } // RealType cdf(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
345
|
Chris@16
|
346 template <class RealType, class Policy>
|
Chris@16
|
347 RealType quantile(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
348 {
|
Chris@16
|
349 BOOST_MATH_STD_USING // Aid ADL for sqrt.
|
Chris@16
|
350 static const char* function = "boost::math::quantile(const triangular_distribution<%1%>&, %1%)";
|
Chris@16
|
351 RealType l = c.dist.lower();
|
Chris@16
|
352 RealType m = c.dist.mode();
|
Chris@16
|
353 RealType u = c.dist.upper();
|
Chris@16
|
354 RealType q = c.param; // probability 0 to 1.
|
Chris@16
|
355 RealType result = 0; // of checks.
|
Chris@16
|
356 if(false == detail::check_triangular(function, l, m, u, &result, Policy()))
|
Chris@16
|
357 {
|
Chris@16
|
358 return result;
|
Chris@16
|
359 }
|
Chris@16
|
360 if(false == detail::check_probability(function, q, &result, Policy()))
|
Chris@16
|
361 {
|
Chris@16
|
362 return result;
|
Chris@16
|
363 }
|
Chris@16
|
364 if(q == 0)
|
Chris@16
|
365 {
|
Chris@16
|
366 return u;
|
Chris@16
|
367 }
|
Chris@16
|
368 if(q == 1)
|
Chris@16
|
369 {
|
Chris@16
|
370 return l;
|
Chris@16
|
371 }
|
Chris@16
|
372 RealType lower = c.dist.lower();
|
Chris@16
|
373 RealType mode = c.dist.mode();
|
Chris@16
|
374 RealType upper = c.dist.upper();
|
Chris@16
|
375
|
Chris@16
|
376 RealType p = 1 - q;
|
Chris@16
|
377 RealType p0 = (mode - lower) / (upper - lower);
|
Chris@16
|
378 if(p < p0)
|
Chris@16
|
379 {
|
Chris@16
|
380 RealType s = (upper - lower) * (mode - lower);
|
Chris@16
|
381 s *= p;
|
Chris@16
|
382 result = sqrt((upper - lower) * (mode - lower) * p) + lower;
|
Chris@16
|
383 }
|
Chris@16
|
384 else if (p == p0)
|
Chris@16
|
385 {
|
Chris@16
|
386 result = mode;
|
Chris@16
|
387 }
|
Chris@16
|
388 else // p > p0
|
Chris@16
|
389 {
|
Chris@16
|
390 result = upper - sqrt((upper - lower) * (upper - mode) * q);
|
Chris@16
|
391 }
|
Chris@16
|
392 return result;
|
Chris@16
|
393 } // RealType quantile(const complemented2_type<triangular_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
394
|
Chris@16
|
395 template <class RealType, class Policy>
|
Chris@16
|
396 inline RealType mean(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
397 {
|
Chris@16
|
398 static const char* function = "boost::math::mean(const triangular_distribution<%1%>&)";
|
Chris@16
|
399 RealType lower = dist.lower();
|
Chris@16
|
400 RealType mode = dist.mode();
|
Chris@16
|
401 RealType upper = dist.upper();
|
Chris@16
|
402 RealType result = 0; // of checks.
|
Chris@16
|
403 if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
|
Chris@16
|
404 {
|
Chris@16
|
405 return result;
|
Chris@16
|
406 }
|
Chris@16
|
407 return (lower + upper + mode) / 3;
|
Chris@16
|
408 } // RealType mean(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
409
|
Chris@16
|
410
|
Chris@16
|
411 template <class RealType, class Policy>
|
Chris@16
|
412 inline RealType variance(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
413 {
|
Chris@16
|
414 static const char* function = "boost::math::mean(const triangular_distribution<%1%>&)";
|
Chris@16
|
415 RealType lower = dist.lower();
|
Chris@16
|
416 RealType mode = dist.mode();
|
Chris@16
|
417 RealType upper = dist.upper();
|
Chris@16
|
418 RealType result = 0; // of checks.
|
Chris@16
|
419 if(false == detail::check_triangular(function, lower, mode, upper, &result, Policy()))
|
Chris@16
|
420 {
|
Chris@16
|
421 return result;
|
Chris@16
|
422 }
|
Chris@16
|
423 return (lower * lower + upper * upper + mode * mode - lower * upper - lower * mode - upper * mode) / 18;
|
Chris@16
|
424 } // RealType variance(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
425
|
Chris@16
|
426 template <class RealType, class Policy>
|
Chris@16
|
427 inline RealType mode(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
428 {
|
Chris@16
|
429 static const char* function = "boost::math::mode(const triangular_distribution<%1%>&)";
|
Chris@16
|
430 RealType mode = dist.mode();
|
Chris@16
|
431 RealType result = 0; // of checks.
|
Chris@16
|
432 if(false == detail::check_triangular_mode(function, mode, &result, Policy()))
|
Chris@16
|
433 { // This should never happen!
|
Chris@16
|
434 return result;
|
Chris@16
|
435 }
|
Chris@16
|
436 return mode;
|
Chris@16
|
437 } // RealType mode
|
Chris@16
|
438
|
Chris@16
|
439 template <class RealType, class Policy>
|
Chris@16
|
440 inline RealType median(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
441 {
|
Chris@16
|
442 BOOST_MATH_STD_USING // ADL of std functions.
|
Chris@16
|
443 static const char* function = "boost::math::median(const triangular_distribution<%1%>&)";
|
Chris@16
|
444 RealType mode = dist.mode();
|
Chris@16
|
445 RealType result = 0; // of checks.
|
Chris@16
|
446 if(false == detail::check_triangular_mode(function, mode, &result, Policy()))
|
Chris@16
|
447 { // This should never happen!
|
Chris@16
|
448 return result;
|
Chris@16
|
449 }
|
Chris@16
|
450 RealType lower = dist.lower();
|
Chris@16
|
451 RealType upper = dist.upper();
|
Chris@16
|
452 if (mode < (upper - lower) / 2)
|
Chris@16
|
453 {
|
Chris@16
|
454 return lower + sqrt((upper - lower) * (mode - lower)) / constants::root_two<RealType>();
|
Chris@16
|
455 }
|
Chris@16
|
456 else
|
Chris@16
|
457 {
|
Chris@16
|
458 return upper - sqrt((upper - lower) * (upper - mode)) / constants::root_two<RealType>();
|
Chris@16
|
459 }
|
Chris@16
|
460 } // RealType mode
|
Chris@16
|
461
|
Chris@16
|
462 template <class RealType, class Policy>
|
Chris@16
|
463 inline RealType skewness(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
464 {
|
Chris@16
|
465 BOOST_MATH_STD_USING // for ADL of std functions
|
Chris@16
|
466 using namespace boost::math::constants; // for root_two
|
Chris@16
|
467 static const char* function = "boost::math::skewness(const triangular_distribution<%1%>&)";
|
Chris@16
|
468
|
Chris@16
|
469 RealType lower = dist.lower();
|
Chris@16
|
470 RealType mode = dist.mode();
|
Chris@16
|
471 RealType upper = dist.upper();
|
Chris@16
|
472 RealType result = 0; // of checks.
|
Chris@16
|
473 if(false == boost::math::detail::check_triangular(function,lower, mode, upper, &result, Policy()))
|
Chris@16
|
474 {
|
Chris@16
|
475 return result;
|
Chris@16
|
476 }
|
Chris@16
|
477 return root_two<RealType>() * (lower + upper - 2 * mode) * (2 * lower - upper - mode) * (lower - 2 * upper + mode) /
|
Chris@16
|
478 (5 * pow((lower * lower + upper + upper + mode * mode - lower * upper - lower * mode - upper * mode), RealType(3)/RealType(2)));
|
Chris@16
|
479 } // RealType skewness(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
480
|
Chris@16
|
481 template <class RealType, class Policy>
|
Chris@16
|
482 inline RealType kurtosis(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
483 { // These checks may be belt and braces as should have been checked on construction?
|
Chris@16
|
484 static const char* function = "boost::math::kurtosis(const triangular_distribution<%1%>&)";
|
Chris@16
|
485 RealType lower = dist.lower();
|
Chris@16
|
486 RealType upper = dist.upper();
|
Chris@16
|
487 RealType mode = dist.mode();
|
Chris@16
|
488 RealType result = 0; // of checks.
|
Chris@16
|
489 if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
|
Chris@16
|
490 {
|
Chris@16
|
491 return result;
|
Chris@16
|
492 }
|
Chris@16
|
493 return static_cast<RealType>(12)/5; // 12/5 = 2.4;
|
Chris@16
|
494 } // RealType kurtosis_excess(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
495
|
Chris@16
|
496 template <class RealType, class Policy>
|
Chris@16
|
497 inline RealType kurtosis_excess(const triangular_distribution<RealType, Policy>& dist)
|
Chris@16
|
498 { // These checks may be belt and braces as should have been checked on construction?
|
Chris@16
|
499 static const char* function = "boost::math::kurtosis_excess(const triangular_distribution<%1%>&)";
|
Chris@16
|
500 RealType lower = dist.lower();
|
Chris@16
|
501 RealType upper = dist.upper();
|
Chris@16
|
502 RealType mode = dist.mode();
|
Chris@16
|
503 RealType result = 0; // of checks.
|
Chris@16
|
504 if(false == detail::check_triangular(function,lower, mode, upper, &result, Policy()))
|
Chris@16
|
505 {
|
Chris@16
|
506 return result;
|
Chris@16
|
507 }
|
Chris@16
|
508 return static_cast<RealType>(-3)/5; // - 3/5 = -0.6
|
Chris@16
|
509 // Assuming mathworld really means kurtosis excess? Wikipedia now corrected to match this.
|
Chris@16
|
510 }
|
Chris@16
|
511
|
Chris@16
|
512 } // namespace math
|
Chris@16
|
513 } // namespace boost
|
Chris@16
|
514
|
Chris@16
|
515 // This include must be at the end, *after* the accessors
|
Chris@16
|
516 // for this distribution have been defined, in order to
|
Chris@16
|
517 // keep compilers that support two-phase lookup happy.
|
Chris@16
|
518 #include <boost/math/distributions/detail/derived_accessors.hpp>
|
Chris@16
|
519
|
Chris@16
|
520 #endif // BOOST_STATS_TRIANGULAR_HPP
|
Chris@16
|
521
|
Chris@16
|
522
|
Chris@16
|
523
|