]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright John Maddock 2006. |
2 | // Use, modification and distribution are subject to the | |
3 | // Boost Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #ifndef BOOST_STATS_EXPONENTIAL_HPP | |
7 | #define BOOST_STATS_EXPONENTIAL_HPP | |
8 | ||
9 | #include <boost/math/distributions/fwd.hpp> | |
10 | #include <boost/math/constants/constants.hpp> | |
11 | #include <boost/math/special_functions/log1p.hpp> | |
12 | #include <boost/math/special_functions/expm1.hpp> | |
13 | #include <boost/math/distributions/complement.hpp> | |
14 | #include <boost/math/distributions/detail/common_error_handling.hpp> | |
15 | #include <boost/config/no_tr1/cmath.hpp> | |
16 | ||
17 | #ifdef BOOST_MSVC | |
18 | # pragma warning(push) | |
19 | # pragma warning(disable: 4127) // conditional expression is constant | |
20 | # pragma warning(disable: 4702) // unreachable code (return after domain_error throw). | |
21 | #endif | |
22 | ||
23 | #include <utility> | |
24 | ||
25 | namespace boost{ namespace math{ | |
26 | ||
27 | namespace detail{ | |
28 | // | |
29 | // Error check: | |
30 | // | |
31 | template <class RealType, class Policy> | |
32 | inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol) | |
33 | { | |
34 | if((l <= 0) || !(boost::math::isfinite)(l)) | |
35 | { | |
36 | *presult = policies::raise_domain_error<RealType>( | |
37 | function, | |
38 | "The scale parameter \"lambda\" must be > 0, but was: %1%.", l, pol); | |
39 | return false; | |
40 | } | |
41 | return true; | |
42 | } | |
43 | ||
44 | template <class RealType, class Policy> | |
45 | inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol) | |
46 | { | |
47 | if((x < 0) || (boost::math::isnan)(x)) | |
48 | { | |
49 | *presult = policies::raise_domain_error<RealType>( | |
50 | function, | |
51 | "The random variable must be >= 0, but was: %1%.", x, pol); | |
52 | return false; | |
53 | } | |
54 | return true; | |
55 | } | |
56 | ||
57 | } // namespace detail | |
58 | ||
59 | template <class RealType = double, class Policy = policies::policy<> > | |
60 | class exponential_distribution | |
61 | { | |
62 | public: | |
63 | typedef RealType value_type; | |
64 | typedef Policy policy_type; | |
65 | ||
66 | exponential_distribution(RealType l_lambda = 1) | |
67 | : m_lambda(l_lambda) | |
68 | { | |
69 | RealType err; | |
70 | detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", l_lambda, &err, Policy()); | |
71 | } // exponential_distribution | |
72 | ||
73 | RealType lambda()const { return m_lambda; } | |
74 | ||
75 | private: | |
76 | RealType m_lambda; | |
77 | }; | |
78 | ||
79 | typedef exponential_distribution<double> exponential; | |
80 | ||
81 | template <class RealType, class Policy> | |
82 | inline const std::pair<RealType, RealType> range(const exponential_distribution<RealType, Policy>& /*dist*/) | |
83 | { // Range of permissible values for random variable x. | |
84 | if (std::numeric_limits<RealType>::has_infinity) | |
85 | { | |
86 | return std::pair<RealType, RealType>(static_cast<RealType>(0), std::numeric_limits<RealType>::infinity()); // 0 to + infinity. | |
87 | } | |
88 | else | |
89 | { | |
90 | using boost::math::tools::max_value; | |
91 | return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max | |
92 | } | |
93 | } | |
94 | ||
95 | template <class RealType, class Policy> | |
96 | inline const std::pair<RealType, RealType> support(const exponential_distribution<RealType, Policy>& /*dist*/) | |
97 | { // Range of supported values for random variable x. | |
98 | // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. | |
99 | using boost::math::tools::max_value; | |
100 | using boost::math::tools::min_value; | |
101 | return std::pair<RealType, RealType>(min_value<RealType>(), max_value<RealType>()); | |
102 | // min_value<RealType>() to avoid a discontinuity at x = 0. | |
103 | } | |
104 | ||
105 | template <class RealType, class Policy> | |
106 | inline RealType pdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x) | |
107 | { | |
108 | BOOST_MATH_STD_USING // for ADL of std functions | |
109 | ||
110 | static const char* function = "boost::math::pdf(const exponential_distribution<%1%>&, %1%)"; | |
111 | ||
112 | RealType lambda = dist.lambda(); | |
113 | RealType result = 0; | |
114 | if(0 == detail::verify_lambda(function, lambda, &result, Policy())) | |
115 | return result; | |
116 | if(0 == detail::verify_exp_x(function, x, &result, Policy())) | |
117 | return result; | |
118 | // Workaround for VC11/12 bug: | |
119 | if ((boost::math::isinf)(x)) | |
120 | return 0; | |
121 | result = lambda * exp(-lambda * x); | |
122 | return result; | |
123 | ||
124 | ||
125 | template <class RealType, class Policy> | |
126 | inline RealType cdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x) | |
127 | { | |
128 | BOOST_MATH_STD_USING // for ADL of std functions | |
129 | ||
130 | static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)"; | |
131 | ||
132 | RealType result = 0; | |
133 | RealType lambda = dist.lambda(); | |
134 | if(0 == detail::verify_lambda(function, lambda, &result, Policy())) | |
135 | return result; | |
136 | if(0 == detail::verify_exp_x(function, x, &result, Policy())) | |
137 | return result; | |
138 | result = -boost::math::expm1(-x * lambda, Policy()); | |
139 | ||
140 | return result; | |
141 | } // cdf | |
142 | ||
143 | template <class RealType, class Policy> | |
144 | inline RealType quantile(const exponential_distribution<RealType, Policy>& dist, const RealType& p) | |
145 | { | |
146 | BOOST_MATH_STD_USING // for ADL of std functions | |
147 | ||
148 | static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)"; | |
149 | ||
150 | RealType result = 0; | |
151 | RealType lambda = dist.lambda(); | |
152 | if(0 == detail::verify_lambda(function, lambda, &result, Policy())) | |
153 | return result; | |
154 | if(0 == detail::check_probability(function, p, &result, Policy())) | |
155 | return result; | |
156 | ||
157 | if(p == 0) | |
158 | return 0; | |
159 | if(p == 1) | |
160 | return policies::raise_overflow_error<RealType>(function, 0, Policy()); | |
161 | ||
162 | result = -boost::math::log1p(-p, Policy()) / lambda; | |
163 | return result; | |
164 | } // quantile | |
165 | ||
166 | template <class RealType, class Policy> | |
167 | inline RealType cdf(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c) | |
168 | { | |
169 | BOOST_MATH_STD_USING // for ADL of std functions | |
170 | ||
171 | static const char* function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)"; | |
172 | ||
173 | RealType result = 0; | |
174 | RealType lambda = c.dist.lambda(); | |
175 | if(0 == detail::verify_lambda(function, lambda, &result, Policy())) | |
176 | return result; | |
177 | if(0 == detail::verify_exp_x(function, c.param, &result, Policy())) | |
178 | return result; | |
179 | // Workaround for VC11/12 bug: | |
180 | if (c.param >= tools::max_value<RealType>()) | |
181 | return 0; | |
182 | result = exp(-c.param * lambda); | |
183 | ||
184 | return result; | |
185 | } | |
186 | ||
187 | template <class RealType, class Policy> | |
188 | inline RealType quantile(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c) | |
189 | { | |
190 | BOOST_MATH_STD_USING // for ADL of std functions | |
191 | ||
192 | static const char* function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)"; | |
193 | ||
194 | RealType result = 0; | |
195 | RealType lambda = c.dist.lambda(); | |
196 | if(0 == detail::verify_lambda(function, lambda, &result, Policy())) | |
197 | return result; | |
198 | ||
199 | RealType q = c.param; | |
200 | if(0 == detail::check_probability(function, q, &result, Policy())) | |
201 | return result; | |
202 | ||
203 | if(q == 1) | |
204 | return 0; | |
205 | if(q == 0) | |
206 | return policies::raise_overflow_error<RealType>(function, 0, Policy()); | |
207 | ||
208 | result = -log(q) / lambda; | |
209 | return result; | |
210 | } | |
211 | ||
212 | template <class RealType, class Policy> | |
213 | inline RealType mean(const exponential_distribution<RealType, Policy>& dist) | |
214 | { | |
215 | RealType result = 0; | |
216 | RealType lambda = dist.lambda(); | |
217 | if(0 == detail::verify_lambda("boost::math::mean(const exponential_distribution<%1%>&)", lambda, &result, Policy())) | |
218 | return result; | |
219 | return 1 / lambda; | |
220 | } | |
221 | ||
222 | template <class RealType, class Policy> | |
223 | inline RealType standard_deviation(const exponential_distribution<RealType, Policy>& dist) | |
224 | { | |
225 | RealType result = 0; | |
226 | RealType lambda = dist.lambda(); | |
227 | if(0 == detail::verify_lambda("boost::math::standard_deviation(const exponential_distribution<%1%>&)", lambda, &result, Policy())) | |
228 | return result; | |
229 | return 1 / lambda; | |
230 | } | |
231 | ||
232 | template <class RealType, class Policy> | |
233 | inline RealType mode(const exponential_distribution<RealType, Policy>& /*dist*/) | |
234 | { | |
235 | return 0; | |
236 | } | |
237 | ||
238 | template <class RealType, class Policy> | |
239 | inline RealType median(const exponential_distribution<RealType, Policy>& dist) | |
240 | { | |
241 | using boost::math::constants::ln_two; | |
242 | return ln_two<RealType>() / dist.lambda(); // ln(2) / lambda | |
243 | } | |
244 | ||
245 | template <class RealType, class Policy> | |
246 | inline RealType skewness(const exponential_distribution<RealType, Policy>& /*dist*/) | |
247 | { | |
248 | return 2; | |
249 | } | |
250 | ||
251 | template <class RealType, class Policy> | |
252 | inline RealType kurtosis(const exponential_distribution<RealType, Policy>& /*dist*/) | |
253 | { | |
254 | return 9; | |
255 | } | |
256 | ||
257 | template <class RealType, class Policy> | |
258 | inline RealType kurtosis_excess(const exponential_distribution<RealType, Policy>& /*dist*/) | |
259 | { | |
260 | return 6; | |
261 | } | |
262 | ||
263 | } // namespace math | |
264 | } // namespace boost | |
265 | ||
266 | #ifdef BOOST_MSVC | |
267 | # pragma warning(pop) | |
268 | #endif | |
269 | ||
270 | // This include must be at the end, *after* the accessors | |
271 | // for this distribution have been defined, in order to | |
272 | // keep compilers that support two-phase lookup happy. | |
273 | #include <boost/math/distributions/detail/derived_accessors.hpp> | |
274 | ||
275 | #endif // BOOST_STATS_EXPONENTIAL_HPP |