diff --git a/include/oneapi/dpl/pstl/algorithm_ranges_impl.h b/include/oneapi/dpl/pstl/algorithm_ranges_impl.h index 6845282fe08..e17a9556750 100644 --- a/include/oneapi/dpl/pstl/algorithm_ranges_impl.h +++ b/include/oneapi/dpl/pstl/algorithm_ranges_impl.h @@ -482,7 +482,7 @@ __pattern_min(_Tag __tag, _ExecutionPolicy&& __exec, _R&& __r, _Comp __comp, _Pr //--------------------------------------------------------------------------------------------------------------------- template -auto +std::pair, oneapi::dpl::__ranges::__iterator_t<_R>> __pattern_minmax_element(_Tag __tag, _ExecutionPolicy&& __exec, _R&& __r, _Comp __comp, _Proj __proj) { static_assert(__is_parallel_tag_v<_Tag> || typename _Tag::__is_vector{}); @@ -495,11 +495,12 @@ __pattern_minmax_element(_Tag __tag, _ExecutionPolicy&& __exec, _R&& __r, _Comp } template -auto +std::pair, oneapi::dpl::__ranges::__iterator_t<_R>> __pattern_minmax_element(__serial_tag, _ExecutionPolicy&&, _R&& __r, _Comp __comp, _Proj __proj) { - return std::ranges::minmax_element(std::forward<_R>(__r), __comp, __proj); + auto __res = std::ranges::minmax_element(std::forward<_R>(__r), __comp, __proj); + return {__res.min, __res.max}; } //--------------------------------------------------------------------------------------------------------------------- @@ -511,7 +512,7 @@ std::pair, std::ranges::range_value_t<_R>> __pattern_minmax(_Tag __tag, _ExecutionPolicy&& __exec, _R&& __r, _Comp __comp, _Proj __proj) { auto [__it_min, __it_max] = - __pattern_minmax_element(__tag, std::forward<_ExecutionPolicy>(__exec), std::forward<_R>(__r), __comp, __proj); + __pattern_minmax_element(__tag, std::forward<_ExecutionPolicy>(__exec), __r, __comp, __proj); return {*__it_min, *__it_max}; } diff --git a/include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h b/include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h index c75cc0d4f26..5c35f856771 100644 --- a/include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h +++ b/include/oneapi/dpl/pstl/glue_algorithm_ranges_impl.h @@ -617,11 +617,12 @@ struct __minmax_element_fn operator()(_ExecutionPolicy&& __exec, _R&& __r, _Comp __comp = {}, _Proj __proj = {}) const { const auto __dispatch_tag = oneapi::dpl::__ranges::__select_backend(__exec); - const auto& [__min, __max] = - oneapi::dpl::__internal::__ranges::__pattern_minmax_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), - std::forward<_R>(__r), __comp, __proj); - return {__min, __max}; + std::pair, oneapi::dpl::__ranges::__iterator_t<_R>> __res = + oneapi::dpl::__internal::__ranges::__pattern_minmax_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __r, __comp, __proj); + + return {__res.first, __res.second}; } }; //__minmax_element_fn } //__internal @@ -2031,9 +2032,14 @@ minmax_element(_ExecutionPolicy&& __exec, _Range&& __rng, _Compare __comp) { const auto __dispatch_tag = oneapi::dpl::__ranges::__select_backend(__exec, __rng); - return oneapi::dpl::__internal::__ranges::__pattern_minmax_element( - __dispatch_tag, ::std::forward<_ExecutionPolicy>(__exec), views::all_read(::std::forward<_Range>(__rng)), - __comp); + auto __view = views::all_read(std::forward<_Range>(__rng)); + auto __v_begin = __view.begin(); + using __v_iterator_t = decltype(__v_begin); + + std::pair<__v_iterator_t, __v_iterator_t> __res = oneapi::dpl::__internal::__ranges::__pattern_minmax_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __view, __comp); + + return {std::distance(__v_begin, __res.first), std::distance(__v_begin, __res.second)}; } template diff --git a/include/oneapi/dpl/pstl/hetero/algorithm_ranges_impl_hetero.h b/include/oneapi/dpl/pstl/hetero/algorithm_ranges_impl_hetero.h index ba83c1cac75..d6f125a094d 100644 --- a/include/oneapi/dpl/pstl/hetero/algorithm_ranges_impl_hetero.h +++ b/include/oneapi/dpl/pstl/hetero/algorithm_ranges_impl_hetero.h @@ -1244,7 +1244,7 @@ __pattern_min_element_impl(_BackendTag __tag, _ExecutionPolicy&& __exec, _Range& { assert(oneapi::dpl::__ranges::__size(__rng) > 0); - using _IteratorValueType = typename ::std::iterator_traits::value_type; + using _IteratorValueType = oneapi::dpl::__internal::__value_t<_Range>; using _IndexValueType = oneapi::dpl::__internal::__difference_t<_Range>; using _ReduceValueType = oneapi::dpl::__internal::tuple<_IndexValueType, _IteratorValueType>; @@ -1312,14 +1312,21 @@ __pattern_min(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _R&& __r, _C // minmax_element //------------------------------------------------------------------------ +template +using __range_index_and_value = + std::pair, oneapi::dpl::__internal::__value_t<_Range>>; + +template +using __pattern_minmax_element_impl_return_t = + std::pair<__range_index_and_value<_Range>, __range_index_and_value<_Range>>; + template -std::pair, oneapi::dpl::__internal::__value_t<_Range>>, - std::pair, oneapi::dpl::__internal::__value_t<_Range>>> +__pattern_minmax_element_impl_return_t<_Range> __pattern_minmax_element_impl(_BackendTag, _ExecutionPolicy&& __exec, _Range&& __rng, _Compare __comp) { assert(oneapi::dpl::__ranges::__size(__rng) > 0); - using _IteratorValueType = typename ::std::iterator_traits::value_type; + using _IteratorValueType = oneapi::dpl::__internal::__value_t<_Range>; using _IndexValueType = oneapi::dpl::__internal::__difference_t<_Range>; using _ReduceValueType = oneapi::dpl::__internal::tuple<_IndexValueType, _IndexValueType, _IteratorValueType, _IteratorValueType>; @@ -1333,7 +1340,7 @@ __pattern_minmax_element_impl(_BackendTag, _ExecutionPolicy&& __exec, _Range&& _ // a `tuple` of `difference_type`, not the `difference_type` itself. oneapi::dpl::__internal::__pattern_minmax_element_transform_fn<_ReduceValueType> __transform_fn; - const auto& [__idx_min, __idx_max, __min, __max] = + const auto& [__idx_min, __idx_max, __val_min, __val_max] = oneapi::dpl::__par_backend_hetero::__parallel_transform_reduce<_ReduceValueType, ::std::false_type /*is_commutative*/>( _BackendTag{}, ::std::forward<_ExecutionPolicy>(__exec), __reduce_fn, __transform_fn, @@ -1341,40 +1348,44 @@ __pattern_minmax_element_impl(_BackendTag, _ExecutionPolicy&& __exec, _Range&& _ oneapi::dpl::__ranges::__get_subscription_view(std::forward<_Range>(__rng))) .get(); - return {{__idx_min, __min}, {__idx_max, __max}}; + return {{__idx_min, __val_min}, {__idx_max, __val_max}}; } template -std::pair, oneapi::dpl::__internal::__difference_t<_Range>> +std::pair, oneapi::dpl::__ranges::__iterator_t<_Range>> __pattern_minmax_element(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Range&& __rng, _Compare __comp) { + auto __begin = oneapi::dpl::__ranges::__begin(__rng); + //If size == 1, result is the zero-indexed element. If size == 0, result is 0. if (oneapi::dpl::__ranges::__size(__rng) < 2) - return {0, 0}; - - [[maybe_unused]] const auto& [__res_min, __res_max] = __pattern_minmax_element_impl( - _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), - oneapi::dpl::__ranges::__get_subscription_view(std::forward<_Range>(__rng)), __comp); + return {__begin, __begin}; - [[maybe_unused]] const auto& [__idx_min, __min] = __res_min; - [[maybe_unused]] const auto& [__idx_max, __max] = __res_max; + __pattern_minmax_element_impl_return_t<_Range> __res = + __pattern_minmax_element_impl(_BackendTag{}, std::forward<_ExecutionPolicy>(__exec), __rng, __comp); - return {__idx_min, __idx_max}; + return {__begin + __res.first.first, __begin + __res.second.first}; } #if _ONEDPL_CPP20_RANGES_PRESENT template -std::pair, std::ranges::borrowed_iterator_t<_R>> +std::pair, std::ranges::iterator_t<_R>> __pattern_minmax_element(__hetero_tag<_BackendTag> __tag, _ExecutionPolicy&& __exec, _R&& __r, _Comp __comp, _Proj __proj) { oneapi::dpl::__internal::__binary_op<_Comp, _Proj, _Proj> __comp_2{__comp, __proj, __proj}; - const auto [__min_idx, __max_idx] = - oneapi::dpl::__internal::__ranges::__pattern_minmax_element(__tag, std::forward<_ExecutionPolicy>(__exec), - oneapi::dpl::__ranges::views::all_read(__r), __comp_2); + auto __r_begin = __r.begin(); + + auto __view = oneapi::dpl::__ranges::views::all_read(__r); + auto __v_begin = __view.begin(); + using __v_iterator_t = decltype(__v_begin); - return {std::ranges::begin(__r) + __min_idx, std::ranges::begin(__r) + __max_idx}; + std::pair<__v_iterator_t, __v_iterator_t> __res = oneapi::dpl::__internal::__ranges::__pattern_minmax_element( + __tag, std::forward<_ExecutionPolicy>(__exec), __view, __comp_2); + + return {__r_begin + std::ranges::distance(__v_begin, __res.first), + __r_begin + std::ranges::distance(__v_begin, __res.second)}; } template @@ -1383,14 +1394,10 @@ __pattern_minmax(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _R&& __r, { oneapi::dpl::__internal::__binary_op<_Comp, _Proj, _Proj> __comp_2{__comp, __proj, __proj}; - [[maybe_unused]] const auto& [__res_min, __res_max] = - __pattern_minmax_element_impl(_BackendTag{}, std::forward<_ExecutionPolicy>(__exec), - oneapi::dpl::__ranges::__get_subscription_view(std::forward<_R>(__r)), __comp_2); - - [[maybe_unused]] const auto& [__idx_min, __min] = __res_min; - [[maybe_unused]] const auto& [__idx_max, __max] = __res_max; + __pattern_minmax_element_impl_return_t<_R> __res = __pattern_minmax_element_impl( + _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), std::forward<_R>(__r), __comp_2); - return {__min, __max}; + return {__res.first.second, __res.second.second}; } template -bool -__empty(_Range&& __rng) +auto +__begin(_Range&& __rng) { - return std::ranges::empty(__rng); +#if _ONEDPL_CPP20_RANGES_PRESENT + return std::ranges::begin(__rng); +#else + return __rng.begin(); +#endif } + +template +auto +__end(_Range&& __rng) +{ +#if _ONEDPL_CPP20_RANGES_PRESENT + return std::ranges::end(__rng); #else + return __rng.end(); +#endif +} + +template +using __iterator_t = decltype(__begin(std::declval<_Range&>())); + template -struct __has_empty : std::false_type +struct __has_size : std::false_type { }; template -struct __has_empty<_R, std::void_t().empty())>> : std::true_type +struct __has_size<_R, std::void_t().size())>> : std::true_type { }; template -bool -__empty(_Range&& __rng) +auto +__size(_Range&& __rng) { - if constexpr (__has_empty<_Range>::value) - return __rng.empty(); +#if _ONEDPL_CPP20_RANGES_PRESENT + return std::ranges::size(__rng); +#else + if constexpr (__has_size<_Range>::value) + return __rng.size(); else - return __rng.begin() == __rng.end(); -} + return std::distance(__begin(__rng), __end(__rng)); #endif +} template -struct __has_size : std::false_type +struct __has_empty : std::false_type { }; template -struct __has_size<_R, std::void_t().size())>> : std::true_type +struct __has_empty<_R, std::void_t().empty())>> : std::true_type { }; template -std::enable_if_t<__has_size<_Range>::value, decltype(std::declval<_Range>().size())> -__size(_Range&& __rng) +bool +__empty(_Range&& __rng) { - return __rng.size(); -} - #if _ONEDPL_CPP20_RANGES_PRESENT -template -std::enable_if_t::value, - decltype(std::ranges::distance(std::declval<_Range>().begin(), std::declval<_Range>().end()))> -__size(_Range&& __rng) -{ - return std::ranges::distance(__rng.begin(), __rng.end()); -} + return std::ranges::empty(__rng); #else -template -std::enable_if_t::value, - decltype(std::distance(std::declval<_Range>().begin(), std::declval<_Range>().end()))> -__size(_Range&& __rng) -{ - return std::distance(__rng.begin(), __rng.end()); -} + if constexpr (__has_empty<_Range>::value) + return __rng.empty(); + else + return __size(__rng) == 0; #endif +} template using __common_size_t = std::common_type_t()))>...>; template -struct __nth_range_size +class __nth_range_size { - private: template auto __nth_range_size_impl(const _Range& __rng, const _Ranges&... __rngs) const @@ -754,13 +762,13 @@ struct __subscription_impl_view_simple : _Base decltype(auto) operator[](index_type __i) { - return *std::next(_Base::begin(), __i); + return *std::next(__begin(*static_cast<_Base*>(this)), __i); } decltype(auto) operator[](index_type __i) const { - return *std::next(_Base::begin(), __i); + return *std::next(__begin(*static_cast(this)), __i); } }; @@ -769,13 +777,9 @@ decltype(auto) __get_subscription_view(_Range&& __rng) { if constexpr (__has_subscription_op<_Range>::value) - { return std::forward<_Range>(__rng); - } else - { return __subscription_impl_view_simple<_Range>(std::forward<_Range>(__rng)); - } } } // namespace __ranges