// Copyright Thijs van den Berg, 2008. // Copyright John Maddock 2008. // 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. // http://en.wikipedia.org/wiki/Laplace_distribution #ifndef BOOST_STATS_LAPLACE_HPP #define BOOST_STATS_LAPLACE_HPP #include namespace boost{ namespace math{ template > class laplace_distribution { public: // ---------------------------------- // public Types // ---------------------------------- typedef RealType value_type; typedef Policy policy_type; // ---------------------------------- // Constructor(s) // ---------------------------------- laplace_distribution(RealType location = 0, RealType scale = 1) : m_location(location), m_scale(scale) { RealType result; const char* function = "boost::math::laplace_distribution<%1%>::laplace_distribution"; check_parameters(function, result, Policy()); } // ---------------------------------------------- // CONCEPT #1 // Runtime access to *set* distribution parameters // // Setting distribution variables at run-time // is something that would be needed when // e.g. distribution data is read from disk // // ---------------------------------------------- bool operator ()(const RealType& location, const RealType& scale) { m_location = location; m_scale = scale; RealType result; const char* function = "boost::math::laplace_distribution<%1%>::operator()"; return check_parameters(function, result, Policy()); } // ---------------------------------- // Public functions // ---------------------------------- RealType location() const { return m_location; } RealType scale() const { return m_scale; } // ---------------------------------------------- // CONCEPT #2 // Centralized checking of parameters in a member // function. // // This function is called in the constructor, // as well as in the () operator. // // This function cannot be "const" as it might // store (cache) checking results in private data. // // We pass result by reference instead of a pointer // to ensure that is has a valid adres. // ---------------------------------------------- bool check_parameters(const char* function, RealType& result, const Policy& pol) { if(false == detail::check_scale(function, m_scale, &result, pol)) return false; if(false == detail::check_location(function, m_location, &result, pol)) return false; return true; } private: RealType m_location; RealType m_scale; }; // class laplace_distribution // // Convenient type synonym // typedef laplace_distribution laplace; // // Non member functions // template inline const std::pair range(const laplace_distribution& /*dist*/) { using boost::math::tools::max_value; return std::pair(-max_value(), max_value()); } template inline const std::pair support(const laplace_distribution&) { using boost::math::tools::max_value; return std::pair(-max_value(), max_value()); } template inline RealType pdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument RealType result; const char* function = "boost::math::pdf(boost::math::pdf(const laplace_distribution<%1%>&, %1%))"; if(false == detail::check_x(function, x, &result, Policy())) return result; // ---------------------------------------------- // CONCEPT #3 // // If annon-member functions need to check parameters // it can use a simular syntax as it does for checking // function arguments: // // CHECK ARG -> if (false == detail::check_x( function, x, &result, Policy())) return result; // CHECK DIST -> if (false == dist.check_parameters(function, &result, Policy())) return result; // ---------------------------------------------- // Pdf boundary values if((boost::math::isinf)(x)) return 0; // pdf + and - infinity is zero. // Pdf interval values 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 inline RealType cdf(const laplace_distribution& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument RealType result; const char* function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)"; if(false == detail::check_x(function, x, &result, Policy())) return result; // Special cdf values if((boost::math::isinf)(x)) { if(x < 0) return 0; // -infinity return 1; // + infinity } // Cdf interval 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 inline RealType quantile(const laplace_distribution& dist, const RealType& p) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument RealType result; const char* function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)"; if(false == detail::check_probability(function, p, &result, Policy())) return result; // Calculate Quantile RealType scale = dist.scale(); RealType location = dist.location(); if (p - 0.5 < 0) result = location + scale*(p - 0.5) * log(2*p); else result = location - scale*(p - 0.5) * log(2 - 2*p); return result; } // quantile template inline RealType cdf(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument RealType result; const char* function = "boost::math::cdf(const complemented2_type, %1%>&)"; if(false == detail::check_x(function, x, &result, Policy()))return result; // Calculate cdf RealType scale = dist.scale(); RealType location = dist.location(); RealType x = c.param; // Special cdf value if((boost::math::isinf)(x)) { if(x < 0) return 1; // cdf complement -infinity is unity. return 0; // cdf complement +infinity is zero } // Cdf interval value if (x < location) result = 1 - exp( (x-location)/scale )/2; else result = exp( (location-x)/scale )/2; return result; } // cdf complement template inline RealType quantile(const complemented2_type, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions // Checking function argument RealType result; const char* function = "quantile(const complemented2_type, %1%>&)"; if(false == detail::check_probability(function, q, &result, Policy())) return result; // Calculate quantile RealType sd = c.dist.standard_deviation(); RealType mean = c.dist.mean(); RealType q = c.param; if (0.5 - q < 0) result = location + scale*(0.5 - q) * log(2 - q); else result = location - scale*(0.5 - q) * log(2 * q); return result; } // quantile template inline RealType mean(const laplace_distribution& dist) { return dist.location(); } template inline RealType standard_deviation(const laplace_distribution& dist) { return constants::root_two() * dist.scale(); } template inline RealType mode(const laplace_distribution& dist) { return dist.location(); } template inline RealType median(const laplace_distribution& dist) { return dist.location(); } template inline RealType skewness(const laplace_distribution& /*dist*/) { return 0; } template inline RealType kurtosis(const laplace_distribution& /*dist*/) { return 6; } template inline RealType kurtosis_excess(const laplace_distribution& /*dist*/) { return 3; } } // 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 #endif // BOOST_STATS_LAPLACE_HPP