351 lines
10 KiB
C++
351 lines
10 KiB
C++
|
// Copyright Thijs van den Berg, 2008.
|
||
|
// Copyright John Maddock 2008.
|
||
|
// Copyright Paul A. Bristow 2008, 2014.
|
||
|
|
||
|
// Use, modification and distribution are subject to the
|
||
|
// Boost Software License, Version 1.0. (See accompanying file
|
||
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
|
||
|
// This module implements the Laplace distribution.
|
||
|
// Weisstein, Eric W. "Laplace Distribution." From MathWorld--A Wolfram Web Resource.
|
||
|
// http://mathworld.wolfram.com/LaplaceDistribution.html
|
||
|
// http://en.wikipedia.org/wiki/Laplace_distribution
|
||
|
//
|
||
|
// Abramowitz and Stegun 1972, p 930
|
||
|
// http://www.math.sfu.ca/~cbm/aands/page_930.htm
|
||
|
|
||
|
#ifndef BOOST_STATS_LAPLACE_HPP
|
||
|
#define BOOST_STATS_LAPLACE_HPP
|
||
|
|
||
|
#include <boost/math/distributions/detail/common_error_handling.hpp>
|
||
|
#include <boost/math/distributions/complement.hpp>
|
||
|
#include <boost/math/constants/constants.hpp>
|
||
|
#include <limits>
|
||
|
|
||
|
namespace boost{ namespace math{
|
||
|
|
||
|
#ifdef BOOST_MSVC
|
||
|
# pragma warning(push)
|
||
|
# pragma warning(disable:4127) // conditional expression is constant
|
||
|
#endif
|
||
|
|
||
|
template <class RealType = double, class Policy = policies::policy<> >
|
||
|
class laplace_distribution
|
||
|
{
|
||
|
public:
|
||
|
// ----------------------------------
|
||
|
// public Types
|
||
|
// ----------------------------------
|
||
|
typedef RealType value_type;
|
||
|
typedef Policy policy_type;
|
||
|
|
||
|
// ----------------------------------
|
||
|
// Constructor(s)
|
||
|
// ----------------------------------
|
||
|
laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
|
||
|
: m_location(l_location), m_scale(l_scale)
|
||
|
{
|
||
|
RealType result;
|
||
|
check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);
|
||
|
}
|
||
|
|
||
|
|
||
|
// ----------------------------------
|
||
|
// Public functions
|
||
|
// ----------------------------------
|
||
|
|
||
|
RealType location() const
|
||
|
{
|
||
|
return m_location;
|
||
|
}
|
||
|
|
||
|
RealType scale() const
|
||
|
{
|
||
|
return m_scale;
|
||
|
}
|
||
|
|
||
|
bool check_parameters(const char* function, RealType* result) const
|
||
|
{
|
||
|
if(false == detail::check_scale(function, m_scale, result, Policy())) return false;
|
||
|
if(false == detail::check_location(function, m_location, result, Policy())) return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
RealType m_location;
|
||
|
RealType m_scale;
|
||
|
}; // class laplace_distribution
|
||
|
|
||
|
//
|
||
|
// Convenient type synonym for double.
|
||
|
typedef laplace_distribution<double> laplace;
|
||
|
|
||
|
//
|
||
|
// Non-member functions.
|
||
|
template <class RealType, class Policy>
|
||
|
inline const std::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
|
||
|
{
|
||
|
if (std::numeric_limits<RealType>::has_infinity)
|
||
|
{ // Can use infinity.
|
||
|
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
|
||
|
}
|
||
|
else
|
||
|
{ // Can only use max_value.
|
||
|
using boost::math::tools::max_value;
|
||
|
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline const std::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
|
||
|
{
|
||
|
if (std::numeric_limits<RealType>::has_infinity)
|
||
|
{ // Can Use infinity.
|
||
|
return std::pair<RealType, RealType>(-std::numeric_limits<RealType>::infinity(), std::numeric_limits<RealType>::infinity()); // - to + infinity.
|
||
|
}
|
||
|
else
|
||
|
{ // Can only use max_value.
|
||
|
using boost::math::tools::max_value;
|
||
|
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
|
||
|
{
|
||
|
BOOST_MATH_STD_USING // for ADL of std functions
|
||
|
|
||
|
// Checking function argument
|
||
|
RealType result = 0;
|
||
|
const char* function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";
|
||
|
|
||
|
// Check scale and location.
|
||
|
if (false == dist.check_parameters(function, &result)) return result;
|
||
|
// Special pdf values.
|
||
|
if((boost::math::isinf)(x))
|
||
|
{
|
||
|
return 0; // pdf + and - infinity is zero.
|
||
|
}
|
||
|
if (false == detail::check_x(function, x, &result, Policy())) return result;
|
||
|
|
||
|
// General case
|
||
|
RealType scale( dist.scale() );
|
||
|
RealType location( dist.location() );
|
||
|
|
||
|
RealType exponent = x - location;
|
||
|
if (exponent>0) exponent = -exponent;
|
||
|
exponent /= scale;
|
||
|
|
||
|
result = exp(exponent);
|
||
|
result /= 2 * scale;
|
||
|
|
||
|
return result;
|
||
|
} // pdf
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
|
||
|
{
|
||
|
BOOST_MATH_STD_USING // For ADL of std functions.
|
||
|
|
||
|
RealType result = 0;
|
||
|
// Checking function argument.
|
||
|
const char* function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";
|
||
|
// Check scale and location.
|
||
|
if (false == dist.check_parameters(function, &result)) return result;
|
||
|
|
||
|
// Special cdf values:
|
||
|
if((boost::math::isinf)(x))
|
||
|
{
|
||
|
if(x < 0) return 0; // -infinity.
|
||
|
return 1; // + infinity.
|
||
|
}
|
||
|
if (false == detail::check_x(function, x, &result, Policy())) return result;
|
||
|
|
||
|
// General cdf values
|
||
|
RealType scale( dist.scale() );
|
||
|
RealType location( dist.location() );
|
||
|
|
||
|
if (x < location)
|
||
|
{
|
||
|
result = exp( (x-location)/scale )/2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = 1 - exp( (location-x)/scale )/2;
|
||
|
}
|
||
|
return result;
|
||
|
} // cdf
|
||
|
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)
|
||
|
{
|
||
|
BOOST_MATH_STD_USING // for ADL of std functions.
|
||
|
|
||
|
// Checking function argument
|
||
|
RealType result = 0;
|
||
|
const char* function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)";
|
||
|
if (false == dist.check_parameters(function, &result)) return result;
|
||
|
if(false == detail::check_probability(function, p, &result, Policy())) return result;
|
||
|
|
||
|
// Extreme values of p:
|
||
|
if(p == 0)
|
||
|
{
|
||
|
result = policies::raise_overflow_error<RealType>(function,
|
||
|
"probability parameter is 0, but must be > 0!", Policy());
|
||
|
return -result; // -std::numeric_limits<RealType>::infinity();
|
||
|
}
|
||
|
|
||
|
if(p == 1)
|
||
|
{
|
||
|
result = policies::raise_overflow_error<RealType>(function,
|
||
|
"probability parameter is 1, but must be < 1!", Policy());
|
||
|
return result; // std::numeric_limits<RealType>::infinity();
|
||
|
}
|
||
|
// Calculate Quantile
|
||
|
RealType scale( dist.scale() );
|
||
|
RealType location( dist.location() );
|
||
|
|
||
|
if (p - 0.5 < 0.0)
|
||
|
result = location + scale*log( static_cast<RealType>(p*2) );
|
||
|
else
|
||
|
result = location - scale*log( static_cast<RealType>(-p*2 + 2) );
|
||
|
|
||
|
return result;
|
||
|
} // quantile
|
||
|
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
|
||
|
{
|
||
|
// Calculate complement of cdf.
|
||
|
BOOST_MATH_STD_USING // for ADL of std functions
|
||
|
|
||
|
RealType scale = c.dist.scale();
|
||
|
RealType location = c.dist.location();
|
||
|
RealType x = c.param;
|
||
|
RealType result = 0;
|
||
|
|
||
|
// Checking function argument.
|
||
|
const char* function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
|
||
|
|
||
|
// Check scale and location.
|
||
|
//if(false == detail::check_scale(function, scale, result, Policy())) return false;
|
||
|
//if(false == detail::check_location(function, location, result, Policy())) return false;
|
||
|
if (false == c.dist.check_parameters(function, &result)) return result;
|
||
|
|
||
|
// Special cdf values.
|
||
|
if((boost::math::isinf)(x))
|
||
|
{
|
||
|
if(x < 0) return 1; // cdf complement -infinity is unity.
|
||
|
return 0; // cdf complement +infinity is zero.
|
||
|
}
|
||
|
if(false == detail::check_x(function, x, &result, Policy()))return result;
|
||
|
|
||
|
// Cdf interval value.
|
||
|
if (-x < -location)
|
||
|
{
|
||
|
result = exp( (-x+location)/scale )/2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = 1 - exp( (-location+x)/scale )/2;
|
||
|
}
|
||
|
return result;
|
||
|
} // cdf complement
|
||
|
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
|
||
|
{
|
||
|
BOOST_MATH_STD_USING // for ADL of std functions.
|
||
|
|
||
|
// Calculate quantile.
|
||
|
RealType scale = c.dist.scale();
|
||
|
RealType location = c.dist.location();
|
||
|
RealType q = c.param;
|
||
|
RealType result = 0;
|
||
|
|
||
|
// Checking function argument.
|
||
|
const char* function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
|
||
|
if (false == c.dist.check_parameters(function, &result)) return result;
|
||
|
|
||
|
// Extreme values.
|
||
|
if(q == 0)
|
||
|
{
|
||
|
return std::numeric_limits<RealType>::infinity();
|
||
|
}
|
||
|
if(q == 1)
|
||
|
{
|
||
|
return -std::numeric_limits<RealType>::infinity();
|
||
|
}
|
||
|
if(false == detail::check_probability(function, q, &result, Policy())) return result;
|
||
|
|
||
|
if (0.5 - q < 0.0)
|
||
|
result = location + scale*log( static_cast<RealType>(-q*2 + 2) );
|
||
|
else
|
||
|
result = location - scale*log( static_cast<RealType>(q*2) );
|
||
|
|
||
|
|
||
|
return result;
|
||
|
} // quantile
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType mean(const laplace_distribution<RealType, Policy>& dist)
|
||
|
{
|
||
|
return dist.location();
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType standard_deviation(const laplace_distribution<RealType, Policy>& dist)
|
||
|
{
|
||
|
return constants::root_two<RealType>() * dist.scale();
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType mode(const laplace_distribution<RealType, Policy>& dist)
|
||
|
{
|
||
|
return dist.location();
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType median(const laplace_distribution<RealType, Policy>& dist)
|
||
|
{
|
||
|
return dist.location();
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType skewness(const laplace_distribution<RealType, Policy>& /*dist*/)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType kurtosis(const laplace_distribution<RealType, Policy>& /*dist*/)
|
||
|
{
|
||
|
return 6;
|
||
|
}
|
||
|
|
||
|
template <class RealType, class Policy>
|
||
|
inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*dist*/)
|
||
|
{
|
||
|
return 3;
|
||
|
}
|
||
|
|
||
|
#ifdef BOOST_MSVC
|
||
|
# pragma warning(pop)
|
||
|
#endif
|
||
|
|
||
|
} // namespace math
|
||
|
} // namespace boost
|
||
|
|
||
|
// This include must be at the end, *after* the accessors
|
||
|
// for this distribution have been defined, in order to
|
||
|
// keep compilers that support two-phase lookup happy.
|
||
|
#include <boost/math/distributions/detail/derived_accessors.hpp>
|
||
|
|
||
|
#endif // BOOST_STATS_LAPLACE_HPP
|
||
|
|
||
|
|