@@ -157,6 +157,7 @@ bits_headers = \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
${bits_srcdir}/range_cmp.h \
+ ${bits_srcdir}/ranges_algo.h \
${bits_srcdir}/refwrap.h \
${bits_srcdir}/regex.h \
${bits_srcdir}/regex.tcc \
@@ -502,6 +502,7 @@ bits_headers = \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
${bits_srcdir}/range_cmp.h \
+ ${bits_srcdir}/ranges_algo.h \
${bits_srcdir}/refwrap.h \
${bits_srcdir}/regex.h \
${bits_srcdir}/regex.tcc \
new file mode 100644
@@ -0,0 +1,3640 @@
+// Core algorithmic facilities -*- C++ -*-
+
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ranges_algo.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{algorithm}
+ */
+
+#ifndef _RANGES_ALGO_H
+#define _RANGES_ALGO_H 1
+
+#if __cplusplus > 201703L
+
+#include <compare>
+#include <cmath>
+#include <iterator>
+// #include <bits/range_concepts.h>
+#include <ranges>
+#include <bits/invoke.h>
+#include <bits/cpp_type_traits.h> // __is_byte
+#include <bits/random.h> // concept uniform_random_bit_generator
+
+#if __cpp_lib_concepts
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace ranges
+{
+ namespace __detail
+ {
+ template<typename _Tp>
+ constexpr inline bool __is_normal_iterator = false;
+
+ template<typename _Iterator, typename _Container>
+ constexpr inline bool
+ __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, _Container>>
+ = true;
+
+ template<typename _Tp>
+ constexpr inline bool __is_reverse_iterator = false;
+
+ template<typename _Iterator>
+ constexpr inline bool
+ __is_reverse_iterator<reverse_iterator<_Iterator>> = true;
+
+ template<typename _Tp>
+ constexpr inline bool __is_move_iterator = false;
+
+ template<typename _Iterator>
+ constexpr inline bool
+ __is_move_iterator<move_iterator<_Iterator>> = true;
+
+ template<typename _Comp, typename _Proj>
+ constexpr auto
+ __make_comp_proj(_Comp& __comp, _Proj& __proj)
+ {
+ return [&] (auto&& __lhs, auto&& __rhs) -> bool {
+ using _TL = decltype(__lhs);
+ using _TR = decltype(__rhs);
+ return std::__invoke(__comp,
+ std::__invoke(__proj, std::forward<_TL>(__lhs)),
+ std::__invoke(__proj, std::forward<_TR>(__rhs)));
+ };
+ }
+
+ template<typename _Pred, typename _Proj>
+ constexpr auto
+ __make_pred_proj(_Pred& __pred, _Proj& __proj)
+ {
+ return [&] <typename _Tp> (_Tp&& __arg) -> bool {
+ return std::__invoke(__pred,
+ std::__invoke(__proj, std::forward<_Tp>(__arg)));
+ };
+ }
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr bool
+ all_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ return false;
+ return true;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr bool
+ all_of(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::all_of(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr bool
+ any_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ return true;
+ return false;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr bool
+ any_of(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::any_of(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr bool
+ none_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ return false;
+ return true;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr bool
+ none_of(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::none_of(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Fp>
+ struct for_each_result
+ {
+ [[no_unique_address]] _Iter in;
+ [[no_unique_address]] _Fp fun;
+
+ template<typename _Iter2, typename _F2p>
+ requires convertible_to<const _Iter&, _Iter2>
+ && convertible_to<const _Fp&, _F2p>
+ operator for_each_result<_Iter2, _F2p>() const &
+ { return {in, fun}; }
+
+ template<typename _Iter2, typename _F2p>
+ requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p>
+ operator for_each_result<_Iter2, _F2p>() &&
+ { return {std::move(in), std::move(fun)}; }
+ };
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirectly_unary_invocable<projected<_Iter, _Proj>> _Fun>
+ constexpr for_each_result<_Iter, _Fun>
+ for_each(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ std::__invoke(__f, std::__invoke(__proj, *__first));
+ return { std::move(__first), std::move(__f) };
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirectly_unary_invocable<projected<iterator_t<_Range>, _Proj>>
+ _Fun>
+ constexpr for_each_result<safe_iterator_t<_Range>, _Fun>
+ for_each(_Range&& __r, _Fun __f, _Proj __proj = {})
+ {
+ return ranges::for_each(ranges::begin(__r), ranges::end(__r),
+ std::move(__f), std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
+ typename _Proj = identity>
+ requires indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>, const _Tp*>
+ constexpr _Iter
+ find(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {})
+ {
+ while (__first != __last
+ && !(std::__invoke(__proj, *__first) == __value))
+ ++__first;
+ return __first;
+ }
+
+ template<input_range _Range, typename _Tp, typename _Proj = identity>
+ requires indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp*>
+ constexpr safe_iterator_t<_Range>
+ find(_Range&& __r, const _Tp& __value, _Proj __proj = {})
+ {
+ return ranges::find(ranges::begin(__r), ranges::end(__r), __value,
+ std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr _Iter
+ find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ while (__first != __last
+ && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ ++__first;
+ return __first;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
+ _Pred>
+ constexpr safe_iterator_t<_Range>
+ find_if(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::find_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr _Iter
+ find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ while (__first != __last
+ && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ ++__first;
+ return __first;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
+ _Pred>
+ constexpr safe_iterator_t<_Range>
+ find_if_not(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::find_if_not(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr _Iter1
+ find_first_of(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ for (; __first1 != __last1; ++__first1)
+ for (auto __iter = __first2; __iter != __last2; ++__iter)
+ if (std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__iter)))
+ return __first1;
+ return __first1;
+ }
+
+ template<input_range _Range1, forward_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr safe_iterator_t<_Range1>
+ find_first_of(_Range1&& __r1, _Range2&& __r2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::find_first_of(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity>
+ requires indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>,
+ const _Tp*>
+ constexpr iter_difference_t<_Iter>
+ count(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {})
+ {
+ iter_difference_t<_Iter> __n = 0;
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__proj, *__first) == __value)
+ ++__n;
+ return __n;
+ }
+
+ template<input_range _Range, typename _Tp, typename _Proj = identity>
+ requires indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp*>
+ constexpr range_difference_t<_Range>
+ count(_Range&& __r, const _Tp& __value, _Proj __proj = {})
+ {
+ return ranges::count(ranges::begin(__r), ranges::end(__r),
+ __value, std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr iter_difference_t<_Iter>
+ count_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ iter_difference_t<_Iter> __n = 0;
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ ++__n;
+ return __n;
+ }
+
+ template<input_range _Range,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr range_difference_t<_Range>
+ count_if(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::count_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter1, typename _Iter2>
+ struct mismatch_result
+ {
+ [[no_unique_address]] _Iter1 in1;
+ [[no_unique_address]] _Iter2 in2;
+
+ template<typename _IIter1, typename _IIter2>
+ requires convertible_to<const _Iter1&, _IIter1>
+ && convertible_to<const _Iter2&, _IIter2>
+ operator mismatch_result<_IIter1, _IIter2>() const &
+ { return {in1, in2}; }
+
+ template<typename _IIter1, typename _IIter2>
+ requires convertible_to<_Iter1, _IIter1>
+ && convertible_to<_Iter2, _IIter2>
+ operator mismatch_result<_IIter1, _IIter2>() &&
+ { return {std::move(in1), std::move(in2)}; }
+ };
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr mismatch_result<_Iter1, _Iter2>
+ mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2
+ && (bool)std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ {
+ ++__first1;
+ ++__first2;
+ }
+ return { std::move(__first1), std::move(__first2) };
+ }
+
+ template<input_range _Range1, input_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>>
+ mismatch(_Range1&& __r1, _Range2&& __r2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::mismatch(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr subrange<_Iter1>
+ search(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ if (__first1 == __last1 || __first2 == __last2)
+ return {__first1, __first1};
+
+ for (;;)
+ {
+ for (;;)
+ {
+ if (__first1 == __last1)
+ return {__first1, __first1};
+ if (std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ break;
+ ++__first1;
+ }
+ auto __cur1 = __first1;
+ auto __cur2 = __first2;
+ for (;;)
+ {
+ if (++__cur2 == __last2)
+ return {__first1, ++__cur1};
+ if (++__cur1 == __last1)
+ return {__cur1, __cur1};
+ if (!(bool)std::__invoke(__pred,
+ std::__invoke(__proj1, *__cur1),
+ std::__invoke(__proj2, *__cur2)))
+ {
+ ++__first1;
+ break;
+ }
+ }
+ }
+ }
+
+ template<forward_range _Range1, forward_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr safe_subrange_t<_Range1>
+ search(_Range1&& __r1, _Range2&& __r2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::search(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
+ typename _Pred = ranges::equal_to, typename _Proj = identity>
+ requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj>
+ constexpr subrange<_Iter>
+ search_n(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count,
+ const _Tp& __value, _Pred __pred = {}, _Proj __proj = {})
+ {
+ if (__count <= 0)
+ return {__first, __first};
+
+ auto __value_comp = [&] <typename _Rp> (_Rp&& __arg) {
+ return std::__invoke(__pred, std::forward<_Rp>(__arg), __value);
+ };
+ if (__count == 1)
+ {
+ __first = ranges::find_if(std::move(__first), __last,
+ std::move(__value_comp), std::move(__proj));
+ if (__first == __last)
+ return {__first, __first};
+ else
+ {
+ auto __end = __first;
+ return {__first, ++__end};
+ }
+ }
+
+ if constexpr (sized_sentinel_for<_Sent, _Iter>)
+ {
+ auto __tail_size = __last - __first;
+ auto __remainder = __count;
+
+ while (__remainder <= __tail_size)
+ {
+ __first += __remainder;
+ __tail_size -= __remainder;
+ auto __backtrack = __first;
+ while (__value_comp(std::__invoke(__proj, *--__backtrack)))
+ {
+ if (--__remainder == 0)
+ return {__first - __count, __first};
+ }
+ }
+ auto __i = __first + __tail_size;
+ return {__i, __i};
+ }
+ else
+ {
+ __first = ranges::find_if(__first, __last, __value_comp, __proj);
+ while (__first != __last)
+ {
+ auto __n = __count;
+ auto __i = __first;
+ ++__i;
+ while (__i != __last && __n != 1
+ && __value_comp(std::__invoke(__proj, *__i)))
+ {
+ ++__i;
+ --__n;
+ }
+ if (__n == 1)
+ return {__first, __i};
+ if (__i == __last)
+ return {__i, __i};
+ __first = ranges::find_if(++__i, __last, __value_comp, __proj);
+ }
+ return {__first, __first};
+ }
+ }
+
+ template<forward_range _Range, typename _Tp,
+ typename _Pred = ranges::equal_to, typename _Proj = identity>
+ requires indirectly_comparable<iterator_t<_Range>, const _Tp*, _Pred, _Proj>
+ constexpr safe_subrange_t<_Range>
+ search_n(_Range&& __r, range_difference_t<_Range> __count,
+ const _Tp& __value, _Pred __pred = {}, _Proj __proj = {})
+ {
+ return ranges::search_n(ranges::begin(__r), ranges::end(__r),
+ std::move(__count), __value,
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr subrange<_Iter1>
+ __find_end(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+ {
+ auto __i = ranges::next(__first1, __last1);
+ if (__first2 == __last2)
+ return {__i, __i};
+
+ auto __result_begin = __i;
+ auto __result_end = __i;
+ for (;;)
+ {
+ auto __new_range = ranges::search(__first1, __last1,
+ __first2, __last2,
+ __pred, __proj1, __proj2);
+ auto __new_result_begin = ranges::begin(__new_range);
+ auto __new_result_end = ranges::end(__new_range);
+ if (__new_result_begin == __last1)
+ return {__result_begin, __result_end};
+ else
+ {
+ __result_begin = __new_result_begin;
+ __result_end = __new_result_end;
+ __first1 = __result_begin;
+ ++__first1;
+ }
+ }
+ }
+
+ template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr subrange<_Iter1>
+ find_end(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ if constexpr (bidirectional_iterator<_Iter1>
+ && bidirectional_iterator<_Iter2>)
+ {
+ auto __i1 = ranges::next(__first1, __last1);
+ auto __i2 = ranges::next(__first2, __last2);
+ auto __rresult
+ = ranges::search(reverse_iterator<_Iter1>{__i1},
+ reverse_iterator<_Iter1>{__first1},
+ reverse_iterator<_Iter2>{__i2},
+ reverse_iterator<_Iter2>{__first2},
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ auto __result_first = ranges::end(__rresult).base();
+ auto __result_last = ranges::begin(__rresult).base();
+ if (__result_last == __first1)
+ return {__i1, __i1};
+ else
+ return {__result_first, __result_last};
+ }
+ else
+ return ranges::__find_end(__first1, __last1, __first2, __last2,
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<forward_range _Range1, forward_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr safe_subrange_t<_Range1>
+ find_end(_Range1&& __r1, _Range2&& __r2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::find_end(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_binary_predicate<projected<_Iter, _Proj>,
+ projected<_Iter, _Proj>> _Pred
+ = ranges::equal_to>
+ constexpr _Iter
+ adjacent_find(_Iter __first, _Sent __last,
+ _Pred __pred = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return __first;
+ auto __next = __first;
+ for (; ++__next != __last; __first = __next)
+ {
+ if (std::__invoke(__pred,
+ std::__invoke(__proj, *__first),
+ std::__invoke(__proj, *__next)))
+ return __first;
+ }
+ return __next;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_binary_predicate<
+ projected<iterator_t<_Range>, _Proj>,
+ projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
+ constexpr safe_iterator_t<_Range>
+ adjacent_find(_Range&& __r, _Pred __pred = {}, _Proj __proj = {})
+ {
+ return ranges::adjacent_find(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Proj1 = identity, typename _Proj2 = identity,
+ indirect_equivalence_relation<projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>> _Pred
+ = ranges::equal_to>
+ constexpr bool
+ is_permutation(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ constexpr bool __sized_iters
+ = (sized_sentinel_for<_Sent1, _Iter1>
+ && sized_sentinel_for<_Sent2, _Iter2>);
+ if constexpr (__sized_iters)
+ {
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
+ if (__d1 != __d2)
+ return false;
+ }
+
+ // Efficiently compare identical prefixes: O(N) if sequences
+ // have the same elements in the same order.
+ for (; __first1 != __last1 && __first2 != __last2;
+ ++__first1, (void)++__first2)
+ if (!(bool)std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ break;
+
+ if constexpr (__sized_iters)
+ {
+ if (__first1 == __last1)
+ return true;
+ }
+ else
+ {
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
+ if (__d1 == 0 && __d2 == 0)
+ return true;
+ if (__d1 != __d2)
+ return false;
+ }
+
+ for (auto __scan = __first1; __scan != __last1; ++__scan)
+ {
+ auto __proj_scan = std::__invoke(__proj1, *__scan);
+ auto __comp_scan = [&] <typename _Tp> (_Tp&& __arg) {
+ return std::__invoke(__pred, __proj_scan,
+ std::forward<_Tp>(__arg));
+ };
+ if (__scan != ranges::find_if(__first1, __scan,
+ __comp_scan, __proj1))
+ continue; // We've seen this one before.
+
+ auto __matches = ranges::count_if(__first2, __last2,
+ __comp_scan, __proj2);
+ if (__matches == 0
+ || ranges::count_if(__scan, __last1,
+ __comp_scan, __proj1) != __matches)
+ return false;
+ }
+ return true;
+ }
+
+ template<forward_range _Range1, forward_range _Range2,
+ typename _Proj1 = identity, typename _Proj2 = identity,
+ indirect_equivalence_relation<
+ projected<iterator_t<_Range1>, _Proj1>,
+ projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to>
+ constexpr bool
+ is_permutation(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::is_permutation(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred, typename _Proj1, typename _Proj2>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr bool
+ __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+ {
+ // TODO: implement more specializations to at least have parity with
+ // std::equal.
+ constexpr bool __sized_iters
+ = (sized_sentinel_for<_Sent1, _Iter1>
+ && sized_sentinel_for<_Sent2, _Iter2>);
+ if constexpr (__sized_iters)
+ {
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
+ if (__d1 != __d2)
+ return false;
+
+ using _ValueType1 = iter_value_t<_Iter1>;
+ using _ValueType2 = iter_value_t<_Iter2>;
+ constexpr bool __use_memcmp
+ = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>)
+ && is_same_v<_ValueType1, _ValueType2>
+ && is_pointer_v<_Iter1>
+ && is_pointer_v<_Iter2>
+ && is_same_v<_Pred, ranges::equal_to>
+ && is_same_v<_Proj1, identity>
+ && is_same_v<_Proj2, identity>);
+ if constexpr (__use_memcmp)
+ {
+ if (const size_t __len = (__last1 - __first1))
+ return !std::__memcmp(__first1, __first2, __len);
+ return true;
+ }
+ else
+ {
+ for (; __first1 != __last1; ++__first1, (void)++__first2)
+ if (!(bool)std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ return false;
+ return true;
+ }
+ }
+ else
+ {
+ for (; __first1 != __last1 && __first2 != __last2;
+ ++__first1, (void)++__first2)
+ if (!(bool)std::__invoke(__pred,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ return false;
+ return __first1 == __last1 && __first2 == __last2;
+ }
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
+ constexpr bool
+ equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::__equal(std::__niter_base(std::move(__first1)),
+ std::__niter_base(std::move(__last1)),
+ std::__niter_base(std::move(__first2)),
+ std::__niter_base(std::move(__last2)),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_range _Range1, input_range _Range2,
+ typename _Pred = ranges::equal_to,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
+ _Pred, _Proj1, _Proj2>
+ constexpr bool
+ equal(_Range1&& __r1, _Range2&& __r2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::equal(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__pred),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<typename _Iter, typename _Out>
+ struct copy_result
+ {
+ [[no_unique_address]] _Iter in;
+ [[no_unique_address]] _Out out;
+
+ template<typename _Iter2, typename _Out2>
+ requires convertible_to<const _Iter&, _Iter2>
+ && convertible_to<const _Out&, _Out2>
+ operator copy_result<_Iter2, _Out2>() const &
+ { return {in, out}; }
+
+ template<typename _Iter2, typename _Out2>
+ requires convertible_to<_Iter, _Iter2>
+ && convertible_to<_Out, _Out2>
+ operator copy_result<_Iter2, _Out2>() &&
+ { return {std::move(in), std::move(out)}; }
+ };
+
+ template<typename _Iter, typename _Out>
+ using move_result = copy_result<_Iter, _Out>;
+
+ template<typename _Iter1, typename _Iter2>
+ using move_backward_result = copy_result<_Iter1, _Iter2>;
+
+ template<typename _Iter1, typename _Iter2>
+ using copy_backward_result = copy_result<_Iter1, _Iter2>;
+
+ template<bool _IsMove,
+ bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ bidirectional_iterator _Out>
+ requires (_IsMove
+ ? indirectly_movable<_Iter, _Out>
+ : indirectly_copyable<_Iter, _Out>)
+ constexpr conditional_t<_IsMove,
+ move_backward_result<_Iter, _Out>,
+ copy_backward_result<_Iter, _Out>>
+ __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result);
+
+ template<bool _IsMove,
+ input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out>
+ requires (_IsMove
+ ? indirectly_movable<_Iter, _Out>
+ : indirectly_copyable<_Iter, _Out>)
+ constexpr conditional_t<_IsMove,
+ move_result<_Iter, _Out>,
+ copy_result<_Iter, _Out>>
+ __copy_or_move(_Iter __first, _Sent __last, _Out __result)
+ {
+ // TODO: implement more specializations to be at least on par with
+ // std::copy/std::move.
+ constexpr bool __normal_iterator_p
+ = (__detail::__is_normal_iterator<_Iter>
+ || __detail::__is_normal_iterator<_Out>);
+ constexpr bool __reverse_p
+ = (__detail::__is_reverse_iterator<_Iter>
+ && __detail::__is_reverse_iterator<_Out>);
+ constexpr bool __move_iterator_p = __detail::__is_move_iterator<_Iter>;
+ if constexpr (__move_iterator_p)
+ {
+ auto [__in, __out]
+ = ranges::__copy_or_move<true>(std::move(__first).base(),
+ std::move(__last).base(),
+ std::move(__result));
+ return {move_iterator{std::move(__in)}, std::move(__out)};
+ }
+ else if constexpr (__reverse_p)
+ {
+ auto [__in,__out]
+ = ranges::__copy_or_move_backward<_IsMove>(__last.base(),
+ __first.base(),
+ __result.base());
+ return {reverse_iterator{std::move(__in)},
+ reverse_iterator{std::move(__out)}};
+ }
+ else if constexpr (__normal_iterator_p)
+ {
+ auto [__in,__out]
+ = ranges::__copy_or_move<_IsMove>(std::__niter_base(__first),
+ std::__niter_base(__last),
+ std::__niter_base(__result));
+ return {std::__niter_wrap(__first, std::move(__in)),
+ std::__niter_wrap(__result, std::move(__out))};
+ }
+ else if constexpr (sized_sentinel_for<_Sent, _Iter>)
+ {
+ using _ValueTypeI = iter_value_t<_Iter>;
+ using _ValueTypeO = iter_value_t<_Out>;
+ constexpr bool __use_memmove
+ = (is_trivially_copyable_v<_ValueTypeI>
+ && is_same_v<_ValueTypeI, _ValueTypeO>
+ && is_pointer_v<_Iter>
+ && is_pointer_v<_Out>);
+
+ if constexpr (__use_memmove)
+ {
+ static_assert(_IsMove
+ ? is_move_assignable_v<_ValueTypeI>
+ : is_copy_assignable_v<_ValueTypeI>);
+ auto __num = __last - __first;
+ if (__num)
+ std::__memmove<_IsMove>(__result, __first, __num);
+ return {__first + __num, __result + __num};
+ }
+ else
+ {
+ for (auto __n = __last - __first; __n > 0; --__n)
+ {
+ if constexpr (_IsMove)
+ *__result = std::move(*__first);
+ else
+ *__result = *__first;
+ ++__first;
+ ++__result;
+ }
+ return {std::move(__first), std::move(__result)};
+ }
+ }
+ else
+ {
+ while (__first != __last)
+ {
+ if constexpr (_IsMove)
+ *__result = std::move(*__first);
+ else
+ *__result = *__first;
+ ++__first;
+ ++__result;
+ }
+ return {std::move(__first), std::move(__result)};
+ }
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr copy_result<_Iter, _Out>
+ copy(_Iter __first, _Sent __last, _Out __result)
+ {
+ return ranges::__copy_or_move<false>(std::move(__first),
+ std::move(__last),
+ std::move(__result));
+ }
+
+ template<input_range _Range, weakly_incrementable _Out>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr copy_result<safe_iterator_t<_Range>, _Out>
+ copy(_Range&& __r, _Out __result)
+ {
+ return ranges::copy(ranges::begin(__r), ranges::end(__r),
+ std::move(__result));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out>
+ requires indirectly_movable<_Iter, _Out>
+ constexpr move_result<_Iter, _Out>
+ move(_Iter __first, _Sent __last, _Out __result)
+ {
+ return ranges::__copy_or_move<true>(std::move(__first),
+ std::move(__last),
+ std::move(__result));
+ }
+
+ template<input_range _Range, weakly_incrementable _Out>
+ requires indirectly_movable<iterator_t<_Range>, _Out>
+ constexpr move_result<safe_iterator_t<_Range>, _Out>
+ move(_Range&& __r, _Out __result)
+ {
+ return ranges::move(ranges::begin(__r), ranges::end(__r),
+ std::move(__result));
+ }
+
+ template<bool _IsMove,
+ bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ bidirectional_iterator _Out>
+ requires (_IsMove
+ ? indirectly_movable<_Iter, _Out>
+ : indirectly_copyable<_Iter, _Out>)
+ constexpr conditional_t<_IsMove,
+ move_backward_result<_Iter, _Out>,
+ copy_backward_result<_Iter, _Out>>
+ __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result)
+ {
+ // TODO: implement more specializations to be at least on par with
+ // std::copy_backward/std::move_backward.
+ constexpr bool __normal_iterator_p
+ = (__detail::__is_normal_iterator<_Iter>
+ || __detail::__is_normal_iterator<_Out>);
+ constexpr bool __reverse_p
+ = (__detail::__is_reverse_iterator<_Iter>
+ && __detail::__is_reverse_iterator<_Out>);
+ if constexpr (__reverse_p)
+ {
+ auto [__in,__out]
+ = ranges::__copy_or_move<_IsMove>(__last.base(),
+ __first.base(),
+ __result.base());
+ return {reverse_iterator{std::move(__in)},
+ reverse_iterator{std::move(__out)}};
+ }
+ else if constexpr (__normal_iterator_p)
+ {
+ auto [__in,__out]
+ = ranges::__copy_or_move_backward<_IsMove>
+ (std::__niter_base(__first),
+ std::__niter_base(__last),
+ std::__niter_base(__result));
+ return {std::__niter_wrap(__first, std::move(__in)),
+ std::__niter_wrap(__result, std::move(__out))};
+ }
+ else if constexpr (sized_sentinel_for<_Sent, _Iter>)
+ {
+ using _ValueTypeI = iter_value_t<_Iter>;
+ using _ValueTypeO = iter_value_t<_Out>;
+ constexpr bool __use_memmove
+ = (is_trivially_copyable_v<_ValueTypeI>
+ && is_same_v<_ValueTypeI, _ValueTypeO>
+ && is_pointer_v<_Iter>
+ && is_pointer_v<_Out>);
+ if constexpr (__use_memmove)
+ {
+ static_assert(_IsMove
+ ? is_move_assignable_v<_ValueTypeI>
+ : is_copy_assignable_v<_ValueTypeI>);
+ auto __num = __last - __first;
+ if (__num)
+ std::__memmove<_IsMove>(__result - __num, __first, __num);
+ return {__first + __num, __result - __num};
+ }
+ else
+ {
+ auto __lasti = ranges::next(__first, __last);
+ auto __tail = __lasti;
+
+ for (auto __n = __last - __first; __n > 0; --__n)
+ {
+ --__tail;
+ --__result;
+ if constexpr (_IsMove)
+ *__result = std::move(*__tail);
+ else
+ *__result = *__tail;
+ }
+ return {std::move(__lasti), std::move(__result)};
+ }
+ }
+ else
+ {
+ auto __lasti = ranges::next(__first, __last);
+ auto __tail = __lasti;
+
+ while (__first != __tail)
+ {
+ --__tail;
+ --__result;
+ if constexpr (_IsMove)
+ *__result = std::move(*__tail);
+ else
+ *__result = *__tail;
+ }
+ return {std::move(__lasti), std::move(__result)};
+ }
+ }
+
+ template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ bidirectional_iterator _Iter2>
+ requires indirectly_copyable<_Iter1, _Iter2>
+ constexpr copy_backward_result<_Iter1, _Iter2>
+ copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result)
+ {
+ return ranges::__copy_or_move_backward<false>(std::move(__first),
+ std::move(__last),
+ std::move(__result));
+ }
+
+ template<bidirectional_range _Range, bidirectional_iterator _Iter>
+ requires indirectly_copyable<iterator_t<_Range>, _Iter>
+ constexpr copy_backward_result<safe_iterator_t<_Range>, _Iter>
+ copy_backward(_Range&& __r, _Iter __result)
+ {
+ return ranges::copy_backward(ranges::begin(__r), ranges::end(__r),
+ std::move(__result));
+ }
+
+ template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ bidirectional_iterator _Iter2>
+ requires indirectly_movable<_Iter1, _Iter2>
+ constexpr move_backward_result<_Iter1, _Iter2>
+ move_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result)
+ {
+ return ranges::__copy_or_move_backward<true>(std::move(__first),
+ std::move(__last),
+ std::move(__result));
+ }
+
+ template<bidirectional_range _Range, bidirectional_iterator _Iter>
+ requires indirectly_movable<iterator_t<_Range>, _Iter>
+ constexpr move_backward_result<safe_iterator_t<_Range>, _Iter>
+ move_backward(_Range&& __r, _Iter __result)
+ {
+ return ranges::move_backward(ranges::begin(__r), ranges::end(__r),
+ std::move(__result));
+ }
+
+ template<typename _Iter, typename _Out>
+ using copy_n_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, weakly_incrementable _Out>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr copy_n_result<_Iter, _Out>
+ copy_n(_Iter __first, iter_difference_t<_Iter> __n, _Out __result)
+ {
+ if constexpr (random_access_iterator<_Iter>)
+ return ranges::copy(__first, __first + __n, std::move(__result));
+ else
+ {
+ for (; __n > 0; --__n, (void)++__result, (void)++__first)
+ *__result = *__first;
+ return {std::move(__first), std::move(__result)};
+ }
+ }
+
+ template<typename _Iter, typename _Out>
+ using copy_if_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out, typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr copy_if_result<_Iter, _Out>
+ copy_if(_Iter __first, _Sent __last, _Out __result,
+ _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ {
+ *__result = *__first;
+ ++__result;
+ }
+ return {std::move(__first), std::move(__result)};
+ }
+
+ template<input_range _Range, weakly_incrementable _Out,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr copy_if_result<safe_iterator_t<_Range>, _Out>
+ copy_if(_Range&& __r, _Out __result, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::copy_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__result),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter1, typename _Iter2>
+ using swap_ranges_result = mismatch_result<_Iter1, _Iter2>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2>
+ requires indirectly_swappable<_Iter1, _Iter2>
+ constexpr swap_ranges_result<_Iter1, _Iter2>
+ swap_ranges(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2)
+ {
+ for (; __first1 != __last1 && __first2 != __last2;
+ ++__first1, (void)++__first2)
+ ranges::iter_swap(__first1, __first2);
+ return {std::move(__first1), std::move(__first2)};
+ }
+
+ template<input_range _Range1, input_range _Range2>
+ requires indirectly_swappable<iterator_t<_Range1>, iterator_t<_Range2>>
+ constexpr swap_ranges_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>>
+ swap_ranges(_Range1&& __r1, _Range2&& __r2)
+ {
+ return ranges::swap_ranges(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2));
+ }
+
+ template<typename _Iter, typename _Out>
+ using unary_transform_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out,
+ copy_constructible _Fp, typename _Proj = identity>
+ requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter, _Proj>>>
+ constexpr unary_transform_result<_Iter, _Out>
+ transform(_Iter __first1, _Sent __last1, _Out __result,
+ _Fp __op, _Proj __proj = {})
+ {
+ for (; __first1 != __last1; ++__first1, (void)++__result)
+ *__result = std::__invoke(__op, std::__invoke(__proj, *__first1));
+ return {std::move(__first1), std::move(__result)};
+ }
+
+ template<input_range _Range, weakly_incrementable _Out,
+ copy_constructible _Fp, typename _Proj = identity>
+ requires writable<_Out,
+ indirect_result_t<_Fp&, projected<iterator_t<_Range>,
+ _Proj>>>
+ constexpr unary_transform_result<safe_iterator_t<_Range>, _Out>
+ transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {})
+ {
+ return ranges::transform(ranges::begin(__r), ranges::end(__r),
+ std::move(__result),
+ std::move(__op), std::move(__proj));
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Out>
+ struct binary_transform_result
+ {
+ [[no_unique_address]] _Iter1 in1;
+ [[no_unique_address]] _Iter2 in2;
+ [[no_unique_address]] _Out out;
+
+ template<typename _IIter1, typename _IIter2, typename _OOut>
+ requires convertible_to<const _Iter1&, _IIter1> &&
+ && convertible_to<const _Iter2&, _IIter2>
+ && convertible_to<const _Out&, _OOut>
+ operator binary_transform_result<_IIter1, _IIter2, _OOut>() const &
+ { return {in1, in2, out}; }
+
+ template<typename _IIter1, typename _IIter2, typename _OOut>
+ requires convertible_to<_Iter1, _IIter1>
+ && convertible_to<_Iter2, _IIter2>
+ && convertible_to<_Out, _OOut>
+ operator binary_transform_result<_IIter1, _IIter2, _OOut>() &&
+ { return {std::move(in1), std::move(in2), std::move(out)}; }
+ };
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, copy_constructible _Fp,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>>>
+ constexpr binary_transform_result<_Iter1, _Iter2, _Out>
+ transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Out __result, _Fp __binary_op,
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ for (; __first1 != __last1 && __first2 != __last2;
+ ++__first1, (void)++__first2, ++__result)
+ *__result = std::__invoke(__binary_op,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2));
+ return {std::move(__first1), std::move(__first2), std::move(__result)};
+ }
+
+ template<input_range _Range1, input_range _Range2,
+ weakly_incrementable _Out, copy_constructible _Fp,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires writable<_Out, indirect_result_t<_Fp&,
+ projected<iterator_t<_Range1>,
+ _Proj1>,
+ projected<iterator_t<_Range2>,
+ _Proj2>>>
+ constexpr binary_transform_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>, _Out>
+ transform(_Range1&& __r1, _Range2&& __r2, _Out __result,
+ _Fp __binary_op, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::transform(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__binary_op),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp1, typename _Tp2, typename _Proj = identity>
+ requires writable<_Iter, const _Tp2&> &&
+ indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>, const _Tp1*>
+ constexpr _Iter
+ replace(_Iter __first, _Sent __last,
+ const _Tp1& __old_value, const _Tp2& __new_value,
+ _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__proj, *__first) == __old_value)
+ *__first = __new_value;
+ return __first;
+ }
+
+ template<input_range _Range,
+ typename _Tp1, typename _Tp2, typename _Proj = identity>
+ requires writable<iterator_t<_Range>, const _Tp2&> &&
+ indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp1*>
+ constexpr safe_iterator_t<_Range>
+ replace(_Range&& __r,
+ const _Tp1& __old_value, const _Tp2& __new_value,
+ _Proj __proj = {})
+ {
+ return ranges::replace(ranges::begin(__r), ranges::end(__r),
+ __old_value, __new_value, std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires writable<_Iter, const _Tp&>
+ constexpr _Iter
+ replace_if(_Iter __first, _Sent __last,
+ _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ *__first = __new_value;
+ return std::move(__first);
+ }
+
+ template<input_range _Range, typename _Tp, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires writable<iterator_t<_Range>, const _Tp&>
+ constexpr safe_iterator_t<_Range>
+ replace_if(_Range&& __r,
+ _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
+ {
+ return ranges::replace_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), __new_value,
+ std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using replace_copy_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp1, typename _Tp2, output_iterator<const _Tp2&> _Out,
+ typename _Proj = identity>
+ requires indirectly_copyable<_Iter, _Out>
+ && indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>, const _Tp1*>
+ constexpr replace_copy_result<_Iter, _Out>
+ replace_copy(_Iter __first, _Sent __last, _Out __result,
+ const _Tp1& __old_value, const _Tp2& __new_value,
+ _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first, (void)++__result)
+ if (std::__invoke(__proj, *__first) == __old_value)
+ *__result = __new_value;
+ else
+ *__result = *__first;
+ return {std::move(__first), std::move(__result)};
+ }
+
+ template<input_range _Range, typename _Tp1, typename _Tp2,
+ output_iterator<const _Tp2&> _Out, typename _Proj = identity>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ && indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp1*>
+ constexpr replace_copy_result<safe_iterator_t<_Range>, _Out>
+ replace_copy(_Range&& __r, _Out __result,
+ const _Tp1& __old_value, const _Tp2& __new_value,
+ _Proj __proj = {})
+ {
+ return ranges::replace_copy(ranges::begin(__r), ranges::end(__r),
+ std::move(__result), __old_value,
+ __new_value, std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using replace_copy_if_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, output_iterator<const _Tp&> _Out,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr replace_copy_if_result<_Iter, _Out>
+ replace_copy_if(_Iter __first, _Sent __last, _Out __result,
+ _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first, (void)++__result)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ *__result = __new_value;
+ else
+ *__result = *__first;
+ return {std::move(__first), std::move(__result)};
+ }
+
+ template<input_range _Range,
+ typename _Tp, output_iterator<const _Tp&> _Out,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr replace_copy_if_result<safe_iterator_t<_Range>, _Out>
+ replace_copy_if(_Range&& __r, _Out __result,
+ _Pred __pred, const _Tp& __new_value, _Proj __proj = {})
+ {
+ return ranges::replace_copy_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__result), std::move(__pred),
+ __new_value, std::move(__proj));
+ }
+
+ template<typename _Tp, output_iterator<const _Tp&> _Out>
+ constexpr _Out
+ fill_n(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value)
+ {
+ // TODO: implement more specializations to be at least on par with
+ // std::fill_n
+ if (__n <= 0)
+ return __first;
+
+ // TODO: is __is_byte the best condition?
+ if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value)
+ {
+ __builtin_memset(__first, static_cast<unsigned char>(__value), __n);
+ return __first + __n;
+ }
+ else if constexpr (is_scalar_v<_Tp>)
+ {
+ const auto __tmp = __value;
+ for (; __n > 0; --__n, (void)++__first)
+ *__first = __tmp;
+ return __first;
+ }
+ else
+ {
+ for (; __n > 0; --__n, (void)++__first)
+ *__first = __value;
+ return __first;
+ }
+ }
+
+ template<typename _Tp,
+ output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent>
+ constexpr _Out
+ fill(_Out __first, _Sent __last, const _Tp& __value)
+ {
+ // TODO: implement more specializations to be at least on par with
+ // std::fill
+ if constexpr (sized_sentinel_for<_Sent, _Out>)
+ {
+ const auto __len = __last - __first;
+ return ranges::fill_n(__first, __len, __value);
+ }
+ else if constexpr (is_scalar_v<_Tp>)
+ {
+ const auto __tmp = __value;
+ for (; __first != __last; ++__first)
+ *__first = __tmp;
+ return __first;
+ }
+ else
+ {
+ for (; __first != __last; ++__first)
+ *__first = __value;
+ return __first;
+ }
+ }
+
+ template<typename _Tp, output_range<const _Tp&> _Range>
+ constexpr safe_iterator_t<_Range>
+ fill(_Range&& __r, const _Tp& __value)
+ {
+ return ranges::fill(ranges::begin(__r), ranges::end(__r), __value);
+ }
+
+ template<input_or_output_iterator _Out, copy_constructible _Fp>
+ requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>>
+ constexpr _Out
+ generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen)
+ {
+ for (; __n > 0; --__n, (void)++__first)
+ *__first = std::__invoke(__gen);
+ return __first;
+ }
+
+ template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent,
+ copy_constructible _Fp>
+ requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>>
+ constexpr _Out
+ generate(_Out __first, _Sent __last, _Fp __gen)
+ {
+ for (; __first != __last; ++__first)
+ *__first = std::__invoke(__gen);
+ return __first;
+ }
+
+ template<typename _Range, copy_constructible _Fp>
+ requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>>
+ constexpr safe_iterator_t<_Range>
+ generate(_Range&& __r, _Fp __gen)
+ {
+ return ranges::generate(ranges::begin(__r), ranges::end(__r),
+ std::move(__gen));
+ }
+
+ template<permutable _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr subrange<_Iter>
+ remove_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ __first = ranges::find_if(__first, __last, __pred, __proj);
+ if (__first == __last)
+ return {__first, __first};
+
+ auto __result = __first;
+ ++__first;
+ for (; __first != __last; ++__first)
+ if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ {
+ *__result = std::move(*__first);
+ ++__result;
+ }
+
+ return {__result, __first};
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires permutable<iterator_t<_Range>>
+ constexpr safe_subrange_t<_Range>
+ remove_if(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::remove_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<permutable _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity>
+ requires indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>,
+ const _Tp*>
+ constexpr subrange<_Iter>
+ remove(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {})
+ {
+ auto __pred = [&] (auto&& __arg) {
+ return std::forward<decltype(__arg)>(__arg) == __value;
+ };
+ return ranges::remove_if(__first, __last,
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<forward_range _Range, typename _Tp, typename _Proj = identity>
+ requires permutable<iterator_t<_Range>> &&
+ indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp*>
+ constexpr safe_subrange_t<_Range>
+ remove(_Range&& __r, const _Tp& __value, _Proj __proj = {})
+ {
+ return ranges::remove(ranges::begin(__r), ranges::end(__r),
+ __value, std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using remove_copy_if_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out, typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr remove_copy_if_result<_Iter, _Out>
+ remove_copy_if(_Iter __first, _Sent __last, _Out __result,
+ _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ {
+ *__result = *__first;
+ ++__result;
+ }
+ return {std::move(__first), std::move(__result)};
+ }
+
+ template<input_range _Range, weakly_incrementable _Out,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr remove_copy_if_result<safe_iterator_t<_Range>, _Out>
+ remove_copy_if(_Range&& __r, _Out __result,
+ _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::remove_copy_if(ranges::begin(__r), ranges::end(__r),
+ std::move(__result),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using remove_copy_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out, typename _Tp, typename _Proj = identity>
+ requires indirectly_copyable<_Iter, _Out>
+ && indirect_binary_predicate<ranges::equal_to,
+ projected<_Iter, _Proj>,
+ const _Tp*>
+ constexpr remove_copy_result<_Iter, _Out>
+ remove_copy(_Iter __first, _Sent __last, _Out __result,
+ const _Tp& __value, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (!(std::__invoke(__proj, *__first) == __value))
+ {
+ *__result = *__first;
+ ++__result;
+ }
+ return {std::move(__first), std::move(__result)};
+ }
+
+ template<input_range _Range, weakly_incrementable _Out,
+ typename _Tp, typename _Proj = identity>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ && indirect_binary_predicate<ranges::equal_to,
+ projected<iterator_t<_Range>, _Proj>,
+ const _Tp*>
+ constexpr remove_copy_result<safe_iterator_t<_Range>, _Out>
+ remove_copy(_Range&& __r, _Out __result,
+ const _Tp& __value, _Proj __proj = {})
+ {
+ return ranges::remove_copy(ranges::begin(__r), ranges::end(__r),
+ std::move(__result), __value,
+ std::move(__proj));
+
+ }
+
+ template<permutable _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_equivalence_relation<
+ projected<_Iter, _Proj>> _Comp = ranges::equal_to>
+ constexpr subrange<_Iter>
+ unique(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ __first = ranges::adjacent_find(__first, __last, __comp, __proj);
+ if (__first == __last)
+ return {__first, __first};
+
+ auto __dest = __first;
+ ++__first;
+ while (++__first != __last)
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__dest),
+ std::__invoke(__proj, *__first)))
+ *++__dest = std::move(*__first);
+ return {++__dest, __first};
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_equivalence_relation<
+ projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
+ requires permutable<iterator_t<_Range>>
+ constexpr safe_subrange_t<_Range>
+ unique(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::unique(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using unique_copy_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out, typename _Proj = identity,
+ indirect_equivalence_relation<
+ projected<_Iter, _Proj>> _Comp = ranges::equal_to>
+ requires indirectly_copyable<_Iter, _Out>
+ && (forward_iterator<_Iter>
+ || (input_iterator<_Out>
+ && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
+ || indirectly_copyable_storable<_Iter, _Out>)
+ constexpr unique_copy_result<_Iter, _Out>
+ unique_copy(_Iter __first, _Sent __last, _Out __result,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return {std::move(__first), std::move(__result)};
+
+ // TODO: perform a closer comparison with reference implementations
+ if constexpr (forward_iterator<_Iter>)
+ {
+ auto __next = __first;
+ *__result = *__next;
+ while (++__next != __last)
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__first),
+ std::__invoke(__proj, *__next)))
+ {
+ __first = __next;
+ *++__result = *__first;
+ }
+ return {__next, std::move(++__result)};
+ }
+ else if constexpr (input_iterator<_Out>
+ && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
+ {
+ *__result = *__first;
+ while (++__first != __last)
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__result),
+ std::__invoke(__proj, *__first)))
+ *++__result = *__first;
+ return {std::move(__first), std::move(++__result)};
+ }
+ else // indirectly_copyable_storable<_Iter, _Out>
+ {
+ auto __value = *__first;
+ *__result = __value;
+ while (++__first != __last)
+ {
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__first),
+ std::__invoke(__proj, __value)))
+ {
+ __value = *__first;
+ *++__result = __value;
+ }
+ }
+ return {std::move(__first), std::move(++__result)};
+ }
+ }
+
+ template<input_range _Range,
+ weakly_incrementable _Out, typename _Proj = identity,
+ indirect_equivalence_relation<
+ projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ && (forward_iterator<iterator_t<_Range>>
+ || (input_iterator<_Out>
+ && same_as<range_value_t<_Range>, iter_value_t<_Out>>)
+ || indirectly_copyable_storable<iterator_t<_Range>, _Out>)
+ constexpr unique_copy_result<safe_iterator_t<_Range>, _Out>
+ unique_copy(_Range&& __r, _Out __result,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::unique_copy(ranges::begin(__r), ranges::end(__r),
+ std::move(__result),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent>
+ requires permutable<_Iter>
+ constexpr _Iter
+ reverse(_Iter __first, _Sent __last)
+ {
+ auto __i = ranges::next(__first, __last);
+ auto __tail = __i;
+
+ if constexpr (random_access_iterator<_Iter>)
+ {
+ if (__first != __last)
+ {
+ --__tail;
+ while (__first < __tail)
+ {
+ ranges::iter_swap(__first, __tail);
+ ++__first;
+ --__tail;
+ }
+ }
+ return __i;
+ }
+ else
+ {
+ for (;;)
+ if (__first == __tail || __first == --__tail)
+ break;
+ else
+ {
+ ranges::iter_swap(__first, __tail);
+ ++__first;
+ }
+ return __i;
+ }
+ }
+
+ template<bidirectional_range _Range>
+ requires permutable<iterator_t<_Range>>
+ constexpr safe_iterator_t<_Range>
+ reverse(_Range&& __r)
+ {
+ return ranges::reverse(ranges::begin(__r), ranges::end(__r));
+ }
+
+ template<typename _Iter, typename _Out>
+ using reverse_copy_result = copy_result<_Iter, _Out>;
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr reverse_copy_result<_Iter, _Out>
+ reverse_copy(_Iter __first, _Sent __last, _Out __result)
+ {
+ auto __i = ranges::next(__first, __last);
+ auto __tail = __i;
+ while (__first != __tail)
+ {
+ --__tail;
+ *__result = *__tail;
+ ++__result;
+ }
+ return {__i, __result};
+ }
+
+ template<bidirectional_range _Range, weakly_incrementable _Out>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr reverse_copy_result<safe_iterator_t<_Range>, _Out>
+ reverse_copy(_Range&& __r, _Out __result)
+ {
+ return ranges::reverse_copy(ranges::begin(__r), ranges::end(__r),
+ std::move(__result));
+ }
+
+ template<permutable _Iter, sentinel_for<_Iter> _Sent>
+ constexpr subrange<_Iter>
+ rotate(_Iter __first, _Iter __middle, _Sent __last)
+ {
+ auto __lasti = ranges::next(__first, __last);
+ if (__first == __middle)
+ return {__lasti, __lasti};
+ if (__last == __middle)
+ return {std::move(__first), std::move(__lasti)};
+
+ if constexpr (random_access_iterator<_Iter>)
+ {
+ auto __n = __lasti - __first;
+ auto __k = __middle - __first;
+
+ if (__k == __n - __k)
+ {
+ ranges::swap_ranges(__first, __middle, __middle, __middle + __k);
+ return {std::move(__middle), std::move(__lasti)};
+ }
+
+ auto __p = __first;
+ auto __ret = __first + (__lasti - __middle);
+
+ for (;;)
+ {
+ if (__k < __n - __k)
+ {
+ // TODO: is_pod is deprecated, but this condition is
+ // consistent with the STL implementation.
+ if constexpr (__is_pod(iter_value_t<_Iter>))
+ if (__k == 1)
+ {
+ auto __t = std::move(*__p);
+ ranges::move(__p + 1, __p + __n, __p);
+ *(__p + __n - 1) = std::move(__t);
+ return {std::move(__ret), std::move(__lasti)};
+ }
+ auto __q = __p + __k;
+ for (decltype(__n) __i = 0; __i < __n - __k; ++ __i)
+ {
+ ranges::iter_swap(__p, __q);
+ ++__p;
+ ++__q;
+ }
+ __n %= __k;
+ if (__n == 0)
+ return {std::move(__ret), std::move(__lasti)};
+ ranges::swap(__n, __k);
+ __k = __n - __k;
+ }
+ else
+ {
+ __k = __n - __k;
+ // TODO: is_pod is deprecated, but this condition is
+ // consistent with the STL implementation.
+ if constexpr (__is_pod(iter_value_t<_Iter>))
+ if (__k == 1)
+ {
+ auto __t = std::move(*(__p + __n - 1));
+ ranges::move_backward(__p, __p + __n - 1, __p + __n);
+ *__p = std::move(__t);
+ return {std::move(__ret), std::move(__lasti)};
+ }
+ auto __q = __p + __n;
+ __p = __q - __k;
+ for (decltype(__n) __i = 0; __i < __n - __k; ++ __i)
+ {
+ --__p;
+ --__q;
+ ranges::iter_swap(__p, __q);
+ }
+ __n %= __k;
+ if (__n == 0)
+ return {std::move(__ret), std::move(__lasti)};
+ std::swap(__n, __k);
+ }
+ }
+ }
+ else if constexpr (bidirectional_iterator<_Iter>)
+ {
+ auto __tail = __lasti;
+
+ ranges::reverse(__first, __middle);
+ ranges::reverse(__middle, __tail);
+
+ while (__first != __middle && __middle != __tail)
+ {
+ ranges::iter_swap(__first, --__tail);
+ ++__first;
+ }
+
+ if (__first == __middle)
+ {
+ ranges::reverse(__middle, __tail);
+ return {std::move(__tail), std::move(__lasti)};
+ }
+ else
+ {
+ ranges::reverse(__first, __middle);
+ return {std::move(__first), std::move(__lasti)};
+ }
+ }
+ else
+ {
+ auto __first2 = __middle;
+ do
+ {
+ ranges::iter_swap(__first, __first2);
+ ++__first;
+ ++__first2;
+ if (__first == __middle)
+ __middle = __first2;
+ } while (__first2 != __last);
+
+ auto __ret = __first;
+
+ __first2 = __middle;
+
+ while (__first2 != __last)
+ {
+ ranges::iter_swap(__first, __first2);
+ ++__first;
+ ++__first2;
+ if (__first == __middle)
+ __middle = __first2;
+ else if (__first2 == __last)
+ __first2 = __middle;
+ }
+ return {std::move(__ret), std::move(__lasti)};
+ }
+ }
+
+ template<forward_range _Range>
+ requires permutable<iterator_t<_Range>>
+ constexpr safe_subrange_t<_Range>
+ rotate(_Range&& __r, iterator_t<_Range> __middle)
+ {
+ return ranges::rotate(ranges::begin(__r),
+ std::move(__middle),
+ ranges::end(__r));
+ }
+
+ template<typename _Iter, typename _Out>
+ using rotate_copy_result = copy_result<_Iter, _Out>;
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out>
+ requires indirectly_copyable<_Iter, _Out>
+ constexpr rotate_copy_result<_Iter, _Out>
+ rotate_copy(_Iter __first, _Iter __middle, _Sent __last, _Out __result)
+ {
+ auto __copy1 = ranges::copy(__middle,
+ std::move(__last),
+ std::move(__result));
+ auto __copy2 = ranges::copy(std::move(__first),
+ std::move(__middle),
+ std::move(__copy1.out));
+ return { std::move(__copy1.in), std::move(__copy2.out) };
+ }
+
+ template<forward_range _Range, weakly_incrementable _Out>
+ requires indirectly_copyable<iterator_t<_Range>, _Out>
+ constexpr rotate_copy_result<safe_iterator_t<_Range>, _Out>
+ rotate_copy(_Range&& __r, iterator_t<_Range> __middle, _Out __result)
+ {
+ return ranges::rotate_copy(ranges::begin(__r),
+ std::move(__middle),
+ ranges::end(__r),
+ std::move(__result));
+ }
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Gen>
+ requires permutable<_Iter>
+ && uniform_random_bit_generator<remove_reference_t<_Gen>>
+ _Iter
+ shuffle(_Iter __first, _Sent __last, _Gen&& __g)
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g));
+ return __lasti;
+ }
+
+ template<random_access_range _Range, typename _Gen>
+ requires permutable<iterator_t<_Range>>
+ && uniform_random_bit_generator<remove_reference_t<_Gen>>
+ safe_iterator_t<_Range>
+ shuffle(_Range&& __r, _Gen&& __g)
+ {
+ return ranges::shuffle(ranges::begin(__r), ranges::end(__r),
+ std::forward<_Gen>(__g));
+ }
+#endif
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ push_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::push_heap(__first, __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ push_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::push_heap(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ pop_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::pop_heap(__first, __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ pop_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::pop_heap(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ make_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::make_heap(__first, __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ make_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::make_heap(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ sort_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::sort_heap(__first, __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ sort_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::sort_heap(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ is_heap_until(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ iter_difference_t<_Iter> __n = ranges::distance(__first, __last);
+ iter_difference_t<_Iter> __parent = 0, __child = 1;
+ for (; __child < __n; ++__child)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *(__first + __parent)),
+ std::__invoke(__proj, *(__first + __child))))
+ return __first + __child;
+ else if ((__child & 1) == 0)
+ ++__parent;
+
+ return __first + __n;
+ }
+
+ template<random_access_range _Range,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ is_heap_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::is_heap_until(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ is_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return (__last
+ == ranges::is_heap_until(__first, __last,
+ std::move(__comp),
+ std::move(__proj)));
+ }
+
+ template<random_access_range _Range,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ is_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::is_heap(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ sort(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::sort(std::move(__first), __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::sort(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ _Iter
+ stable_sort(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::stable_sort(std::move(__first), __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ safe_iterator_t<_Range>
+ stable_sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::stable_sort(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ partial_sort(_Iter __first, _Iter __middle, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __middle)
+ return ranges::next(__first, __last);
+
+ ranges::make_heap(__first, __middle, __comp, __proj);
+ auto __i = __middle;
+ for (; __i != __last; ++__i)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *__first)))
+ {
+ ranges::pop_heap(__first, __middle, __comp, __proj);
+ ranges::iter_swap(__middle-1, __i);
+ ranges::push_heap(__first, __middle, __comp, __proj);
+ }
+ ranges::sort_heap(__first, __middle, __comp, __proj);
+
+ return __i;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ partial_sort(_Range&& __r, iterator_t<_Range> __middle,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::partial_sort(ranges::begin(__r),
+ std::move(__middle),
+ ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out>
+ using partial_sort_copy_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_copyable<_Iter1, _Iter2>
+ && sortable<_Iter2, _Comp, _Proj2>
+ && indirect_strict_weak_order<_Comp,
+ projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>>
+ constexpr partial_sort_copy_result<_Iter1, _Iter2>
+ partial_sort_copy(_Iter1 __first, _Sent1 __last,
+ _Iter2 __result_first, _Sent2 __result_last,
+ _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ if (__result_first == __result_last)
+ {
+ // TODO: Eliminating the variable __lasti triggers an ICE.
+ auto __lasti = ranges::next(std::move(__first),
+ std::move(__last));
+ return {std::move(__lasti), std::move(__result_first)};
+ }
+
+ auto __result_real_last = __result_first;
+ while (__first != __last && __result_real_last != __result_last)
+ {
+ *__result_real_last = *__first;
+ ++__result_real_last;
+ ++__first;
+ }
+
+ ranges::make_heap(__result_first, __result_real_last, __comp, __proj2);
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first),
+ std::__invoke(__proj2, *__result_first)))
+ {
+ ranges::pop_heap(__result_first, __result_real_last,
+ __comp, __proj2);
+ *(__result_real_last-1) = *__first;
+ ranges::push_heap(__result_first, __result_real_last,
+ __comp, __proj2);
+ }
+ ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2);
+
+ return {std::move(__first), std::move(__result_real_last)};
+ }
+
+ template<input_range _Range1, random_access_range _Range2,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires indirectly_copyable<iterator_t<_Range1>, iterator_t<_Range2>>
+ && sortable<iterator_t<_Range2>, _Comp, _Proj2>
+ && indirect_strict_weak_order<_Comp,
+ projected<iterator_t<_Range1>, _Proj1>,
+ projected<iterator_t<_Range2>, _Proj2>>
+ constexpr partial_sort_copy_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>>
+ partial_sort_copy(_Range1&& __r, _Range2&& __out, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::partial_sort_copy(ranges::begin(__r), ranges::end(__r),
+ ranges::begin(__out), ranges::end(__out),
+ std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ is_sorted_until(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return __first;
+
+ auto __next = __first;
+ for (++__next; __next != __last; __first = __next, (void)++__next)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__next),
+ std::__invoke(__proj, *__first)))
+ return __next;
+ return __next;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ is_sorted_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::is_sorted_until(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ is_sorted(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return true;
+
+ auto __next = __first;
+ for (++__next; __next != __last; __first = __next, (void)++__next)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__next),
+ std::__invoke(__proj, *__first)))
+ return false;
+ return true;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ is_sorted(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::is_sorted(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr _Iter
+ nth_element(_Iter __first, _Iter __nth, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::nth_element(std::move(__first), std::move(__nth), __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<random_access_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr safe_iterator_t<_Range>
+ nth_element(_Range&& __r, iterator_t<_Range> __nth,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::nth_element(ranges::begin(__r), std::move(__nth),
+ ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ lower_bound(_Iter __first, _Sent __last,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __len = ranges::distance(__first, __last);
+
+ while (__len > 0)
+ {
+ auto __half = __len / 2;
+ auto __middle = __first;
+ ranges::advance(__middle, __half);
+ if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value))
+ {
+ __first = __middle;
+ ++__first;
+ __len = __len - __half - 1;
+ }
+ else
+ __len = __half;
+ }
+ return __first;
+ }
+
+ template<forward_range _Range, typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*,
+ projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ lower_bound(_Range&& __r,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::lower_bound(ranges::begin(__r), ranges::end(__r),
+ __value,
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ upper_bound(_Iter __first, _Sent __last,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __len = ranges::distance(__first, __last);
+
+ while (__len > 0)
+ {
+ auto __half = __len / 2;
+ auto __middle = __first;
+ ranges::advance(__middle, __half);
+ if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle)))
+ __len = __half;
+ else
+ {
+ __first = __middle;
+ ++__first;
+ __len = __len - __half - 1;
+ }
+ }
+ return __first;
+ }
+
+ template<forward_range _Range, typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*,
+ projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ upper_bound(_Range&& __r,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::upper_bound(ranges::begin(__r), ranges::end(__r),
+ __value,
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr subrange<_Iter>
+ equal_range(_Iter __first, _Sent __last,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __len = ranges::distance(__first, __last);
+
+ while (__len > 0)
+ {
+ auto __half = __len / 2;
+ auto __middle = __first;
+ ranges::advance(__middle, __half);
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__middle),
+ __value))
+ {
+ __first = __middle;
+ ++__first;
+ __len = __len - __half - 1;
+ }
+ else if (std::__invoke(__comp,
+ __value,
+ std::__invoke(__proj, *__middle)))
+ __len = __half;
+ else
+ {
+ auto __left
+ = ranges::lower_bound(__first, __middle,
+ __value, __comp, __proj);
+ ranges::advance(__first, __len);
+ auto __right
+ = ranges::upper_bound(++__middle, __first,
+ __value, __comp, __proj);
+ return {__left, __right};
+ }
+ }
+ return {__first, __first};
+ }
+
+ template<forward_range _Range,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*,
+ projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_subrange_t<_Range>
+ equal_range(_Range&& __r, const _Tp& __value,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::equal_range(ranges::begin(__r), ranges::end(__r),
+ __value,
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ binary_search(_Iter __first, _Sent __last,
+ const _Tp& __value, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj);
+ if (__i == __last)
+ return false;
+ return !(bool)std::__invoke(__comp, __value, std::__invoke(__proj, *__i));
+ }
+
+ template<forward_range _Range,
+ typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<const _Tp*,
+ projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr bool
+ binary_search(_Range&& __r, const _Tp& __value, _Comp __comp = {},
+ _Proj __proj = {})
+ {
+ return ranges::binary_search(ranges::begin(__r), ranges::end(__r),
+ __value,
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr bool
+ is_partitioned(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ __first = ranges::find_if_not(std::move(__first), __last, __pred, __proj);
+ if (__first == __last)
+ return true;
+ ++__first;
+ return ranges::none_of(std::move(__first), std::move(__last),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr bool
+ is_partitioned(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::is_partitioned(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<permutable _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr subrange<_Iter>
+ partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ if constexpr (bidirectional_iterator<_Iter>)
+ {
+ auto __lasti = ranges::next(__first, __last);
+ auto __tail = __lasti;
+ for (;;)
+ {
+ for (;;)
+ if (__first == __tail)
+ return {std::move(__first), std::move(__lasti)};
+ else if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ ++__first;
+ else
+ break;
+ --__tail;
+ for (;;)
+ if (__first == __tail)
+ return {std::move(__first), std::move(__lasti)};
+ else if (!(bool)std::__invoke(__pred,
+ std::__invoke(__proj, *__tail)))
+ --__tail;
+ else
+ break;
+ ranges::iter_swap(__first, __tail);
+ ++__first;
+ }
+ }
+ else
+ {
+ if (__first == __last)
+ return {std::move(__first), std::move(__first)};
+
+ while (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ if (++__first == __last)
+ return {std::move(__first), std::move(__first)};
+
+ auto __next = __first;
+ while (++__next != __last)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__next)))
+ {
+ ranges::iter_swap(__first, __next);
+ ++__first;
+ }
+
+ return {std::move(__first), std::move(__next)};
+ }
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires permutable<iterator_t<_Range>>
+ constexpr safe_subrange_t<_Range>
+ partition(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::partition(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires permutable<_Iter>
+ subrange<_Iter>
+ stable_partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ auto __middle
+ = std::stable_partition(std::move(__first), __lasti,
+ __detail::__make_pred_proj(__pred, __proj));
+ return {std::move(__middle), std::move(__lasti)};
+ }
+
+ template<bidirectional_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires permutable<iterator_t<_Range>>
+ safe_subrange_t<_Range>
+ stable_partition(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::stable_partition(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter, typename _Out1, typename _O2>
+ struct partition_copy_result
+ {
+ [[no_unique_address]] _Iter in;
+ [[no_unique_address]] _Out1 out1;
+ [[no_unique_address]] _O2 out2;
+
+ template<typename _IIter, typename _OOut1, typename _OOut2>
+ requires convertible_to<const _Iter&, _IIter>
+ && convertible_to<const _Out1&, _OOut1>
+ && convertible_to<const _O2&, _OOut2>
+ operator partition_copy_result<_IIter, _OOut1, _OOut2>() const &
+ { return {in, out1, out2}; }
+
+ template<typename _IIter, typename _OOut1, typename _OOut2>
+ requires convertible_to<_Iter, _IIter>
+ && convertible_to<_Out1, _OOut1>
+ && convertible_to<_O2, _OOut2>
+ operator partition_copy_result<_IIter, _OOut1, _OOut2>() &&
+ { return {std::move(in), std::move(out1), std::move(out2)}; }
+ };
+
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out1, weakly_incrementable _O2,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ requires indirectly_copyable<_Iter, _Out1>
+ && indirectly_copyable<_Iter, _O2>
+ constexpr partition_copy_result<_Iter, _Out1, _O2>
+ partition_copy(_Iter __first, _Sent __last,
+ _Out1 __out_true, _O2 __out_false,
+ _Pred __pred, _Proj __proj = {})
+ {
+ for (; __first != __last; ++__first)
+ if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
+ {
+ *__out_true = *__first;
+ ++__out_true;
+ }
+ else
+ {
+ *__out_false = *__first;
+ ++__out_false;
+ }
+
+ return {std::move(__first), std::move(__out_true), std::move(__out_false)};
+ }
+
+ template<input_range _Range, weakly_incrementable _Out1,
+ weakly_incrementable _O2,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _Out1>
+ && indirectly_copyable<iterator_t<_Range>, _O2>
+ constexpr partition_copy_result<safe_iterator_t<_Range>, _Out1, _O2>
+ partition_copy(_Range&& __r, _Out1 out_true, _O2 out_false,
+ _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::partition_copy(ranges::begin(__r), ranges::end(__r),
+ std::move(out_true), std::move(out_false),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+ constexpr _Iter
+ partition_point(_Iter __first, _Sent __last,
+ _Pred __pred, _Proj __proj = {})
+ {
+ auto __len = ranges::distance(__first, __last);
+
+ while (__len > 0)
+ {
+ auto __half = __len / 2;
+ auto __middle = __first;
+ ranges::advance(__middle, __half);
+ if (std::__invoke(__pred, std::__invoke(__proj, *__middle)))
+ {
+ __first = __middle;
+ ++__first;
+ __len = __len - __half - 1;
+ }
+ else
+ __len = __half;
+ }
+ return __first;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ constexpr safe_iterator_t<_Range>
+ partition_point(_Range&& __r, _Pred __pred, _Proj __proj = {})
+ {
+ return ranges::partition_point(ranges::begin(__r), ranges::end(__r),
+ std::move(__pred), std::move(__proj));
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Out>
+ using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
+ constexpr merge_result<_Iter1, _Iter2, _Out>
+ merge(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Out __result,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ {
+ *__result = *__first2;
+ ++__first2;
+ }
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ }
+ ++__result;
+ }
+ auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
+ std::move(__result));
+ auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
+ std::move(__copy1.out));
+ return { std::move(__copy1.in), std::move(__copy2.in),
+ std::move(__copy2.out) };
+ }
+
+ template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
+ _Comp, _Proj1, _Proj2>
+ constexpr merge_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>,
+ _Out>
+ merge(_Range1&& __r1, _Range2&& __r2, _Out __result,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::merge(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less,
+ typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ _Iter
+ inplace_merge(_Iter __first, _Iter __middle, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __lasti = ranges::next(__first, __last);
+ std::inplace_merge(std::move(__first), std::move(__middle), __lasti,
+ __detail::__make_comp_proj(__comp, __proj));
+ return __lasti;
+ }
+
+ template<bidirectional_range _Range,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ safe_iterator_t<_Range>
+ inplace_merge(_Range&& __r, iterator_t<_Range> __middle,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::inplace_merge(ranges::begin(__r), std::move(__middle),
+ ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Proj1 = identity, typename _Proj2 = identity,
+ indirect_strict_weak_order<projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>>
+ _Comp = ranges::less>
+ constexpr bool
+ includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ return false;
+ else if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ ++__first1;
+ else
+ {
+ ++__first1;
+ ++__first2;
+ }
+
+ return __first2 == __last2;
+ }
+
+ template<input_range _Range1, input_range _Range2, typename _Proj1 = identity,
+ typename _Proj2 = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
+ projected<iterator_t<_Range2>, _Proj2>>
+ _Comp = ranges::less>
+ constexpr bool
+ includes(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::includes(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Out>
+ using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
+ constexpr set_union_result<_Iter1, _Iter2, _Out>
+ set_union(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Out __result, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ {
+ *__result = *__first1;
+ ++__first1;
+ }
+ else if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ {
+ *__result = *__first2;
+ ++__first2;
+ }
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ }
+ ++__result;
+ }
+ auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
+ std::move(__result));
+ auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
+ std::move(__copy1.out));
+ return {std::move(__copy1.in), std::move(__copy2.in),
+ std::move(__copy2.out)};
+ }
+
+ template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
+ _Comp, _Proj1, _Proj2>
+ constexpr set_union_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>, _Out>
+ set_union(_Range1&& __r1, _Range2&& __r2, _Out __result, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::set_union(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Out>
+ using set_intersection_result = binary_transform_result<_Iter1, _Iter2, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
+ constexpr set_intersection_result<_Iter1, _Iter2, _Out>
+ set_intersection(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Out __result,
+ _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ ++__first1;
+ else if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ ++__first2;
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ ++__result;
+ }
+ // TODO: Eliminating these variables triggers an ICE.
+ auto __last1i = ranges::next(std::move(__first1), std::move(__last1));
+ auto __last2i = ranges::next(std::move(__first2), std::move(__last2));
+ return {std::move(__last1i), std::move(__last2i), std::move(__result)};
+ }
+
+ template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
+ _Comp, _Proj1, _Proj2>
+ constexpr set_intersection_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>, _Out>
+ set_intersection(_Range1&& __r1, _Range2&& __r2, _Out __result,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::set_intersection(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<typename _Iter, typename _Out>
+ using set_difference_result = copy_result<_Iter, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
+ constexpr set_difference_result<_Iter1, _Out>
+ set_difference(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2, _Out __result,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__result;
+ }
+ else if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ ++__first2;
+ else
+ {
+ ++__first1;
+ ++__first2;
+ }
+ return ranges::copy(std::move(__first1), std::move(__last1),
+ std::move(__result));
+ }
+
+ template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
+ _Comp, _Proj1, _Proj2>
+ constexpr set_difference_result<safe_iterator_t<_Range1>, _Out>
+ set_difference(_Range1&& __r1, _Range2&& __r2, _Out __result,
+ _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return ranges::set_difference(ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__comp),
+ std::move(__proj1), std::move(__proj2));
+ }
+
+ template<typename _Iter1, typename _Iter2, typename _Out>
+ using set_symmetric_difference_result
+ = binary_transform_result<_Iter1, _Iter2, _Out>;
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ weakly_incrementable _Out, typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
+ constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out>
+ set_symmetric_difference(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Out __result, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__result;
+ }
+ else if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ {
+ *__result = *__first2;
+ ++__first2;
+ ++__result;
+ }
+ else
+ {
+ ++__first1;
+ ++__first2;
+ }
+ auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
+ std::move(__result));
+ auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
+ std::move(__copy1.out));
+ return {std::move(__copy1.in), std::move(__copy2.in),
+ std::move(__copy2.out)};
+ }
+
+ template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
+ typename _Comp = ranges::less,
+ typename _Proj1 = identity, typename _Proj2 = identity>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
+ _Comp, _Proj1, _Proj2>
+ constexpr set_symmetric_difference_result<safe_iterator_t<_Range1>,
+ safe_iterator_t<_Range2>,
+ _Out>
+ set_symmetric_difference(_Range1&& __r1, _Range2&& __r2, _Out __result,
+ _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return (ranges::set_symmetric_difference
+ (ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__result), std::move(__comp),
+ std::move(__proj1), std::move(__proj2)));
+ }
+
+ template<typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr const _Tp&
+ min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (std::__invoke(std::move(__comp),
+ std::__invoke(__proj, __b),
+ std::__invoke(__proj, __a)))
+ return __b;
+ else
+ return __a;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ requires indirectly_copyable_storable<iterator_t<_Range>,
+ range_value_t<_Range>*>
+ constexpr range_value_t<_Range>
+ min(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __first = ranges::begin(__r);
+ auto __last = ranges::end(__r);
+ __glibcxx_assert(__first != __last);
+ auto __result = *__first;
+ while (++__first != __last)
+ {
+ auto __tmp = *__first;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, __tmp),
+ std::__invoke(__proj, __result)))
+ __result = std::move(__tmp);
+ }
+ return __result;
+ }
+
+ template<copyable _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Tp
+ min(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::min(ranges::subrange(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr const _Tp&
+ max(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (std::__invoke(std::move(__comp),
+ std::__invoke(__proj, __a),
+ std::__invoke(__proj, __b)))
+ return __b;
+ else
+ return __a;
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ requires indirectly_copyable_storable<iterator_t<_Range>,
+ range_value_t<_Range>*>
+ constexpr range_value_t<_Range>
+ max(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __first = ranges::begin(__r);
+ auto __last = ranges::end(__r);
+ __glibcxx_assert(__first != __last);
+ auto __result = *__first;
+ while (++__first != __last)
+ {
+ auto __tmp = *__first;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, __result),
+ std::__invoke(__proj, __tmp)))
+ __result = std::move(__tmp);
+ }
+ return __result;
+ }
+
+ template<copyable _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Tp
+ max(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::max(ranges::subrange(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Tp>
+ struct minmax_result
+ {
+ [[no_unique_address]] _Tp min;
+ [[no_unique_address]] _Tp max;
+
+ template<typename _Tp2>
+ requires convertible_to<const _Tp&, _Tp2>
+ operator minmax_result<_Tp2>() const &
+ { return {min, max}; }
+
+ template<typename _Tp2>
+ requires convertible_to<_Tp, _Tp2>
+ operator minmax_result<_Tp2>() &&
+ { return {std::move(min), std::move(max)}; }
+ };
+
+ template<typename _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr minmax_result<const _Tp&>
+ minmax(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (std::__invoke(std::move(__comp),
+ std::__invoke(__proj, __b),
+ std::__invoke(__proj, __a)))
+ return {__b, __a};
+ else
+ return {__a, __b};
+ }
+
+ template<input_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ requires indirectly_copyable_storable<iterator_t<_Range>,
+ range_value_t<_Range>*>
+ constexpr minmax_result<range_value_t<_Range>>
+ minmax(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ auto __first = ranges::begin(__r);
+ auto __last = ranges::end(__r);
+ __glibcxx_assert(__first != __last);
+ minmax_result<range_value_t<_Range>> __result = {*__first, *__first};
+ while (++__first != __last)
+ {
+ auto __tmp = *__first;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, __tmp),
+ std::__invoke(__proj, __result.min)))
+ __result.min = std::move(__tmp);
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, __tmp),
+ std::__invoke(__proj, __result.max)))
+ __result.max = std::move(__tmp);
+ }
+ return __result;
+ }
+
+ template<copyable _Tp, typename _Proj = identity,
+ indirect_strict_weak_order<projected<const _Tp*, _Proj>>
+ _Comp = ranges::less>
+ constexpr minmax_result<_Tp>
+ minmax(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::minmax(ranges::subrange(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ min_element(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return __first;
+
+ auto __i = __first;
+ while (++__i != __last)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *__first)))
+ __first = __i;
+ }
+ return __first;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ min_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::min_element(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr _Iter
+ max_element(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return __first;
+
+ auto __i = __first;
+ while (++__i != __last)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__first),
+ std::__invoke(__proj, *__i)))
+ __first = __i;
+ }
+ return __first;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr safe_iterator_t<_Range>
+ max_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::max_element(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Iter>
+ using minmax_element_result = minmax_result<_Iter>;
+
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ indirect_strict_weak_order<projected<_Iter, _Proj>>
+ _Comp = ranges::less>
+ constexpr minmax_element_result<_Iter>
+ minmax_element(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return {__first, __first};
+
+ minmax_element_result<_Iter> __result = {__first, __first};
+ auto __i = __first;
+ while (++__i != __last)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *__result.min)))
+ __result.min = __i;
+ if (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *__result.max)))
+ __result.max = __i;
+ }
+ return __result;
+ }
+
+ template<forward_range _Range, typename _Proj = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
+ _Comp = ranges::less>
+ constexpr minmax_element_result<safe_iterator_t<_Range>>
+ minmax_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::minmax_element(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Proj1, typename _Proj2,
+ indirect_strict_weak_order<projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>> _Comp>
+ constexpr bool
+ __lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Comp __comp, _Proj1 __proj1, _Proj2 __proj2)
+ {
+ constexpr bool __sized_iters
+ = (sized_sentinel_for<_Sent1, _Iter1>
+ && sized_sentinel_for<_Sent2, _Iter2>);
+ if constexpr (__sized_iters)
+ {
+ auto __d1 = ranges::distance(__first1, __last1);
+ auto __d2 = ranges::distance(__first2, __last2);
+
+ using _ValueType1 = iter_value_t<_Iter1>;
+ using _ValueType2 = iter_value_t<_Iter2>;
+ constexpr bool __use_memcmp
+ = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>)
+ && is_same_v<_ValueType1, _ValueType2>
+ && is_pointer_v<_Iter1>
+ && is_pointer_v<_Iter2>
+ && (is_same_v<_Comp, ranges::less>
+ || is_same_v<_Comp, ranges::greater>)
+ && is_same_v<_Proj1, identity>
+ && is_same_v<_Proj2, identity>);
+ if constexpr (__use_memcmp)
+ {
+ if (const auto __len = std::min(__d1, __d2))
+ {
+ const auto __c = std::__memcmp(__first1, __first2, __len);
+ if constexpr (is_same_v<_Comp, ranges::less>)
+ {
+ if (__c < 0)
+ return true;
+ if (__c > 0)
+ return false;
+ }
+ else if constexpr (is_same_v<_Comp, ranges::greater>)
+ {
+ if (__c > 0)
+ return true;
+ if (__c < 0)
+ return false;
+ }
+ else
+ __builtin_unreachable();
+ }
+ return (__last1 - __first1 < __last2 - __first2);
+ }
+ }
+
+ for (; __first1 != __last1 && __first2 != __last2;
+ ++__first1, (void) ++__first2)
+ {
+ if (std::__invoke(__comp,
+ std::__invoke(__proj1, *__first1),
+ std::__invoke(__proj2, *__first2)))
+ return true;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj2, *__first2),
+ std::__invoke(__proj1, *__first1)))
+ return false;
+ }
+ return __first1 == __last1 && __first2 != __last2;
+ }
+
+ template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ typename _Proj1 = identity, typename _Proj2 = identity,
+ indirect_strict_weak_order<projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>>
+ _Comp = ranges::less>
+ constexpr bool
+ lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
+ _Iter2 __first2, _Sent2 __last2,
+ _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return (ranges::__lexicographical_compare
+ (std::__niter_base(std::move(__first1)),
+ std::__niter_base(std::move(__last1)),
+ std::__niter_base(std::move(__first2)),
+ std::__niter_base(std::move(__last2)),
+ std::move(__comp),
+ std::move(__proj1), std::move(__proj2)));
+ }
+
+ template<input_range _Range1, input_range _Range2, typename _Proj1 = identity,
+ typename _Proj2 = identity,
+ indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
+ projected<iterator_t<_Range2>, _Proj2>>
+ _Comp = ranges::less>
+ constexpr bool
+ lexicographical_compare(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
+ _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
+ {
+ return (ranges::lexicographical_compare
+ (ranges::begin(__r1), ranges::end(__r1),
+ ranges::begin(__r2), ranges::end(__r2),
+ std::move(__comp),
+ std::move(__proj1), std::move(__proj2)));
+ }
+
+ template<typename _Iter>
+ struct next_permutation_result
+ {
+ bool found;
+ _Iter in;
+ };
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr next_permutation_result<_Iter>
+ next_permutation(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return {false, std::move(__first)};
+
+ auto __i = __first;
+ ++__i;
+ if (__i == __last)
+ return {false, std::move(__i)};
+
+ auto __lasti = ranges::next(__first, __last);
+ __i = __lasti;
+ --__i;
+
+ for (;;)
+ {
+ auto __ii = __i;
+ --__i;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *__ii)))
+ {
+ auto __j = __lasti;
+ while (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *__i),
+ std::__invoke(__proj, *--__j)))
+ ;
+ ranges::iter_swap(__i, __j);
+ ranges::reverse(__ii, __last);
+ return {true, std::move(__lasti)};
+ }
+ if (__i == __first)
+ {
+ ranges::reverse(__first, __last);
+ return {false, std::move(__lasti)};
+ }
+ }
+ }
+
+ template<bidirectional_range _Range, typename _Comp = ranges::less,
+ typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr next_permutation_result<safe_iterator_t<_Range>>
+ next_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::next_permutation(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+ template<typename _Iter>
+ using prev_permutation_result = next_permutation_result<_Iter>;
+
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Comp = ranges::less, typename _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ constexpr prev_permutation_result<_Iter>
+ prev_permutation(_Iter __first, _Sent __last,
+ _Comp __comp = {}, _Proj __proj = {})
+ {
+ if (__first == __last)
+ return {false, std::move(__first)};
+
+ auto __i = __first;
+ ++__i;
+ if (__i == __last)
+ return {false, std::move(__i)};
+
+ auto __lasti = ranges::next(__first, __last);
+ __i = __lasti;
+ --__i;
+
+ for (;;)
+ {
+ auto __ii = __i;
+ --__i;
+ if (std::__invoke(__comp,
+ std::__invoke(__proj, *__ii),
+ std::__invoke(__proj, *__i)))
+ {
+ auto __j = __lasti;
+ while (!(bool)std::__invoke(__comp,
+ std::__invoke(__proj, *--__j),
+ std::__invoke(__proj, *__i)))
+ ;
+ ranges::iter_swap(__i, __j);
+ ranges::reverse(__ii, __last);
+ return {true, std::move(__lasti)};
+ }
+ if (__i == __first)
+ {
+ ranges::reverse(__first, __last);
+ return {false, std::move(__lasti)};
+ }
+ }
+ }
+
+ template<bidirectional_range _Range, typename _Comp = ranges::less,
+ typename _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ constexpr prev_permutation_result<safe_iterator_t<_Range>>
+ prev_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {})
+ {
+ return ranges::prev_permutation(ranges::begin(__r), ranges::end(__r),
+ std::move(__comp), std::move(__proj));
+ }
+
+} // namespace ranges
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // concepts
+#endif // C++20
+#endif // _RANGES_ALGO_H
@@ -60,6 +60,9 @@
#include <utility> // UK-300.
#include <bits/stl_algobase.h>
#include <bits/stl_algo.h>
+#if __cplusplus > 201703L
+# include <bits/ranges_algo.h>
+#endif
#if __cplusplus > 201402L
// Parallel STL algorithms
new file mode 100644
@@ -0,0 +1,68 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ int y[] = { 2, 7, 8, 8, 9 };
+
+ VERIFY( ranges::adjacent_find(x, x+6, {}, &X::i) == x+0 );
+ VERIFY( ranges::adjacent_find(x+1, x+6, {}, &X::i) == x+6 );
+ VERIFY( ranges::adjacent_find(y) == y+2 );
+ VERIFY( ranges::adjacent_find(y, y+4) == y+2 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ VERIFY( ranges::adjacent_find(c, {}, &X::i) == ranges::begin(c) );
+
+ test_range<int, forward_iterator_wrapper> r(y);
+ auto res = ranges::adjacent_find(r);
+ VERIFY( *res == 8 && *++res == 8 );
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ static constexpr X y[] = { {2}, {6}, {8}, {10}, {11} };
+ static_assert(ranges::adjacent_find(x, {}, &X::i) == x+0);
+ static_assert(ranges::adjacent_find(y, {}, &X::i) == y+5);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
+
new file mode 100644
@@ -0,0 +1,90 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+struct XLess
+{
+ int val;
+ bool operator()(X& x) const { return x.i < val; }
+};
+
+struct ILess
+{
+ int val;
+ bool operator()(int& i) const { return i < val; }
+};
+
+template<typename T>
+struct NotZero
+{
+ bool operator()(T& t) const { return t != 0; }
+};
+
+void
+test01()
+{
+ X x[] = { {2}, {4}, {6}, {8}, {10}, {11} };
+
+ VERIFY( ranges::all_of(x, x+5, XLess{11}) );
+ VERIFY( ranges::all_of(x, x+5, ILess{11}, &X::i) );
+ VERIFY( !ranges::all_of(x, x+6, ILess{11}, &X::i) );
+ VERIFY( !ranges::all_of(x, XLess{11}) );
+ VERIFY( ranges::all_of(x, XLess{12}) );
+ VERIFY( ranges::all_of(x, ILess{12}, &X::i) );
+ VERIFY( !ranges::all_of(x, ILess{11}, &X::i) );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ VERIFY( ranges::all_of(c, NotZero<int>{}, &X::i) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ VERIFY( ranges::all_of(r, NotZero<int>{}, &X::i) );
+
+ r.bounds.first = x;
+ VERIFY( ranges::all_of(r, NotZero<X* const>{}, [](X& x) { return &x; }) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::all_of(y, [](int j) { return j%2 == 0; }, &Y::j));
+ static_assert(ranges::all_of(y, [](const Y& y) { return y.j == y.i * 2; }));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,88 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+struct XLess
+{
+ int val;
+ bool operator()(X& x) const { return x.i < val; }
+};
+
+struct ILess
+{
+ int val;
+ bool operator()(int& i) const { return i < val; }
+};
+
+template<typename T>
+struct NotZero
+{
+ bool operator()(T& t) const { return t != 0; }
+};
+
+void
+test01()
+{
+ X x[] = { {2}, {4}, {6}, {8}, {10}, {11} };
+
+ VERIFY( ranges::any_of(x, x+6, XLess{3}) );
+ VERIFY( ranges::any_of(x, x+6, ILess{3}, &X::i) );
+ VERIFY( !ranges::any_of(x+1, x+6, XLess{3}) );
+ VERIFY( !ranges::any_of(x+1, x+6, ILess{3}, &X::i) );
+ VERIFY( ranges::any_of(x, XLess{5}) );
+ VERIFY( ranges::any_of(x, ILess{5}, &X::i) );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ VERIFY( ranges::any_of(c, NotZero<int>{}, &X::i) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ VERIFY( ranges::any_of(r, NotZero<int>{}, &X::i) );
+ VERIFY( ranges::any_of(r, NotZero<X* const>{}, [](X& x) { return &x; }) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::any_of(y, [](int i) { return i%2 == 0; }, &Y::i));
+ static_assert(ranges::any_of(y, [](const Y& y) { return y.i + y.j == 3; }));
+ static_assert(!ranges::any_of(y, [](const Y& y) { return y.i == y.j; }));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ float x[] = {1, 2, 3, 4, 5, 5, 6, 7};
+ test_container<float, forward_iterator_wrapper> cx(x);
+ for (int i = 0; i < 7; i++)
+ {
+ VERIFY( ranges::binary_search(cx, i, {}, [] (int a) { return a-1; }) );
+ VERIFY( !ranges::binary_search(cx.begin(), cx.end(), i+0.5) );
+ }
+ VERIFY( !ranges::binary_search(cx, 0) );
+
+ ranges::reverse(x);
+ test_range<float, forward_iterator_wrapper> rx(x);
+ VERIFY( ranges::binary_search(rx, 5, ranges::greater{}) );
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1, 2, 3};
+ return (ranges::binary_search(x, 3)
+ && !ranges::binary_search(x, x, 3));
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,225 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ {
+ int x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ int y[7] = { 0 };
+ int z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::copy(x, y);
+ VERIFY( ranges::equal(x, y) && in == x+7 && out == y+7 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ char y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_container<int, forward_iterator_wrapper> cx(x);
+ test_container<char, forward_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::copy(cx, ranges::begin(cy));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ char x[3] = { 1, 2, 3 };
+ int y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_range<char, input_iterator_wrapper> rx(x);
+ test_range<int, output_iterator_wrapper> ry(y);
+ auto [in, out] = ranges::copy(rx, ranges::begin(ry));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::copy(x, ranges::begin(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::copy(x, ranges::begin(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::copy(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.end()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::copy(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.end()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+}
+
+struct X
+{
+ int i;
+ constexpr X (int a) : i(a) { }
+};
+
+void
+test02()
+{
+ int x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ int z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::copy(x, y);
+ VERIFY( ranges::equal(x, x+5, y, y+5, {}, {}, &X::i) );
+ VERIFY( in == x+5 );
+ VERIFY( out == y+5 );
+ VERIFY( y[5].i == 2 );
+ VERIFY( ranges::equal(x, z) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ int x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ int z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::copy(x, y);
+ ok &= ranges::equal(x, x+5, y, y+5, {}, {}, &X::i);
+ ok &= (in == x+5);
+ ok &= (out == y+5);
+ ok &= (y[5].i == 2);
+ ok &= ranges::equal(x, z);
+ return ok;
+}
+
+struct Y
+{
+ int i;
+ int moved = 0;
+
+ constexpr Y(int a) : i(a) { }
+
+ constexpr Y(const Y&) = delete;
+ constexpr Y& operator=(const Y&) = delete;
+
+ constexpr Y(Y&& other)
+ {
+ *this = std::move(other);
+ }
+
+ constexpr Y&
+ operator=(Y&& other)
+ {
+ other.moved++;
+ i = other.i;
+ return *this;
+ }
+
+ friend constexpr bool
+ operator==(const Y& a, const Y& b)
+ { return a.i == b.i; }
+};
+
+void
+test04()
+{
+ Y x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ Y y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ Y z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ test_range<Y, input_iterator_wrapper> rx(x);
+ auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(rx)},
+ std::move_sentinel{ranges::end(rx)},
+ ranges::begin(y));
+ VERIFY( ranges::equal(x, y) && std::move(in).base().ptr == x+7 && out == y+7 );
+ VERIFY( ranges::equal(x, z) );
+ for (const auto& v : x)
+ VERIFY( v.moved == 1 );
+ for (const auto& v : y)
+ VERIFY( v.moved == 0 );
+}
+
+constexpr bool
+test05()
+{
+ bool ok = true;
+ Y x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ Y y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ Y z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(x)},
+ std::move_sentinel{ranges::end(x)},
+ ranges::begin(y));
+ ok &= ranges::equal(x, y);
+ ok &= in.base() == x+7;
+ ok &= out == y+7;
+ ok &= ranges::equal(x, z);
+ for (const auto& v : x)
+ ok &= v.moved == 1;
+ for (const auto& v : y)
+ ok &= v.moved == 0;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+ test04();
+ static_assert(test05());
+}
new file mode 100644
@@ -0,0 +1,193 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ {
+ int x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ int y[7] = { 0 };
+ int z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::copy_backward(x, ranges::end(y));
+ VERIFY( ranges::equal(x, y) && in == x+7 && out == y);
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ char y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_container<int, bidirectional_iterator_wrapper> cx(x);
+ test_container<char, bidirectional_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::copy_backward(cx, ranges::end(cy));
+ VERIFY( ranges::equal(x, x+3, y+1, y+4) && in.ptr == x+3 && out.ptr == y+1 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::copy_backward(x, ranges::end(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::copy_backward(x, ranges::end(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::copy_backward(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.begin()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::copy_backward(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.begin()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ int x[] = { {2}, {2}, {6}, {8}, {10} };
+ int y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ const int z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::copy_backward(x, ranges::end(y));
+ ok &= ranges::equal(x, x+5, y+1, y+6);
+ ok &= (in == x+5);
+ ok &= (out == y+1);
+ ok &= (y[0] == 2);
+ ok &= ranges::equal(x, z);
+ return ok;
+}
+
+/* move_iterators are always input_iterators and therefore do not model
+ * bidirectional_iterator, so I think the following tests are rightly invalid.
+
+struct Y
+{
+ int i;
+ int moved = 0;
+
+ constexpr Y(int a) : i(a) { }
+
+ constexpr Y(const Y&) = delete;
+ constexpr Y& operator=(const Y&) = delete;
+
+ constexpr Y(Y&& other)
+ {
+ *this = std::move(other);
+ }
+
+ constexpr Y&
+ operator=(Y&& other)
+ {
+ other.moved++;
+ i = other.i;
+ return *this;
+ }
+
+ friend constexpr bool
+ operator==(const Y& a, const Y& b)
+ { return a.i == b.i; }
+};
+
+void
+test02()
+{
+ Y x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ Y y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ Y z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ test_range<Y, bidirectional_iterator_wrapper> rx(x);
+ auto [in, out] = ranges::copy_backward(std::move_iterator{ranges::begin(rx)},
+ std::move_sentinel{ranges::end(rx)},
+ ranges::end(y));
+ VERIFY( ranges::equal(x, y) && std::move(in).base().ptr == x+7 && out == y );
+ VERIFY( ranges::equal(x, z) );
+ for (const auto& v : x)
+ VERIFY( v.moved == 1 );
+ for (const auto& v : y)
+ VERIFY( v.moved == 0 );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ Y x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ Y y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ Y z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::copy_backward(std::move_iterator{ranges::begin(x)},
+ std::move_sentinel{ranges::end(x)},
+ ranges::end(y));
+ ok &= ranges::equal(x, y);
+ ok &= in.base() == x+7;
+ ok &= out == y;
+ ok &= ranges::equal(x, z);
+ for (const auto& v : x)
+ ok &= v.moved == 1;
+ for (const auto& v : y)
+ ok &= v.moved == 0;
+ return ok;
+}
+*/
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1,2,3,4,5,6,7};
+
+ {
+ const int y[] = {2,4,6};
+ int w[7];
+ test_range<int, input_iterator_wrapper> rx(x);
+ test_range<int, output_iterator_wrapper> rw(w);
+ auto [in,out] = ranges::copy_if(rx, rw.begin(),
+ [] (int a) { return (a%2)==0; });
+ VERIFY( in == rx.end() && out.ptr == w+3 );
+ VERIFY( ranges::equal(w, w+3, y, y+3) );
+ }
+
+ {
+ const int y[] = {1,3,5,7};
+ int w[7];
+ test_range<int, input_iterator_wrapper> rx(x);
+ test_range<int, output_iterator_wrapper> rw(w);
+ auto [in,out] = ranges::copy_if(rx, rw.begin(),
+ [] (int a) { return (a%2)==0; },
+ [] (int a) { return a+1; });
+ VERIFY( in == rx.end() && out.ptr == w+4 );
+ VERIFY( ranges::equal(w, w+4, y, y+4) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3};
+ const int y[] = {1,3};
+ int w[3];
+ auto [in,out] = ranges::copy_if(x, w, [] (int a) { return (a%2)==1; });
+ return ranges::equal(w, out, y, y+2);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,72 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<template<typename> typename in_wrapper,
+ template<typename> typename out_wrapper>
+void
+test01()
+{
+ int x[] = {1,2,3,4,5,6,7};
+ for (int i = -1; i <= 7; i++)
+ {
+ test_range<int, in_wrapper> rx(x);
+ int w[7];
+ test_range<int, out_wrapper> rw(w);
+ ranges::copy_n(rx.begin(), i, rw.begin());
+ if (i >= 0)
+ VERIFY( ranges::equal(x, x+i, w, w+i) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3};
+ int y[2];
+ auto [in,out] = ranges::copy_n(x, 2, y);
+ return (in == x+2
+ && out == y+2
+ && ranges::equal(x, x+2, y, y+2));
+}
+
+int
+main()
+{
+ test01<input_iterator_wrapper,
+ output_iterator_wrapper>();
+ test01<random_access_iterator_wrapper,
+ output_iterator_wrapper>();
+ test01<random_access_iterator_wrapper,
+ random_access_iterator_wrapper>();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,75 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {2} };
+ auto res = ranges::count(x, x+7, 2, &X::i);
+ VERIFY( res == 3 );
+ res = ranges::count(x, x+7, 8, &X::i);
+ VERIFY( res == 1 );
+ res = ranges::count(x, x+7, 9, &X::i);
+ VERIFY( res == 0 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ res = ranges::count(c, 6, &X::i);
+ VERIFY( res == 1 );
+ res = ranges::count(c, 9, &X::i);
+ VERIFY( res == 0 );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ res = ranges::count(r, 2, &X::i);
+ VERIFY( res == 3 );
+
+ r.bounds.first = x;
+ res = ranges::count(r, 9, &X::i);
+ VERIFY( res == 0 );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6}, {1,6} };
+ static_assert(ranges::count(y, 6, &Y::j) == 2);
+ static_assert(ranges::count(y, 5, &Y::j) == 0);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,73 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {2} };
+ auto res = ranges::count_if(x, x+7, [] (int i) { return i % 2 == 0; }, &X::i);
+ VERIFY( res == 6 );
+ res = ranges::count_if(x, x+7, [] (int i) { return i % 2 == 1; }, &X::i);
+ VERIFY( res == 1 );
+ res = ranges::count_if(x, x+7, [] (int i) { return i < 0; }, &X::i);
+ VERIFY( res == 0 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ res = ranges::count_if(c, [] (int i) { return i == 2; }, &X::i);
+ VERIFY( res == 3 );
+ res = ranges::count_if(c, [] (int i) { return i < 0; }, &X::i);
+ VERIFY( res == 0 );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ res = ranges::count_if(c, [] (int i) { return i == 2; }, &X::i);
+ VERIFY( res == 3 );
+ res = ranges::count_if(c, [] (int i) { return i < 0; }, &X::i);
+ VERIFY( res == 0 );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6}, {1,6} };
+ static_assert(ranges::count_if(y, [] (int i) { return i < 5; }, &Y::j) == 2);
+ static_assert(ranges::count_if(y, [] (int i) { return i != 4; }, &Y::j) == 3);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,96 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ int x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {11} };
+ int y[] = { {2}, {2}, {6}, {8}, {10}, {11}, {11} };
+ X z[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+ int w[] = { {1}, {1}, {1}, {1}, {1} };
+
+ VERIFY( ranges::equal(w, w+4, w+1, w+5) );
+ VERIFY( ranges::equal(w, w+5, w, w+5, ranges::greater{},
+ [] (int a) { return a+1; }) );
+
+ test_container<int, forward_iterator_wrapper> cx(x), cy(y);
+ test_container<X, forward_iterator_wrapper> cz(z);
+ VERIFY( ranges::equal(cx, cy) );
+ VERIFY( !ranges::equal(cx, cy, {}, [] (int a) { return a+1; }) );
+ VERIFY( !ranges::equal(cx, cz, {}, {}, &X::i) );
+
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ test_range<X, input_iterator_wrapper> rz(z);
+ VERIFY( ranges::equal(rx, ry) );
+
+ rx.bounds.first = x;
+ ry.bounds.first = y;
+ VERIFY( !ranges::equal(rx, ry, {}, {}, [] (int a) { return a+1; }) );
+
+ rx.bounds.first = x;
+ rz.bounds.first = z;
+ VERIFY( !ranges::equal(rx, rz, {}, {}, &X::i) );
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ static constexpr X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+ static constexpr int w[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+
+ static_assert(ranges::equal(z, w));
+ static_assert(!ranges::equal(z, z+5, w+1, w+6));
+ static_assert(!ranges::equal(z, z, {}, {}, [] (int a) { return a+1; }));
+ static_assert(!ranges::equal(x, y, {}, &X::i, &X::i));
+}
+
+void
+test03()
+{
+ std::vector<int> x = { {2}, {2}, {6}, {8}, {10}, {11} };
+ std::vector<int> y = { {2}, {2}, {6}, {8}, {10}, {11} };
+ std::vector<int> z = { {2}, {2}, {6}, {8}, {10}, {12} };
+ VERIFY( ranges::equal(x, y) );
+ VERIFY( !ranges::equal(x, z) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
new file mode 100644
@@ -0,0 +1,69 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1, 2, 3, 4, 5, 5, 6, 7};
+ for (unsigned i = 0; i < 5; i++)
+ for (unsigned j = 6; j < 8; j++)
+ {
+ test_container<int, forward_iterator_wrapper> cx(x);
+ auto range = ranges::equal_range(std::next(cx.begin(), i),
+ std::next(cx.begin(), j),
+ 4, {}, [] (int a) { return a-1; });
+ VERIFY( range.begin().ptr == x+4 && range.end().ptr == x+6 );
+ }
+
+ ranges::reverse(x);
+ test_range<int, forward_iterator_wrapper> rx(x);
+ auto range = ranges::equal_range(rx, 5, ranges::greater{},
+ [] (int a) { return a+1; });
+ VERIFY( range.begin().ptr == x+4 && range.end().ptr == x+5 );
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ auto range1 = ranges::equal_range(x, 6);
+ auto range2 = ranges::equal_range(x, x, 6);
+ auto range3 = ranges::equal_range(x, 1);
+ return (range1.begin() == x+5 && range1.end() == x+5
+ && range2.begin() == x && range2.end() == x
+ && range3.begin() == x && range3.end() == x+1);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,92 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <list>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+};
+
+void
+test01()
+{
+ const int c[6] = { 17, 17, 17, 17, 17, 17 };
+ {
+ X x[6];
+ VERIFY( ranges::fill(x, X{17}) == x+6 );
+ VERIFY( ranges::equal(x, c, {}, &X::i) );
+ }
+
+ {
+ char x[6];
+ VERIFY( ranges::fill(x, 17) == x+6 );
+ VERIFY( ranges::equal(x, c) );
+ }
+
+ {
+ X x[6];
+ test_container<X, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::fill(cx, X{17}) == cx.end() );
+ VERIFY( ranges::equal(cx, c, {}, &X::i) );
+ }
+
+ {
+ int x[6];
+ test_range<int, output_iterator_wrapper> rx(x);
+ VERIFY( ranges::fill(rx, 17) == rx.end() );
+ VERIFY( ranges::equal(x, c) );
+ }
+
+ {
+ std::list<int> list(6);
+ ranges::fill(list, 17);
+ VERIFY( ranges::equal(list, c) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ int x[5];
+ ranges::fill(x, 17);
+ for (auto v : x)
+ ok &= v == 17;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <list>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+};
+
+void
+test01()
+{
+ const int c[6] = { 17, 17, 17, 4, 5, 6 };
+ {
+ X x[6] = { {1}, {2}, {3}, {4}, {5}, {6} };
+ VERIFY( ranges::fill_n(x, 3, X{17}) == x+3 );
+ VERIFY( ranges::equal(x, c, {}, &X::i) );
+ }
+
+ {
+ char x[6];
+ VERIFY( ranges::fill_n(x, 3, 17) == x+3 );
+ VERIFY( ranges::equal(x, x+3, c, c+3) );
+ }
+
+ {
+ X x[6] = { 1, 2, 3, 4, 5, 6 };
+ test_container<X, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::fill_n(cx.begin(), 3, X{17})->i == 4 );
+ VERIFY( ranges::equal(cx, c, {}, &X::i) );
+ }
+
+ {
+ int x[6] = { 1, 2, 3, 4, 5, 6 };;
+ test_range<int, output_iterator_wrapper> rx(x);
+ ranges::fill_n(ranges::begin(rx), 3, 17);
+ VERIFY( ranges::equal(x, c) );
+ }
+
+ {
+ std::list<int> list({1, 2, 3, 4, 5, 6});
+ ranges::fill_n(list.begin(), 3, 17);
+ VERIFY( ranges::equal(list, c) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ int x[6] = { 1, 2, 3, 4, 5, 6 };
+ const int y[6] = { 1, 2, 3, 4, 5, 6 };
+ const int z[6] = { 17, 17, 17, 4, 5, 6 };
+
+ ranges::fill_n(x, 0, 17);
+ ranges::fill_n(x, -1, 17);
+ ok &= ranges::equal(x, y);
+
+ ranges::fill_n(x, 3, 17);
+ ok &= ranges::equal(x, z);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,75 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::find(x, x+6, 8, &X::i);
+ VERIFY( res == x+3 );
+ res = ranges::find(x, x+6, 2, &X::i);
+ VERIFY( res == x+0 );
+ res = ranges::find(x, x+6, 9, &X::i);
+ VERIFY( res == x+6 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res2 = ranges::find(c, 8, &X::i);
+ VERIFY( res2 != ranges::end(c) && res2->i == 8 );
+ res2 = ranges::find(c, 9, &X::i);
+ VERIFY( res2 == ranges::end(c) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ auto res3 = ranges::find(r, 8, &X::i);
+ VERIFY( res3 != ranges::end(r) && res3->i == 8 );
+
+ r.bounds.first = x;
+ res3 = ranges::find(r, 9, &X::i);
+ VERIFY( res3 == ranges::end(r) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::find(y, 4, &Y::j) == y+1);
+ static_assert(ranges::find(y, 5, &Y::j) == y+3);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {10}, {11}, {2}, {6}, {8}, {10}, {11} };
+ X y[] = { {10}, {11} };
+ {
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res = ranges::find_end(c, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(c) );
+ res = ranges::find_end(c, c, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(c)
+ && std::get<1>(res) == ranges::end(c) );
+ }
+
+ {
+ test_range<X, forward_iterator_wrapper> r(x);
+ auto res = ranges::find_end(r, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) );
+ res = ranges::find_end(r, r, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(r)
+ && std::get<1>(res) == ranges::end(r) );
+ }
+
+ {
+ test_range<X, bidirectional_iterator_wrapper> r(x);
+ auto res = ranges::find_end(r, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) );
+ res = ranges::find_end(r, r, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(r)
+ && std::get<1>(res) == ranges::end(r) );
+ }
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {6}, {8}, {11} };
+ static constexpr X y[] = { {6}, {8} };
+ static constexpr int z[] = { 2, 8 };
+ static constexpr int w[] = { 2 };
+
+ static_assert(std::get<0>(ranges::find_end(x, y, {}, &X::i, &X::i)) == x+5);
+ static_assert(std::get<1>(ranges::find_end(x, y, {}, &X::i, &X::i)) == x+7);
+
+ static_assert(std::get<0>(ranges::find_end(x, z, {}, &X::i)) == x+8);
+ static_assert(std::get<1>(ranges::find_end(x, z, {}, &X::i)) == x+8);
+
+ static_assert(std::get<0>(ranges::find_end(x, w, {}, &X::i)) == x+1);
+ static_assert(std::get<1>(ranges::find_end(x, w, {}, &X::i)) == x+2);
+
+ static_assert(std::get<0>(ranges::find_end(x, x+6, w, w, {}, &X::i)) == x+6);
+ static_assert(std::get<1>(ranges::find_end(x, x+6, w, w, {}, &X::i)) == x+6);
+
+ static_assert(std::get<0>(ranges::find_end(x, x, w, w+1, {}, &X::i)) == x+0);
+ static_assert(std::get<1>(ranges::find_end(x, x, w, w+1, {}, &X::i)) == x+0);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,83 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ int y[] = { 2, 7, 8, 9 };
+ X w[] = { {2}, {7}, {8}, {9} };
+
+ auto res = ranges::find_first_of(x, x+6, y+1, y+4, {}, &X::i);
+ VERIFY( res == x+3 );
+ res = ranges::find_first_of(x, x+6, w, w+4, {}, &X::i, &X::i);
+ VERIFY( res == x+0 );
+ res = ranges::find_first_of(x, x+6, y+3, y+4, {}, &X::i);
+ VERIFY( res == x+6 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ test_container<int, forward_iterator_wrapper> d1(y+1, y+4);
+ auto res2 = ranges::find_first_of(c, d1, {}, &X::i);
+ VERIFY( res2 != ranges::end(c) && res2->i == 8 );
+
+ test_container<X, forward_iterator_wrapper> d2(w+3, w+4);
+ res2 = ranges::find_first_of(c, d2, {}, &X::i, &X::i);
+ VERIFY( res2 == ranges::end(c) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ test_range<int, forward_iterator_wrapper> s1(y+1, y+4);
+ auto res3 = ranges::find_first_of(r, s1, {}, &X::i);
+ VERIFY( res3 != ranges::end(r) && res3->i == 8 );
+
+ test_range<X, forward_iterator_wrapper> s2(w+3, w+4);
+ r.bounds.first = x;
+ res3 = ranges::find_first_of(r, s2, {}, &X::i, &X::i);
+ VERIFY( res3 == ranges::end(r) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::find_first_of(y, y, {}, &Y::j, &Y::i) == y);
+ static_assert(ranges::find_first_of(y, y, {}, &Y::i, &Y::j) == y+1);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::find_if(x, x+6, [] (X& v) { return v.i == 8; });
+ VERIFY( res == x+3 );
+ res = ranges::find_if(x, x+6, [] (X& v) { return v.i % 2 == 0; });
+ VERIFY( res == x+0 );
+ res = ranges::find_if(x, x+6, [] (X& v) { return v.i == 9; });
+ VERIFY( res == x+6 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res2 = ranges::find_if(c, [] (int i) { return i > 7; }, &X::i);
+ VERIFY( res2 != ranges::end(c) && res2->i == 8 );
+ res2 = ranges::find_if(c, [] (int i) { return i > 11; }, &X::i);
+ VERIFY( res2 == ranges::end(c) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ auto res3 = ranges::find_if(r, [] (int i) { return i > 10; }, &X::i);
+ VERIFY( res3 != ranges::end(r) && res3->i == 11 );
+
+ r.bounds.first = x;
+ res3 = ranges::find_if(r, [] (int i) { return i == 9; }, &X::i);
+ VERIFY( res3 == ranges::end(r) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::find_if(y, [] (int i) { return i > 3; }, &Y::j)
+ == y+1);
+ static_assert(ranges::find_if(y, [] (int i) { return i == 5; }, &Y::j)
+ == y+3);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i != 8; });
+ VERIFY( res == x+3 );
+ res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i % 2 == 1; });
+ VERIFY( res == x+0 );
+ res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i != 9; });
+ VERIFY( res == x+6 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res2 = ranges::find_if_not(c, [] (int i) { return i <= 7; }, &X::i);
+ VERIFY( res2 != ranges::end(c) && res2->i == 8 );
+ res2 = ranges::find_if_not(c, [] (int i) { return i <= 11; }, &X::i);
+ VERIFY( res2 == ranges::end(c) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ auto res3 = ranges::find_if_not(r, [] (int i) { return i <= 10; }, &X::i);
+ VERIFY( res3 != ranges::end(r) && res3->i == 11 );
+
+ r.bounds.first = x;
+ res3 = ranges::find_if_not(r, [] (int i) { return i != 9; }, &X::i);
+ VERIFY( res3 == ranges::end(r) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(ranges::find_if_not(y, [] (int i) { return i <= 3; }, &Y::j)
+ == y+1);
+ static_assert(ranges::find_if_not(y, [] (int i) { return i != 5; }, &Y::j)
+ == y+3);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,83 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+static int a;
+
+void
+f(int& i)
+{
+ a += i;
+}
+
+void
+test01()
+{
+ X x[] = { {2}, {4}, {6}, {8}, {10}, {11} };
+
+ auto res = ranges::for_each(x, x+6, f, &X::i);
+ VERIFY( res.in == x+6 );
+ VERIFY( res.fun == &f );
+ VERIFY( a == 41 );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ int p = 0;
+ ranges::for_each(c, [&p](int i) { ++p; }, &X::i);
+ VERIFY( p == 6 );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ int q = 0;
+ ranges::for_each(r, [&q](X&) { ++q; });
+ VERIFY( q == 6 );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ auto f = []
+ {
+ Y y[] = { {1,2}, {2,4}, {3,6} };
+ int a = 0;
+ ranges::for_each(y, [&a](int i) { a += i; }, &Y::i);
+ return a;
+ };
+ static_assert(f() == 6);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ const int c[6] = { 1, 2, 3, 4, 5, 6 };
+
+ {
+ int x[6];
+ int a = 1;
+ VERIFY( ranges::generate(x, [&] { return a++; }) == x+6 );
+ VERIFY( ranges::equal(x, c) );
+ }
+
+ {
+ int x[6];
+ int a = 1;
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::generate(cx, [&] { return a++; }) == cx.end() );
+ VERIFY( ranges::equal(cx, c) );
+ }
+
+ {
+ int x[6];
+ int a = 1;
+ test_range<int, output_iterator_wrapper> rx(x);
+ VERIFY( ranges::generate(rx, [&] { return a++; }) == rx.end() );
+ VERIFY( ranges::equal(x, c) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ const int c[6] = { 1, 2, 3, 4, 5, 6 };
+ int x[6];
+ int a = 1;
+ ranges::generate(x, [&] { return a++; });
+ return ranges::equal(x, c);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,84 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ const int c[6] = { 1, 2, 3, 4, 5, 6 };
+
+ {
+ int x[6] = { 7, 8, 9, 4, 5, 6 };
+ int a = 1;
+ VERIFY( ranges::generate_n(x, 3, [&] { return a++; }) == x+3 );
+ VERIFY( ranges::equal(x, c) );
+ }
+
+ {
+ int x[6] = { 7, 8, 9, 4, 5, 6 };
+ int a = 1;
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( *ranges::generate_n(cx.begin(), 3, [&] { return a++; })
+ == 4 );
+ VERIFY( ranges::equal(cx, c) );
+ }
+
+ {
+ int x[6] = { 7, 8, 9, 4, 5, 6 };
+ int a = 1;
+ test_range<int, output_iterator_wrapper> rx(x);
+ ranges::generate_n(ranges::begin(rx), 3, [&] { return a++; });
+ VERIFY( ranges::equal(x, c) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ int c[6] = { 1, 2, 3, 4, 5, 6 };
+ int x[6];
+ int a = 1;
+ ranges::generate_n(x, 6, [&] { return a++; });
+ ok &= ranges::equal(x, c);
+ ranges::generate_n(c, 0, [] { return -1; });
+ ok &= ranges::equal(x, c);
+ ranges::generate_n(c, -2, [] { return -1; });
+ ok &= ranges::equal(x, c);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,107 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<template<typename, template<typename> typename> typename container>
+void
+test01()
+{
+ int x[50];
+
+ auto pred = std::greater{};
+ auto proj = [] (int a) { return -a; };
+ for (int i = 0; i < 50; i++)
+ {
+ std::iota(x, x+50, 1);
+ container<int, random_access_iterator_wrapper> rx(x);
+
+ std::ranlux48_base g(i);
+ ranges::shuffle(rx, g);
+
+ auto iter = ranges::make_heap(rx, pred, proj);
+ VERIFY( iter == rx.end() );
+ VERIFY( ranges::is_heap(rx, pred, proj) );
+ VERIFY( ranges::is_heap_until(rx, pred, proj) == rx.end() );
+
+ iter = ranges::pop_heap(rx, pred, proj);
+ VERIFY( iter == rx.end() );
+ VERIFY( *(iter-1) == 50 );
+ VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 );
+
+ iter = ranges::pop_heap(rx.begin(), iter-1, pred, proj);
+ VERIFY( iter+1 == rx.end() );
+ VERIFY( *(iter-1) == 49 );
+ VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 );
+
+ *(iter-1) = i;
+ iter = ranges::push_heap(rx.begin(), iter, pred, proj);
+ VERIFY( iter+1 == rx.end() );
+ VERIFY( ranges::is_heap_until(rx, pred, proj) == iter );
+
+ *iter = 2*i;
+ iter = ranges::push_heap(rx.begin(), rx.end(), pred, proj);
+ VERIFY( iter == rx.end() );
+ VERIFY( ranges::is_heap_until(rx, pred, proj) == iter );
+
+ *(rx.begin()+1) *= -1;
+ VERIFY( !ranges::is_heap(rx, pred, proj) );
+ *(rx.begin()+1) *= -1;
+ VERIFY( ranges::is_heap(rx, pred, proj) );
+
+ iter = ranges::sort_heap(rx, pred, proj);
+ VERIFY( iter == rx.end() );
+ VERIFY( ranges::is_sorted(rx, pred, proj) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ int x[] = {1,2,3,4,5};
+ ranges::make_heap(x);
+ ranges::pop_heap(x);
+ x[4] = 7;
+ ranges::push_heap(x);
+ ok &= ranges::is_heap(x);
+ ok &= ranges::is_heap_until(x) == x+5;
+ ranges::sort_heap(x);
+ ok &= ranges::equal(x, (int[]){1,2,3,4,7});
+ return ok;
+}
+
+int
+main()
+{
+ test01<test_range>();
+ test01<test_container>();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,74 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1,2,3,4,5,6,7};
+ int y[] = {2,4,6};
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+
+ VERIFY( ranges::includes(rx, ry) );
+
+ rx.bounds.first = x;
+ ry.bounds.first = y;
+ VERIFY( ranges::includes(rx, ry,
+ ranges::greater{},
+ std::negate<>{},
+ std::negate<>{}) );
+
+ test_container<int, forward_iterator_wrapper> cx(x), cy(y);
+ VERIFY( ranges::includes(cx.begin(), cx.end(),
+ cy.begin(), cy.end(),
+ {},
+ [] (int a) { return a+1; },
+ [] (int a) { return a+2; }) );
+
+ VERIFY( ranges::includes(x, x+1, y, y) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ ok &= ranges::includes((int[]){1,2,3},
+ (int[]){1});
+ ok &= !ranges::includes((int[]){1,2,3},
+ (int[]){1,2,3,4});
+ return true;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,69 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1,2,3,4,5};
+ for (int i = 0; i <= 5; i++)
+ for (int j = 0; j <= 5; j++)
+ {
+ std::vector<int> v(x, x+i);
+ v.insert(v.end(), x, x+j);
+ ranges::sort(v);
+
+ test_range<int, bidirectional_iterator_wrapper> rz(&v[0], &v[0]+i+j);
+ auto result = ranges::inplace_merge(rz, next(ranges::begin(rz), i));
+ VERIFY( result == rz.end() );
+
+ VERIFY( ranges::is_sorted(rz) );
+ }
+}
+
+void
+test02()
+{
+ struct X { int i, j; };
+ X x[] = { {1, 1}, {3, 4}, {5, 5}, {2, 2}, {2, 3} };
+ auto comp = ranges::greater{};
+ auto proj = [] (X a) { return -a.i; };
+ ranges::inplace_merge(x, x+3, x+5, comp, proj);
+ VERIFY( ranges::is_sorted(x, {}, &X::i) );
+ VERIFY( ranges::is_sorted(x, {}, &X::j) );
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,58 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {2,4,6,1,3,5};
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::is_partitioned(cx, [] (int a) { return a%2==0; }) );
+
+ test_range<int, input_iterator_wrapper> rx(x);
+ VERIFY( ranges::is_partitioned(rx,
+ [] (int a) { return a%2==1; },
+ [] (int a) { return a+1; }) );
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3,4,5,6,1};
+ return (ranges::is_partitioned(x, x+6, [] (int a) { return a<=2; })
+ && !ranges::is_partitioned(x, x+7, [] (int a) { return a<=2; }));
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,85 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ int x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ int y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ int z[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+
+ VERIFY( ranges::is_permutation(x, x+6, y, y+6) );
+ VERIFY( !ranges::is_permutation(x, x+6, y, y+5) );
+
+ test_container<int, forward_iterator_wrapper> cx(x), cy(y), cz(z);
+ test_range<int, forward_iterator_wrapper> rx(x), ry(y), rz(z);
+ VERIFY( ranges::is_permutation(cx, ry) );
+ VERIFY( !ranges::is_permutation(rx, cz) );
+ VERIFY( ranges::is_permutation(rx, cy) );
+ VERIFY( !ranges::is_permutation(cx, rz) );
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ static constexpr X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+ static_assert(ranges::is_permutation(x, y, {}, &X::i, &X::i));
+ static_assert(!ranges::is_permutation(x, z, {}, &X::i));
+ static_assert(!ranges::is_permutation(z, y, {}, {}, &X::i));
+}
+
+void
+test03()
+{
+ int x[] = { 1, 2, 3, 4 };
+ int y[] = { 1, 2, 3, 3 };
+ test_container<int, bidirectional_iterator_wrapper> cx(x);
+ do
+ do
+ {
+ VERIFY( ranges::is_permutation(cx, x) );
+ VERIFY( !ranges::is_permutation(y, cx) );
+ } while (std::next_permutation(y, y+4));
+ while (std::next_permutation(std::begin(cx), std::end(cx)));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
new file mode 100644
@@ -0,0 +1,67 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {3,4,5,1};
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::is_sorted(cx.begin(), ranges::next(cx.begin(), 3)) );
+ VERIFY( !ranges::is_sorted(cx) );
+ VERIFY( !ranges::is_sorted(cx, ranges::greater{}) );
+ VERIFY( ranges::is_sorted(cx, {}, [] (int a) { return 0; }) );
+}
+
+void
+test02()
+{
+ int x[] = {1,2,3,4,5};
+ test_range<int, forward_iterator_wrapper> rx(x);
+ VERIFY( ranges::is_sorted(rx) );
+ VERIFY( !ranges::is_sorted(ranges::begin(rx),
+ next(ranges::begin(rx), 2),
+ ranges::greater{}) );
+}
+
+constexpr bool
+test03()
+{
+ int x[] = { 1,2 };
+ return (ranges::is_sorted(x)
+ && ranges::is_sorted(x, x) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,72 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {3,4,5,1};
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::is_sorted_until(cx.begin(),
+ ranges::next(cx.begin(), 3))
+ == ranges::next(cx.begin(), 3) );
+ VERIFY( ranges::is_sorted_until(cx) == ranges::next(cx.begin(), 3) );
+ VERIFY( ranges::is_sorted_until(cx, ranges::greater{})
+ == ranges::next(cx.begin(), 1) );
+ VERIFY( ranges::is_sorted_until(cx, {}, [] (int a) { return 0; })
+ == cx.end() );
+}
+
+void
+test02()
+{
+ int x[] = {1,2,3,4,5};
+ test_range<int, forward_iterator_wrapper> rx(x);
+ VERIFY( ranges::is_sorted_until(rx) == ranges::end(rx) );
+ VERIFY( ranges::is_sorted_until(ranges::begin(rx),
+ next(ranges::begin(rx), 2),
+ ranges::greater{})
+ == next(ranges::begin(rx), 1) );
+}
+
+constexpr bool
+test03()
+{
+ int x[] = { 1,2 };
+ return (ranges::is_sorted_until(x) == x+2
+ && ranges::is_sorted_until(x, x) == x );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,164 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ char y[] = {1, 2, 3, 5};
+ long z[] = {1, 2, 3, 4, 5, 6};
+
+ {
+ test_range<int, input_iterator_wrapper> rx(x);
+ test_range<char, input_iterator_wrapper> ry(y);
+ test_range<long, input_iterator_wrapper> rz(z);
+
+ VERIFY( ranges::lexicographical_compare(rx, ry) );
+ rx.bounds.first = x;
+ ry.bounds.first = y;
+ VERIFY( !ranges::lexicographical_compare(ry, rx) );
+ }
+
+ test_range<int, forward_iterator_wrapper> rx(x);
+ test_range<char, forward_iterator_wrapper> ry(y);
+ test_range<long, forward_iterator_wrapper> rz(z);
+
+ VERIFY( ranges::lexicographical_compare(rx, rz) );
+ VERIFY( !ranges::lexicographical_compare(rz, rx) );
+
+ VERIFY( !ranges::lexicographical_compare(rx, rx) );
+ VERIFY( ranges::lexicographical_compare(rx, rx, {}, std::negate<>{}) );
+ VERIFY( ranges::lexicographical_compare(rx, rx, std::greater{},
+ {}, std::negate<>{}) );
+
+ VERIFY( !ranges::lexicographical_compare(rx, ry, {},
+ std::negate<>{},
+ std::negate<>{}) );
+ VERIFY( ranges::lexicographical_compare(ry, rx, {},
+ std::negate<>{},
+ std::negate<>{}) );
+
+ VERIFY( ranges::lexicographical_compare(rx, rz, ranges::greater{}) );
+ VERIFY( !ranges::lexicographical_compare(rz, rx, ranges::greater{}) );
+
+ VERIFY( ranges::lexicographical_compare(rx, ry, ranges::greater{},
+ std::negate<>{},
+ std::negate<>{}) );
+ VERIFY( !ranges::lexicographical_compare(ry, rx, ranges::greater{},
+ std::negate<>{},
+ std::negate<>{}) );
+}
+
+void
+test02()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ int y[] = {1, 2, 3, 5};
+ int z[] = {1, 2, 3, 4, 5, 6};
+
+ VERIFY( ranges::lexicographical_compare(x, y) );
+ VERIFY( !ranges::lexicographical_compare(y, x) );
+
+ VERIFY( ranges::lexicographical_compare(x, z) );
+ VERIFY( !ranges::lexicographical_compare(z, x) );
+
+ VERIFY( !ranges::lexicographical_compare(x, x) );
+
+ VERIFY( !ranges::lexicographical_compare(x, y, {},
+ std::negate<>{},
+ std::negate<>{}) );
+ VERIFY( ranges::lexicographical_compare(y, x, {},
+ std::negate<>{},
+ std::negate<>{}) );
+
+ VERIFY( ranges::lexicographical_compare(x, z, ranges::greater{}) );
+ VERIFY( !ranges::lexicographical_compare(z, x, ranges::greater{}) );
+
+ VERIFY( ranges::lexicographical_compare(x, y, ranges::greater{},
+ std::negate<>{},
+ std::negate<>{}) );
+ VERIFY( !ranges::lexicographical_compare(y, x, ranges::greater{},
+ std::negate<>{},
+ std::negate<>{}) );
+}
+
+void
+test03()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ int y[] = {1, 2, 5, 3};
+ int z[] = {1, 2, 3, 5};
+
+ do
+ {
+ VERIFY( ranges::lexicographical_compare(x, y) );
+ VERIFY( !ranges::lexicographical_compare(x, y, ranges::greater{}) );
+ VERIFY( !ranges::lexicographical_compare(y, x) );
+ VERIFY( ranges::lexicographical_compare(y, x, ranges::greater{}) );
+
+ test_container<int, forward_iterator_wrapper> cy(y);
+ VERIFY( ranges::lexicographical_compare(x, cy) );
+ VERIFY( !ranges::lexicographical_compare(x, cy, ranges::greater{}) );
+ VERIFY( !ranges::lexicographical_compare(cy, x) );
+ VERIFY( ranges::lexicographical_compare(cy, x, ranges::greater{}) );
+
+ test_container<int, forward_iterator_wrapper> cz(z);
+ VERIFY( ranges::lexicographical_compare(cz.begin(), cz.end(),
+ cy.begin(), cy.end()) );
+ VERIFY( !ranges::lexicographical_compare(cy.begin(), cy.end(),
+ cz.begin(), cz.end()) );
+
+ std::vector<int> vx(x, x+5), vy(y, y+5);
+ VERIFY( ranges::lexicographical_compare(vx, vy) );
+ VERIFY( !ranges::lexicographical_compare(vx, vy, ranges::greater{}) );
+ VERIFY( !ranges::lexicographical_compare(vy, vx) );
+ VERIFY( ranges::lexicographical_compare(vy, vx, ranges::greater{}) );
+ } while (ranges::next_permutation(y).found);
+}
+
+constexpr bool
+test04()
+{
+ int x[] = {1};
+ int y[] = {1};
+ return (ranges::lexicographical_compare((int[]){1,2,3,5},
+ (int[]){1,2,4})
+ && !ranges::lexicographical_compare(x, x, y, y));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ static_assert(test04());
+}
new file mode 100644
@@ -0,0 +1,66 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1, 2, 3, 4, 5, 5, 6, 7};
+ for (unsigned i = 0; i < 5; i++)
+ for (unsigned j = 5; j < 8; j++)
+ {
+ test_container<int, forward_iterator_wrapper> cx(x);
+ auto result = ranges::lower_bound(std::next(cx.begin(), i),
+ std::next(cx.begin(), j),
+ 4, {}, [] (int a) { return a-1; });
+ VERIFY( result.ptr == x+4 );
+ }
+
+ ranges::reverse(x);
+ test_range<int, forward_iterator_wrapper> rx(x);
+ auto result = ranges::lower_bound(rx, 5, ranges::greater{},
+ [] (int a) { return a+1; });
+ VERIFY( result.ptr == x+4 );
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ return (ranges::lower_bound(x, 6) == x+5
+ && ranges::lower_bound(x, x, 6) == x
+ && ranges::lower_bound(x, 1) == x);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,82 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i, j;
+};
+
+void
+test01()
+{
+ VERIFY( ranges::max(1, 2) == 2);
+ VERIFY( ranges::max(2, 1) == 2);
+ VERIFY( ranges::max(1, 2, ranges::greater{}) == 1);
+ VERIFY( ranges::max(1, 2, ranges::greater{}, std::negate<>{}) == 2);
+ VERIFY( ranges::max(1, 2, {}, std::negate<>{}) == 1);
+ VERIFY( ranges::max(X{1,2}, X{1,3}, {}, &X::i).j == 2 );
+}
+
+void
+test02()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, input_iterator_wrapper> cx(x);
+ VERIFY( ranges::max(cx) == 4 );
+ cx.bounds.first = x;
+ VERIFY( ranges::max(cx, ranges::greater{}) == 1 );
+ cx.bounds.first = x;
+ VERIFY( ranges::max(cx, {}, std::negate<>{}) == 1);
+ cx.bounds.first = x;
+ VERIFY( ranges::max(cx, ranges::greater{}, std::negate<>{}) == 4 );
+ } while (ranges::next_permutation(x).found);
+
+ constexpr X y[] = {{0,5},{1,2},{1,3}};
+ static_assert(ranges::max(y, {}, &X::i).j == 2);
+}
+
+void
+test03()
+{
+ VERIFY( ranges::max({2,3,1,4}) == 4 );
+ VERIFY( ranges::max({2,3,1,4}, ranges::greater{}) == 1 );
+ VERIFY( ranges::max({2,3,1,4}, {}, std::negate<>{}) == 1 );
+ VERIFY( ranges::max({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 4 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
new file mode 100644
@@ -0,0 +1,60 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i, j;
+};
+
+void
+test01()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, forward_iterator_wrapper> cx(x);
+ VERIFY( *ranges::max_element(cx) == 4 );
+ VERIFY( *ranges::max_element(cx, ranges::greater{}) == 1 );
+ VERIFY( *ranges::max_element(cx, {}, std::negate<>{}) == 1);
+ VERIFY( *ranges::max_element(cx, ranges::greater{}, std::negate<>{}) == 4 );
+ } while (ranges::next_permutation(x).found);
+
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::max_element(cx.begin(), cx.begin()) == cx.begin() );
+
+ constexpr X y[] = {{0,5},{1,2},{1,3}};
+ static_assert(ranges::max_element(y, y+3, {}, &X::i)->j == 2);
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,75 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1,2,3,4,5};
+ for (int i = 0; i <= 5; i++)
+ for (int j = 0; j <= 5; j++)
+ {
+ int z[10];
+ test_range<int, input_iterator_wrapper> rx(x, x+i), ry(x, x+j);
+ test_range<int, output_iterator_wrapper> rz(z, z+i+j);
+ auto [in1,in2,out] = ranges::merge(rx, ry, rz.begin());
+ VERIFY( in1 == rx.end() );
+ VERIFY( in2 == ry.end() );
+ VERIFY( out == rz.end() );
+
+ std::vector<int> v(x, x+i);
+ v.insert(v.end(), x, x+j);
+ ranges::sort(v);
+
+ VERIFY( ranges::equal(v.begin(), v.end(), z, z+i+j) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {-1,-3,-5};
+ int y[] = {2,4,6};
+ int z[6];
+ ranges::merge(x, x+3, y, y+3, z,
+ ranges::greater{}, {}, [] (int a) { return -a; });
+
+ const int w[6] = {-1, 2, -3, 4, -5, 6};
+ return ranges::equal(w, z);
+}
+
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,82 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i, j;
+};
+
+void
+test01()
+{
+ VERIFY( ranges::min(1, 2) == 1);
+ VERIFY( ranges::min(2, 1) == 1);
+ VERIFY( ranges::min(1, 2, ranges::greater{}) == 2);
+ VERIFY( ranges::min(1, 2, ranges::greater{}, std::negate<>{}) == 1);
+ VERIFY( ranges::min(1, 2, {}, std::negate<>{}) == 2);
+ VERIFY( ranges::min(X{1,2}, X{1,3}, {}, &X::i).j == 2 );
+}
+
+void
+test02()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, input_iterator_wrapper> cx(x);
+ VERIFY( ranges::min(cx) == 1 );
+ cx.bounds.first = x;
+ VERIFY( ranges::min(cx, ranges::greater{}) == 4 );
+ cx.bounds.first = x;
+ VERIFY( ranges::min(cx, {}, std::negate<>{}) == 4);
+ cx.bounds.first = x;
+ VERIFY( ranges::min(cx, ranges::greater{}, std::negate<>{}) == 1 );
+ } while (ranges::next_permutation(x).found);
+
+ constexpr X y[] = {{5,0},{1,2},{1,3}};
+ static_assert(ranges::min(y, {}, &X::i).j == 2);
+}
+
+void
+test03()
+{
+ VERIFY( ranges::min({2,3,1,4}) == 1 );
+ VERIFY( ranges::min({2,3,1,4}, ranges::greater{}) == 4 );
+ VERIFY( ranges::min({2,3,1,4}, {}, std::negate<>{}) == 4 );
+ VERIFY( ranges::min({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 1 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
new file mode 100644
@@ -0,0 +1,60 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i, j;
+};
+
+void
+test01()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, forward_iterator_wrapper> cx(x);
+ VERIFY( *ranges::min_element(cx) == 1 );
+ VERIFY( *ranges::min_element(cx, ranges::greater{}) == 4 );
+ VERIFY( *ranges::min_element(cx, {}, std::negate<>{}) == 4);
+ VERIFY( *ranges::min_element(cx, ranges::greater{}, std::negate<>{}) == 1 );
+ } while (ranges::next_permutation(x).found);
+
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::min_element(cx.begin(), cx.begin()) == cx.begin() );
+
+ constexpr X y[] = {{5,0},{1,2},{1,3}};
+ static_assert(ranges::min_element(y, y+3, {}, &X::i)->j == 2);
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<typename T1, typename T2>
+constexpr bool
+operator==(const ranges::minmax_result<T1>& lhs,
+ const ranges::minmax_result<T2>& rhs)
+{
+ return (lhs.min == rhs.min
+ && rhs.max == rhs.max);
+}
+
+
+struct X
+{
+ int i, j;
+};
+
+using res_t = ranges::minmax_result<int>;
+
+void
+test01()
+{
+ VERIFY( ranges::minmax(1, 2) == res_t(1,2) );
+ VERIFY( ranges::minmax(2, 1) == res_t(1,2) );
+ VERIFY( ranges::minmax(1, 2, ranges::greater{}) == res_t(2,1) );
+ VERIFY( ranges::minmax(1, 2, ranges::greater{}, std::negate<>{}) == res_t(1,2) );
+ VERIFY( ranges::minmax(1, 2, {}, std::negate<>{}) == res_t(2,1) );
+ VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).min.j == 2 );
+ VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).max.j == 3 );
+}
+
+void
+test02()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, input_iterator_wrapper> cx(x);
+ VERIFY( ranges::minmax(cx) == res_t(1,4) );
+ cx.bounds.first = x;
+ VERIFY( ranges::minmax(cx, ranges::greater{}) == res_t(4,1) );
+ cx.bounds.first = x;
+ VERIFY( ranges::minmax(cx, {}, std::negate<>{}) == res_t(4,1));
+ cx.bounds.first = x;
+ VERIFY( ranges::minmax(cx, ranges::greater{}, std::negate<>{})
+ == res_t(1,4) );
+ } while (ranges::next_permutation(x).found);
+
+ constexpr X y[] = {{1,5},{1,2},{1,3}};
+ static_assert(ranges::minmax(y, {}, &X::i).min.j == 5);
+ static_assert(ranges::minmax(y, {}, &X::i).max.j == 3);
+}
+
+void
+test03()
+{
+ VERIFY( ranges::minmax({2,3,1,4}) == res_t(1,4) );
+ VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}) == res_t(4,1) );
+ VERIFY( ranges::minmax({2,3,1,4}, {}, std::negate<>{}) == res_t(4,1) );
+ VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}, std::negate<>{})
+ == res_t(1,4) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
new file mode 100644
@@ -0,0 +1,68 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i, j;
+};
+
+void
+test01()
+{
+ int x[] = {1,2,3,4};
+ do
+ {
+ test_range<int, forward_iterator_wrapper> cx(x);
+ VERIFY( *ranges::minmax_element(cx).min == 1 );
+ VERIFY( *ranges::minmax_element(cx).max == 4 );
+ VERIFY( *ranges::minmax_element(cx, ranges::greater{}).min == 4 );
+ VERIFY( *ranges::minmax_element(cx, ranges::greater{}).max == 1 );
+ VERIFY( *ranges::minmax_element(cx, {}, std::negate<>{}).min == 4);
+ VERIFY( *ranges::minmax_element(cx, {}, std::negate<>{}).max == 1);
+ VERIFY( *ranges::minmax_element(cx, ranges::greater{}, std::negate<>{}).min
+ == 1 );
+ VERIFY( *ranges::minmax_element(cx, ranges::greater{}, std::negate<>{}).max
+ == 4 );
+ } while (ranges::next_permutation(x).found);
+
+ test_container<int, forward_iterator_wrapper> cx(x);
+ VERIFY( ranges::minmax_element(cx.begin(), cx.begin()).min == cx.begin() );
+ VERIFY( ranges::minmax_element(cx.begin(), cx.begin()).max == cx.begin() );
+
+ constexpr X y[] = {{1,5},{1,2},{1,3}};
+ static_assert(ranges::minmax_element(y, y+3, {}, &X::i).min->j == 5);
+ static_assert(ranges::minmax_element(y, y+3, {}, &X::i).max->j == 3);
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X xa[] = { {1}, {2}, {3}, {4}, {5}, {6} };
+ X xb[] = { {1}, {2}, {3}, {3}, {5}, {6} };
+ auto res = ranges::mismatch(xa, xa+6, xb, xb+6, {}, &X::i, &X::i);
+ VERIFY( res.in1 == xa+3 && res.in2 == xb+3 );
+
+ test_container<X, forward_iterator_wrapper> ca(xa);
+ test_container<X, forward_iterator_wrapper> cb(xb);
+ auto res2 = ranges::mismatch(ca, cb, {}, &X::i, &X::i);
+ VERIFY( res2.in1->i == 4 && res2.in2->i == 3 );
+ res2 = ranges::mismatch(ca, ca, {}, &X::i, &X::i);
+ VERIFY( res2.in1 == ranges::end(ca) && res2.in2 == ranges::end(ca) );
+
+ test_range<X, input_iterator_wrapper> ra(xa);
+ test_range<X, input_iterator_wrapper> rb(xb);
+ auto res3 = ranges::mismatch(ra, rb, {}, &X::i, &X::i);
+ VERIFY( res3.in1->i == 4 && res3.in2->i == 3 );
+
+ test_range<X, input_iterator_wrapper> ra2(xa);
+ ra.bounds.first = xa;
+ res3 = ranges::mismatch(ra, ra2, {}, &X::i, &X::i);
+ VERIFY( res3.in1 == ranges::end(ra) && res3.in2 == ranges::end(ra2) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y ya[] = { {1,2}, {2,4}, {3,6}, {1,6} };
+ static constexpr Y yb[] = { {2,1}, {4,2}, {4,2}, {7,1} };
+ static_assert(ranges::mismatch(ya, yb, {}, &Y::i, &Y::j).in1 == ya+2);
+ static_assert(ranges::mismatch(ya, yb, {}, &Y::i, &Y::j).in2 == yb+2);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,203 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+ int moved = 0;
+
+ constexpr X() : i(0) { }
+ constexpr X(int a) : i(a) { }
+
+ constexpr X(const X&) = delete;
+ constexpr X& operator=(const X&) = delete;
+
+ constexpr X(X&& other)
+ {
+ *this = std::move(other);
+ }
+
+ constexpr X&
+ operator=(X&& other)
+ {
+ other.moved++;
+ i = other.i;
+ return *this;
+ }
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ { return a.i == b.i; }
+};
+
+void
+test01()
+{
+ {
+ X x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ X z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::move(x, y);
+ VERIFY( ranges::equal(x, y) && in == x+7 && out == y+7 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ char y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_container<int, forward_iterator_wrapper> cx(x);
+ test_container<char, forward_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::move(cx, cy.begin());
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ char x[3] = { 1, 2, 3 };
+ int y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_range<char, input_iterator_wrapper> cx(x);
+ test_range<int, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::move(cx, ranges::begin(cy));
+ VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x= {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::move(x, ranges::begin(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::move(x, ranges::begin(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::move(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.end()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::move(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.end()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+}
+
+void
+test02()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ X z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::move(x, y);
+ VERIFY( ranges::equal(x, x+5, y, y+5) );
+ VERIFY( in == x+5 );
+ VERIFY( out == y+5 );
+ VERIFY( y[5].i == 2 );
+ VERIFY( ranges::equal(x, z) );
+ VERIFY( ranges::count(x, 1, &X::moved) == 5 );
+ VERIFY( ranges::count(y, 0, &X::moved) == 6 );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ X x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ X z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::move(x, y);
+ ok &= ranges::equal(x, x+5, y, y+5);
+ ok &= (in == x+5);
+ ok &= (out == y+5);
+ ok &= (y[5].i == 2);
+ ok &= ranges::equal(x, z);
+ ok &= ranges::count(x, 1, &X::moved) == 5;
+ ok &= ranges::count(y, 0, &X::moved) == 6;
+ return ok;
+}
+
+void
+test04()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ X z[] = { {2}, {2}, {6}, {8}, {10} };
+ test_range<X, input_iterator_wrapper> rx(x);
+ auto [in, out] = ranges::move(std::move_iterator{ranges::begin(rx)},
+ std::move_sentinel{ranges::end(rx)},
+ ranges::begin(y));
+ VERIFY( ranges::equal(x, x+5, y, y+5) );
+ VERIFY( std::move(in).base().ptr == x+5 );
+ VERIFY( out == y+5 );
+ VERIFY( y[5].i == 2 );
+ VERIFY( ranges::equal(x, z) );
+ VERIFY( ranges::count(x, 1, &X::moved) == 5 );
+ VERIFY( ranges::count(y, 0, &X::moved) == 6 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+ test04();
+}
new file mode 100644
@@ -0,0 +1,170 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+ int moved = 0;
+
+ constexpr X() : i(0) { }
+ constexpr X(int a) : i(a) { }
+
+ constexpr X(const X&) = delete;
+ constexpr X& operator=(const X&) = delete;
+
+ constexpr X(X&& other)
+ {
+ *this = std::move(other);
+ }
+
+ constexpr X&
+ operator=(X&& other)
+ {
+ other.moved++;
+ i = other.i;
+ return *this;
+ }
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ { return a.i == b.i; }
+};
+
+void
+test01()
+{
+ {
+ X x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X y[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ X z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ auto [in, out] = ranges::move_backward(x, y+7);
+ VERIFY( ranges::equal(x, y) && in == x+7 && out == y );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ char y[4] = { 0 };
+ int z[3] = { 1, 2, 3 };
+ test_container<int, bidirectional_iterator_wrapper> cx(x);
+ test_container<char, bidirectional_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::move_backward(cx, cy.end());
+ VERIFY( ranges::equal(x, x+3, y+1, y+4) && in.ptr == x+3 && out.ptr == y+1 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x= {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::move_backward(x, ranges::end(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in, out] = ranges::move_backward(x, ranges::end(y));
+ VERIFY( in.base() == x.data()+3 );
+ VERIFY( out.base() == y.data() );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<int> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::move_backward(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.begin()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+
+ {
+ std::vector<char> x = {1,2,3};
+ std::vector<int> y(3);
+ const int z[3] = { 1, 2, 3 };
+ auto [in,out] = ranges::move_backward(make_reverse_iterator(x.end()),
+ make_reverse_iterator(x.begin()),
+ make_reverse_iterator(y.begin()));
+ VERIFY( in.base().base() == x.data()+3 );
+ VERIFY( out.base().base() == y.data()+3 );
+ VERIFY( ranges::equal(y, z) && ranges::equal(x, z) );
+ }
+}
+
+void
+test02()
+{
+ X x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ const X z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::move_backward(x, ranges::end(y));
+ VERIFY( ranges::equal(x, x+5, y+1, y+6) );
+ VERIFY( in == x+5 );
+ VERIFY( out == y+1 );
+ VERIFY( y[0].i == 2 );
+ VERIFY( ranges::equal(x, z) );
+ VERIFY( ranges::count(x, 1, &X::moved) == 5 );
+ VERIFY( ranges::count(y, 0, &X::moved) == 6 );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ X x[] = { {2}, {2}, {6}, {8}, {10} };
+ X y[] = { {2}, {6}, {8}, {10}, {11}, {2} };
+ const X z[] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::move_backward(x, ranges::end(y));
+ ok &= ranges::equal(x, x+5, y+1, y+6);
+ ok &= (in == x+5);
+ ok &= (out == y+1);
+ ok &= (y[0].i == 2);
+ ok &= ranges::equal(x, z);
+ ok &= ranges::count(x, 1, &X::moved) == 5;
+ ok &= ranges::count(y, 0, &X::moved) == 6;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,83 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ int y[] = {1, 2, 3, 4, 5};
+
+ for (int i = 0; i <= 5; i++)
+ {
+ test_container<int, bidirectional_iterator_wrapper> cx(x, x+i);
+ test_container<int, bidirectional_iterator_wrapper> cy(y, y+i);
+ for (int j = 0; ; j++)
+ {
+ auto found1 = std::next_permutation(cx.begin(), cx.end());
+ auto [found2,last] = ranges::next_permutation(cy.begin(), cy.end());
+ VERIFY( found1 == found2 );
+ VERIFY( ranges::equal(cx, cy) );
+ if (!found2)
+ break;
+ }
+ }
+}
+
+void
+test02()
+{
+ int x[] = {5, 4, 3, 2, 1};
+ test_range<int, bidirectional_iterator_wrapper> rx(x);
+ auto [found,last] = ranges::next_permutation(rx, ranges::greater{});
+ VERIFY( found && last == rx.end() );
+ VERIFY( last == rx.end() );
+ VERIFY( ranges::equal(rx, (int[]){5,4,3,1,2}) );
+ ranges::next_permutation(rx, {}, [] (int a) { return -a; });
+ VERIFY( ranges::equal(rx, (int[]){5,4,2,3,1}) );
+
+ VERIFY( !ranges::next_permutation(x, x).found );
+ VERIFY( !ranges::next_permutation(x, x+1).found );
+}
+
+constexpr bool
+test03()
+{
+ int x[] = {1,2,3};
+ ranges::next_permutation(x);
+ return ranges::equal(x, (int[]){1,3,2});
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,88 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+struct XLess
+{
+ int val;
+ bool operator()(X& x) const { return x.i < val; }
+};
+
+struct ILess
+{
+ int val;
+ bool operator()(int& i) const { return i < val; }
+};
+
+template<typename T>
+struct NotZero
+{
+ bool operator()(T& t) const { return t != 0; }
+};
+
+void
+test01()
+{
+ X x[] = { {2}, {4}, {6}, {8}, {10}, {11} };
+
+ VERIFY( !ranges::none_of(x, x+6, XLess{3}) );
+ VERIFY( !ranges::none_of(x, x+6, ILess{3}, &X::i) );
+ VERIFY( ranges::none_of(x+1, x+6, XLess{3}) );
+ VERIFY( ranges::none_of(x+1, x+6, ILess{3}, &X::i) );
+ VERIFY( !ranges::none_of(x, XLess{5}) );
+ VERIFY( !ranges::none_of(x, ILess{5}, &X::i) );
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ VERIFY( !ranges::none_of(c, NotZero<int>{}, &X::i) );
+
+ test_range<X, input_iterator_wrapper> r(x);
+ VERIFY( !ranges::none_of(r, NotZero<int>{}, &X::i) );
+ VERIFY( !ranges::none_of(r, NotZero<X* const>{}, [](X& x) { return &x; }) );
+}
+
+struct Y { int i; int j; };
+
+void
+test02()
+{
+ static constexpr Y y[] = { {1,2}, {2,4}, {3,6} };
+ static_assert(!ranges::none_of(y, [](int i) { return i%2 == 0; }, &Y::i));
+ static_assert(!ranges::none_of(y, [](const Y& y) { return y.i + y.j == 3; }));
+ static_assert(ranges::none_of(y, [](const Y& y) { return y.i == y.j; }));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[50];
+ std::iota(x, x+50, 0);
+
+ auto pred = std::greater{};
+ auto proj = [] (int a) { return -a; };
+ for (int i = 0; i < 50; i++)
+ {
+ test_range<int, random_access_iterator_wrapper> rx(x);
+ std::ranlux48_base g(i);
+ ranges::shuffle(rx, g);
+
+ auto result = ranges::nth_element(rx, rx.begin()+i, pred, proj);
+ VERIFY( result == rx.end() );
+ VERIFY( x[i] == i );
+ for (int j = 0; j < i; j++)
+ for (int k = i; k < 50; k++)
+ VERIFY( !pred(proj(x[k]), proj(x[j])) );
+
+ result = ranges::nth_element(rx, rx.begin()+i, pred);
+ VERIFY( result == rx.end() );
+ VERIFY( x[i] == 49-i );
+ for (int j = 0; j < i; j++)
+ for (int k = i; k < 50; k++)
+ VERIFY( !pred(x[k], x[j]) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {5,2,1,3,4};
+ ranges::nth_element(x, x+3);
+ return x[3] == 4;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,84 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ for (unsigned size = 0; size < 50; ++size)
+ {
+ std::vector<int> vref(size);
+ std::iota(vref.begin(), vref.end(), 0);
+ std::vector<int> v1(vref), v2(vref);
+ test_container<int, random_access_iterator_wrapper> c
+ = {&v1[0], &v1[0] + size};
+ test_range<int, random_access_iterator_wrapper> r
+ = {&v2[0], &v2[0] + size};
+
+ std::ranlux48_base g1(size), g2(size + 1);
+ ranges::shuffle(c, g1);
+ ranges::shuffle(ranges::begin(r), ranges::end(r), g2);
+
+ for (unsigned middle = 0; middle < std::min(size, 10U); ++middle)
+ {
+ auto res1 = ranges::partial_sort(c.begin(), c.begin()+middle, c.end(),
+ {}, std::negate<>{});
+ VERIFY( res1 == c.end() );
+
+ auto res2 = ranges::partial_sort(r,
+ ranges::begin(r)+middle,
+ ranges::greater{});
+ VERIFY( res2 == ranges::end(r) );
+
+ VERIFY( ranges::equal(c.begin(), c.begin()+middle,
+ r.begin(), r.begin()+middle) );
+ VERIFY( ranges::equal(c.begin(), c.begin()+middle,
+ vref.rbegin(), vref.rbegin()+middle) );
+ }
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = { 5,4,1,3,2 };
+ const int y[] = { 1,2,3 };
+ ranges::partial_sort(x, x+3, x+5);
+ return ranges::equal(x, x+3, y, y+3);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,97 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ for (unsigned size = 0; size < 50; ++size)
+ {
+ std::vector<int> vref(size);
+ std::iota(vref.begin(), vref.end(), 0);
+ std::vector<int> v1(vref), v2(vref);
+
+ std::ranlux48_base g1(size), g2(size + 1);
+ ranges::shuffle(v1, g1);
+ ranges::shuffle(v2, g2);
+
+ for (unsigned middle = 0; middle < 10; ++middle)
+ {
+ test_container<int, forward_iterator_wrapper> c
+ = {&v1[0], &v1[0] + size};
+ test_range<int, input_iterator_wrapper> r
+ = {&v2[0], &v2[0] + size};
+
+ std::vector<int> o1(middle), o2(middle);
+ test_range<int, random_access_iterator_wrapper> w1
+ = {&o1[0], &o1[0]+middle};
+ test_range<int, random_access_iterator_wrapper> w2
+ = {&o2[0], &o2[0]+middle};
+
+ auto [in1, out1] = ranges::partial_sort_copy(c.begin(), c.end(),
+ w1.begin(), w1.end(),
+ {},
+ std::negate<>{},
+ std::negate<>{});
+ VERIFY( in1 == c.end() );
+ VERIFY( out1 == w1.begin() + std::min(size, middle) );
+
+ auto [in2,out2] = ranges::partial_sort_copy(r, w2, ranges::greater{});
+ VERIFY( in2 == ranges::end(r) );
+ VERIFY( out2 == w2.begin() + std::min(size, middle) );
+
+ VERIFY( ranges::equal(w1.begin(), out1, w2.begin(), out2) );
+ VERIFY( ranges::equal(w1.begin(), out1,
+ vref.rbegin(),
+ vref.rbegin()+(out1-w1.begin())) );
+ }
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = { 5,4,1,3,2 };
+ int w[3];
+ const int y[] = { 1,2,3 };
+ ranges::partial_sort_copy(x, x+5, w, w+3);
+ return ranges::equal(w, y);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,71 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<template<typename> typename wrapper>
+void
+test01()
+{
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10};
+ test_container<int, wrapper> cx(x);
+ auto range = ranges::partition(cx, [] (int a) { return a%2==0; });
+ VERIFY( range.begin().ptr == x+5 );
+ VERIFY( range.end().ptr == x+10 );
+ VERIFY( ranges::is_partitioned(cx, [] (int a) { return a%2==0; }) );
+ }
+
+ {
+ int x[] = {1,2,3,4,5,6,7,8};
+ test_range<int, wrapper> rx(x);
+ auto range = ranges::partition(rx,
+ [] (int a) { return a%2==0; },
+ [] (int a) { return a+1; });
+ VERIFY( range.begin().ptr == x+4 );
+ VERIFY( range.end().ptr == x+8 );
+ VERIFY( ranges::is_partitioned(rx, [] (int a) { return a%2==1; }) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3,4,5,6,7,8,9,10};
+ auto range = ranges::partition(x, x+9, [] (int a) { return a < 100; });
+ return (range.begin() == x+9 && range.end() == x+9);
+}
+
+int
+main()
+{
+ test01<forward_iterator_wrapper>();
+ test01<bidirectional_iterator_wrapper>();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,81 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10,11};
+ int y[5], z[6];
+ test_container<int, forward_iterator_wrapper> cx(x);
+ test_container<int, forward_iterator_wrapper> cy(y), cz(z);
+ auto pred = [] (int a) { return a%2==0; };
+ auto [in,out_true,out_false]
+ = ranges::partition_copy(cx, cy.begin(), cz.begin(), pred);
+ VERIFY( in.ptr == x+11 );
+ VERIFY( out_true.ptr == y+5 );
+ VERIFY( out_false.ptr == z+6 );
+ VERIFY( ranges::all_of(cy, pred) );
+ VERIFY( ranges::none_of(cz, pred) );
+ }
+
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10,11};
+ int y[6], z[5];
+ test_range<int, input_iterator_wrapper> cx(x);
+ test_range<int, output_iterator_wrapper> cy(y), cz(z);
+ auto pred = [] (int a) { return a%2==0; };
+ auto proj = [] (int a) { return a+1; };
+ auto [in,out_true,out_false]
+ = ranges::partition_copy(cx, cy.begin(), cz.begin(), pred, proj);
+ VERIFY( in.ptr == x+11 );
+ VERIFY( out_true.ptr == y+6 );
+ VERIFY( out_false.ptr == z+5 );
+ VERIFY( ranges::none_of(y, pred) );
+ VERIFY( ranges::all_of(z, pred) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3,4,5,6,7,8,9,10};
+ auto range = ranges::partition(x, x+9, [] (int a) { return a < 100; });
+ return (range.begin() == x+9 && range.end() == x+9);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,67 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ for (int k = 1; k <= 7; k++)
+ {
+ int x[] = {1,2,3,4,5,6,7};
+ test_container<int, forward_iterator_wrapper> cx(x);
+ auto pred = [&] (int a) { return a <= k; };
+ auto middle = ranges::partition_point(cx, pred);
+ VERIFY( middle.ptr == x+k );
+ }
+
+ for (int k = 1; k <= 8; k++)
+ {
+ int x[] = {1,2,3,4,5,6,7,8};
+ test_range<int, forward_iterator_wrapper> rx(x);
+ auto pred = [&] (int a) { return a > -k; };
+ auto proj = [] (int a) { return -a; };
+ auto middle = ranges::partition_point(rx, pred, proj);
+ VERIFY( middle.ptr == x+k-1 );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1,2,3,4,5};
+ return (ranges::partition_point(x, x+5, [] (int a) { return a < 6; }) == x+5
+ && ranges::partition_point(x, x+5, [] (int a) { return a < 0; }) == x);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,84 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {5, 4, 3, 2, 1};
+ int y[] = {5, 4, 3, 2, 1};
+
+ for (int i = 0; i <= 5; i++)
+ {
+ test_container<int, bidirectional_iterator_wrapper> cx(x, x+i);
+ test_container<int, bidirectional_iterator_wrapper> cy(y, y+i);
+ for (int j = 0; ; j++)
+ {
+ auto found1 = std::prev_permutation(cx.begin(), cx.end());
+ auto [found2,last] = ranges::prev_permutation(cy.begin(), cy.end());
+ VERIFY( found1 == found2 );
+ VERIFY( ranges::equal(cx, cy) );
+ if (!found2)
+ break;
+ }
+ }
+}
+
+void
+test02()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ test_range<int, bidirectional_iterator_wrapper> rx(x);
+ auto [found,last] = ranges::prev_permutation(rx, ranges::greater{});
+ VERIFY( found && last == rx.end() );
+ VERIFY( last == rx.end() );
+ VERIFY( ranges::equal(rx, (int[]){1,2,3,5,4}) );
+ ranges::prev_permutation(rx, {}, [] (int a) { return -a; });
+ VERIFY( ranges::equal(rx, (int[]){1,2,4,3,5}) );
+
+ VERIFY( !ranges::prev_permutation(x, x).found );
+ VERIFY( !ranges::prev_permutation(x, x+1).found );
+}
+
+constexpr bool
+test03()
+{
+ int x[] = {3,2,1};
+ ranges::prev_permutation(x);
+ return ranges::equal(x, (int[]){3,1,2});
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
+
new file mode 100644
@@ -0,0 +1,97 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+};
+
+void
+test01()
+{
+ int x[5] = { 1, 2, 3, 4, 5 };
+ const int y[4] = { 1, 2, 4, 5 };
+ auto res = ranges::remove(x, 3);
+ VERIFY( res.begin() == x+4 && res.end() == x+5 );
+ VERIFY( ranges::equal(x, x+4, y, y+4) );
+}
+
+void
+test02()
+{
+ int x[1];
+ test_container<int, forward_iterator_wrapper> c(x, x);
+ auto res = ranges::remove(c, 1);
+ VERIFY( res.begin().ptr == x && res.end().ptr == x );
+}
+
+void
+test03()
+{
+ int x[1] = {1};
+ test_container<int, forward_iterator_wrapper> c(x);
+ auto res = ranges::remove(c, 0);
+ VERIFY( res.begin().ptr == x+1 && res.end().ptr == x+1 );
+ res = ranges::remove(c, 1);
+ VERIFY( res.begin().ptr == x && res.end().ptr == x+1 );
+}
+
+void
+test04()
+{
+ X x[8] = { {0}, {1}, {0}, {1}, {0}, {0}, {1}, {1} };
+ const int y[4] = { 0, 0, 0, 0 };
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res = ranges::remove(c, 1, &X::i);
+ VERIFY( res.begin().ptr == x+4 && res.end().ptr == x+8 );
+ VERIFY( ranges::equal(x, x+4, y, y+4, {}, &X::i) );
+}
+
+constexpr bool
+test05()
+{
+ int x[6] = { 3, 2, 3, 3, 5, 3 };
+ const int y[2] = { 2, 5 };
+ auto res = ranges::remove(x, 3);
+ return ranges::equal(x, res.begin(), y, y+2);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ static_assert(test05());
+}
new file mode 100644
@@ -0,0 +1,109 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[4];
+ X z[4] = { {2}, {2}, {6}, {10} };
+ auto [in,out] = ranges::remove_copy(x, x+5, y, 8, &X::i);
+ VERIFY( in == x+5 && out == y+4 );
+ VERIFY( ranges::equal(y, z) );
+ }
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in,out] = ranges::remove_copy(x, x+5, y, 11, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {2} };
+ X y[3];
+ X z[3] = { {6}, {8}, {10} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y), cz(z);
+ auto [in, out] = ranges::remove_copy(cx, cy.begin(), 2, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(cy, cz) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[4];
+ const X z[4] = { {6}, {8}, {10}, {11} };
+ test_range<X, input_iterator_wrapper> cx(x);
+ test_range<X, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::remove_copy(cx, cy.begin(), 2, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(y, z) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[3] = { {3,2}, {2,4}, {3,6} };
+ Y y[1];
+ Y z[1] = { {2,4} };
+ auto [in, out] = ranges::remove_copy(x, y, 3, &Y::i);
+ ok &= in == x+3;
+ ok &= out == y+1;
+ ok &= ranges::equal(y, z, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(y, z, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,113 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ auto is_negative_p = [] (int a) { return a < 0; };
+ auto is_two_p = [] (int a) { return a == 2; };
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} };
+ X y[2];
+ X z[2] = { {6}, {8} };
+ auto [in, out] = ranges::remove_copy_if(x, x+5, y, is_two_p, &X::i);
+ VERIFY( in == x+5 && out == y+2 );
+ VERIFY( ranges::equal(y, z) );
+ }
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::remove_copy_if(x, x+5, y, is_negative_p, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[4];
+ X z[4] = { {6}, {8}, {10}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y), cz(z);
+ auto [in, out] = ranges::remove_copy_if(cx, cy.begin(), is_two_p, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(cy, cz) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[4];
+ const X z[4] = { {6}, {8}, {10}, {11} };
+ test_range<X, input_iterator_wrapper> cx(x);
+ test_range<X, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::remove_copy_if(cx, cy.begin(), is_two_p, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(y, z) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[3] = { {3,2}, {2,4}, {3,6} };
+ Y y[1];
+ Y z[1] = { {2,4} };
+ auto [in, out]
+ = ranges::remove_copy_if(x, y, [] (int a) { return a%2 == 1; }, &Y::i);
+ ok &= in == x+3;
+ ok &= out == y+1;
+ ok &= ranges::equal(y, z, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(y, z, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,97 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+};
+
+void
+test01()
+{
+ int x[5] = { 1, 2, 3, 4, 5 };
+ const int y[4] = { 1, 2, 4, 5 };
+ auto res = ranges::remove_if(x, [] (int a) { return a == 3; });
+ VERIFY( res.begin() == x+4 && res.end() == x+5 );
+ VERIFY( ranges::equal(x, x+4, y, y+4) );
+}
+
+void
+test02()
+{
+ int x[1];
+ test_container<int, forward_iterator_wrapper> c(x, x);
+ auto res = ranges::remove_if(c, [] (int a) { return a == 1; });
+ VERIFY( res.begin().ptr == x && res.end().ptr == x );
+}
+
+void
+test03()
+{
+ int x[1] = {1};
+ test_container<int, forward_iterator_wrapper> c(x);
+ auto res = ranges::remove_if(c, [] (int a) { return a == 0; });
+ VERIFY( res.begin().ptr == x+1 && res.end().ptr == x+1 );
+ res = ranges::remove_if(c, [] (int a) { return a == 1; });
+ VERIFY( res.begin().ptr == x && res.end().ptr == x+1 );
+}
+
+void
+test04()
+{
+ X x[8] = { {0}, {1}, {0}, {1}, {0}, {0}, {1}, {1} };
+ const int y[4] = { 0, 0, 0, 0 };
+ test_range<X, forward_iterator_wrapper> c(x);
+ auto res = ranges::remove_if(c, [] (int a) { return a == 1; }, &X::i);
+ VERIFY( res.begin().ptr == x+4 && res.end().ptr == x+8 );
+ VERIFY( ranges::equal(x, x+4, y, y+4, {}, &X::i) );
+}
+
+constexpr bool
+test05()
+{
+ int x[6] = { 3, 2, 3, 3, 5, 3 };
+ const int y[2] = { 2, 5 };
+ auto res = ranges::remove_if(x, [] (int a) { return a == 3; });
+ return ranges::equal(x, res.begin(), y, y+2);
+}
+
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ static_assert(test05());
+}
new file mode 100644
@@ -0,0 +1,104 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {2}, {2}, {6}, {9}, {10}, {11} };
+ auto res = ranges::replace(x, x+5, 8, X{9}, &X::i);
+ VERIFY( res == x+5 );
+ VERIFY( ranges::equal(x, y) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::replace(x, x+5, 7, X{9}, &X::i);
+ VERIFY( res == x+5 );
+ VERIFY( ranges::equal(x, y) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y);
+ auto res = ranges::replace(cx, 2, X{7}, &X::i);
+ VERIFY( res == cx.end() );
+ VERIFY( ranges::equal(cx, cy) );
+ }
+
+ {
+ int x[6] = { {2}, {2}, {6}, {8}, {10}, {2} };
+ int y[6] = { {7}, {7}, {6}, {8}, {10}, {7} };
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ auto res = ranges::replace(rx, 2, 7);
+ VERIFY( res == rx.end() );
+
+ rx.bounds.first = x;
+ ry.bounds.first = y;
+ VERIFY( ranges::equal(rx, ry) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[] = { {3,2}, {2,4}, {3,6} };
+ Y y[] = { {4,5}, {2,4}, {4,5} };
+ auto res = ranges::replace(x, 3, Y{4,5}, &Y::i);
+ ok &= res == x+3;
+ ok &= ranges::equal(x, y, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(x, y, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,109 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {2}, {2}, {6}, {9}, {10} };
+ auto [in,out] = ranges::replace_copy(x, x+5, y, 8, X{9}, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(y, z) );
+ }
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in,out] = ranges::replace_copy(x, x+5, y, 7, X{9}, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6];
+ X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y), cz(z);
+ auto [in, out] = ranges::replace_copy(cx, cy.begin(), 2, X{7}, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(cy, cz) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6];
+ const X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_range<X, input_iterator_wrapper> cx(x);
+ test_range<X, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::replace_copy(cx, cy.begin(), 2, X{7}, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(y, z) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[] = { {3,2}, {2,4}, {3,6} };
+ Y y[] = { {4,5}, {2,4}, {4,5} };
+ Y z[] = { {4,5}, {2,4}, {4,5} };
+ auto [in, out] = ranges::replace_copy(x, y, 3, Y{4,5}, &Y::i);
+ ok &= in == x+3;
+ ok &= out == y+3;
+ ok &= ranges::equal(y, z, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(y, z, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,118 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ auto is_negative_p = [] (int a) { return a < 0; };
+ auto is_two_p = [] (int a) { return a == 2; };
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {9}, {9}, {6}, {8}, {10} };
+ auto [in, out] = ranges::replace_copy_if(x, x+5, y,
+ is_two_p, X{9}, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(y, z) );
+ }
+
+ {
+ const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[5];
+ X z[5] = { {2}, {2}, {6}, {8}, {10} };
+ auto [in, out] = ranges::replace_copy_if(x, x+5, y,
+ is_negative_p, X{9}, &X::i);
+ VERIFY( in == x+5 && out == y+5 );
+ VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6];
+ X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y), cz(z);
+ auto [in, out] = ranges::replace_copy_if(cx, cy.begin(),
+ is_two_p, X{7}, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(cy, cz) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6];
+ const X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_range<X, input_iterator_wrapper> cx(x);
+ test_range<X, output_iterator_wrapper> cy(y);
+ auto [in, out] = ranges::replace_copy_if(cx, cy.begin(),
+ is_two_p, X{7}, &X::i);
+ VERIFY( in == cx.end() && out == cy.end() );
+ VERIFY( ranges::equal(y, z) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[] = { {3,2}, {2,4}, {3,6} };
+ Y y[] = { {4,5}, {2,4}, {4,5} };
+ Y z[] = { {4,5}, {2,4}, {4,5} };
+ auto [in, out]
+ = ranges::replace_copy_if(x, y,
+ [] (int a) { return a%2 == 1; }, Y{4,5}, &Y::i);
+ ok &= in == x+3;
+ ok &= out == y+3;
+ ok &= ranges::equal(y, z, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(y, z, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,109 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ {
+ return a.i == b.i;
+ }
+};
+
+void
+test01()
+{
+ auto is_even_p = [] (int a) { return a%2 == 0; };
+ auto is_negative_p = [] (int a) { return a < 0; };
+ auto is_two_p = [] (int a) { return a == 2; };
+ {
+ X x[6] = { {1}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {1}, {9}, {9}, {9}, {9}, {11} };
+ auto res = ranges::replace_if(x, x+5, is_even_p, X{9}, &X::i);
+ VERIFY( res == x+5 );
+ VERIFY( ranges::equal(x, y) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::replace_if(x, x+5, is_negative_p, X{9}, &X::i);
+ VERIFY( res == x+5 );
+ VERIFY( ranges::equal(x, y) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ X y[6] = { {7}, {7}, {6}, {8}, {10}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x), cy(y);
+ auto res = ranges::replace_if(cx, is_two_p, X{7}, &X::i);
+ VERIFY( res == cx.end() );
+ VERIFY( ranges::equal(cx, cy) );
+ }
+
+ {
+ int x[6] = { {2}, {2}, {6}, {8}, {10}, {2} };
+ int y[6] = { {7}, {7}, {6}, {8}, {10}, {7} };
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ auto res = ranges::replace_if(rx, is_two_p, 7);
+ VERIFY( res == rx.end() );
+
+ rx.bounds.first = x;
+ ry.bounds.first = y;
+ VERIFY( ranges::equal(rx, ry) );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ Y x[] = { {3,2}, {2,4}, {3,6} };
+ Y y[] = { {4,5}, {2,4}, {4,5} };
+ auto res = ranges::replace_if(x, [] (int a) { return a%2 == 1; },
+ Y{4,5}, &Y::i);
+ ok &= res == x+3;
+ ok &= ranges::equal(x, y, {}, &Y::i, &Y::i);
+ ok &= ranges::equal(x, y, {}, &Y::j, &Y::j);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
+
new file mode 100644
@@ -0,0 +1,77 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_range;
+using __gnu_test::test_container;
+using __gnu_test::bidirectional_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<template<typename> typename wrapper>
+void
+test01()
+{
+ int x[] = { 1, 2, 3, 4 };
+ test_container<int, wrapper> cx(x);
+ const int y[] = { 4, 3, 2, 1 };
+
+ auto res = ranges::reverse(cx);
+ VERIFY( res == ranges::end(cx) );
+ VERIFY( ranges::equal(cx, y) );
+}
+
+template<template<typename> typename wrapper>
+void
+test02()
+{
+ int x[] = { 1, 2, 3, 4, 5 };
+ test_range<int, wrapper> rx(x);
+ const int y[] = { 5, 4, 3, 2, 1 };
+
+ auto res = ranges::reverse(rx);
+ VERIFY( res == ranges::end(rx) );
+ VERIFY( ranges::equal(rx, y) );
+}
+
+constexpr bool
+test03()
+{
+ int x[] = { 1, 2, 3 };
+ const int y[] = { 2, 1, 3 };
+ ranges::reverse(x, x+2);
+ return ranges::equal(x, y);
+}
+
+int
+main()
+{
+ test01<bidirectional_iterator_wrapper>();
+ test02<bidirectional_iterator_wrapper>();
+
+ test01<random_access_iterator_wrapper>();
+ test02<random_access_iterator_wrapper>();
+
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,74 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_range;
+using __gnu_test::test_container;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = { 1, 2, 3, 4 };
+ int w[4];
+ test_container<int, bidirectional_iterator_wrapper> cx(x), cw(w);
+ const int y[] = { 4, 3, 2, 1 };
+
+ auto [in,out] = ranges::reverse_copy(cx, cw.begin());
+ VERIFY( in == ranges::end(cx) && out == cw.end() );
+ VERIFY( ranges::equal(cw, y) );
+}
+
+void
+test02()
+{
+ int x[] = { 1, 2, 3, 4, 5 };
+ int w[5];
+ test_range<int, bidirectional_iterator_wrapper> rx(x), rw(w);
+ const int y[] = { 5, 4, 3, 2, 1 };
+
+ auto [in,out] = ranges::reverse_copy(rx, ranges::begin(rw));
+ VERIFY( in == ranges::end(rx) && out == ranges::end(rw) );
+ VERIFY( ranges::equal(rw, y) );
+}
+
+constexpr bool
+test03()
+{
+ const int x[] = { 1, 2, 3 };
+ int w[2];
+ const int y[] = { 2, 1 };
+ ranges::reverse_copy(x, x+2, w);
+ return ranges::equal(w, y);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,97 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+ X (int a) : i(a) { }
+
+ friend bool
+ operator==(const X& lhs, const X& rhs)
+ {
+ return lhs.i == rhs.i;
+ }
+};
+
+static_assert(!std::is_trivial_v<X>);
+
+template<template<typename, template<typename> typename> typename container,
+ template<typename> typename wrapper,
+ typename T = int>
+void
+test01()
+{
+ for (int a = 0; a <= 7; a++)
+ {
+ T x[] = {1, 2, 3, 4, 5, 6, 7};
+ container<T, wrapper> rx(x);
+ auto i = ranges::begin(rx);
+ std::advance(i, a);
+ auto res = ranges::rotate(rx, i);
+ if (a == 0)
+ VERIFY( ranges::begin(res) == ranges::end(rx) );
+ else
+ VERIFY( ranges::begin(res)
+ == std::next(ranges::begin(rx),
+ ranges::distance(i, ranges::end(rx))) );
+ VERIFY( ranges::end(res) == ranges::end(rx) );
+ for (int k = 0; k < 7; k++)
+ VERIFY( x[k] == (k+a)%7 + 1 );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1, 2, 3, 4};
+ const int y[] = { 2, 3, 1, 4 };
+ ranges::rotate(x, x+1, x+3);
+ return ranges::equal(x, y);
+}
+
+int
+main()
+{
+ test01<test_container, forward_iterator_wrapper>();
+ test01<test_range, forward_iterator_wrapper>();
+
+ test01<test_container, bidirectional_iterator_wrapper>();
+ test01<test_range, bidirectional_iterator_wrapper>();
+
+ test01<test_container, random_access_iterator_wrapper>();
+ test01<test_range, random_access_iterator_wrapper>();
+
+ test01<test_container, random_access_iterator_wrapper, X>();
+ test01<test_range, random_access_iterator_wrapper, X>();
+
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,93 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+ X () : i(0) { }
+ X (int a) : i(a) { }
+
+ friend bool
+ operator==(const X& lhs, const X& rhs)
+ {
+ return lhs.i == rhs.i;
+ }
+};
+
+static_assert(!std::is_trivial_v<X>);
+
+template<template<typename, template<typename> typename> typename container,
+ template<typename> typename wrapper,
+ typename T = int>
+void
+test01()
+{
+ for (int a = 0; a <= 7; a++)
+ {
+ T x[] = {1, 2, 3, 4, 5, 6, 7};
+ T w[7];
+ container<T, wrapper> rx(x), rw(w);
+ auto i = ranges::begin(rx);
+ std::advance(i, a);
+ auto [in,out] = ranges::rotate_copy(rx, i, ranges::begin(rw));
+ VERIFY( in == ranges::end(rx) );
+ VERIFY( out == ranges::end(rw) );
+ for (int k = 0; k < 7; k++)
+ VERIFY( w[k] == (k+a)%7 + 1 );
+ }
+}
+
+constexpr bool
+test02()
+{
+ const int x[] = {1, 2, 3, 4};
+ int w[3];
+ const int y[] = { 2, 3, 1};
+ auto [in,out] = ranges::rotate_copy(x, x+1, x+3, w);
+ return (in == x+3
+ && out == w+3
+ && ranges::equal(w, y));
+}
+
+int
+main()
+{
+ test01<test_container, forward_iterator_wrapper>();
+ test01<test_range, forward_iterator_wrapper>();
+
+ test01<test_container, random_access_iterator_wrapper>();
+ test01<test_range, random_access_iterator_wrapper>();
+
+ test01<test_container, random_access_iterator_wrapper, X>();
+ test01<test_range, random_access_iterator_wrapper, X>();
+
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,88 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ X x[] = { {2}, {6}, {8}, {10}, {11} };
+ X y[] = { {10}, {11} };
+ {
+
+ test_container<X, forward_iterator_wrapper> c(x);
+ auto res = ranges::search(c, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(c) );
+ res = ranges::search(c, c, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(c)
+ && std::get<1>(res) == ranges::end(c) );
+ }
+
+ {
+ test_range<X, forward_iterator_wrapper> r(x);
+ auto res = ranges::search(r, y, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) );
+ res = ranges::search(r, r, {}, &X::i, &X::i);
+ VERIFY( std::get<0>(res) == ranges::begin(r)
+ && std::get<1>(res) == ranges::end(r) );
+ }
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ static constexpr X y[] = { {6}, {8} };
+ static constexpr int z[] = { 2, 8 };
+ static constexpr int w[] = { 2 };
+
+ static_assert(std::get<0>(ranges::search(x, y, {}, &X::i, &X::i)) == x+2);
+ static_assert(std::get<1>(ranges::search(x, y, {}, &X::i, &X::i)) == x+4);
+
+ static_assert(std::get<0>(ranges::search(x, z, {}, &X::i)) == x+6);
+ static_assert(std::get<1>(ranges::search(x, z, {}, &X::i)) == x+6);
+
+ static_assert(std::get<0>(ranges::search(x, w, {}, &X::i)) == x+0);
+ static_assert(std::get<1>(ranges::search(x, w, {}, &X::i)) == x+1);
+
+ static_assert(std::get<0>(ranges::search(x, x+6, w, w, {}, &X::i)) == x+0);
+ static_assert(std::get<1>(ranges::search(x, x+6, w, w, {}, &X::i)) == x+0);
+
+ static_assert(std::get<0>(ranges::search(x, x, w, w+1, {}, &X::i)) == x+0);
+ static_assert(std::get<1>(ranges::search(x, x, w, w+1, {}, &X::i)) == x+0);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,80 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ int x[] = { {2}, {2}, {6}, {8}, {10}, {11} };
+ auto res = ranges::search_n(x+0, x+6, 2, 2);
+ VERIFY( res.begin() == x+0 && res.end() == x+2 );
+
+ int z[] = { {1}, {2}, {2}, {4}, {5}, {6} };
+ res = ranges::search_n(z, 3, 3, std::greater<int>());
+ VERIFY( res.begin() == z+3 && res.end() == z+6 );
+
+ test_container<int, forward_iterator_wrapper> cx(x);
+ auto res2 = ranges::search_n(cx, 2, 2);
+ VERIFY( res2.begin() == cx.begin() && *res2.end() == 6 );
+
+ int y[] = { {2}, {2}, {8}, {2}, {2}, {2}, {5} };
+ test_range<int, forward_iterator_wrapper> ry(y);
+ auto res3 = ranges::search_n(ry, 3, 2);
+ VERIFY( *res3.begin() == 2 && *res3.end() == 5 );
+
+ auto res4 = ranges::search_n(ry, 1, 8);
+ VERIFY( res4.begin().ptr == y+2 && res4.end().ptr == y+3 );
+}
+
+void
+test02()
+{
+ static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {2} };
+ static constexpr X y[] = { {2}, {6}, {8}, {8}, {8}, {2} };
+ static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} };
+
+ static_assert(ranges::search_n(z, 0, 5).end() == z+0);
+ static_assert(ranges::search_n(z, 1, 5).begin() == z+6);
+ static_assert(ranges::search_n(x, 2, 3, {}, &X::i).begin() == x+6);
+ static_assert(ranges::search_n(x, 2, 2, {}, &X::i).end() == x+2);
+ static_assert(ranges::search_n(y, 3, 8, {}, &X::i).begin() == y+2);
+ static_assert(ranges::search_n(y, 3, 8, {}, &X::i).end() == y+5);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
+
new file mode 100644
@@ -0,0 +1,87 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {4,2,1,1,0};
+ int y[] = {3,2,1};
+ int z[3];
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ test_range<int, output_iterator_wrapper> rz(z);
+ auto [in,out]
+ = ranges::set_difference(rx, ry, rz.begin(), ranges::greater{});
+ VERIFY( in.ptr == x+5 );
+ VERIFY( out.ptr == z+3 );
+ VERIFY( ranges::equal(z, (int[]){4,1,0}) );
+}
+
+void
+test02()
+{
+ int x[] = {3,2,1,1,0};
+ int y[] = {3,2,2,1,0};
+ int z[1];
+ test_container<int, forward_iterator_wrapper> rx(x), ry(y);
+ test_container<int, forward_iterator_wrapper> rz(z);
+ auto [in,out]
+ = ranges::set_difference(rx.begin(), rx.end(),
+ ry.begin(), ry.end(),
+ rz.begin(),
+ {},
+ std::negate<>{},
+ std::negate<>{});
+ VERIFY( in.ptr == x+5 );
+ VERIFY( out.ptr == z+1 );
+ VERIFY( ranges::equal(z, (int[]){1}) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ int x[1] = {0};
+ int y[1] = {1};
+ int z[1];
+ ok &= ranges::set_difference(x, x, y, y+1, z).out == z;
+ ok &= ranges::set_difference(x, x+1, y, y, z).out == z+1;
+ ok &= z[0] == 0;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,88 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {4,2,1,1,0};
+ int y[] = {3,2,1};
+ int z[2];
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ test_range<int, output_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_intersection(rx, ry, rz.begin(), ranges::greater{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+3 );
+ VERIFY( out.ptr == z+2 );
+ VERIFY( ranges::equal(z, (int[]){2,1}) );
+}
+
+void
+test02()
+{
+ int x[] = {3,2,1,1,0};
+ int y[] = {3,2,1,0};
+ int z[4];
+ test_container<int, forward_iterator_wrapper> rx(x), ry(y);
+ test_container<int, forward_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_intersection(rx.begin(), rx.end(),
+ ry.begin(), ry.end(),
+ rz.begin(),
+ {},
+ std::negate<>{},
+ std::negate<>{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+4 );
+ VERIFY( out.ptr == z+4 );
+ VERIFY( ranges::equal(z, (int[]){3,2,1,0}) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ int x[1] = {0};
+ int y[1] = {1};
+ int z[1];
+ ok &= ranges::set_intersection(x, x, y, y+1, z).out == z;
+ ok &= ranges::set_intersection(x, x+1, y, y, z).out == z;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,123 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {4,2,1,1,0};
+ int y[] = {3,2,2,1};
+ int z[5];
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ test_range<int, output_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_symmetric_difference(rx, ry, rz.begin(), ranges::greater{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+4 );
+ VERIFY( out.ptr == z+5 );
+ VERIFY( ranges::equal(z, (int[]){4,3,2,1,0}) );
+}
+
+void
+test02()
+{
+ int x[] = {3,2,1,1,0};
+ int y[] = {3,2,1,0};
+ int z[1];
+ test_container<int, forward_iterator_wrapper> rx(x), ry(y);
+ test_container<int, forward_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_symmetric_difference(rx.begin(), rx.end(),
+ ry.begin(), ry.end(),
+ rz.begin(),
+ {},
+ std::negate<>{},
+ std::negate<>{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+4 );
+ VERIFY( out.ptr == z+1 );
+ VERIFY( ranges::equal(z, (int[]){1}) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ int x[1] = {0};
+ int y[1] = {1};
+ int z[1];
+ ok &= ranges::set_symmetric_difference(x, x, y, y+1, z).out == z+1;
+ ok &= z[0] == 1;
+ ok &= ranges::set_symmetric_difference(x, x+1, y, y, z).out == z+1;
+ ok &= z[0] == 0;
+ return ok;
+}
+
+void
+test04()
+{
+ int x[15] = {5,5,5,5,5,4,4,4,4,3,3,3,2,2,1};
+ int y[15] = {5,5,5,5,5,4,4,4,4,3,3,3,2,2,1};
+ for (int k = 0; k < 100; k++)
+ {
+ std::ranlux48_base g(k);
+ ranges::shuffle(x, g);
+ ranges::shuffle(y, g);
+ ranges::sort(x, x+10);
+ ranges::sort(y, y+10);
+
+ int z[15];
+ auto z_out = ranges::set_symmetric_difference(x, x+10, y, y+10, z).out;
+
+ int w1[15];
+ auto w1_out = ranges::set_difference(x, x+10, y, y+10, w1).out;
+
+ int w2[15];
+ auto w2_out = ranges::set_difference(y, y+10, x, x+10, w2).out;
+
+ int w3[15];
+ auto w3_out = ranges::set_union(w1, w1_out, w2, w2_out, w3).out;
+
+ VERIFY( ranges::equal(z, z_out, w3, w3_out) );
+ }
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+ test04();
+}
new file mode 100644
@@ -0,0 +1,91 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {4,2,1,1,0};
+ int y[] = {3,2,1};
+ int z[6];
+ test_range<int, input_iterator_wrapper> rx(x), ry(y);
+ test_range<int, output_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_union(rx, ry, rz.begin(),
+ ranges::greater{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+3 );
+ VERIFY( out.ptr == z+6 );
+ VERIFY( ranges::equal(z, (int[]){4,3,2,1,1,0}) );
+}
+
+void
+test02()
+{
+ int x[] = {4,2,1,1,0};
+ int y[] = {3,2,1,1,0};
+ int z[6];
+ test_container<int, forward_iterator_wrapper> rx(x), ry(y);
+ test_container<int, forward_iterator_wrapper> rz(z);
+ auto [in1,in2,out]
+ = ranges::set_union(rx.begin(), rx.end(),
+ ry.begin(), ry.end(),
+ rz.begin(),
+ {},
+ std::negate<>{},
+ std::negate<>{});
+ VERIFY( in1.ptr == x+5 );
+ VERIFY( in2.ptr == y+5 );
+ VERIFY( out.ptr == z+6 );
+ VERIFY( ranges::equal(z, (int[]){4,3,2,1,1,0}) );
+}
+
+constexpr bool
+test03()
+{
+ bool ok = true;
+ int x[1] = {0};
+ int y[1] = {1};
+ int z[1];
+ ranges::set_union(x, x, y, y+1, z);
+ ok &= z[0] == 1;
+ ranges::set_union(x, x+1, y, y, z);
+ ok &= z[0] == 0;
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ static_assert(test03());
+}
new file mode 100644
@@ -0,0 +1,70 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+// This test is adapted from 25_algorithms/shuffle/1.cc.
+
+void
+test01()
+{
+ for (unsigned size = 0; size < 50; ++size)
+ {
+ std::vector<int> vref(size);
+ std::iota(vref.begin(), vref.end(), 0);
+ std::vector<int> v1(vref), v2(vref);
+ test_container<int, random_access_iterator_wrapper> c
+ = {&v1[0], &v1[0] + size};
+ test_range<int, random_access_iterator_wrapper> r
+ = {&v2[0], &v2[0] + size};
+
+ std::ranlux48_base g1(size), g2(size + 1);
+ VERIFY( ranges::shuffle(c, g1) == c.end() );
+ VERIFY( ranges::shuffle(ranges::begin(r), ranges::end(r), g2)
+ == ranges::end(r) );
+
+ if (size >= 10)
+ {
+ VERIFY( !ranges::equal(c, vref) );
+ VERIFY( !ranges::equal(r, vref) );
+ VERIFY( !ranges::equal(c, r) );
+ }
+
+ VERIFY( ranges::is_permutation(c, vref) );
+ VERIFY( ranges::is_permutation(r, vref) );
+ }
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,81 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ for (unsigned size = 0; size < 50; ++size)
+ {
+ std::vector<int> vref(size);
+ std::iota(vref.begin(), vref.end(), 0);
+ std::vector<int> v1(vref), v2(vref);
+ test_container<int, random_access_iterator_wrapper> c
+ = {&v1[0], &v1[0] + size};
+ test_range<int, random_access_iterator_wrapper> r
+ = {&v2[0], &v2[0] + size};
+
+ std::ranlux48_base g1(size), g2(size + 1);
+ ranges::shuffle(c, g1);
+ ranges::shuffle(ranges::begin(r), ranges::end(r), g2);
+
+ VERIFY( ranges::sort(c) == c.end() );
+ VERIFY( ranges::sort(r) == ranges::end(r) );
+
+ VERIFY( ranges::equal(c, vref) );
+ VERIFY( ranges::equal(r, vref) );
+ }
+}
+
+struct X
+{
+ int i;
+ constexpr X(int a) : i(a) { }
+};
+
+constexpr bool
+test02()
+{
+ X x[] = {3,4,2,1,5};
+ const X y[] = {4,3,2,1,5};
+
+ auto res = ranges::sort(x, x+4, ranges::greater{}, &X::i);
+ return (res == x+4
+ && ranges::equal(x, y, {}, &X::i, &X::i));
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
new file mode 100644
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10};
+ test_container<int, bidirectional_iterator_wrapper> cx(x);
+ auto pred = [] (int a) { return a%2==0; };
+ auto range = ranges::stable_partition(cx, pred);
+ VERIFY( ranges::all_of(cx.begin(), range.begin(), pred) );
+ VERIFY( ranges::none_of(range, pred) );
+ }
+
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10,11};
+ test_range<int, bidirectional_iterator_wrapper> cx(x);
+ auto pred = [] (int a) { return a%2==0; };
+ auto range = ranges::stable_partition(cx, pred);
+ VERIFY( ranges::all_of(cx.begin(), range.begin(), pred) );
+ VERIFY( ranges::none_of(range, pred) );
+ }
+}
+
+void
+test02()
+{
+ for (int k = 1; k <= 10; k++)
+ {
+ int x[] = {1,2,3,4,5,6,7,8,9,10};
+ auto pred = [&] (int a) { return a >= k; };
+ auto proj = [] (int a) { return a-1; };
+ auto range = ranges::stable_partition(x, x+10, pred, proj);
+ VERIFY( ranges::all_of(x, range.begin(), pred, proj) );
+ VERIFY( ranges::none_of(range, pred, proj) );
+
+ int y[] = {0,1,2,3,4,5,6,7,8,9};
+ ranges::rotate(y, y+k);
+ VERIFY( ranges::equal(x, y, {}, proj) );
+ }
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
new file mode 100644
@@ -0,0 +1,70 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-cstdint "" }
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::random_access_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+// This test doesn't verify the stability property of ranges::stable_sort,
+// because at the moment it's just defined to be a wrapper over
+// std::stable_sort.
+
+void
+test01()
+{
+ for (unsigned size = 0; size < 50; ++size)
+ {
+ std::vector<int> vref(size);
+ std::iota(vref.begin(), vref.end(), 0);
+ std::vector<int> v1(vref), v2(vref);
+ test_container<int, random_access_iterator_wrapper> c
+ = {&v1[0], &v1[0] + size};
+ test_range<int, random_access_iterator_wrapper> r
+ = {&v2[0], &v2[0] + size};
+
+ std::ranlux48_base g1(size), g2(size + 1);
+ ranges::shuffle(c, g1);
+ ranges::shuffle(ranges::begin(r), ranges::end(r), g2);
+
+ auto res1 = ranges::stable_sort(c.begin(), c.end(), {}, std::negate<>{});
+ VERIFY( res1 == c.end() );
+
+ auto res2 = ranges::stable_sort(r, ranges::greater{});
+ VERIFY( res2 == ranges::end(r) );
+
+ VERIFY( ranges::equal(c, r) );
+ VERIFY( ranges::equal(c.begin(), c.end(), vref.rbegin(), vref.rend()) );
+ }
+}
+
+int
+main()
+{
+ test01();
+}
new file mode 100644
@@ -0,0 +1,124 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+using __gnu_test::bidirectional_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+ int moved = 0;
+
+ constexpr X(int a) : i(a) { }
+
+ constexpr X(const X&) = delete;
+ constexpr X& operator=(const X&) = delete;
+
+ constexpr X(X&& other)
+ {
+ *this = std::move(other);
+ }
+
+ constexpr X&
+ operator=(X&& other)
+ {
+ other.moved++;
+ i = other.i;
+ return *this;
+ }
+
+ friend constexpr bool
+ operator==(const X& a, const X& b)
+ { return a.i == b.i; }
+};
+
+void
+test01()
+{
+ {
+ X x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X y[7] = { 2, 4, 3, 5, 8, 9, 1 };
+ X z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X w[7] = { 2, 4, 3, 5, 8, 9, 1 };
+ auto [x_iter, y_iter] = ranges::swap_ranges(x, y);
+ VERIFY( ranges::equal(y, z) && x_iter == x+7 && y_iter == y+7 );
+ VERIFY( ranges::equal(x, w) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ int y[4] = { 2, 4, 6, 0 };
+ int z[3] = { 1, 2, 3 };
+ int w[3] = { 2, 4, 6 };
+ test_container<int, forward_iterator_wrapper> cx(x);
+ test_container<int, forward_iterator_wrapper> cy(y);
+ auto [x_iter, y_iter] = ranges::swap_ranges(cx, cy);
+ VERIFY( ranges::equal(y, y+3, z, z+3) );
+ VERIFY( x_iter.ptr == x+3 && y_iter.ptr == y+3 );
+ VERIFY( y[3] == 0 );
+ VERIFY( ranges::equal(x, w) );
+ }
+
+ {
+ int x[3] = { 1, 2, 3 };
+ int y[4] = { 2, 4, 6, 0 };
+ int z[3] = { 1, 2, 3 };
+ int w[3] = { 2, 4, 6 };
+ test_range<int, input_iterator_wrapper> cx(x);
+ test_range<int, input_iterator_wrapper> cy(y);
+ auto [y_iter, x_iter] = ranges::swap_ranges(cy, cx);
+ VERIFY( ranges::equal(y, y+3, z, z+3) );
+ VERIFY( x_iter.ptr == x+3 && y_iter.ptr == y+3 );
+ VERIFY( y[3] == 0 );
+ VERIFY( ranges::equal(x, w) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ bool ok = true;
+ X x[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X y[7] = { 2, 4, 3, 5, 8, 9, 1 };
+ X z[7] = { 1, 2, 3, 4, 5, 6, 7 };
+ X w[7] = { 2, 4, 3, 5, 8, 9, 1 };
+ auto [x_iter, y_iter] = ranges::swap_ranges(x, y);
+ ok &= ranges::equal(y, z) && x_iter == x+7 && y_iter == y+7;
+ ok &= ranges::equal(x, w);
+ return ok;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}
+
+
new file mode 100644
@@ -0,0 +1,148 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+struct X { int i; };
+
+void
+test01()
+{
+ {
+ int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} };
+ auto [in, out] = ranges::transform(x, x, [] (int a) { return a+1; });
+ VERIFY( in == x+6 && out == x+6 );
+ VERIFY( ranges::equal(x, y) );
+ }
+
+ {
+ X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} };
+ int z[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} };
+ test_container<X, forward_iterator_wrapper> cx(x);
+ test_container<int, forward_iterator_wrapper> cy(y), cz(z);
+ auto [in, out]
+ = ranges::transform(cx, cz.begin(), [] (int a) { return a+1; }, &X::i);
+ VERIFY( ranges::equal(cy, cz) );
+ VERIFY( in == cx.end() && ++out == cz.end() );
+ }
+
+ {
+ X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ X y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} };
+ int z[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} };
+ test_range<X, input_iterator_wrapper> rx(x), ry(y);
+ test_range<int, output_iterator_wrapper> rz(z);
+ auto [in, out]
+ = ranges::transform(rx, rz.begin(), [] (int a) { return a+1; }, &X::i);
+ VERIFY( ranges::equal(ry, z, {}, &X::i) );
+ VERIFY( in == rx.end() && out.ptr == z+6 );
+ }
+}
+
+struct Y { int i; int j; };
+
+constexpr bool
+test02()
+{
+ int x[] = { 1, 2, 3 };
+ Y y[] = { {1,2}, {2,4}, {3,6} };
+ ranges::transform(y, y+3, x, [] (int a) { return -a; }, &Y::i);
+ return x[0] == -1 && x[1] == -2 && x[2] == -3;
+}
+
+void
+test03()
+{
+ {
+ int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ const int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} };
+ int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} };
+ auto [in1, in2, out] = ranges::transform(x, y, x, std::plus<>{});
+ VERIFY( in1 == x+6 && in2 == y+6 && out == x+6 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ const int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} };
+ int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} };
+ auto [in1, in2, out] = ranges::transform(y, x, x, std::plus<>{});
+ VERIFY( in1 == y+6 && in2 == x+6 && out == x+6 );
+ VERIFY( ranges::equal(x, z) );
+ }
+
+ {
+ X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} };
+ int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} };
+ int w[6];
+ test_container<X, forward_iterator_wrapper> cx(x);
+ test_container<int, forward_iterator_wrapper> cy(y), cz(z), cw(w);
+ auto [in1, in2, out]
+ = ranges::transform(cx, cy, cw.begin(), std::plus<>{}, &X::i);
+ VERIFY( in1 == cx.end() && ++in2 == cy.end() && out == cw.end() );
+ VERIFY( ranges::equal(cw, cz) );
+ }
+
+ {
+ X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} };
+ int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} };
+ int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} };
+ int w[6];
+ test_range<X, input_iterator_wrapper> rx(x);
+ test_range<int, input_iterator_wrapper> ry(y), rz(z);
+ test_range<int, output_iterator_wrapper> rw(w);
+ auto [in1, in2, out]
+ = ranges::transform(rx, ry, rw.begin(), std::plus<>{}, &X::i);
+ VERIFY( in1 == rx.end() && ++in2 == ry.end() && out.ptr == w+6 );
+ VERIFY( ranges::equal(w, rz) );
+ }
+}
+
+constexpr bool
+test04()
+{
+ int x[3];
+ const Y y[3] = { {1,2}, {2,4}, {3,6} };
+ ranges::transform(y, y+3, y, y+3, x, std::plus<>{}, &Y::i, &Y::j);
+ return x[0] == 3 && x[1] == 6 && x[2] == 9;
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+ test03();
+ static_assert(test04());
+}
+
new file mode 100644
@@ -0,0 +1,143 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <list>
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+
+namespace ranges = std::ranges;
+
+struct X
+{
+ int i;
+};
+
+void
+test01()
+{
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} };
+ const int y[5] = { {2}, {6}, {8}, {2}, {11} };
+ test_container<X, forward_iterator_wrapper> cx(x);
+ auto res = ranges::unique(cx, {}, &X::i);
+ VERIFY( res.end() == cx.end() );
+ VERIFY( ranges::equal(cx.begin(), res.begin(), y, y+5, {}, &X::i) );
+ }
+
+ {
+ X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} };
+ const int y[5] = { {2}, {6}, {8}, {2}, {11} };
+ test_range<X, forward_iterator_wrapper> rx(x);
+ auto res = ranges::unique(rx, {}, &X::i);
+ VERIFY( res.end() == rx.end() );
+ VERIFY( ranges::equal(rx.begin(), res.begin(), y, y+5, {}, &X::i) );
+ }
+}
+
+constexpr bool
+test02()
+{
+ int x[2] = {2, 2};
+ const int y[1] = {2};
+ auto res = ranges::unique(x);
+ return ranges::equal(x, res.begin(), y, y+1, ranges::equal_to{});
+}
+
+/* The following is adapted from 25_algorithms/unique/2.cc. */
+
+namespace two_dot_cc
+{
+ const int T1[] = {1, 4, 4, 6, 1, 2, 2, 3, 1, 6, 6, 6, 5, 7, 5, 4, 4};
+ const int T2[] = {1, 1, 1, 2, 2, 1, 1, 7, 6, 6, 7, 8, 8, 8, 8, 9, 9};
+ const int N = sizeof(T1) / sizeof(int);
+
+ const int A1[] = {1, 4, 6, 1, 2, 3, 1, 6, 5, 7, 5, 4};
+ const int A2[] = {1, 4, 4, 6, 6, 6, 6, 7};
+ const int A3[] = {1, 1, 1};
+
+ const int B1[] = {1, 2, 1, 7, 6, 7, 8, 9};
+ const int B2[] = {1, 1, 1, 2, 2, 7, 7, 8, 8, 8, 8, 9, 9};
+ const int B3[] = {9, 9, 8, 8, 8, 8, 7, 6, 6, 1, 1, 1, 1, 1};
+
+ void test01()
+ {
+ using namespace std;
+
+ list<int>::iterator pos;
+
+ list<int> coll(T1, T1 + N);
+ pos = ranges::unique(coll.begin(), coll.end()).begin();
+ VERIFY( equal(coll.begin(), pos, A1) );
+
+ list<int> coll2(T2, T2 + N);
+ pos = ranges::unique(coll2.begin(), coll2.end()).begin();
+ VERIFY( equal(coll2.begin(), pos, B1) );
+ }
+
+ void test02()
+ {
+ using namespace std;
+
+ list<int>::iterator pos;
+
+ list<int> coll(T1, T1 + N);
+ pos = ranges::unique(coll.begin(), coll.end(), greater<int>()).begin();
+ VERIFY( equal(coll.begin(), pos, A2) );
+
+ list<int> coll2(T2, T2 + N);
+ pos = ranges::unique(coll2.begin(), coll2.end(), greater<int>()).begin();
+ VERIFY( equal(coll2.begin(), pos, B2) );
+ }
+
+ void test03()
+ {
+ using namespace std;
+
+ list<int>::iterator pos;
+
+ list<int> coll(T1, T1 + N);
+ pos = ranges::unique(coll.begin(), coll.end(), less<int>()).begin();
+ VERIFY( equal(coll.begin(), pos, A3) );
+
+ list<int> coll2(T2, T2 + N);
+ reverse(coll2.begin(), coll2.end());
+ pos = ranges::unique(coll2.begin(), coll2.end(), less<int>()).begin();
+ VERIFY( equal(coll2.begin(), pos, B3) );
+ }
+} // namespace two_dot_cc
+
+int main()
+{
+ test01();
+ static_assert(test02());
+
+ two_dot_cc::test01();
+ two_dot_cc::test02();
+ two_dot_cc::test03();
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,113 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_range;
+using __gnu_test::input_iterator_wrapper;
+using __gnu_test::output_iterator_wrapper;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+template<template<typename> typename source_wrapper,
+ template<typename> typename dest_wrapper>
+void
+test01()
+{
+ int x[6] = {0, 0, 0, 1, 1, 1};
+ int y[2];
+ const int z[2] = {0, 1};
+
+ test_range<int, source_wrapper> rx(x);
+ test_range<int, dest_wrapper> ry(y);
+ auto [in,out] = ranges::unique_copy(rx, ry.begin());
+ VERIFY( in == ranges::end(rx) && out == ranges::end(ry) );
+ VERIFY( ranges::equal(y, z) );
+}
+
+template<template<typename> typename source_wrapper,
+ template<typename> typename dest_wrapper>
+void
+test02()
+{
+ int x[6] = {0, 0, 0, 1, 1, 1};
+ int y[2] = {0, 0};
+ const int z[2] = {0, 0};
+
+ test_range<int, source_wrapper> rx(x, x);
+ test_range<int, dest_wrapper> ry(y, y);
+ auto [in, out] = ranges::unique_copy(rx.begin(), rx.end(), ry.begin());
+ VERIFY( in.ptr == x && out.ptr == y );
+ VERIFY( ranges::equal(y, z) );
+}
+
+template<template<typename> typename source_wrapper,
+ template<typename> typename dest_wrapper>
+void
+test03()
+{
+ struct X { int i; };
+ X x[6] = { {1}, {2}, {2}, {4}, {4}, {6} };
+ X y[4] = { {1}, {2}, {4}, {6} };
+ const X z[4] = { {1}, {2}, {4}, {6} };
+
+ test_range<X, source_wrapper> rx(x);
+ test_range<X, dest_wrapper> ry(y);
+ auto [in, out]
+ = ranges::unique_copy(rx, ry.begin(), ranges::equal_to{}, &X::i);
+ VERIFY( in == ranges::end(rx) && out == ranges::end(ry) );
+ VERIFY( ranges::equal(y, z, {}, &X::i, &X::i) );
+}
+
+constexpr bool
+test04()
+{
+ struct X { int i; };
+ X x[7] = { {1}, {2}, {2}, {2}, {4}, {4}, {6} };
+ X y[4] = { {1}, {2}, {4}, {6} };
+ const X z[4] = { {1}, {2}, {4}, {6} };
+
+ auto [in, out]
+ = ranges::unique_copy(x, x+7, y, ranges::equal_to{}, &X::i);
+ return (in == ranges::end(x)
+ && out == ranges::end(y)
+ && ranges::equal(y, z, {}, &X::i, &X::i));
+}
+
+int
+main()
+{
+ test01<input_iterator_wrapper, output_iterator_wrapper>();
+ test01<input_iterator_wrapper, forward_iterator_wrapper>();
+ test01<forward_iterator_wrapper, output_iterator_wrapper>();
+
+ test02<input_iterator_wrapper, output_iterator_wrapper>();
+ test02<input_iterator_wrapper, forward_iterator_wrapper>();
+ test02<forward_iterator_wrapper, output_iterator_wrapper>();
+
+ test03<input_iterator_wrapper, output_iterator_wrapper>();
+ test03<input_iterator_wrapper, forward_iterator_wrapper>();
+ test03<forward_iterator_wrapper, output_iterator_wrapper>();
+
+ static_assert(test04());
+}
new file mode 100644
@@ -0,0 +1,66 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::test_range;
+using __gnu_test::forward_iterator_wrapper;
+
+namespace ranges = std::ranges;
+
+void
+test01()
+{
+ int x[] = {1, 2, 3, 4, 5, 5, 6, 7};
+ for (unsigned i = 0; i < 5; i++)
+ for (unsigned j = 6; j < 8; j++)
+ {
+ test_container<int, forward_iterator_wrapper> cx(x);
+ auto result = ranges::upper_bound(std::next(cx.begin(), i),
+ std::next(cx.begin(), j),
+ 4, {}, [] (int a) { return a-1; });
+ VERIFY( result.ptr == x+6 );
+ }
+
+ ranges::reverse(x);
+ test_range<int, forward_iterator_wrapper> rx(x);
+ auto result = ranges::upper_bound(rx, 5, ranges::greater{},
+ [] (int a) { return a+1; });
+ VERIFY( result.ptr == x+5 );
+}
+
+constexpr bool
+test02()
+{
+ int x[] = {1, 2, 3, 4, 5};
+ return (ranges::upper_bound(x, 6) == x+5
+ && ranges::upper_bound(x, x, 6) == x
+ && ranges::upper_bound(x, 1) == x+1);
+}
+
+int
+main()
+{
+ test01();
+ static_assert(test02());
+}