diff --git a/include/boost/math/statistics/bivariate_statistics.hpp b/include/boost/math/statistics/bivariate_statistics.hpp index e94cefc354..d6f91faa93 100644 --- a/include/boost/math/statistics/bivariate_statistics.hpp +++ b/include/boost/math/statistics/bivariate_statistics.hpp @@ -323,23 +323,6 @@ ReturnType correlation_coefficient_parallel_impl(ForwardIterator u_begin, Forwar #endif // BOOST_MATH_EXEC_COMPATIBLE -template -ReturnType chatterjee_correlation(ForwardIterator u_begin, ForwardIterator u_end, ForwardIterator v_begin, ForwardIterator v_end) -{ - BOOST_MATH_ASSERT_MSG(std::is_sorted(u_begin, u_end), "Data set must be sorted in order to calculate the chatterjee correlation."); - - const auto rank_vector = rank(v_begin, v_end); - - std::size_t sum = 0; - for (std::size_t i = 1; i < rank_vector.size(); ++i) - { - // avoids unsigned underflow even though the result will always be >= 0 - sum += rank_vector[i] > rank_vector[i-1] ? rank_vector[i] - rank_vector[i-1] : rank_vector[i-1] - rank_vector[i]; - } - - return static_cast(1) - static_cast(3 * sum) / static_cast(rank_vector.size() - 1); -} - } // namespace detail #ifdef BOOST_MATH_EXEC_COMPATIBLE diff --git a/include/boost/math/statistics/chatterjee_correlation.hpp b/include/boost/math/statistics/chatterjee_correlation.hpp index 833ecd64f7..7aab06fc73 100644 --- a/include/boost/math/statistics/chatterjee_correlation.hpp +++ b/include/boost/math/statistics/chatterjee_correlation.hpp @@ -12,11 +12,18 @@ #include #include #include +#include #include #include #include #include +#ifdef BOOST_MATH_EXEC_COMPATIBLE +#include +#include +#include +#endif + namespace boost { namespace math { namespace statistics { namespace detail { @@ -26,7 +33,7 @@ ReturnType chatterjee_correlation_seq_impl(ForwardIterator u_begin, ForwardItera { using std::abs; - BOOST_MATH_ASSERT_MSG(std::is_sorted(u_begin, u_end), "The x values must be sorted in order to use this funtionality"); + BOOST_MATH_ASSERT_MSG(std::is_sorted(u_begin, u_end), "The x values must be sorted in order to use this functionality"); const std::vector rank_vector = rank(v_begin, v_end); @@ -46,7 +53,7 @@ ReturnType chatterjee_correlation_seq_impl(ForwardIterator u_begin, ForwardItera ReturnType result = static_cast(1) - (static_cast(3 * sum) / static_cast(rank_vector.size() * rank_vector.size() - 1)); - // If the result is 1 then Y is constant and all of the elements must be ties + // If the result is 1 then Y is constant and all the elements must be ties if (abs(result - static_cast(1)) < std::numeric_limits::epsilon()) { return std::numeric_limits::quiet_NaN(); @@ -66,4 +73,70 @@ inline ReturnType chatterjee_correlation(const Container& u, const Container& v) }}} // Namespace boost::math::statistics +#ifdef BOOST_MATH_EXEC_COMPATIBLE + +namespace boost::math::statistics { + +namespace detail { + +template +struct rank_compare_value +{ + Real operator()(Real val_i, Real val_im1) + { + if (val_i > val_im1) + { + return val_i - val_im1; + } + else + { + return val_im1 - val_i; + } + } +}; + +template +ReturnType chatterjee_correlation_par_impl(ExecutionPolicy&& exec, ForwardIterator u_begin, ForwardIterator u_end, + ForwardIterator v_begin, ForwardIterator v_end) +{ + using std::abs; + BOOST_MATH_ASSERT_MSG(std::is_sorted(std::forward(exec), u_begin, u_end), "The x values must be sorted in order to use this functionality"); + + const auto rank_vector = rank(std::forward(exec), v_begin, v_end); + std::size_t sum = std::reduce(std::forward(exec), rank_vector.cbegin() + 1, rank_vector.cend(), rank_compare_value()); + + ReturnType result = static_cast(1) - (static_cast(3 * sum) / static_cast(rank_vector.size() * rank_vector.size() - 1)); + + // If the result is 1 then Y is constant and all the elements must be ties + if (abs(result - static_cast(1)) < std::numeric_limits::epsilon()) + { + return std::numeric_limits::quiet_NaN(); + } + + return result; +} + +} // Namespace detail + +template , double, Real>> +inline ReturnType chatterjee_correlation(ExecutionPolicy&& exec, const Container& u, const Container& v) +{ + if constexpr (std::is_same_v, decltype(std::execution::seq)>) + { + return detail::chatterjee_correlation_seq_impl(std::cbegin(u), std::cend(u), + std::cbegin(v), std::cend(v)); + } + else + { + return detail::chatterjee_correlation_par_impl(std::forward(exec), + std::cbegin(u), std::cend(u), + std::cbegin(v), std::cend(v)); + } +} + +} // Namespace boost::math::statistics + +#endif + #endif // BOOST_MATH_STATISTICS_CHATTERJEE_CORRELATION_HPP diff --git a/include/boost/math/statistics/detail/rank.hpp b/include/boost/math/statistics/detail/rank.hpp index 9157702462..4e5211607e 100644 --- a/include/boost/math/statistics/detail/rank.hpp +++ b/include/boost/math/statistics/detail/rank.hpp @@ -14,6 +14,10 @@ #include #include +#ifdef BOOST_MATH_EXEC_COMPATIBLE +#include +#endif + namespace boost { namespace math { namespace statistics { namespace detail { struct pair_equal @@ -75,8 +79,6 @@ inline auto rank(const Container& c) -> std::vector #else -#include - namespace boost::math::statistics::detail { template ::value_type>