// (C) Copyright Matt Borland 2022 // 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_STATISTICS_DETAIL_RANK_HPP #define BOOST_MATH_STATISTICS_DETAIL_RANK_HPP #include #include #include #include #include #include #include #ifdef BOOST_MATH_EXEC_COMPATIBLE #include #endif namespace boost { namespace math { namespace statistics { namespace detail { struct pair_equal { template bool operator()(const std::pair& a, const std::pair& b) const { return a.first == b.first; } }; }}}} // Namespaces #ifndef BOOST_MATH_EXEC_COMPATIBLE namespace boost { namespace math { namespace statistics { namespace detail { template ::value_type> auto rank(ForwardIterator first, ForwardIterator last) -> std::vector { std::size_t elements = std::distance(first, last); std::vector> rank_vector(elements); std::size_t i = 0; while (first != last) { rank_vector[i] = std::make_pair(*first, i); ++i; ++first; } std::sort(rank_vector.begin(), rank_vector.end()); // Remove duplicates rank_vector.erase(std::unique(rank_vector.begin(), rank_vector.end(), pair_equal()), rank_vector.end()); elements = rank_vector.size(); std::pair rank; std::vector result(elements); for (i = 0; i < elements; ++i) { if (rank_vector[i].first != rank.first) { rank = std::make_pair(rank_vector[i].first, i); } result[rank_vector[i].second] = rank.second; } return result; } template inline auto rank(const Container& c) -> std::vector { return rank(std::begin(c), std::end(c)); } }}}} // Namespaces #else namespace boost::math::statistics::detail { template ::value_type> auto rank(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last) { std::size_t elements = std::distance(first, last); std::vector> rank_vector(elements); std::size_t i = 0; while (first != last) { rank_vector[i] = std::make_pair(*first, i); ++i; ++first; } std::sort(exec, rank_vector.begin(), rank_vector.end()); // Remove duplicates rank_vector.erase(std::unique(exec, rank_vector.begin(), rank_vector.end(), pair_equal()), rank_vector.end()); elements = rank_vector.size(); std::pair rank; std::vector result(elements); for (i = 0; i < elements; ++i) { if (rank_vector[i].first != rank.first) { rank = std::make_pair(rank_vector[i].first, i); } result[rank_vector[i].second] = rank.second; } return result; } template inline auto rank(ExecutionPolicy&& exec, const Container& c) { return rank(exec, std::cbegin(c), std::cend(c)); } template ::value_type> inline auto rank(ForwardIterator first, ForwardIterator last) { return rank(std::execution::seq, first, last); } template inline auto rank(const Container& c) { return rank(std::execution::seq, std::cbegin(c), std::cend(c)); } } // Namespaces #endif // BOOST_MATH_EXEC_COMPATIBLE #endif // BOOST_MATH_STATISTICS_DETAIL_RANK_HPP