1#ifndef _STDEX_ALGORITHM_H
2#define _STDEX_ALGORITHM_H
9#include "./iterator.hpp"
23 namespace algorithm_cpp11
25#ifndef STDEX_DO_NOT_ADD_CPP11_STD
32 typedef std::size_t size_t;
37 namespace algorithm_cpp11
41 template<
class _InputIt,
class _UnaryPredicate>
43 bool all_of(_InputIt _first,
44 typename detail::_if_iterator_cat_is_input<_InputIt>::type _last, _UnaryPredicate _p)
46 for (; _first != _last; ++_first) {
56 template<
class _InputIt,
class _UnaryPredicate>
58 bool any_of(_InputIt _first,
59 typename detail::_if_iterator_cat_is_input<_InputIt>::type _last, _UnaryPredicate _p)
61 return std::find_if(_first, _last, _p) != _last;
66 template<
class _InputIt,
class _UnaryPredicate>
68 bool none_of(_InputIt _first,
69 typename detail::_if_iterator_cat_is_input<_InputIt>::type _last, _UnaryPredicate _p)
71 for (; _first != _last; ++_first) {
72 if (_p(*_first))
return false;
81 using algorithm_cpp11::all_of;
86 using algorithm_cpp11::any_of;
91 using algorithm_cpp11::none_of;
124 namespace algorithm_cpp11
129 template<
class _InputIt,
class _UnaryPredicate>
131 _InputIt find_if_not(_InputIt _first,
132 typename detail::_if_iterator_cat_is_input<_InputIt>::type _last, _UnaryPredicate _p)
134 for (; _first != _last; ++_first) {
146 using algorithm_cpp11::find_if_not;
154 using std::find_first_of;
158 using std::adjacent_find;
175 template<
class _InputIt,
class _OutputIt>
176 struct _copy_if_args_check :
179 typename std::iterator_traits<_InputIt>::iterator_category,
180 std::input_iterator_tag
181 >::value == bool(true) &&
182 _iterator_cat_is_valid<
183 typename std::iterator_traits<_OutputIt>::iterator_category,
184 std::output_iterator_tag
185 >::value == bool(true),
190 template<
class _InputIt,
class _OutputIt>
191 struct _copy_if_args_check<_InputIt, const _OutputIt> :
192 _iterator_enable_if<false, void>
195 namespace algorithm_cpp11
200 template<
class _InputIt,
class _OutputIt,
class _UnaryPredicate>
204 typename detail::_copy_if_args_check<_InputIt, _OutputIt>::type _last,
208 while (_first != _last) {
210 * _d_first++ = *_first;
220 using algorithm_cpp11::copy_if;
224 namespace algorithm_detail
226 _iterator_no_type copy_n(...);
228 _iterator_no_type _copy_n_check(_iterator_no_type);
229 _iterator_yes_type _copy_n_check(...);
231 struct _dummy_input_iterator :
232 public std::iterator<std::input_iterator_tag, int>
234 reference operator*();
235 _dummy_input_iterator& operator++ ();
236 _dummy_input_iterator operator++ (
int);
239 struct _dummy_output_iterator :
240 public std::iterator<std::output_iterator_tag, int>
242 reference operator*();
243 _dummy_output_iterator& operator++ ();
244 _dummy_output_iterator operator++ (
int);
247 struct _has_buggy_copy_n1
249 static const int _B[20];
250 static const bool value =
sizeof(_copy_n_check(copy_n(_B,
sizeof(_B) /
sizeof(
int), _dummy_output_iterator()))) ==
sizeof(_iterator_yes_type);
253 struct _has_buggy_copy_n2
256 static const bool value =
sizeof(_copy_n_check(copy_n(_dummy_input_iterator(),
sizeof(_A) /
sizeof(
int), _A))) ==
sizeof(_iterator_yes_type);
259 struct _has_buggy_copy_n3
262 static const int _B[20];
263 static const bool value =
sizeof(_copy_n_check(copy_n(_B,
sizeof(_A) /
sizeof(
int), _A))) ==
sizeof(_iterator_yes_type);
267 template<
class _InputIt,
class _OutputT>
268 struct _copy_n_input_it_check :
271 typename std::iterator_traits<_InputIt>::iterator_category,
272 std::input_iterator_tag
273 >::value == bool(true) &&
274 algorithm_detail::_has_buggy_copy_n2::value == bool(false),
279 template<
class _InputIt,
class _OutputT>
280 struct _copy_n_input_it_check<_InputIt, const _OutputT> :
281 _iterator_enable_if<false, void>
284 template<
class _InputIt,
class _OutputT>
285 struct _copy_n_input_it_check1 :
288 typename std::iterator_traits<_InputIt>::iterator_category,
289 std::input_iterator_tag
290 >::value == bool(true) &&
291 algorithm_detail::_has_buggy_copy_n3::value == bool(false),
296 template<
class _InputIt,
class _OutputT>
297 struct _copy_n_input_it_check1<_InputIt, const _OutputT> :
298 _iterator_enable_if<false, void>
301 template<
class _OutputIt>
302 struct _copy_n_output_it_check :
305 typename std::iterator_traits<_OutputIt>::iterator_category,
306 std::output_iterator_tag
307 >::value == bool(true) &&
308 algorithm_detail::_has_buggy_copy_n1::value == bool(false),
315 namespace algorithm_cpp11
320 template<
class _InputT, cstddef::
size_t _InputSize,
class _OutputIt>
322 _OutputIt copy_n(_InputT(&_first_arr)[_InputSize],
323 typename detail::_copy_n_output_it_check<_OutputIt>::type _count, _OutputIt _result)
325 assert(_count <= _InputSize);
327 _InputT* _first = _first_arr;
330 *_result++ = *_first;
331 for (cstddef::size_t _i = 1; _i < _count; ++_i) {
332 *_result++ = *++_first;
340 template<
class _InputIt,
class _OutputT, cstddef::
size_t _OutputSize>
342 _OutputT* copy_n(_InputIt _first,
343 typename detail::_copy_n_input_it_check<_InputIt, _OutputT>::type _count, _OutputT(&_result_arr)[_OutputSize])
345 assert(_count <= _OutputSize);
347 _OutputT* _result = _result_arr;
350 *_result++ = *_first;
351 for (cstddef::size_t _i = 1; _i < _count; ++_i) {
352 *_result++ = *++_first;
361 class _InputT, cstddef::size_t _InputSize,
362 class _OutputT, cstddef::size_t _OutputSize
365 _OutputT* copy_n(_InputT(&_first_arr)[_InputSize],
366 cstddef::size_t _count, _OutputT(&_result_arr)[_OutputSize])
368 assert(_count <= _OutputSize);
369 assert(_count <= _InputSize);
371 _InputT* _first = _first_arr;
372 _OutputT* _result = _result_arr;
375 *_result++ = *_first;
376 for (cstddef::size_t _i = 1; _i < _count; ++_i) {
377 *_result++ = *++_first;
386 namespace algorithm_detail
391 template<
class _InputIt,
class _OutputIt>
394 static const bool value =
sizeof(_copy_n_check(copy_n(declval<_InputIt>(), 0, declval<_OutputIt>()))) ==
sizeof(_iterator_yes_type);
398 template<
class _InputIt,
class _OutputIt>
399 struct _copy_n_args_check :
402 typename std::iterator_traits<_InputIt>::iterator_category,
403 std::input_iterator_tag
404 >::value == bool(true) &&
405 _iterator_cat_is_valid<
406 typename std::iterator_traits<_OutputIt>::iterator_category,
407 std::output_iterator_tag
408 >::value == bool(true) &&
409 algorithm_detail::_has_copy_n<_InputIt, _OutputIt>::value == bool(false),
415 namespace algorithm_cpp11
419 template<
class _InputIt,
class _OutputIt>
421 _OutputIt copy_n(_InputIt _first,
422 typename detail::_copy_n_args_check<_InputIt, _OutputIt>::type _count, _OutputIt _result)
425 *_result++ = *_first;
426 for (cstddef::size_t _i = 1; _i < _count; ++_i) {
427 *_result++ = *++_first;
436 using algorithm_cpp11::copy_n;
440 using std::copy_backward;
462 using std::transform;
470 using std::generate_n;
478 using std::remove_if;
482 using std::remove_copy;
486 using std::remove_copy_if;
494 using std::replace_if;
498 using std::replace_copy;
502 using std::replace_copy_if;
510 using std::swap_ranges;
514 using std::iter_swap;
522 using std::reverse_copy;
530 using std::rotate_copy;
532 namespace algorithm_cpp11
534 template<
class _RandomIt>
536 void random_shuffle(_RandomIt _first,
537 typename detail::_if_iterator_cat_is_rand_access<_RandomIt>::type _last)
540 typename std::iterator_traits<_RandomIt>::difference_type _i, _n;
542 for (_i = _n - 1; _i > 0; --_i) {
543 swap(_first[_i], _first[std::rand() % (_i + 1)]);
553 template<
class _RandomIt,
class _RandomFunc>
555 void random_shuffle(_RandomIt _first,
556 typename detail::_if_iterator_cat_is_rand_access<_RandomIt>::type _last, _RandomFunc& _r)
558 typename std::iterator_traits<_RandomIt>::difference_type _i, _n;
560 for (_i = _n - 1; _i > 0; --_i) {
561 swap(_first[_i], _first[_r(_i + 1)]);
568 using algorithm_cpp11::random_shuffle;
581 using std::unique_copy;
585 namespace algorithm_cpp11
587 template<
class _InputIt,
class _UnaryPredicate>
589 bool is_partitioned(_InputIt _first,
590 typename detail::_if_iterator_cat_is_input<_InputIt>::type _last, _UnaryPredicate _pred)
592 _first = stdex::find_if_not(_first, _last, _pred);
596 return stdex::none_of(_first, _last, _pred);
602 using algorithm_cpp11::is_partitioned;
606 using std::partition;
610 template<
class _InputIt,
class _OutputIt1,
class _OutputIt2>
611 struct _partition_copy_args_check :
614 typename std::iterator_traits<_InputIt>::iterator_category,
615 std::input_iterator_tag
616 >::value == bool(true) &&
617 _iterator_cat_is_valid<
618 typename std::iterator_traits<_OutputIt1>::iterator_category,
619 std::output_iterator_tag
620 >::value == bool(true) &&
621 _iterator_cat_is_valid<
622 typename std::iterator_traits<_OutputIt2>::iterator_category,
623 std::output_iterator_tag
624 >::value == bool(true),
629 template<
class _InputIt,
class _OutputIt1,
class _OutputIt2>
630 struct _partition_copy_args_check<_InputIt, const _OutputIt1, _OutputIt2> :
631 _iterator_traits_enable_if<false, void>
634 template<
class _InputIt,
class _OutputIt1,
class _OutputIt2>
635 struct _partition_copy_args_check<_InputIt, _OutputIt1, const _OutputIt2> :
636 _iterator_traits_enable_if<false, void>
639 template<
class _InputIt,
class _OutputIt1,
class _OutputIt2>
640 struct _partition_copy_args_check<_InputIt, const _OutputIt1, const _OutputIt2> :
641 _iterator_traits_enable_if<false, void>
645 namespace algorithm_cpp11
647 template<
class _InputIt,
class _OutputIt1,
class _OutputIt2,
class _UnaryPredicate>
649 std::pair<_OutputIt1, _OutputIt2>
652 typename detail::_partition_copy_args_check<_InputIt, _OutputIt1, _OutputIt2>::type _last,
653 _OutputIt1 _d_first_true,
654 _OutputIt2 _d_first_false,
657 while (_first != _last) {
659 *_d_first_true = *_first;
663 *_d_first_false = *_first;
668 return std::pair<_OutputIt1, _OutputIt2>(_d_first_true, _d_first_false);
675 using algorithm_cpp11::partition_copy;
679 using std::stable_partition;
688 namespace algorithm_cpp11
693 template<
class _ForwardIt>
695 _ForwardIt is_sorted_until(_ForwardIt _first,
696 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last)
698 if (_first != _last) {
699 _ForwardIt _next = _first;
700 while (++_next != _last) {
701 if (*_next < *_first)
712 template <
class _ForwardIt,
class _Compare>
714 _ForwardIt is_sorted_until(_ForwardIt _first,
715 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last, _Compare _comp)
717 if (_first != _last) {
718 _ForwardIt _next = _first;
719 while (++_next != _last) {
720 if (
true == comp(*_next, *_first))
731 template<
class _ForwardIt>
733 bool is_sorted(_ForwardIt _first,
734 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last)
736 return algorithm_cpp11::is_sorted_until(_first, _last) == _last;
742 template<
class _ForwardIt,
class _Compare>
744 bool is_sorted(_ForwardIt _first,
745 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last, _Compare _comp)
747 return algorithm_cpp11::is_sorted_until(_first, _last, _comp) == _last;
754 using algorithm_cpp11::is_sorted_until;
759 using algorithm_cpp11::is_sorted;
767 using std::partial_sort;
771 using std::partial_sort_copy;
775 using std::stable_sort;
779 using std::nth_element;
785 using std::lower_bound;
789 using std::upper_bound;
793 using std::binary_search;
797 using std::equal_range;
807 using std::inplace_merge;
815 using std::set_difference;
819 using std::set_intersection;
823 using std::set_symmetric_difference;
827 using std::set_union;
843 using std::make_heap;
847 using std::push_heap;
855 using std::sort_heap;
870 using std::max_element;
878 using std::min_element;
880 namespace algorithm_cpp11
887 std::pair<const _Tp&, const _Tp&> minmax(
const _Tp& _a,
const _Tp& _b)
889 return (_b < _a) ? std::pair<const _Tp&, const _Tp&>(_b, _a)
890 : std::pair<const _Tp&, const _Tp&>(_a, _b);
896 template<
class _Tp,
class _Compare>
898 std::pair<const _Tp&, const _Tp&> minmax(
const _Tp& _a,
const _Tp& _b, _Compare _comp)
900 return comp(_b, _a) ? std::pair<const _Tp&, const _Tp&>(_b, _a)
901 : std::pair<const _Tp&, const _Tp&>(_a, _b);
907 template<
class _ForwardIt,
class _Compare>
909 std::pair<_ForwardIt, _ForwardIt>
910 minmax_element(_ForwardIt _first,
911 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last, _Compare _comp)
913 std::pair<_ForwardIt, _ForwardIt> _result(_first, _first);
915 if (_first == _last)
return _result;
916 if (++_first == _last)
return _result;
918 if (_comp(*_first, *_result.first)) {
919 _result.first = _first;
922 _result.second = _first;
924 while (++_first != _last) {
925 _ForwardIt _i = _first;
926 if (++_first == _last) {
927 if (_comp(*_i, *_result.first)) _result.first = _i;
928 else if (!(_comp(*_i, *_result.second))) _result.second = _i;
932 if (_comp(*_first, *_i)) {
933 if (_comp(*_first, *_result.first)) _result.first = _first;
934 if (!(_comp(*_i, *_result.second))) _result.second = _i;
937 if (_comp(*_i, *_result.first)) _result.first = _i;
938 if (!(_comp(*_first, *_result.second))) _result.second = _first;
948 template<
class _ForwardIt>
950 std::pair<_ForwardIt, _ForwardIt>
951 minmax_element(_ForwardIt _first,
952 typename detail::_if_iterator_cat_is_forward<_ForwardIt>::type _last)
954 typedef typename std::iterator_traits<_ForwardIt>::value_type _value_type;
955 return algorithm_cpp11::minmax_element(_first, _last, std::less<_value_type>());
962 using algorithm_cpp11::minmax;
966 using algorithm_cpp11::minmax_element;
970 using std::lexicographical_compare;
974 template<
class _ForwardIt1,
class _ForwardIt2>
975 struct _if_iterators_cat_are_forward :
976 _iterator_traits_enable_if<
978 typename std::iterator_traits<_ForwardIt1>::iterator_category,
979 std::forward_iterator_tag
980 >::value == bool(true) &&
982 typename std::iterator_traits<_ForwardIt2>::iterator_category,
983 std::forward_iterator_tag
984 >::value == bool(true),
989 template<
class _Tp,
class _BinaryPredicate>
990 struct _BinaryToUnaryPredicate {
991 _BinaryToUnaryPredicate(
const _Tp& value_, _BinaryPredicate& pred_) :
996 _BinaryPredicate& pred;
998 bool operator()(
const _Tp& input)
const
1000 return pred(value, input);
1006 _BinaryToUnaryPredicate &operator=(
const _BinaryToUnaryPredicate &other)
1012 template<
class _Tp,
class _BinaryPredicate>
1013 _BinaryToUnaryPredicate<_Tp, _BinaryPredicate>
1014 _make_b2u_predicate(
const _Tp& value_, _BinaryPredicate& pred_)
1016 return _BinaryToUnaryPredicate<_Tp, _BinaryPredicate>(value_, pred_);
1020 namespace algorithm_cpp11
1025 template<
class _ForwardIt1,
class _ForwardIt2>
1027 bool is_permutation(_ForwardIt1 _first,
1028 typename detail::_if_iterators_cat_are_forward<_ForwardIt1, _ForwardIt2>::type _last, _ForwardIt2 _d_first)
1031 std::pair<_ForwardIt1, _ForwardIt2> _tie = std::mismatch(_first, _last, _d_first);
1032 _first = _tie.first;
1033 _d_first = _tie.second;
1036 if (_first != _last) {
1037 _ForwardIt2 _d_last = _d_first;
1038 std::advance(_d_last, std::distance(_first, _last));
1039 for (_ForwardIt1 _i = _first; _i != _last; ++_i) {
1040 if (_i != std::find(_first, _i, *_i))
continue;
1041 typename iterator_traits<_ForwardIt2>::difference_type _m = std::count(_d_first, _d_last, *_i);
1042 if (_m == 0 || std::count(_i, _last, *_i) != _m) {
1050 template<
class _ForwardIt1,
class _ForwardIt2,
class _BinaryPredicate>
1052 bool is_permutation(_ForwardIt1 _first,
1053 typename detail::_if_iterators_cat_are_forward<_ForwardIt1, _ForwardIt2>::type _last,
1054 _ForwardIt2 _d_first, _BinaryPredicate _pred)
1057 std::pair<_ForwardIt1, _ForwardIt2> _tie = std::mismatch(_first, _last, _d_first, _pred);
1058 _first = _tie.first;
1059 _d_first = _tie.second;
1062 if (_first != _last) {
1063 _ForwardIt2 _d_last = _d_first;
1064 std::advance(_d_last, std::distance(_first, _last));
1065 for (_ForwardIt1 _i = _first; _i != _last; ++_i) {
1066 if (_i != std::find_if(_first, _i, detail::_make_b2u_predicate(*_i, _pred)))
continue;
1067 typename iterator_traits<_ForwardIt2>::difference_type _m = std::count_if(_d_first, _d_last, detail::_make_b2u_predicate(*_i, _pred));
1068 if (_m == 0 || std::count_if(_i, _last, detail::_make_b2u_predicate(*_i, _pred)) != _m) {
1080 using algorithm_cpp11::is_permutation;
1084 using std::next_permutation;
1088 using std::prev_permutation;