Chris@16
|
1 // Copyright Thijs van den Berg, 2008.
|
Chris@16
|
2 // Copyright John Maddock 2008.
|
Chris@101
|
3 // Copyright Paul A. Bristow 2008, 2014.
|
Chris@16
|
4
|
Chris@16
|
5 // Use, modification and distribution are subject to the
|
Chris@16
|
6 // Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 // This module implements the Laplace distribution.
|
Chris@16
|
10 // Weisstein, Eric W. "Laplace Distribution." From MathWorld--A Wolfram Web Resource.
|
Chris@16
|
11 // http://mathworld.wolfram.com/LaplaceDistribution.html
|
Chris@16
|
12 // http://en.wikipedia.org/wiki/Laplace_distribution
|
Chris@16
|
13 //
|
Chris@16
|
14 // Abramowitz and Stegun 1972, p 930
|
Chris@16
|
15 // http://www.math.sfu.ca/~cbm/aands/page_930.htm
|
Chris@16
|
16
|
Chris@16
|
17 #ifndef BOOST_STATS_LAPLACE_HPP
|
Chris@16
|
18 #define BOOST_STATS_LAPLACE_HPP
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/math/distributions/detail/common_error_handling.hpp>
|
Chris@16
|
21 #include <boost/math/distributions/complement.hpp>
|
Chris@16
|
22 #include <boost/math/constants/constants.hpp>
|
Chris@16
|
23 #include <limits>
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost{ namespace math{
|
Chris@16
|
26
|
Chris@101
|
27 #ifdef BOOST_MSVC
|
Chris@101
|
28 # pragma warning(push)
|
Chris@101
|
29 # pragma warning(disable:4127) // conditional expression is constant
|
Chris@101
|
30 #endif
|
Chris@101
|
31
|
Chris@16
|
32 template <class RealType = double, class Policy = policies::policy<> >
|
Chris@16
|
33 class laplace_distribution
|
Chris@16
|
34 {
|
Chris@16
|
35 public:
|
Chris@16
|
36 // ----------------------------------
|
Chris@16
|
37 // public Types
|
Chris@16
|
38 // ----------------------------------
|
Chris@16
|
39 typedef RealType value_type;
|
Chris@16
|
40 typedef Policy policy_type;
|
Chris@16
|
41
|
Chris@16
|
42 // ----------------------------------
|
Chris@16
|
43 // Constructor(s)
|
Chris@16
|
44 // ----------------------------------
|
Chris@16
|
45 laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
|
Chris@16
|
46 : m_location(l_location), m_scale(l_scale)
|
Chris@16
|
47 {
|
Chris@16
|
48 RealType result;
|
Chris@16
|
49 check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);
|
Chris@16
|
50 }
|
Chris@16
|
51
|
Chris@16
|
52
|
Chris@16
|
53 // ----------------------------------
|
Chris@16
|
54 // Public functions
|
Chris@16
|
55 // ----------------------------------
|
Chris@16
|
56
|
Chris@16
|
57 RealType location() const
|
Chris@16
|
58 {
|
Chris@16
|
59 return m_location;
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 RealType scale() const
|
Chris@16
|
63 {
|
Chris@16
|
64 return m_scale;
|
Chris@16
|
65 }
|
Chris@16
|
66
|
Chris@16
|
67 bool check_parameters(const char* function, RealType* result) const
|
Chris@16
|
68 {
|
Chris@16
|
69 if(false == detail::check_scale(function, m_scale, result, Policy())) return false;
|
Chris@16
|
70 if(false == detail::check_location(function, m_location, result, Policy())) return false;
|
Chris@16
|
71 return true;
|
Chris@16
|
72 }
|
Chris@16
|
73
|
Chris@16
|
74 private:
|
Chris@16
|
75 RealType m_location;
|
Chris@16
|
76 RealType m_scale;
|
Chris@16
|
77 }; // class laplace_distribution
|
Chris@16
|
78
|
Chris@16
|
79 //
|
Chris@101
|
80 // Convenient type synonym for double.
|
Chris@16
|
81 typedef laplace_distribution<double> laplace;
|
Chris@16
|
82
|
Chris@16
|
83 //
|
Chris@101
|
84 // Non-member functions.
|
Chris@16
|
85 template <class RealType, class Policy>
|
Chris@16
|
86 inline const std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
|
Chris@16
|
87 {
|
Chris@101
|
88 if (std::numeric_limits<RealType>::has_infinity)
|
Chris@101
|
89 { // Can use infinity.
|
Chris@101
|
90 return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
|
Chris@101
|
91 }
|
Chris@101
|
92 else
|
Chris@101
|
93 { // Can only use max_value.
|
Chris@101
|
94 using boost::math::tools::max_value;
|
Chris@101
|
95 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
|
Chris@101
|
96 }
|
Chris@101
|
97
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 template <class RealType, class Policy>
|
Chris@16
|
101 inline const std::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
|
Chris@16
|
102 {
|
Chris@101
|
103 if (std::numeric_limits<RealType>::has_infinity)
|
Chris@101
|
104 { // Can Use infinity.
|
Chris@101
|
105 return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
|
Chris@101
|
106 }
|
Chris@101
|
107 else
|
Chris@101
|
108 { // Can only use max_value.
|
Chris@101
|
109 using boost::math::tools::max_value;
|
Chris@101
|
110 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
|
Chris@101
|
111 }
|
Chris@16
|
112 }
|
Chris@16
|
113
|
Chris@16
|
114 template <class RealType, class Policy>
|
Chris@16
|
115 inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
116 {
|
Chris@16
|
117 BOOST_MATH_STD_USING // for ADL of std functions
|
Chris@16
|
118
|
Chris@16
|
119 // Checking function argument
|
Chris@16
|
120 RealType result = 0;
|
Chris@16
|
121 const char* function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";
|
Chris@101
|
122
|
Chris@101
|
123 // Check scale and location.
|
Chris@16
|
124 if (false == dist.check_parameters(function, &result)) return result;
|
Chris@101
|
125 // Special pdf values.
|
Chris@101
|
126 if((boost::math::isinf)(x))
|
Chris@101
|
127 {
|
Chris@101
|
128 return 0; // pdf + and - infinity is zero.
|
Chris@101
|
129 }
|
Chris@16
|
130 if (false == detail::check_x(function, x, &result, Policy())) return result;
|
Chris@16
|
131
|
Chris@16
|
132 // General case
|
Chris@16
|
133 RealType scale( dist.scale() );
|
Chris@16
|
134 RealType location( dist.location() );
|
Chris@16
|
135
|
Chris@16
|
136 RealType exponent = x - location;
|
Chris@16
|
137 if (exponent>0) exponent = -exponent;
|
Chris@16
|
138 exponent /= scale;
|
Chris@16
|
139
|
Chris@16
|
140 result = exp(exponent);
|
Chris@16
|
141 result /= 2 * scale;
|
Chris@16
|
142
|
Chris@16
|
143 return result;
|
Chris@16
|
144 } // pdf
|
Chris@16
|
145
|
Chris@16
|
146 template <class RealType, class Policy>
|
Chris@16
|
147 inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
|
Chris@16
|
148 {
|
Chris@101
|
149 BOOST_MATH_STD_USING // For ADL of std functions.
|
Chris@16
|
150
|
Chris@16
|
151 RealType result = 0;
|
Chris@101
|
152 // Checking function argument.
|
Chris@16
|
153 const char* function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";
|
Chris@101
|
154 // Check scale and location.
|
Chris@16
|
155 if (false == dist.check_parameters(function, &result)) return result;
|
Chris@16
|
156
|
Chris@16
|
157 // Special cdf values:
|
Chris@16
|
158 if((boost::math::isinf)(x))
|
Chris@16
|
159 {
|
Chris@101
|
160 if(x < 0) return 0; // -infinity.
|
Chris@101
|
161 return 1; // + infinity.
|
Chris@16
|
162 }
|
Chris@101
|
163 if (false == detail::check_x(function, x, &result, Policy())) return result;
|
Chris@16
|
164
|
Chris@16
|
165 // General cdf values
|
Chris@16
|
166 RealType scale( dist.scale() );
|
Chris@16
|
167 RealType location( dist.location() );
|
Chris@16
|
168
|
Chris@16
|
169 if (x < location)
|
Chris@16
|
170 {
|
Chris@16
|
171 result = exp( (x-location)/scale )/2;
|
Chris@16
|
172 }
|
Chris@16
|
173 else
|
Chris@16
|
174 {
|
Chris@16
|
175 result = 1 - exp( (location-x)/scale )/2;
|
Chris@16
|
176 }
|
Chris@16
|
177 return result;
|
Chris@16
|
178 } // cdf
|
Chris@16
|
179
|
Chris@16
|
180
|
Chris@16
|
181 template <class RealType, class Policy>
|
Chris@16
|
182 inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)
|
Chris@16
|
183 {
|
Chris@16
|
184 BOOST_MATH_STD_USING // for ADL of std functions.
|
Chris@16
|
185
|
Chris@16
|
186 // Checking function argument
|
Chris@16
|
187 RealType result = 0;
|
Chris@16
|
188 const char* function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)";
|
Chris@16
|
189 if (false == dist.check_parameters(function, &result)) return result;
|
Chris@16
|
190 if(false == detail::check_probability(function, p, &result, Policy())) return result;
|
Chris@16
|
191
|
Chris@16
|
192 // Extreme values of p:
|
Chris@16
|
193 if(p == 0)
|
Chris@16
|
194 {
|
Chris@16
|
195 result = policies::raise_overflow_error<RealType>(function,
|
Chris@16
|
196 "probability parameter is 0, but must be > 0!", Policy());
|
Chris@16
|
197 return -result; // -std::numeric_limits<RealType>::infinity();
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 if(p == 1)
|
Chris@16
|
201 {
|
Chris@16
|
202 result = policies::raise_overflow_error<RealType>(function,
|
Chris@16
|
203 "probability parameter is 1, but must be < 1!", Policy());
|
Chris@16
|
204 return result; // std::numeric_limits<RealType>::infinity();
|
Chris@16
|
205 }
|
Chris@16
|
206 // Calculate Quantile
|
Chris@16
|
207 RealType scale( dist.scale() );
|
Chris@16
|
208 RealType location( dist.location() );
|
Chris@16
|
209
|
Chris@16
|
210 if (p - 0.5 < 0.0)
|
Chris@16
|
211 result = location + scale*log( static_cast<RealType>(p*2) );
|
Chris@16
|
212 else
|
Chris@16
|
213 result = location - scale*log( static_cast<RealType>(-p*2 + 2) );
|
Chris@16
|
214
|
Chris@16
|
215 return result;
|
Chris@16
|
216 } // quantile
|
Chris@16
|
217
|
Chris@16
|
218
|
Chris@16
|
219 template <class RealType, class Policy>
|
Chris@16
|
220 inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
221 {
|
Chris@101
|
222 // Calculate complement of cdf.
|
Chris@16
|
223 BOOST_MATH_STD_USING // for ADL of std functions
|
Chris@16
|
224
|
Chris@16
|
225 RealType scale = c.dist.scale();
|
Chris@16
|
226 RealType location = c.dist.location();
|
Chris@16
|
227 RealType x = c.param;
|
Chris@101
|
228 RealType result = 0;
|
Chris@16
|
229
|
Chris@101
|
230 // Checking function argument.
|
Chris@16
|
231 const char* function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
|
Chris@16
|
232
|
Chris@101
|
233 // Check scale and location.
|
Chris@101
|
234 //if(false == detail::check_scale(function, scale, result, Policy())) return false;
|
Chris@101
|
235 //if(false == detail::check_location(function, location, result, Policy())) return false;
|
Chris@101
|
236 if (false == c.dist.check_parameters(function, &result)) return result;
|
Chris@16
|
237
|
Chris@101
|
238 // Special cdf values.
|
Chris@16
|
239 if((boost::math::isinf)(x))
|
Chris@16
|
240 {
|
Chris@16
|
241 if(x < 0) return 1; // cdf complement -infinity is unity.
|
Chris@16
|
242 return 0; // cdf complement +infinity is zero.
|
Chris@16
|
243 }
|
Chris@101
|
244 if(false == detail::check_x(function, x, &result, Policy()))return result;
|
Chris@16
|
245
|
Chris@16
|
246 // Cdf interval value.
|
Chris@16
|
247 if (-x < -location)
|
Chris@16
|
248 {
|
Chris@16
|
249 result = exp( (-x+location)/scale )/2;
|
Chris@16
|
250 }
|
Chris@16
|
251 else
|
Chris@16
|
252 {
|
Chris@16
|
253 result = 1 - exp( (-location+x)/scale )/2;
|
Chris@16
|
254 }
|
Chris@16
|
255 return result;
|
Chris@16
|
256 } // cdf complement
|
Chris@16
|
257
|
Chris@16
|
258
|
Chris@16
|
259 template <class RealType, class Policy>
|
Chris@16
|
260 inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
261 {
|
Chris@16
|
262 BOOST_MATH_STD_USING // for ADL of std functions.
|
Chris@16
|
263
|
Chris@16
|
264 // Calculate quantile.
|
Chris@16
|
265 RealType scale = c.dist.scale();
|
Chris@16
|
266 RealType location = c.dist.location();
|
Chris@16
|
267 RealType q = c.param;
|
Chris@101
|
268 RealType result = 0;
|
Chris@16
|
269
|
Chris@16
|
270 // Checking function argument.
|
Chris@16
|
271 const char* function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
|
Chris@101
|
272 if (false == c.dist.check_parameters(function, &result)) return result;
|
Chris@101
|
273
|
Chris@101
|
274 // Extreme values.
|
Chris@101
|
275 if(q == 0)
|
Chris@101
|
276 {
|
Chris@101
|
277 return std::numeric_limits<RealType>::infinity();
|
Chris@101
|
278 }
|
Chris@101
|
279 if(q == 1)
|
Chris@101
|
280 {
|
Chris@101
|
281 return -std::numeric_limits<RealType>::infinity();
|
Chris@101
|
282 }
|
Chris@16
|
283 if(false == detail::check_probability(function, q, &result, Policy())) return result;
|
Chris@16
|
284
|
Chris@16
|
285 if (0.5 - q < 0.0)
|
Chris@16
|
286 result = location + scale*log( static_cast<RealType>(-q*2 + 2) );
|
Chris@16
|
287 else
|
Chris@16
|
288 result = location - scale*log( static_cast<RealType>(q*2) );
|
Chris@16
|
289
|
Chris@16
|
290
|
Chris@16
|
291 return result;
|
Chris@16
|
292 } // quantile
|
Chris@16
|
293
|
Chris@16
|
294 template <class RealType, class Policy>
|
Chris@16
|
295 inline RealType mean(const laplace_distribution<RealType, Policy>& dist)
|
Chris@16
|
296 {
|
Chris@16
|
297 return dist.location();
|
Chris@16
|
298 }
|
Chris@16
|
299
|
Chris@16
|
300 template <class RealType, class Policy>
|
Chris@16
|
301 inline RealType standard_deviation(const laplace_distribution<RealType, Policy>& dist)
|
Chris@16
|
302 {
|
Chris@16
|
303 return constants::root_two<RealType>() * dist.scale();
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 template <class RealType, class Policy>
|
Chris@16
|
307 inline RealType mode(const laplace_distribution<RealType, Policy>& dist)
|
Chris@16
|
308 {
|
Chris@16
|
309 return dist.location();
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 template <class RealType, class Policy>
|
Chris@16
|
313 inline RealType median(const laplace_distribution<RealType, Policy>& dist)
|
Chris@16
|
314 {
|
Chris@16
|
315 return dist.location();
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 template <class RealType, class Policy>
|
Chris@16
|
319 inline RealType skewness(const laplace_distribution<RealType, Policy>& /*dist*/)
|
Chris@16
|
320 {
|
Chris@16
|
321 return 0;
|
Chris@16
|
322 }
|
Chris@16
|
323
|
Chris@16
|
324 template <class RealType, class Policy>
|
Chris@16
|
325 inline RealType kurtosis(const laplace_distribution<RealType, Policy>& /*dist*/)
|
Chris@16
|
326 {
|
Chris@16
|
327 return 6;
|
Chris@16
|
328 }
|
Chris@16
|
329
|
Chris@16
|
330 template <class RealType, class Policy>
|
Chris@16
|
331 inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*dist*/)
|
Chris@16
|
332 {
|
Chris@16
|
333 return 3;
|
Chris@16
|
334 }
|
Chris@16
|
335
|
Chris@101
|
336 #ifdef BOOST_MSVC
|
Chris@101
|
337 # pragma warning(pop)
|
Chris@101
|
338 #endif
|
Chris@101
|
339
|
Chris@16
|
340 } // namespace math
|
Chris@16
|
341 } // namespace boost
|
Chris@16
|
342
|
Chris@16
|
343 // This include must be at the end, *after* the accessors
|
Chris@16
|
344 // for this distribution have been defined, in order to
|
Chris@16
|
345 // keep compilers that support two-phase lookup happy.
|
Chris@16
|
346 #include <boost/math/distributions/detail/derived_accessors.hpp>
|
Chris@16
|
347
|
Chris@16
|
348 #endif // BOOST_STATS_LAPLACE_HPP
|
Chris@16
|
349
|
Chris@16
|
350
|