@@ -870,6 +870,190 @@ sycl::event count_if(sycl::queue &q, util::allocation_group &scratch_allocations
870870 deps);
871871}
872872
873+ template <class ForwardIt >
874+ sycl::event
875+ min_element (sycl::queue &q, util::allocation_group &scratch_allocations,
876+ ForwardIt first, ForwardIt last,
877+ std::pair<ForwardIt, typename
878+ std::iterator_traits<ForwardIt>::value_type> *out,
879+ const std::vector<sycl::event> &deps= {}) {
880+ auto problem_size = std::distance (first, last);
881+ if (problem_size == 0 )
882+ return sycl::event{};
883+
884+ using ValueT = typename std::iterator_traits<ForwardIt>::value_type;
885+ using MinPair = std::pair<ForwardIt, ValueT>;
886+
887+ auto kernel = [=](sycl::id<1 > idx, auto & reducer) {
888+ auto input = first;
889+ std::advance (input, idx[0 ]);
890+ MinPair p = std::make_pair (input, *input);
891+ reducer.combine (p);
892+ };
893+
894+ auto reduce = [first] (MinPair a, MinPair b) {
895+ // Preserve strict total order over two equivalent
896+ // pointers, i.e. return the element that appears
897+ // in the sequence nearest to first.
898+ if (!(a.second < b.second ) && !(b.second < a.second )) {
899+ if (std::distance (first, a.first ) < std::distance (first, b.first ))
900+ return a;
901+ else
902+ return b;
903+ }
904+ #if __cplusplus < 202002L
905+ else if (a.second < b.second )
906+ #else
907+ else if (std::less{}(a.second , b.second ))
908+ #endif
909+ return a;
910+ else
911+ return b;
912+ };
913+
914+ MinPair init = std::make_pair (first, *first);
915+
916+ return detail::transform_reduce_impl (q, scratch_allocations, out, init,
917+ problem_size, kernel, reduce, deps);
918+ }
919+
920+ template <class ForwardIt , class Compare >
921+ sycl::event
922+ min_element (sycl::queue &q, util::allocation_group &scratch_allocations,
923+ ForwardIt first, ForwardIt last, Compare comp,
924+ std::pair<ForwardIt, typename
925+ std::iterator_traits<ForwardIt>::value_type> *out,
926+ const std::vector<sycl::event> &deps= {}) {
927+ auto problem_size = std::distance (first, last);
928+ if (problem_size == 0 )
929+ return sycl::event{};
930+
931+ using ValueT = typename std::iterator_traits<ForwardIt>::value_type;
932+ using MinPair = std::pair<ForwardIt, ValueT>;
933+
934+ auto kernel = [=](sycl::id<1 > idx, auto & reducer) {
935+ auto input = first;
936+ std::advance (input, idx[0 ]);
937+ MinPair p = std::make_pair (input, *input);
938+ reducer.combine (p);
939+ };
940+
941+ auto reduce = [comp, first] (MinPair a, MinPair b) {
942+ // Comp used for associative containers must always
943+ // return false for equal values. (Effective STL, Item 21)
944+ // In cases where it does not (for eg. std::less_equal),
945+ // implementation aligns behaviour to libstdc++, returning
946+ // the element furthest from first.
947+ if (std::distance (first, a.first ) < std::distance (first, b.first ))
948+ if (comp (b.second , a.second ) == false )
949+ return a;
950+ else
951+ return b;
952+ else
953+ if (comp (a.second , b.second ) == false )
954+ return b;
955+ else
956+ return a;
957+ };
958+
959+ MinPair init = std::make_pair (first, *first);
960+
961+ return detail::transform_reduce_impl (q, scratch_allocations, out, init,
962+ problem_size, kernel, reduce, deps);
963+ }
964+
965+ template <class ForwardIt >
966+ sycl::event
967+ max_element (sycl::queue &q, util::allocation_group &scratch_allocations,
968+ ForwardIt first, ForwardIt last,
969+ std::pair<ForwardIt, typename
970+ std::iterator_traits<ForwardIt>::value_type> *out,
971+ const std::vector<sycl::event> &deps= {}) {
972+ auto problem_size = std::distance (first, last);
973+ if (problem_size == 0 )
974+ return sycl::event{};
975+
976+ using ValueT = typename std::iterator_traits<ForwardIt>::value_type;
977+ using MaxPair = std::pair<ForwardIt, ValueT>;
978+
979+ auto kernel = [=](sycl::id<1 > idx, auto & reducer) {
980+ auto input = first;
981+ std::advance (input, idx[0 ]);
982+ MaxPair p = std::make_pair (input, *input);
983+ reducer.combine (p);
984+ };
985+
986+ auto reduce = [first] (MaxPair a, MaxPair b) {
987+ // Preserve strict total order over two equivalent
988+ // pointers, i.e. return the element that appears
989+ // in the sequence nearest to first.
990+ if (!(a.second < b.second ) && !(b.second < a.second )) {
991+ if (std::distance (first, a.first ) < std::distance (first, b.first ))
992+ return a;
993+ else
994+ return b;
995+ }
996+ #if __cplusplus < 202002L
997+ else if (a.second < b.second )
998+ #else
999+ else if (std::less{}(a.second , b.second ))
1000+ #endif
1001+ return b;
1002+ else
1003+ return a;
1004+ };
1005+
1006+ MaxPair init = std::make_pair (first, *first);
1007+
1008+ return detail::transform_reduce_impl (q, scratch_allocations, out, init,
1009+ problem_size, kernel, reduce, deps);
1010+ }
1011+
1012+ template <class ForwardIt , class Compare >
1013+ sycl::event
1014+ max_element (sycl::queue &q, util::allocation_group &scratch_allocations,
1015+ ForwardIt first, ForwardIt last, Compare comp,
1016+ std::pair<ForwardIt, typename
1017+ std::iterator_traits<ForwardIt>::value_type> *out,
1018+ const std::vector<sycl::event> &deps= {}) {
1019+ auto problem_size = std::distance (first, last);
1020+ if (problem_size == 0 )
1021+ return sycl::event{};
1022+
1023+ using ValueT = typename std::iterator_traits<ForwardIt>::value_type;
1024+ using MaxPair = std::pair<ForwardIt, ValueT>;
1025+
1026+ auto kernel = [=](sycl::id<1 > idx, auto & reducer) {
1027+ auto input = first;
1028+ std::advance (input, idx[0 ]);
1029+ MaxPair p = std::make_pair (input, *input);
1030+ reducer.combine (p);
1031+ };
1032+
1033+ auto reduce = [comp, first] (MaxPair a, MaxPair b) {
1034+ // Comp used for associative containers must always
1035+ // return false for equal values. (Effective STL, Item 21)
1036+ // In cases where it does not (for eg. std::less_equal),
1037+ // implementation aligns behaviour to libstdc++, returning
1038+ // the element furthest from first.
1039+ if (std::distance (first, a.first ) < std::distance (first, b.first ))
1040+ if (comp (a.second , b.second ) == false )
1041+ return a;
1042+ else
1043+ return b;
1044+ else
1045+ if (comp (b.second , a.second ) == false )
1046+ return b;
1047+ else
1048+ return a;
1049+ };
1050+
1051+ MaxPair init = std::make_pair (first, *first);
1052+
1053+ return detail::transform_reduce_impl (q, scratch_allocations, out, init,
1054+ problem_size, kernel, reduce, deps);
1055+ }
1056+
8731057template <class ForwardIt1 , class ForwardIt2 >
8741058sycl::event equal (sycl::queue &q,
8751059 ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
0 commit comments