File indexing completed on 2024-11-16 09:19:18
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MATH_STATISTICS_DETAIL_RANK_HPP
0007 #define BOOST_MATH_STATISTICS_DETAIL_RANK_HPP
0008
0009 #include <cstdint>
0010 #include <vector>
0011 #include <numeric>
0012 #include <utility>
0013 #include <iterator>
0014 #include <algorithm>
0015 #include <boost/math/tools/config.hpp>
0016
0017 #ifdef BOOST_MATH_EXEC_COMPATIBLE
0018 #include <execution>
0019 #endif
0020
0021 namespace boost { namespace math { namespace statistics { namespace detail {
0022
0023 struct pair_equal
0024 {
0025 template <typename T1, typename T2>
0026 bool operator()(const std::pair<T1, T2>& a, const std::pair<T1, T2>& b) const
0027 {
0028 return a.first == b.first;
0029 }
0030 };
0031
0032 }}}}
0033
0034 #ifndef BOOST_MATH_EXEC_COMPATIBLE
0035
0036 namespace boost { namespace math { namespace statistics { namespace detail {
0037
0038 template <typename ForwardIterator, typename T = typename std::iterator_traits<ForwardIterator>::value_type>
0039 auto rank(ForwardIterator first, ForwardIterator last) -> std::vector<std::size_t>
0040 {
0041 std::size_t elements = std::distance(first, last);
0042
0043 std::vector<std::pair<T, std::size_t>> rank_vector(elements);
0044 std::size_t i = 0;
0045 while (first != last)
0046 {
0047 rank_vector[i] = std::make_pair(*first, i);
0048 ++i;
0049 ++first;
0050 }
0051
0052 std::sort(rank_vector.begin(), rank_vector.end());
0053
0054
0055 rank_vector.erase(std::unique(rank_vector.begin(), rank_vector.end(), pair_equal()), rank_vector.end());
0056 elements = rank_vector.size();
0057
0058 std::pair<T, std::size_t> rank;
0059 std::vector<std::size_t> result(elements);
0060 for (i = 0; i < elements; ++i)
0061 {
0062 if (rank_vector[i].first != rank.first)
0063 {
0064 rank = std::make_pair(rank_vector[i].first, i);
0065 }
0066 result[rank_vector[i].second] = rank.second;
0067 }
0068
0069 return result;
0070 }
0071
0072 template <typename Container>
0073 inline auto rank(const Container& c) -> std::vector<std::size_t>
0074 {
0075 return rank(std::begin(c), std::end(c));
0076 }
0077
0078 }}}}
0079
0080 #else
0081
0082 namespace boost::math::statistics::detail {
0083
0084 template <typename ExecutionPolicy, typename ForwardIterator, typename T = typename std::iterator_traits<ForwardIterator>::value_type>
0085 auto rank(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last)
0086 {
0087 std::size_t elements = std::distance(first, last);
0088
0089 std::vector<std::pair<T, std::size_t>> rank_vector(elements);
0090 std::size_t i = 0;
0091 while (first != last)
0092 {
0093 rank_vector[i] = std::make_pair(*first, i);
0094 ++i;
0095 ++first;
0096 }
0097
0098 std::sort(exec, rank_vector.begin(), rank_vector.end());
0099
0100
0101 rank_vector.erase(std::unique(exec, rank_vector.begin(), rank_vector.end(), pair_equal()), rank_vector.end());
0102 elements = rank_vector.size();
0103
0104 std::pair<T, std::size_t> rank;
0105 std::vector<std::size_t> result(elements);
0106 for (i = 0; i < elements; ++i)
0107 {
0108 if (rank_vector[i].first != rank.first)
0109 {
0110 rank = std::make_pair(rank_vector[i].first, i);
0111 }
0112 result[rank_vector[i].second] = rank.second;
0113 }
0114
0115 return result;
0116 }
0117
0118 template <typename ExecutionPolicy, typename Container>
0119 inline auto rank(ExecutionPolicy&& exec, const Container& c)
0120 {
0121 return rank(exec, std::cbegin(c), std::cend(c));
0122 }
0123
0124 template <typename ForwardIterator, typename T = typename std::iterator_traits<ForwardIterator>::value_type>
0125 inline auto rank(ForwardIterator first, ForwardIterator last)
0126 {
0127 return rank(std::execution::seq, first, last);
0128 }
0129
0130 template <typename Container>
0131 inline auto rank(const Container& c)
0132 {
0133 return rank(std::execution::seq, std::cbegin(c), std::cend(c));
0134 }
0135
0136 }
0137
0138 #endif
0139
0140 #endif