Ticket #9672: laplace.hpp

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