| // Copyright Nick Thompson 2019. |
| // 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) |
| |
| #ifndef BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP |
| #define BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP |
| #include <algorithm> |
| #include <iterator> |
| #include <stdexcept> |
| #include <type_traits> |
| #include <utility> |
| |
| #include <boost/math/tools/is_standalone.hpp> |
| #ifndef BOOST_MATH_STANDALONE |
| #include <boost/config.hpp> |
| #ifdef BOOST_MATH_NO_CXX17_IF_CONSTEXPR |
| #error "The header <boost/math/norms.hpp> can only be used in C++17 and later." |
| #endif |
| #endif |
| |
| namespace boost { namespace math{ |
| |
| template<class RandomAccessContainer> |
| class empirical_cumulative_distribution_function { |
| using Real = typename RandomAccessContainer::value_type; |
| public: |
| empirical_cumulative_distribution_function(RandomAccessContainer && v, bool sorted = false) |
| { |
| if (v.size() == 0) { |
| throw std::domain_error("At least one sample is required to compute an empirical CDF."); |
| } |
| m_v = std::move(v); |
| if (!sorted) { |
| std::sort(m_v.begin(), m_v.end()); |
| } |
| } |
| |
| auto operator()(Real x) const { |
| if constexpr (std::is_integral_v<Real>) |
| { |
| if (x < m_v[0]) { |
| return static_cast<double>(0); |
| } |
| if (x >= m_v[m_v.size()-1]) { |
| return static_cast<double>(1); |
| } |
| auto it = std::upper_bound(m_v.begin(), m_v.end(), x); |
| return static_cast<double>(std::distance(m_v.begin(), it))/static_cast<double>(m_v.size()); |
| } |
| else |
| { |
| if (x < m_v[0]) { |
| return Real(0); |
| } |
| if (x >= m_v[m_v.size()-1]) { |
| return Real(1); |
| } |
| auto it = std::upper_bound(m_v.begin(), m_v.end(), x); |
| return static_cast<Real>(std::distance(m_v.begin(), it))/static_cast<Real>(m_v.size()); |
| } |
| } |
| |
| RandomAccessContainer&& return_data() { |
| return std::move(m_v); |
| } |
| |
| private: |
| RandomAccessContainer m_v; |
| }; |
| |
| }} |
| #endif |