@@ -870,6 +870,190 @@ sycl::event count_if(sycl::queue &q, util::allocation_group &scratch_allocations
870
870
deps);
871
871
}
872
872
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
+
873
1057
template <class ForwardIt1 , class ForwardIt2 >
874
1058
sycl::event equal (sycl::queue &q,
875
1059
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
0 commit comments