empirical_cumulative_distribution_function.hpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // Copyright Nick Thompson 2019.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP
  6. #define BOOST_MATH_DISTRIBUTIONS_EMPIRICAL_CUMULATIVE_DISTRIBUTION_FUNCTION_HPP
  7. #include <algorithm>
  8. #include <iterator>
  9. #include <stdexcept>
  10. namespace boost { namespace math{
  11. template<class RandomAccessContainer>
  12. class empirical_cumulative_distribution_function {
  13. using Real = typename RandomAccessContainer::value_type;
  14. public:
  15. empirical_cumulative_distribution_function(RandomAccessContainer && v, bool sorted = false)
  16. {
  17. if (v.size() == 0) {
  18. throw std::domain_error("At least one sample is required to compute an empirical CDF.");
  19. }
  20. m_v = std::move(v);
  21. if (!sorted) {
  22. std::sort(m_v.begin(), m_v.end());
  23. }
  24. }
  25. auto operator()(Real x) const {
  26. if constexpr (std::is_integral_v<Real>)
  27. {
  28. if (x < m_v[0]) {
  29. return double(0);
  30. }
  31. if (x >= m_v[m_v.size()-1]) {
  32. return double(1);
  33. }
  34. auto it = std::upper_bound(m_v.begin(), m_v.end(), x);
  35. return static_cast<double>(std::distance(m_v.begin(), it))/static_cast<double>(m_v.size());
  36. }
  37. else
  38. {
  39. if (x < m_v[0]) {
  40. return Real(0);
  41. }
  42. if (x >= m_v[m_v.size()-1]) {
  43. return Real(1);
  44. }
  45. auto it = std::upper_bound(m_v.begin(), m_v.end(), x);
  46. return static_cast<Real>(std::distance(m_v.begin(), it))/static_cast<Real>(m_v.size());
  47. }
  48. }
  49. RandomAccessContainer&& return_data() {
  50. return std::move(m_v);
  51. }
  52. private:
  53. RandomAccessContainer m_v;
  54. };
  55. }}
  56. #endif