1 // Core algorithmic facilities -*- C++ -*-
2 
3 // Copyright (C) 2020-2021 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/ranges_algo.h
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{algorithm}
28  */
29 
30 #ifndef _RANGES_ALGO_H
31 #define _RANGES_ALGO_H 1
32 
33 #if __cplusplus > 201703L
34 
35 #include <bits/ranges_algobase.h>
36 #include <bits/ranges_util.h>
37 #include <bits/uniform_int_dist.h> // concept uniform_random_bit_generator
38 
39 #if __cpp_lib_concepts
_GLIBCXX_VISIBILITY(default)40 namespace std _GLIBCXX_VISIBILITY(default)
41 {
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
43 namespace ranges
44 {
45   namespace __detail
46   {
47     template<typename _Comp, typename _Proj>
48       constexpr auto
49       __make_comp_proj(_Comp& __comp, _Proj& __proj)
50       {
51 	return [&] (auto&& __lhs, auto&& __rhs) -> bool {
52 	  using _TL = decltype(__lhs);
53 	  using _TR = decltype(__rhs);
54 	  return std::__invoke(__comp,
55 			       std::__invoke(__proj, std::forward<_TL>(__lhs)),
56 			       std::__invoke(__proj, std::forward<_TR>(__rhs)));
57 	};
58       }
59 
60     template<typename _Pred, typename _Proj>
61       constexpr auto
62       __make_pred_proj(_Pred& __pred, _Proj& __proj)
63       {
64 	return [&] <typename _Tp> (_Tp&& __arg) -> bool {
65 	  return std::__invoke(__pred,
66 			       std::__invoke(__proj, std::forward<_Tp>(__arg)));
67 	};
68       }
69   } // namespace __detail
70 
71   struct __all_of_fn
72   {
73     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
74 	     typename _Proj = identity,
75 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
76       constexpr bool
77       operator()(_Iter __first, _Sent __last,
78 		 _Pred __pred, _Proj __proj = {}) const
79       {
80 	for (; __first != __last; ++__first)
81 	  if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
82 	    return false;
83 	return true;
84       }
85 
86     template<input_range _Range, typename _Proj = identity,
87 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
88 	       _Pred>
89       constexpr bool
90       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
91       {
92 	return (*this)(ranges::begin(__r), ranges::end(__r),
93 		       std::move(__pred), std::move(__proj));
94       }
95   };
96 
97   inline constexpr __all_of_fn all_of{};
98 
99   struct __any_of_fn
100   {
101     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
102 	     typename _Proj = identity,
103 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
104       constexpr bool
105       operator()(_Iter __first, _Sent __last,
106 		 _Pred __pred, _Proj __proj = {}) const
107       {
108 	for (; __first != __last; ++__first)
109 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
110 	    return true;
111 	return false;
112       }
113 
114     template<input_range _Range, typename _Proj = identity,
115 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
116 	       _Pred>
117       constexpr bool
118       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
119       {
120 	return (*this)(ranges::begin(__r), ranges::end(__r),
121 		       std::move(__pred), std::move(__proj));
122       }
123   };
124 
125   inline constexpr __any_of_fn any_of{};
126 
127   struct __none_of_fn
128   {
129     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
130 	     typename _Proj = identity,
131 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
132       constexpr bool
133       operator()(_Iter __first, _Sent __last,
134 		 _Pred __pred, _Proj __proj = {}) const
135       {
136 	for (; __first != __last; ++__first)
137 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
138 	    return false;
139 	return true;
140       }
141 
142     template<input_range _Range, typename _Proj = identity,
143 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
144 	       _Pred>
145       constexpr bool
146       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
147       {
148 	return (*this)(ranges::begin(__r), ranges::end(__r),
149 		       std::move(__pred), std::move(__proj));
150       }
151   };
152 
153   inline constexpr __none_of_fn none_of{};
154 
155   template<typename _Iter, typename _Fp>
156     struct in_fun_result
157     {
158       [[no_unique_address]] _Iter in;
159       [[no_unique_address]] _Fp fun;
160 
161       template<typename _Iter2, typename _F2p>
162 	requires convertible_to<const _Iter&, _Iter2>
163 	  && convertible_to<const _Fp&, _F2p>
164 	constexpr
165 	operator in_fun_result<_Iter2, _F2p>() const &
166 	{ return {in, fun}; }
167 
168       template<typename _Iter2, typename _F2p>
169 	requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p>
170 	constexpr
171 	operator in_fun_result<_Iter2, _F2p>() &&
172 	{ return {std::move(in), std::move(fun)}; }
173     };
174 
175   template<typename _Iter, typename _Fp>
176     using for_each_result = in_fun_result<_Iter, _Fp>;
177 
178   struct __for_each_fn
179   {
180     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
181 	     typename _Proj = identity,
182 	     indirectly_unary_invocable<projected<_Iter, _Proj>> _Fun>
183       constexpr for_each_result<_Iter, _Fun>
184       operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const
185       {
186 	for (; __first != __last; ++__first)
187 	  std::__invoke(__f, std::__invoke(__proj, *__first));
188 	return { std::move(__first), std::move(__f) };
189       }
190 
191     template<input_range _Range, typename _Proj = identity,
192 	     indirectly_unary_invocable<projected<iterator_t<_Range>, _Proj>>
193 	       _Fun>
194       constexpr for_each_result<borrowed_iterator_t<_Range>, _Fun>
195       operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const
196       {
197 	return (*this)(ranges::begin(__r), ranges::end(__r),
198 		       std::move(__f), std::move(__proj));
199       }
200   };
201 
202   inline constexpr __for_each_fn for_each{};
203 
204   template<typename _Iter, typename _Fp>
205     using for_each_n_result = in_fun_result<_Iter, _Fp>;
206 
207   struct __for_each_n_fn
208   {
209     template<input_iterator _Iter, typename _Proj = identity,
210 	     indirectly_unary_invocable<projected<_Iter, _Proj>> _Fun>
211       constexpr for_each_n_result<_Iter, _Fun>
212       operator()(_Iter __first, iter_difference_t<_Iter> __n,
213 		 _Fun __f, _Proj __proj = {}) const
214       {
215 	if constexpr (random_access_iterator<_Iter>)
216 	  {
217 	    if (__n <= 0)
218 	      return {std::move(__first), std::move(__f)};
219 	    auto __last = __first + __n;
220 	    return ranges::for_each(std::move(__first), std::move(__last),
221 				    std::move(__f), std::move(__proj));
222 	  }
223 	else
224 	  {
225 	    while (__n-- > 0)
226 	      {
227 		std::__invoke(__f, std::__invoke(__proj, *__first));
228 		++__first;
229 	      }
230 	    return {std::move(__first), std::move(__f)};
231 	  }
232       }
233   };
234 
235   inline constexpr __for_each_n_fn for_each_n{};
236 
237   // find, find_if and find_if_not are defined in <bits/ranges_util.h>.
238 
239   struct __find_first_of_fn
240   {
241     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
242 	     forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
243 	     typename _Pred = ranges::equal_to,
244 	     typename _Proj1 = identity, typename _Proj2 = identity>
245       requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
246       constexpr _Iter1
247       operator()(_Iter1 __first1, _Sent1 __last1,
248 		 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
249 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
250       {
251 	for (; __first1 != __last1; ++__first1)
252 	  for (auto __iter = __first2; __iter != __last2; ++__iter)
253 	    if (std::__invoke(__pred,
254 			      std::__invoke(__proj1, *__first1),
255 			      std::__invoke(__proj2, *__iter)))
256 	      return __first1;
257 	return __first1;
258       }
259 
260     template<input_range _Range1, forward_range _Range2,
261 	     typename _Pred = ranges::equal_to,
262 	     typename _Proj1 = identity, typename _Proj2 = identity>
263       requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
264 				     _Pred, _Proj1, _Proj2>
265       constexpr borrowed_iterator_t<_Range1>
266       operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
267 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
268       {
269 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
270 		       ranges::begin(__r2), ranges::end(__r2),
271 		       std::move(__pred),
272 		       std::move(__proj1), std::move(__proj2));
273       }
274   };
275 
276   inline constexpr __find_first_of_fn find_first_of{};
277 
278   struct __count_fn
279   {
280     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
281 	     typename _Tp, typename _Proj = identity>
282       requires indirect_binary_predicate<ranges::equal_to,
283 					 projected<_Iter, _Proj>,
284 					 const _Tp*>
285       constexpr iter_difference_t<_Iter>
286       operator()(_Iter __first, _Sent __last,
287 		 const _Tp& __value, _Proj __proj = {}) const
288       {
289 	iter_difference_t<_Iter> __n = 0;
290 	for (; __first != __last; ++__first)
291 	  if (std::__invoke(__proj, *__first) == __value)
292 	    ++__n;
293 	return __n;
294       }
295 
296     template<input_range _Range, typename _Tp, typename _Proj = identity>
297       requires indirect_binary_predicate<ranges::equal_to,
298 					 projected<iterator_t<_Range>, _Proj>,
299 					 const _Tp*>
300       constexpr range_difference_t<_Range>
301       operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
302       {
303 	return (*this)(ranges::begin(__r), ranges::end(__r),
304 		       __value, std::move(__proj));
305       }
306   };
307 
308   inline constexpr __count_fn count{};
309 
310   struct __count_if_fn
311   {
312     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
313 	     typename _Proj = identity,
314 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
315       constexpr iter_difference_t<_Iter>
316       operator()(_Iter __first, _Sent __last,
317 		 _Pred __pred, _Proj __proj = {}) const
318       {
319 	iter_difference_t<_Iter> __n = 0;
320 	for (; __first != __last; ++__first)
321 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
322 	    ++__n;
323 	return __n;
324       }
325 
326     template<input_range _Range,
327 	     typename _Proj = identity,
328 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
329 	       _Pred>
330       constexpr range_difference_t<_Range>
331       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
332       {
333 	return (*this)(ranges::begin(__r), ranges::end(__r),
334 		       std::move(__pred), std::move(__proj));
335       }
336   };
337 
338   inline constexpr __count_if_fn count_if{};
339 
340   // in_in_result, mismatch and search are defined in <bits/ranges_util.h>.
341 
342   struct __search_n_fn
343   {
344     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
345 	     typename _Pred = ranges::equal_to, typename _Proj = identity>
346       requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj>
347       constexpr subrange<_Iter>
348       operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count,
349 		 const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const
350       {
351 	if (__count <= 0)
352 	  return {__first, __first};
353 
354 	auto __value_comp = [&] <typename _Rp> (_Rp&& __arg) -> bool {
355 	    return std::__invoke(__pred, std::forward<_Rp>(__arg), __value);
356 	};
357 	if (__count == 1)
358 	  {
359 	    __first = ranges::find_if(std::move(__first), __last,
360 				      std::move(__value_comp),
361 				      std::move(__proj));
362 	    if (__first == __last)
363 	      return {__first, __first};
364 	    else
365 	      {
366 		auto __end = __first;
367 		return {__first, ++__end};
368 	      }
369 	  }
370 
371 	if constexpr (sized_sentinel_for<_Sent, _Iter>
372 		      && random_access_iterator<_Iter>)
373 	  {
374 	    auto __tail_size = __last - __first;
375 	    auto __remainder = __count;
376 
377 	    while (__remainder <= __tail_size)
378 	      {
379 		__first += __remainder;
380 		__tail_size -= __remainder;
381 		auto __backtrack = __first;
382 		while (__value_comp(std::__invoke(__proj, *--__backtrack)))
383 		  {
384 		    if (--__remainder == 0)
385 		      return {__first - __count, __first};
386 		  }
387 		__remainder = __count + 1 - (__first - __backtrack);
388 	      }
389 	    auto __i = __first + __tail_size;
390 	    return {__i, __i};
391 	  }
392 	else
393 	  {
394 	    __first = ranges::find_if(__first, __last, __value_comp, __proj);
395 	    while (__first != __last)
396 	      {
397 		auto __n = __count;
398 		auto __i = __first;
399 		++__i;
400 		while (__i != __last && __n != 1
401 		       && __value_comp(std::__invoke(__proj, *__i)))
402 		  {
403 		    ++__i;
404 		    --__n;
405 		  }
406 		if (__n == 1)
407 		  return {__first, __i};
408 		if (__i == __last)
409 		  return {__i, __i};
410 		__first = ranges::find_if(++__i, __last, __value_comp, __proj);
411 	      }
412 	    return {__first, __first};
413 	  }
414       }
415 
416     template<forward_range _Range, typename _Tp,
417 	     typename _Pred = ranges::equal_to, typename _Proj = identity>
418       requires indirectly_comparable<iterator_t<_Range>, const _Tp*,
419 				     _Pred, _Proj>
420       constexpr borrowed_subrange_t<_Range>
421       operator()(_Range&& __r, range_difference_t<_Range> __count,
422 	       const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const
423       {
424 	return (*this)(ranges::begin(__r), ranges::end(__r),
425 		       std::move(__count), __value,
426 		       std::move(__pred), std::move(__proj));
427       }
428   };
429 
430   inline constexpr __search_n_fn search_n{};
431 
432   struct __find_end_fn
433   {
434     template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
435 	     forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
436 	     typename _Pred = ranges::equal_to,
437 	     typename _Proj1 = identity, typename _Proj2 = identity>
438       requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
439       constexpr subrange<_Iter1>
440       operator()(_Iter1 __first1, _Sent1 __last1,
441 		 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
442 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
443       {
444 	if constexpr (bidirectional_iterator<_Iter1>
445 		      && bidirectional_iterator<_Iter2>)
446 	  {
447 	    auto __i1 = ranges::next(__first1, __last1);
448 	    auto __i2 = ranges::next(__first2, __last2);
449 	    auto __rresult
450 	      = ranges::search(reverse_iterator<_Iter1>{__i1},
451 			       reverse_iterator<_Iter1>{__first1},
452 			       reverse_iterator<_Iter2>{__i2},
453 			       reverse_iterator<_Iter2>{__first2},
454 			       std::move(__pred),
455 			       std::move(__proj1), std::move(__proj2));
456 	    auto __result_first = ranges::end(__rresult).base();
457 	    auto __result_last = ranges::begin(__rresult).base();
458 	    if (__result_last == __first1)
459 	      return {__i1, __i1};
460 	    else
461 	      return {__result_first, __result_last};
462 	  }
463 	else
464 	  {
465 	    auto __i = ranges::next(__first1, __last1);
466 	    if (__first2 == __last2)
467 	      return {__i, __i};
468 
469 	    auto __result_begin = __i;
470 	    auto __result_end = __i;
471 	    for (;;)
472 	      {
473 		auto __new_range = ranges::search(__first1, __last1,
474 						  __first2, __last2,
475 						  __pred, __proj1, __proj2);
476 		auto __new_result_begin = ranges::begin(__new_range);
477 		auto __new_result_end = ranges::end(__new_range);
478 		if (__new_result_begin == __last1)
479 		  return {__result_begin, __result_end};
480 		else
481 		  {
482 		    __result_begin = __new_result_begin;
483 		    __result_end = __new_result_end;
484 		    __first1 = __result_begin;
485 		    ++__first1;
486 		  }
487 	      }
488 	  }
489       }
490 
491     template<forward_range _Range1, forward_range _Range2,
492 	     typename _Pred = ranges::equal_to,
493 	     typename _Proj1 = identity, typename _Proj2 = identity>
494       requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
495 				     _Pred, _Proj1, _Proj2>
496       constexpr borrowed_subrange_t<_Range1>
497       operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
498 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
499       {
500 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
501 		       ranges::begin(__r2), ranges::end(__r2),
502 		       std::move(__pred),
503 		       std::move(__proj1), std::move(__proj2));
504       }
505   };
506 
507   inline constexpr __find_end_fn find_end{};
508 
509   struct __adjacent_find_fn
510   {
511     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
512 	     typename _Proj = identity,
513 	     indirect_binary_predicate<projected<_Iter, _Proj>,
514 				       projected<_Iter, _Proj>> _Pred
515 	       = ranges::equal_to>
516       constexpr _Iter
517       operator()(_Iter __first, _Sent __last,
518 		 _Pred __pred = {}, _Proj __proj = {}) const
519       {
520 	if (__first == __last)
521 	  return __first;
522 	auto __next = __first;
523 	for (; ++__next != __last; __first = __next)
524 	  {
525 	    if (std::__invoke(__pred,
526 			      std::__invoke(__proj, *__first),
527 			      std::__invoke(__proj, *__next)))
528 	      return __first;
529 	  }
530 	return __next;
531       }
532 
533     template<forward_range _Range, typename _Proj = identity,
534 	     indirect_binary_predicate<
535 	       projected<iterator_t<_Range>, _Proj>,
536 	       projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
537       constexpr borrowed_iterator_t<_Range>
538       operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const
539       {
540 	return (*this)(ranges::begin(__r), ranges::end(__r),
541 		       std::move(__pred), std::move(__proj));
542       }
543   };
544 
545   inline constexpr __adjacent_find_fn adjacent_find{};
546 
547   struct __is_permutation_fn
548   {
549     template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
550 	     forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
551 	     typename _Proj1 = identity, typename _Proj2 = identity,
552 	     indirect_equivalence_relation<projected<_Iter1, _Proj1>,
553 					   projected<_Iter2, _Proj2>> _Pred
554 	       = ranges::equal_to>
555       constexpr bool
556       operator()(_Iter1 __first1, _Sent1 __last1,
557 		 _Iter2 __first2, _Sent2 __last2, _Pred __pred = {},
558 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
559       {
560 	constexpr bool __sized_iters
561 	  = (sized_sentinel_for<_Sent1, _Iter1>
562 	     && sized_sentinel_for<_Sent2, _Iter2>);
563 	if constexpr (__sized_iters)
564 	  {
565 	    auto __d1 = ranges::distance(__first1, __last1);
566 	    auto __d2 = ranges::distance(__first2, __last2);
567 	    if (__d1 != __d2)
568 	      return false;
569 	  }
570 
571 	// Efficiently compare identical prefixes:  O(N) if sequences
572 	// have the same elements in the same order.
573 	for (; __first1 != __last1 && __first2 != __last2;
574 	     ++__first1, (void)++__first2)
575 	  if (!(bool)std::__invoke(__pred,
576 				   std::__invoke(__proj1, *__first1),
577 				   std::__invoke(__proj2, *__first2)))
578 	      break;
579 
580 	if constexpr (__sized_iters)
581 	  {
582 	    if (__first1 == __last1)
583 	      return true;
584 	  }
585 	else
586 	  {
587 	    auto __d1 = ranges::distance(__first1, __last1);
588 	    auto __d2 = ranges::distance(__first2, __last2);
589 	    if (__d1 == 0 && __d2 == 0)
590 	      return true;
591 	    if (__d1 != __d2)
592 	      return false;
593 	  }
594 
595 	for (auto __scan = __first1; __scan != __last1; ++__scan)
596 	  {
597 	    auto&& __proj_scan = std::__invoke(__proj1, *__scan);
598 	    auto __comp_scan = [&] <typename _Tp> (_Tp&& __arg) -> bool {
599 	      return std::__invoke(__pred, __proj_scan,
600 				   std::forward<_Tp>(__arg));
601 	    };
602 	    if (__scan != ranges::find_if(__first1, __scan,
603 					  __comp_scan, __proj1))
604 	      continue; // We've seen this one before.
605 
606 	    auto __matches = ranges::count_if(__first2, __last2,
607 					      __comp_scan, __proj2);
608 	    if (__matches == 0
609 		|| ranges::count_if(__scan, __last1,
610 				    __comp_scan, __proj1) != __matches)
611 	      return false;
612 	  }
613 	return true;
614       }
615 
616     template<forward_range _Range1, forward_range _Range2,
617 	     typename _Proj1 = identity, typename _Proj2 = identity,
618 	     indirect_equivalence_relation<
619 	       projected<iterator_t<_Range1>, _Proj1>,
620 	       projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to>
621       constexpr bool
622       operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {},
623 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
624       {
625 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
626 		       ranges::begin(__r2), ranges::end(__r2),
627 		       std::move(__pred),
628 		       std::move(__proj1), std::move(__proj2));
629       }
630   };
631 
632   inline constexpr __is_permutation_fn is_permutation{};
633 
634   template<typename _Iter, typename _Out>
635     using copy_if_result = in_out_result<_Iter, _Out>;
636 
637   struct __copy_if_fn
638   {
639     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
640 	     weakly_incrementable _Out, typename _Proj = identity,
641 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
642       requires indirectly_copyable<_Iter, _Out>
643       constexpr copy_if_result<_Iter, _Out>
644       operator()(_Iter __first, _Sent __last, _Out __result,
645 		 _Pred __pred, _Proj __proj = {}) const
646       {
647 	for (; __first != __last; ++__first)
648 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
649 	    {
650 	      *__result = *__first;
651 	      ++__result;
652 	    }
653 	return {std::move(__first), std::move(__result)};
654       }
655 
656     template<input_range _Range, weakly_incrementable _Out,
657 	     typename _Proj = identity,
658 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
659 	       _Pred>
660       requires indirectly_copyable<iterator_t<_Range>, _Out>
661       constexpr copy_if_result<borrowed_iterator_t<_Range>, _Out>
662       operator()(_Range&& __r, _Out __result,
663 		 _Pred __pred, _Proj __proj = {}) const
664       {
665 	return (*this)(ranges::begin(__r), ranges::end(__r),
666 		       std::move(__result),
667 		       std::move(__pred), std::move(__proj));
668       }
669   };
670 
671   inline constexpr __copy_if_fn copy_if{};
672 
673   template<typename _Iter1, typename _Iter2>
674     using swap_ranges_result = in_in_result<_Iter1, _Iter2>;
675 
676   struct __swap_ranges_fn
677   {
678     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
679 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2>
680       requires indirectly_swappable<_Iter1, _Iter2>
681       constexpr swap_ranges_result<_Iter1, _Iter2>
682       operator()(_Iter1 __first1, _Sent1 __last1,
683 		 _Iter2 __first2, _Sent2 __last2) const
684       {
685 	for (; __first1 != __last1 && __first2 != __last2;
686 	     ++__first1, (void)++__first2)
687 	  ranges::iter_swap(__first1, __first2);
688 	return {std::move(__first1), std::move(__first2)};
689       }
690 
691     template<input_range _Range1, input_range _Range2>
692       requires indirectly_swappable<iterator_t<_Range1>, iterator_t<_Range2>>
693       constexpr swap_ranges_result<borrowed_iterator_t<_Range1>,
694 				   borrowed_iterator_t<_Range2>>
695       operator()(_Range1&& __r1, _Range2&& __r2) const
696       {
697 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
698 		       ranges::begin(__r2), ranges::end(__r2));
699       }
700   };
701 
702   inline constexpr __swap_ranges_fn swap_ranges{};
703 
704   template<typename _Iter, typename _Out>
705     using unary_transform_result = in_out_result<_Iter, _Out>;
706 
707   template<typename _Iter1, typename _Iter2, typename _Out>
708     struct in_in_out_result
709     {
710       [[no_unique_address]] _Iter1 in1;
711       [[no_unique_address]] _Iter2 in2;
712       [[no_unique_address]] _Out  out;
713 
714       template<typename _IIter1, typename _IIter2, typename _OOut>
715 	requires convertible_to<const _Iter1&, _IIter1>
716 	  && convertible_to<const _Iter2&, _IIter2>
717 	  && convertible_to<const _Out&, _OOut>
718 	constexpr
719 	operator in_in_out_result<_IIter1, _IIter2, _OOut>() const &
720 	{ return {in1, in2, out}; }
721 
722       template<typename _IIter1, typename _IIter2, typename _OOut>
723 	requires convertible_to<_Iter1, _IIter1>
724 	  && convertible_to<_Iter2, _IIter2>
725 	  && convertible_to<_Out, _OOut>
726 	constexpr
727 	operator in_in_out_result<_IIter1, _IIter2, _OOut>() &&
728 	{ return {std::move(in1), std::move(in2), std::move(out)}; }
729     };
730 
731   template<typename _Iter1, typename _Iter2, typename _Out>
732     using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>;
733 
734   struct __transform_fn
735   {
736     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
737 	     weakly_incrementable _Out,
738 	     copy_constructible _Fp, typename _Proj = identity>
739       requires indirectly_writable<_Out,
740 				   indirect_result_t<_Fp&,
741 				     projected<_Iter, _Proj>>>
742       constexpr unary_transform_result<_Iter, _Out>
743       operator()(_Iter __first1, _Sent __last1, _Out __result,
744 		 _Fp __op, _Proj __proj = {}) const
745       {
746 	for (; __first1 != __last1; ++__first1, (void)++__result)
747 	  *__result = std::__invoke(__op, std::__invoke(__proj, *__first1));
748 	return {std::move(__first1), std::move(__result)};
749       }
750 
751     template<input_range _Range, weakly_incrementable _Out,
752 	     copy_constructible _Fp, typename _Proj = identity>
753       requires indirectly_writable<_Out,
754 				   indirect_result_t<_Fp&,
755 				     projected<iterator_t<_Range>, _Proj>>>
756       constexpr unary_transform_result<borrowed_iterator_t<_Range>, _Out>
757       operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const
758       {
759 	return (*this)(ranges::begin(__r), ranges::end(__r),
760 		       std::move(__result),
761 		       std::move(__op), std::move(__proj));
762       }
763 
764     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
765 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
766 	     weakly_incrementable _Out, copy_constructible _Fp,
767 	     typename _Proj1 = identity, typename _Proj2 = identity>
768       requires indirectly_writable<_Out,
769 				   indirect_result_t<_Fp&,
770 				     projected<_Iter1, _Proj1>,
771 				     projected<_Iter2, _Proj2>>>
772       constexpr binary_transform_result<_Iter1, _Iter2, _Out>
773       operator()(_Iter1 __first1, _Sent1 __last1,
774 		 _Iter2 __first2, _Sent2 __last2,
775 		 _Out __result, _Fp __binary_op,
776 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
777       {
778 	for (; __first1 != __last1 && __first2 != __last2;
779 	     ++__first1, (void)++__first2, ++__result)
780 	  *__result = std::__invoke(__binary_op,
781 				    std::__invoke(__proj1, *__first1),
782 				    std::__invoke(__proj2, *__first2));
783 	return {std::move(__first1), std::move(__first2), std::move(__result)};
784       }
785 
786     template<input_range _Range1, input_range _Range2,
787 	     weakly_incrementable _Out, copy_constructible _Fp,
788 	     typename _Proj1 = identity, typename _Proj2 = identity>
789       requires indirectly_writable<_Out,
790 				   indirect_result_t<_Fp&,
791 				     projected<iterator_t<_Range1>, _Proj1>,
792 				     projected<iterator_t<_Range2>, _Proj2>>>
793       constexpr binary_transform_result<borrowed_iterator_t<_Range1>,
794 					borrowed_iterator_t<_Range2>, _Out>
795       operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Fp __binary_op,
796 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
797       {
798 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
799 		       ranges::begin(__r2), ranges::end(__r2),
800 		       std::move(__result), std::move(__binary_op),
801 		       std::move(__proj1), std::move(__proj2));
802       }
803   };
804 
805   inline constexpr __transform_fn transform{};
806 
807   struct __replace_fn
808   {
809     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
810 	     typename _Tp1, typename _Tp2, typename _Proj = identity>
811       requires indirectly_writable<_Iter, const _Tp2&>
812 	&& indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
813 				     const _Tp1*>
814       constexpr _Iter
815       operator()(_Iter __first, _Sent __last,
816 		 const _Tp1& __old_value, const _Tp2& __new_value,
817 		 _Proj __proj = {}) const
818       {
819 	for (; __first != __last; ++__first)
820 	  if (std::__invoke(__proj, *__first) == __old_value)
821 	    *__first = __new_value;
822 	return __first;
823       }
824 
825     template<input_range _Range,
826 	     typename _Tp1, typename _Tp2, typename _Proj = identity>
827       requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
828 	&& indirect_binary_predicate<ranges::equal_to,
829 				     projected<iterator_t<_Range>, _Proj>,
830 				     const _Tp1*>
831       constexpr borrowed_iterator_t<_Range>
832       operator()(_Range&& __r,
833 		 const _Tp1& __old_value, const _Tp2& __new_value,
834 		 _Proj __proj = {}) const
835       {
836 	return (*this)(ranges::begin(__r), ranges::end(__r),
837 		       __old_value, __new_value, std::move(__proj));
838       }
839   };
840 
841   inline constexpr __replace_fn replace{};
842 
843   struct __replace_if_fn
844   {
845     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
846 	     typename _Tp, typename _Proj = identity,
847 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
848       requires indirectly_writable<_Iter, const _Tp&>
849       constexpr _Iter
850       operator()(_Iter __first, _Sent __last,
851 		 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
852       {
853 	for (; __first != __last; ++__first)
854 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
855 	    *__first = __new_value;
856 	return std::move(__first);
857       }
858 
859     template<input_range _Range, typename _Tp, typename _Proj = identity,
860 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
861 	       _Pred>
862       requires indirectly_writable<iterator_t<_Range>, const _Tp&>
863       constexpr borrowed_iterator_t<_Range>
864       operator()(_Range&& __r,
865 		 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
866       {
867 	return (*this)(ranges::begin(__r), ranges::end(__r),
868 		       std::move(__pred), __new_value, std::move(__proj));
869       }
870   };
871 
872   inline constexpr __replace_if_fn replace_if{};
873 
874   template<typename _Iter, typename _Out>
875     using replace_copy_result = in_out_result<_Iter, _Out>;
876 
877   struct __replace_copy_fn
878   {
879     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
880 	     typename _Tp1, typename _Tp2, output_iterator<const _Tp2&> _Out,
881 	     typename _Proj = identity>
882       requires indirectly_copyable<_Iter, _Out>
883 	&& indirect_binary_predicate<ranges::equal_to,
884 				     projected<_Iter, _Proj>, const _Tp1*>
885       constexpr replace_copy_result<_Iter, _Out>
886       operator()(_Iter __first, _Sent __last, _Out __result,
887 		 const _Tp1& __old_value, const _Tp2& __new_value,
888 		 _Proj __proj = {}) const
889       {
890 	for (; __first != __last; ++__first, (void)++__result)
891 	  if (std::__invoke(__proj, *__first) == __old_value)
892 	    *__result = __new_value;
893 	  else
894 	    *__result = *__first;
895 	return {std::move(__first), std::move(__result)};
896       }
897 
898     template<input_range _Range, typename _Tp1, typename _Tp2,
899 	     output_iterator<const _Tp2&> _Out, typename _Proj = identity>
900       requires indirectly_copyable<iterator_t<_Range>, _Out>
901 	&& indirect_binary_predicate<ranges::equal_to,
902 				     projected<iterator_t<_Range>, _Proj>,
903 				     const _Tp1*>
904       constexpr replace_copy_result<borrowed_iterator_t<_Range>, _Out>
905       operator()(_Range&& __r, _Out __result,
906 		 const _Tp1& __old_value, const _Tp2& __new_value,
907 		 _Proj __proj = {}) const
908       {
909 	return (*this)(ranges::begin(__r), ranges::end(__r),
910 		       std::move(__result), __old_value,
911 		       __new_value, std::move(__proj));
912       }
913   };
914 
915   inline constexpr __replace_copy_fn replace_copy{};
916 
917   template<typename _Iter, typename _Out>
918     using replace_copy_if_result = in_out_result<_Iter, _Out>;
919 
920   struct __replace_copy_if_fn
921   {
922     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
923 	     typename _Tp, output_iterator<const _Tp&> _Out,
924 	     typename _Proj = identity,
925 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
926       requires indirectly_copyable<_Iter, _Out>
927       constexpr replace_copy_if_result<_Iter, _Out>
928       operator()(_Iter __first, _Sent __last, _Out __result,
929 		 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
930       {
931 	for (; __first != __last; ++__first, (void)++__result)
932 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
933 	    *__result = __new_value;
934 	  else
935 	    *__result = *__first;
936 	return {std::move(__first), std::move(__result)};
937       }
938 
939     template<input_range _Range,
940 	     typename _Tp, output_iterator<const _Tp&> _Out,
941 	     typename _Proj = identity,
942 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
943 	       _Pred>
944       requires indirectly_copyable<iterator_t<_Range>, _Out>
945       constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _Out>
946       operator()(_Range&& __r, _Out __result,
947 		 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
948       {
949 	return (*this)(ranges::begin(__r), ranges::end(__r),
950 		       std::move(__result), std::move(__pred),
951 		       __new_value, std::move(__proj));
952       }
953   };
954 
955   inline constexpr __replace_copy_if_fn replace_copy_if{};
956 
957   struct __generate_n_fn
958   {
959     template<input_or_output_iterator _Out, copy_constructible _Fp>
960       requires invocable<_Fp&>
961 	&& indirectly_writable<_Out, invoke_result_t<_Fp&>>
962       constexpr _Out
963       operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const
964       {
965 	for (; __n > 0; --__n, (void)++__first)
966 	  *__first = std::__invoke(__gen);
967 	return __first;
968       }
969   };
970 
971   inline constexpr __generate_n_fn generate_n{};
972 
973   struct __generate_fn
974   {
975     template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent,
976 	     copy_constructible _Fp>
977       requires invocable<_Fp&>
978 	&& indirectly_writable<_Out, invoke_result_t<_Fp&>>
979       constexpr _Out
980       operator()(_Out __first, _Sent __last, _Fp __gen) const
981       {
982 	for (; __first != __last; ++__first)
983 	  *__first = std::__invoke(__gen);
984 	return __first;
985       }
986 
987     template<typename _Range, copy_constructible _Fp>
988       requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>>
989       constexpr borrowed_iterator_t<_Range>
990       operator()(_Range&& __r, _Fp __gen) const
991       {
992 	return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__gen));
993       }
994   };
995 
996   inline constexpr __generate_fn generate{};
997 
998   struct __remove_if_fn
999   {
1000     template<permutable _Iter, sentinel_for<_Iter> _Sent,
1001 	     typename _Proj = identity,
1002 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
1003       constexpr subrange<_Iter>
1004       operator()(_Iter __first, _Sent __last,
1005 		 _Pred __pred, _Proj __proj = {}) const
1006       {
1007 	__first = ranges::find_if(__first, __last, __pred, __proj);
1008 	if (__first == __last)
1009 	  return {__first, __first};
1010 
1011 	auto __result = __first;
1012 	++__first;
1013 	for (; __first != __last; ++__first)
1014 	  if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
1015 	    {
1016 	      *__result = std::move(*__first);
1017 	      ++__result;
1018 	    }
1019 
1020 	return {__result, __first};
1021       }
1022 
1023     template<forward_range _Range, typename _Proj = identity,
1024 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
1025 	       _Pred>
1026       requires permutable<iterator_t<_Range>>
1027       constexpr borrowed_subrange_t<_Range>
1028       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
1029       {
1030 	return (*this)(ranges::begin(__r), ranges::end(__r),
1031 		       std::move(__pred), std::move(__proj));
1032       }
1033   };
1034 
1035   inline constexpr __remove_if_fn remove_if{};
1036 
1037   struct __remove_fn
1038   {
1039     template<permutable _Iter, sentinel_for<_Iter> _Sent,
1040 	     typename _Tp, typename _Proj = identity>
1041       requires indirect_binary_predicate<ranges::equal_to,
1042 					 projected<_Iter, _Proj>,
1043 					 const _Tp*>
1044       constexpr subrange<_Iter>
1045       operator()(_Iter __first, _Sent __last,
1046 		 const _Tp& __value, _Proj __proj = {}) const
1047       {
1048 	auto __pred = [&] (auto&& __arg) -> bool {
1049 	  return std::forward<decltype(__arg)>(__arg) == __value;
1050 	};
1051 	return ranges::remove_if(__first, __last,
1052 				 std::move(__pred), std::move(__proj));
1053       }
1054 
1055     template<forward_range _Range, typename _Tp, typename _Proj = identity>
1056       requires permutable<iterator_t<_Range>>
1057 	&& indirect_binary_predicate<ranges::equal_to,
1058 				     projected<iterator_t<_Range>, _Proj>,
1059 				     const _Tp*>
1060       constexpr borrowed_subrange_t<_Range>
1061       operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
1062       {
1063 	return (*this)(ranges::begin(__r), ranges::end(__r),
1064 		       __value, std::move(__proj));
1065       }
1066   };
1067 
1068   inline constexpr __remove_fn remove{};
1069 
1070   template<typename _Iter, typename _Out>
1071     using remove_copy_if_result = in_out_result<_Iter, _Out>;
1072 
1073   struct __remove_copy_if_fn
1074   {
1075     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
1076 	     weakly_incrementable _Out, typename _Proj = identity,
1077 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
1078       requires indirectly_copyable<_Iter, _Out>
1079       constexpr remove_copy_if_result<_Iter, _Out>
1080       operator()(_Iter __first, _Sent __last, _Out __result,
1081 		 _Pred __pred, _Proj __proj = {}) const
1082       {
1083 	for (; __first != __last; ++__first)
1084 	  if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
1085 	    {
1086 	      *__result = *__first;
1087 	      ++__result;
1088 	    }
1089 	return {std::move(__first), std::move(__result)};
1090       }
1091 
1092     template<input_range _Range, weakly_incrementable _Out,
1093 	     typename _Proj = identity,
1094 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
1095 	       _Pred>
1096       requires indirectly_copyable<iterator_t<_Range>, _Out>
1097       constexpr remove_copy_if_result<borrowed_iterator_t<_Range>, _Out>
1098       operator()(_Range&& __r, _Out __result,
1099 		 _Pred __pred, _Proj __proj = {}) const
1100       {
1101 	return (*this)(ranges::begin(__r), ranges::end(__r),
1102 		       std::move(__result),
1103 		       std::move(__pred), std::move(__proj));
1104       }
1105   };
1106 
1107   inline constexpr __remove_copy_if_fn remove_copy_if{};
1108 
1109   template<typename _Iter, typename _Out>
1110     using remove_copy_result = in_out_result<_Iter, _Out>;
1111 
1112   struct __remove_copy_fn
1113   {
1114     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
1115 	     weakly_incrementable _Out, typename _Tp, typename _Proj = identity>
1116       requires indirectly_copyable<_Iter, _Out>
1117 	&& indirect_binary_predicate<ranges::equal_to,
1118 				     projected<_Iter, _Proj>,
1119 				     const _Tp*>
1120       constexpr remove_copy_result<_Iter, _Out>
1121       operator()(_Iter __first, _Sent __last, _Out __result,
1122 		 const _Tp& __value, _Proj __proj = {}) const
1123       {
1124 	for (; __first != __last; ++__first)
1125 	  if (!(std::__invoke(__proj, *__first) == __value))
1126 	    {
1127 	      *__result = *__first;
1128 	      ++__result;
1129 	    }
1130 	return {std::move(__first), std::move(__result)};
1131       }
1132 
1133     template<input_range _Range, weakly_incrementable _Out,
1134 	     typename _Tp, typename _Proj = identity>
1135       requires indirectly_copyable<iterator_t<_Range>, _Out>
1136 	&& indirect_binary_predicate<ranges::equal_to,
1137 				     projected<iterator_t<_Range>, _Proj>,
1138 				     const _Tp*>
1139       constexpr remove_copy_result<borrowed_iterator_t<_Range>, _Out>
1140       operator()(_Range&& __r, _Out __result,
1141 		 const _Tp& __value, _Proj __proj = {}) const
1142       {
1143 	return (*this)(ranges::begin(__r), ranges::end(__r),
1144 		       std::move(__result), __value, std::move(__proj));
1145       }
1146   };
1147 
1148   inline constexpr __remove_copy_fn remove_copy{};
1149 
1150   struct __unique_fn
1151   {
1152     template<permutable _Iter, sentinel_for<_Iter> _Sent,
1153 	     typename _Proj = identity,
1154 	     indirect_equivalence_relation<
1155 	       projected<_Iter, _Proj>> _Comp = ranges::equal_to>
1156       constexpr subrange<_Iter>
1157       operator()(_Iter __first, _Sent __last,
1158 		 _Comp __comp = {}, _Proj __proj = {}) const
1159       {
1160 	__first = ranges::adjacent_find(__first, __last, __comp, __proj);
1161 	if (__first == __last)
1162 	  return {__first, __first};
1163 
1164 	auto __dest = __first;
1165 	++__first;
1166 	while (++__first != __last)
1167 	  if (!std::__invoke(__comp,
1168 			     std::__invoke(__proj, *__dest),
1169 			     std::__invoke(__proj, *__first)))
1170 	    *++__dest = std::move(*__first);
1171 	return {++__dest, __first};
1172       }
1173 
1174     template<forward_range _Range, typename _Proj = identity,
1175 	     indirect_equivalence_relation<
1176 	       projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
1177       requires permutable<iterator_t<_Range>>
1178       constexpr borrowed_subrange_t<_Range>
1179       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1180       {
1181 	return (*this)(ranges::begin(__r), ranges::end(__r),
1182 		       std::move(__comp), std::move(__proj));
1183       }
1184   };
1185 
1186   inline constexpr __unique_fn unique{};
1187 
1188   namespace __detail
1189   {
1190     template<typename _Out, typename _Tp>
1191       concept __can_reread_output = input_iterator<_Out>
1192 	&& same_as<_Tp, iter_value_t<_Out>>;
1193   }
1194 
1195   template<typename _Iter, typename _Out>
1196     using unique_copy_result = in_out_result<_Iter, _Out>;
1197 
1198   struct __unique_copy_fn
1199   {
1200     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
1201 	     weakly_incrementable _Out, typename _Proj = identity,
1202 	     indirect_equivalence_relation<
1203 	       projected<_Iter, _Proj>> _Comp = ranges::equal_to>
1204       requires indirectly_copyable<_Iter, _Out>
1205 	&& (forward_iterator<_Iter>
1206 	    || __detail::__can_reread_output<_Out, iter_value_t<_Iter>>
1207 	    || indirectly_copyable_storable<_Iter, _Out>)
1208       constexpr unique_copy_result<_Iter, _Out>
1209       operator()(_Iter __first, _Sent __last, _Out __result,
1210 		 _Comp __comp = {}, _Proj __proj = {}) const
1211       {
1212 	if (__first == __last)
1213 	  return {std::move(__first), std::move(__result)};
1214 
1215 	// TODO: perform a closer comparison with reference implementations
1216 	if constexpr (forward_iterator<_Iter>)
1217 	  {
1218 	    auto __next = __first;
1219 	    *__result = *__next;
1220 	    while (++__next != __last)
1221 	      if (!std::__invoke(__comp,
1222 				 std::__invoke(__proj, *__first),
1223 				 std::__invoke(__proj, *__next)))
1224 		{
1225 		  __first = __next;
1226 		  *++__result = *__first;
1227 		}
1228 	    return {__next, std::move(++__result)};
1229 	  }
1230 	else if constexpr (__detail::__can_reread_output<_Out, iter_value_t<_Iter>>)
1231 	  {
1232 	    *__result = *__first;
1233 	    while (++__first != __last)
1234 	      if (!std::__invoke(__comp,
1235 				 std::__invoke(__proj, *__result),
1236 				 std::__invoke(__proj, *__first)))
1237 		  *++__result = *__first;
1238 	    return {std::move(__first), std::move(++__result)};
1239 	  }
1240 	else // indirectly_copyable_storable<_Iter, _Out>
1241 	  {
1242 	    auto __value = *__first;
1243 	    *__result = __value;
1244 	    while (++__first != __last)
1245 	      {
1246 		if (!(bool)std::__invoke(__comp,
1247 					 std::__invoke(__proj, *__first),
1248 					 std::__invoke(__proj, __value)))
1249 		  {
1250 		    __value = *__first;
1251 		    *++__result = __value;
1252 		  }
1253 	      }
1254 	    return {std::move(__first), std::move(++__result)};
1255 	  }
1256       }
1257 
1258     template<input_range _Range,
1259 	     weakly_incrementable _Out, typename _Proj = identity,
1260 	     indirect_equivalence_relation<
1261 	       projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
1262       requires indirectly_copyable<iterator_t<_Range>, _Out>
1263 	&& (forward_iterator<iterator_t<_Range>>
1264 	    || __detail::__can_reread_output<_Out, range_value_t<_Range>>
1265 	    || indirectly_copyable_storable<iterator_t<_Range>, _Out>)
1266       constexpr unique_copy_result<borrowed_iterator_t<_Range>, _Out>
1267       operator()(_Range&& __r, _Out __result,
1268 		 _Comp __comp = {}, _Proj __proj = {}) const
1269       {
1270 	return (*this)(ranges::begin(__r), ranges::end(__r),
1271 		       std::move(__result),
1272 		       std::move(__comp), std::move(__proj));
1273       }
1274   };
1275 
1276   inline constexpr __unique_copy_fn unique_copy{};
1277 
1278   struct __reverse_fn
1279   {
1280     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent>
1281       requires permutable<_Iter>
1282       constexpr _Iter
1283       operator()(_Iter __first, _Sent __last) const
1284       {
1285 	auto __i = ranges::next(__first, __last);
1286 	auto __tail = __i;
1287 
1288 	if constexpr (random_access_iterator<_Iter>)
1289 	  {
1290 	    if (__first != __last)
1291 	      {
1292 		--__tail;
1293 		while (__first < __tail)
1294 		  {
1295 		    ranges::iter_swap(__first, __tail);
1296 		    ++__first;
1297 		    --__tail;
1298 		  }
1299 	      }
1300 	    return __i;
1301 	  }
1302 	else
1303 	  {
1304 	    for (;;)
1305 	      if (__first == __tail || __first == --__tail)
1306 		break;
1307 	      else
1308 		{
1309 		  ranges::iter_swap(__first, __tail);
1310 		  ++__first;
1311 		}
1312 	    return __i;
1313 	  }
1314       }
1315 
1316     template<bidirectional_range _Range>
1317       requires permutable<iterator_t<_Range>>
1318       constexpr borrowed_iterator_t<_Range>
1319       operator()(_Range&& __r) const
1320       {
1321 	return (*this)(ranges::begin(__r), ranges::end(__r));
1322       }
1323   };
1324 
1325   inline constexpr __reverse_fn reverse{};
1326 
1327   template<typename _Iter, typename _Out>
1328     using reverse_copy_result = in_out_result<_Iter, _Out>;
1329 
1330   struct __reverse_copy_fn
1331   {
1332     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
1333 	     weakly_incrementable _Out>
1334       requires indirectly_copyable<_Iter, _Out>
1335       constexpr reverse_copy_result<_Iter, _Out>
1336       operator()(_Iter __first, _Sent __last, _Out __result) const
1337       {
1338 	auto __i = ranges::next(__first, __last);
1339 	auto __tail = __i;
1340 	while (__first != __tail)
1341 	  {
1342 	    --__tail;
1343 	    *__result = *__tail;
1344 	    ++__result;
1345 	  }
1346 	return {__i, std::move(__result)};
1347       }
1348 
1349     template<bidirectional_range _Range, weakly_incrementable _Out>
1350       requires indirectly_copyable<iterator_t<_Range>, _Out>
1351       constexpr reverse_copy_result<borrowed_iterator_t<_Range>, _Out>
1352       operator()(_Range&& __r, _Out __result) const
1353       {
1354 	return (*this)(ranges::begin(__r), ranges::end(__r),
1355 		       std::move(__result));
1356       }
1357   };
1358 
1359   inline constexpr __reverse_copy_fn reverse_copy{};
1360 
1361   struct __rotate_fn
1362   {
1363     template<permutable _Iter, sentinel_for<_Iter> _Sent>
1364       constexpr subrange<_Iter>
1365       operator()(_Iter __first, _Iter __middle, _Sent __last) const
1366       {
1367 	auto __lasti = ranges::next(__first, __last);
1368 	if (__first == __middle)
1369 	  return {__lasti, __lasti};
1370 	if (__last == __middle)
1371 	  return {std::move(__first), std::move(__lasti)};
1372 
1373 	if constexpr (random_access_iterator<_Iter>)
1374 	  {
1375 	    auto __n = __lasti - __first;
1376 	    auto __k = __middle - __first;
1377 
1378 	    if (__k == __n - __k)
1379 	      {
1380 		ranges::swap_ranges(__first, __middle, __middle, __middle + __k);
1381 		return {std::move(__middle), std::move(__lasti)};
1382 	      }
1383 
1384 	    auto __p = __first;
1385 	    auto __ret = __first + (__lasti - __middle);
1386 
1387 	    for (;;)
1388 	      {
1389 		if (__k < __n - __k)
1390 		  {
1391 		    // TODO: is_pod is deprecated, but this condition is
1392 		    // consistent with the STL implementation.
1393 		    if constexpr (__is_pod(iter_value_t<_Iter>))
1394 		      if (__k == 1)
1395 			{
1396 			  auto __t = std::move(*__p);
1397 			  ranges::move(__p + 1, __p + __n, __p);
1398 			  *(__p + __n - 1) = std::move(__t);
1399 			  return {std::move(__ret), std::move(__lasti)};
1400 			}
1401 		    auto __q = __p + __k;
1402 		    for (decltype(__n) __i = 0; __i < __n - __k; ++ __i)
1403 		      {
1404 			ranges::iter_swap(__p, __q);
1405 			++__p;
1406 			++__q;
1407 		      }
1408 		    __n %= __k;
1409 		    if (__n == 0)
1410 		      return {std::move(__ret), std::move(__lasti)};
1411 		    ranges::swap(__n, __k);
1412 		    __k = __n - __k;
1413 		  }
1414 		else
1415 		  {
1416 		    __k = __n - __k;
1417 		    // TODO: is_pod is deprecated, but this condition is
1418 		    // consistent with the STL implementation.
1419 		    if constexpr (__is_pod(iter_value_t<_Iter>))
1420 		      if (__k == 1)
1421 			{
1422 			  auto __t = std::move(*(__p + __n - 1));
1423 			  ranges::move_backward(__p, __p + __n - 1, __p + __n);
1424 			  *__p = std::move(__t);
1425 			  return {std::move(__ret), std::move(__lasti)};
1426 			}
1427 		    auto __q = __p + __n;
1428 		    __p = __q - __k;
1429 		    for (decltype(__n) __i = 0; __i < __n - __k; ++ __i)
1430 		      {
1431 			--__p;
1432 			--__q;
1433 			ranges::iter_swap(__p, __q);
1434 		      }
1435 		    __n %= __k;
1436 		    if (__n == 0)
1437 		      return {std::move(__ret), std::move(__lasti)};
1438 		    std::swap(__n, __k);
1439 		  }
1440 	      }
1441 	  }
1442 	else if constexpr (bidirectional_iterator<_Iter>)
1443 	  {
1444 	    auto __tail = __lasti;
1445 
1446 	    ranges::reverse(__first, __middle);
1447 	    ranges::reverse(__middle, __tail);
1448 
1449 	    while (__first != __middle && __middle != __tail)
1450 	      {
1451 		ranges::iter_swap(__first, --__tail);
1452 		++__first;
1453 	      }
1454 
1455 	    if (__first == __middle)
1456 	      {
1457 		ranges::reverse(__middle, __tail);
1458 		return {std::move(__tail), std::move(__lasti)};
1459 	      }
1460 	    else
1461 	      {
1462 		ranges::reverse(__first, __middle);
1463 		return {std::move(__first), std::move(__lasti)};
1464 	      }
1465 	  }
1466 	else
1467 	  {
1468 	    auto __first2 = __middle;
1469 	    do
1470 	      {
1471 		ranges::iter_swap(__first, __first2);
1472 		++__first;
1473 		++__first2;
1474 		if (__first == __middle)
1475 		  __middle = __first2;
1476 	      } while (__first2 != __last);
1477 
1478 	    auto __ret = __first;
1479 
1480 	    __first2 = __middle;
1481 
1482 	    while (__first2 != __last)
1483 	      {
1484 		ranges::iter_swap(__first, __first2);
1485 		++__first;
1486 		++__first2;
1487 		if (__first == __middle)
1488 		  __middle = __first2;
1489 		else if (__first2 == __last)
1490 		  __first2 = __middle;
1491 	      }
1492 	    return {std::move(__ret), std::move(__lasti)};
1493 	  }
1494       }
1495 
1496     template<forward_range _Range>
1497       requires permutable<iterator_t<_Range>>
1498       constexpr borrowed_subrange_t<_Range>
1499       operator()(_Range&& __r, iterator_t<_Range> __middle) const
1500       {
1501 	return (*this)(ranges::begin(__r), std::move(__middle),
1502 		       ranges::end(__r));
1503       }
1504   };
1505 
1506   inline constexpr __rotate_fn rotate{};
1507 
1508   template<typename _Iter, typename _Out>
1509     using rotate_copy_result = in_out_result<_Iter, _Out>;
1510 
1511   struct __rotate_copy_fn
1512   {
1513     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
1514 	     weakly_incrementable _Out>
1515       requires indirectly_copyable<_Iter, _Out>
1516       constexpr rotate_copy_result<_Iter, _Out>
1517       operator()(_Iter __first, _Iter __middle, _Sent __last,
1518 		 _Out __result) const
1519       {
1520 	auto __copy1 = ranges::copy(__middle,
1521 				    std::move(__last),
1522 				    std::move(__result));
1523 	auto __copy2 = ranges::copy(std::move(__first),
1524 				    std::move(__middle),
1525 				    std::move(__copy1.out));
1526 	return { std::move(__copy1.in), std::move(__copy2.out) };
1527       }
1528 
1529     template<forward_range _Range, weakly_incrementable _Out>
1530       requires indirectly_copyable<iterator_t<_Range>, _Out>
1531       constexpr rotate_copy_result<borrowed_iterator_t<_Range>, _Out>
1532       operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const
1533       {
1534 	return (*this)(ranges::begin(__r), std::move(__middle),
1535 		       ranges::end(__r), std::move(__result));
1536       }
1537   };
1538 
1539   inline constexpr __rotate_copy_fn rotate_copy{};
1540 
1541   struct __sample_fn
1542   {
1543     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
1544 	     weakly_incrementable _Out, typename _Gen>
1545       requires (forward_iterator<_Iter> || random_access_iterator<_Out>)
1546 	&& indirectly_copyable<_Iter, _Out>
1547 	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
1548       _Out
1549       operator()(_Iter __first, _Sent __last, _Out __out,
1550 		 iter_difference_t<_Iter> __n, _Gen&& __g) const
1551       {
1552 	if constexpr (forward_iterator<_Iter>)
1553 	  {
1554 	    // FIXME: Forwarding to std::sample here requires computing __lasti
1555 	    // which may take linear time.
1556 	    auto __lasti = ranges::next(__first, __last);
1557 	    return _GLIBCXX_STD_A::
1558 	      sample(std::move(__first), std::move(__lasti), std::move(__out),
1559 		     __n, std::forward<_Gen>(__g));
1560 	  }
1561 	else
1562 	  {
1563 	    using __distrib_type
1564 	      = uniform_int_distribution<iter_difference_t<_Iter>>;
1565 	    using __param_type = typename __distrib_type::param_type;
1566 	    __distrib_type __d{};
1567 	    iter_difference_t<_Iter> __sample_sz = 0;
1568 	    while (__first != __last && __sample_sz != __n)
1569 	      {
1570 		__out[__sample_sz++] = *__first;
1571 		++__first;
1572 	      }
1573 	    for (auto __pop_sz = __sample_sz; __first != __last;
1574 		++__first, (void) ++__pop_sz)
1575 	      {
1576 		const auto __k = __d(__g, __param_type{0, __pop_sz});
1577 		if (__k < __n)
1578 		  __out[__k] = *__first;
1579 	      }
1580 	    return __out + __sample_sz;
1581 	  }
1582       }
1583 
1584     template<input_range _Range, weakly_incrementable _Out, typename _Gen>
1585       requires (forward_range<_Range> || random_access_iterator<_Out>)
1586 	&& indirectly_copyable<iterator_t<_Range>, _Out>
1587 	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
1588       _Out
1589       operator()(_Range&& __r, _Out __out,
1590 		 range_difference_t<_Range> __n, _Gen&& __g) const
1591       {
1592 	return (*this)(ranges::begin(__r), ranges::end(__r),
1593 		       std::move(__out), __n,
1594 		       std::forward<_Gen>(__g));
1595       }
1596   };
1597 
1598   inline constexpr __sample_fn sample{};
1599 
1600 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
1601   struct __shuffle_fn
1602   {
1603     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1604 	     typename _Gen>
1605       requires permutable<_Iter>
1606 	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
1607       _Iter
1608       operator()(_Iter __first, _Sent __last, _Gen&& __g) const
1609       {
1610 	auto __lasti = ranges::next(__first, __last);
1611 	std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g));
1612 	return __lasti;
1613       }
1614 
1615     template<random_access_range _Range, typename _Gen>
1616       requires permutable<iterator_t<_Range>>
1617 	&& uniform_random_bit_generator<remove_reference_t<_Gen>>
1618       borrowed_iterator_t<_Range>
1619       operator()(_Range&& __r, _Gen&& __g) const
1620       {
1621 	return (*this)(ranges::begin(__r), ranges::end(__r),
1622 		       std::forward<_Gen>(__g));
1623       }
1624   };
1625 
1626   inline constexpr __shuffle_fn shuffle{};
1627 #endif
1628 
1629   struct __push_heap_fn
1630   {
1631     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1632 	     typename _Comp = ranges::less, typename _Proj = identity>
1633       requires sortable<_Iter, _Comp, _Proj>
1634       constexpr _Iter
1635       operator()(_Iter __first, _Sent __last,
1636 		 _Comp __comp = {}, _Proj __proj = {}) const
1637       {
1638 	auto __lasti = ranges::next(__first, __last);
1639 	std::push_heap(__first, __lasti,
1640 		       __detail::__make_comp_proj(__comp, __proj));
1641 	return __lasti;
1642       }
1643 
1644     template<random_access_range _Range,
1645 	     typename _Comp = ranges::less, typename _Proj = identity>
1646       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1647       constexpr borrowed_iterator_t<_Range>
1648       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1649       {
1650 	return (*this)(ranges::begin(__r), ranges::end(__r),
1651 		       std::move(__comp), std::move(__proj));
1652       }
1653   };
1654 
1655   inline constexpr __push_heap_fn push_heap{};
1656 
1657   struct __pop_heap_fn
1658   {
1659     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1660 	     typename _Comp = ranges::less, typename _Proj = identity>
1661       requires sortable<_Iter, _Comp, _Proj>
1662       constexpr _Iter
1663       operator()(_Iter __first, _Sent __last,
1664 		 _Comp __comp = {}, _Proj __proj = {}) const
1665       {
1666 	auto __lasti = ranges::next(__first, __last);
1667 	std::pop_heap(__first, __lasti,
1668 		      __detail::__make_comp_proj(__comp, __proj));
1669 	return __lasti;
1670       }
1671 
1672     template<random_access_range _Range,
1673 	     typename _Comp = ranges::less, typename _Proj = identity>
1674       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1675       constexpr borrowed_iterator_t<_Range>
1676       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1677       {
1678 	return (*this)(ranges::begin(__r), ranges::end(__r),
1679 		       std::move(__comp), std::move(__proj));
1680       }
1681   };
1682 
1683   inline constexpr __pop_heap_fn pop_heap{};
1684 
1685   struct __make_heap_fn
1686   {
1687     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1688 	     typename _Comp = ranges::less, typename _Proj = identity>
1689       requires sortable<_Iter, _Comp, _Proj>
1690       constexpr _Iter
1691       operator()(_Iter __first, _Sent __last,
1692 		 _Comp __comp = {}, _Proj __proj = {}) const
1693       {
1694 	auto __lasti = ranges::next(__first, __last);
1695 	std::make_heap(__first, __lasti,
1696 		       __detail::__make_comp_proj(__comp, __proj));
1697 	return __lasti;
1698       }
1699 
1700     template<random_access_range _Range,
1701 	     typename _Comp = ranges::less, typename _Proj = identity>
1702       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1703       constexpr borrowed_iterator_t<_Range>
1704       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1705       {
1706 	return (*this)(ranges::begin(__r), ranges::end(__r),
1707 		       std::move(__comp), std::move(__proj));
1708       }
1709   };
1710 
1711   inline constexpr __make_heap_fn make_heap{};
1712 
1713   struct __sort_heap_fn
1714   {
1715     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1716 	     typename _Comp = ranges::less, typename _Proj = identity>
1717       requires sortable<_Iter, _Comp, _Proj>
1718       constexpr _Iter
1719       operator()(_Iter __first, _Sent __last,
1720 		 _Comp __comp = {}, _Proj __proj = {}) const
1721       {
1722 	auto __lasti = ranges::next(__first, __last);
1723 	std::sort_heap(__first, __lasti,
1724 		       __detail::__make_comp_proj(__comp, __proj));
1725 	return __lasti;
1726       }
1727 
1728     template<random_access_range _Range,
1729 	     typename _Comp = ranges::less, typename _Proj = identity>
1730       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1731       constexpr borrowed_iterator_t<_Range>
1732       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1733       {
1734 	return (*this)(ranges::begin(__r), ranges::end(__r),
1735 		       std::move(__comp), std::move(__proj));
1736       }
1737   };
1738 
1739   inline constexpr __sort_heap_fn sort_heap{};
1740 
1741   struct __is_heap_until_fn
1742   {
1743     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1744 	     typename _Proj = identity,
1745 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
1746 	       _Comp = ranges::less>
1747       constexpr _Iter
1748       operator()(_Iter __first, _Sent __last,
1749 		 _Comp __comp = {}, _Proj __proj = {}) const
1750       {
1751 	iter_difference_t<_Iter> __n = ranges::distance(__first, __last);
1752 	iter_difference_t<_Iter> __parent = 0, __child = 1;
1753 	for (; __child < __n; ++__child)
1754 	  if (std::__invoke(__comp,
1755 			    std::__invoke(__proj, *(__first + __parent)),
1756 			    std::__invoke(__proj, *(__first + __child))))
1757 	    return __first + __child;
1758 	  else if ((__child & 1) == 0)
1759 	    ++__parent;
1760 
1761 	return __first + __n;
1762       }
1763 
1764     template<random_access_range _Range,
1765 	     typename _Proj = identity,
1766 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
1767 	       _Comp = ranges::less>
1768       constexpr borrowed_iterator_t<_Range>
1769       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1770       {
1771 	return (*this)(ranges::begin(__r), ranges::end(__r),
1772 		       std::move(__comp), std::move(__proj));
1773       }
1774   };
1775 
1776   inline constexpr __is_heap_until_fn is_heap_until{};
1777 
1778   struct __is_heap_fn
1779   {
1780     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1781 	     typename _Proj = identity,
1782 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
1783 	       _Comp = ranges::less>
1784       constexpr bool
1785       operator()(_Iter __first, _Sent __last,
1786 		 _Comp __comp = {}, _Proj __proj = {}) const
1787       {
1788 	return (__last
1789 		== ranges::is_heap_until(__first, __last,
1790 					 std::move(__comp),
1791 					 std::move(__proj)));
1792       }
1793 
1794     template<random_access_range _Range,
1795 	     typename _Proj = identity,
1796 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
1797 	       _Comp = ranges::less>
1798       constexpr bool
1799       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1800       {
1801 	return (*this)(ranges::begin(__r), ranges::end(__r),
1802 		       std::move(__comp), std::move(__proj));
1803       }
1804   };
1805 
1806   inline constexpr __is_heap_fn is_heap{};
1807 
1808   struct __sort_fn
1809   {
1810     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1811 	     typename _Comp = ranges::less, typename _Proj = identity>
1812       requires sortable<_Iter, _Comp, _Proj>
1813       constexpr _Iter
1814       operator()(_Iter __first, _Sent __last,
1815 		 _Comp __comp = {}, _Proj __proj = {}) const
1816       {
1817 	auto __lasti = ranges::next(__first, __last);
1818 	_GLIBCXX_STD_A::sort(std::move(__first), __lasti,
1819 			     __detail::__make_comp_proj(__comp, __proj));
1820 	return __lasti;
1821       }
1822 
1823     template<random_access_range _Range,
1824 	     typename _Comp = ranges::less, typename _Proj = identity>
1825       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1826       constexpr borrowed_iterator_t<_Range>
1827       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1828       {
1829 	return (*this)(ranges::begin(__r), ranges::end(__r),
1830 		       std::move(__comp), std::move(__proj));
1831       }
1832   };
1833 
1834   inline constexpr __sort_fn sort{};
1835 
1836   struct __stable_sort_fn
1837   {
1838     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1839 	     typename _Comp = ranges::less, typename _Proj = identity>
1840       requires sortable<_Iter, _Comp, _Proj>
1841       _Iter
1842       operator()(_Iter __first, _Sent __last,
1843 		 _Comp __comp = {}, _Proj __proj = {}) const
1844       {
1845 	auto __lasti = ranges::next(__first, __last);
1846 	std::stable_sort(std::move(__first), __lasti,
1847 			 __detail::__make_comp_proj(__comp, __proj));
1848 	return __lasti;
1849       }
1850 
1851     template<random_access_range _Range,
1852 	     typename _Comp = ranges::less, typename _Proj = identity>
1853       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1854       borrowed_iterator_t<_Range>
1855       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
1856       {
1857 	return (*this)(ranges::begin(__r), ranges::end(__r),
1858 		       std::move(__comp), std::move(__proj));
1859       }
1860   };
1861 
1862   inline constexpr __stable_sort_fn stable_sort{};
1863 
1864   struct __partial_sort_fn
1865   {
1866     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
1867 	     typename _Comp = ranges::less, typename _Proj = identity>
1868       requires sortable<_Iter, _Comp, _Proj>
1869       constexpr _Iter
1870       operator()(_Iter __first, _Iter __middle, _Sent __last,
1871 		 _Comp __comp = {}, _Proj __proj = {}) const
1872       {
1873 	if (__first == __middle)
1874 	  return ranges::next(__first, __last);
1875 
1876 	ranges::make_heap(__first, __middle, __comp, __proj);
1877 	auto __i = __middle;
1878 	for (; __i != __last; ++__i)
1879 	  if (std::__invoke(__comp,
1880 			    std::__invoke(__proj, *__i),
1881 			    std::__invoke(__proj, *__first)))
1882 	    {
1883 	      ranges::pop_heap(__first, __middle, __comp, __proj);
1884 	      ranges::iter_swap(__middle-1, __i);
1885 	      ranges::push_heap(__first, __middle, __comp, __proj);
1886 	    }
1887 	ranges::sort_heap(__first, __middle, __comp, __proj);
1888 
1889 	return __i;
1890       }
1891 
1892     template<random_access_range _Range,
1893 	     typename _Comp = ranges::less, typename _Proj = identity>
1894       requires sortable<iterator_t<_Range>, _Comp, _Proj>
1895       constexpr borrowed_iterator_t<_Range>
1896       operator()(_Range&& __r, iterator_t<_Range> __middle,
1897 		 _Comp __comp = {}, _Proj __proj = {}) const
1898       {
1899 	return (*this)(ranges::begin(__r), std::move(__middle),
1900 		       ranges::end(__r),
1901 		       std::move(__comp), std::move(__proj));
1902       }
1903   };
1904 
1905   inline constexpr __partial_sort_fn partial_sort{};
1906 
1907   template<typename _Iter, typename _Out>
1908     using partial_sort_copy_result = in_out_result<_Iter, _Out>;
1909 
1910   struct __partial_sort_copy_fn
1911   {
1912     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
1913 	     random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
1914 	     typename _Comp = ranges::less,
1915 	     typename _Proj1 = identity, typename _Proj2 = identity>
1916       requires indirectly_copyable<_Iter1, _Iter2>
1917 	&& sortable<_Iter2, _Comp, _Proj2>
1918 	&& indirect_strict_weak_order<_Comp,
1919 				      projected<_Iter1, _Proj1>,
1920 				      projected<_Iter2, _Proj2>>
1921       constexpr partial_sort_copy_result<_Iter1, _Iter2>
1922       operator()(_Iter1 __first, _Sent1 __last,
1923 		 _Iter2 __result_first, _Sent2 __result_last,
1924 		 _Comp __comp = {},
1925 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
1926       {
1927 	if (__result_first == __result_last)
1928 	  {
1929 	    // TODO: Eliminating the variable __lasti triggers an ICE.
1930 	    auto __lasti = ranges::next(std::move(__first),
1931 					std::move(__last));
1932 	    return {std::move(__lasti), std::move(__result_first)};
1933 	  }
1934 
1935 	auto __result_real_last = __result_first;
1936 	while (__first != __last && __result_real_last != __result_last)
1937 	  {
1938 	    *__result_real_last = *__first;
1939 	    ++__result_real_last;
1940 	    ++__first;
1941 	  }
1942 
1943 	ranges::make_heap(__result_first, __result_real_last, __comp, __proj2);
1944 	for (; __first != __last; ++__first)
1945 	  if (std::__invoke(__comp,
1946 			    std::__invoke(__proj1, *__first),
1947 			    std::__invoke(__proj2, *__result_first)))
1948 	    {
1949 	      ranges::pop_heap(__result_first, __result_real_last,
1950 			       __comp, __proj2);
1951 	      *(__result_real_last-1) = *__first;
1952 	      ranges::push_heap(__result_first, __result_real_last,
1953 				__comp, __proj2);
1954 	    }
1955 	ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2);
1956 
1957 	return {std::move(__first), std::move(__result_real_last)};
1958       }
1959 
1960     template<input_range _Range1, random_access_range _Range2,
1961 	     typename _Comp = ranges::less,
1962 	     typename _Proj1 = identity, typename _Proj2 = identity>
1963       requires indirectly_copyable<iterator_t<_Range1>, iterator_t<_Range2>>
1964 	&& sortable<iterator_t<_Range2>, _Comp, _Proj2>
1965 	&& indirect_strict_weak_order<_Comp,
1966 				      projected<iterator_t<_Range1>, _Proj1>,
1967 				      projected<iterator_t<_Range2>, _Proj2>>
1968       constexpr partial_sort_copy_result<borrowed_iterator_t<_Range1>,
1969 					 borrowed_iterator_t<_Range2>>
1970       operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {},
1971 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
1972       {
1973 	return (*this)(ranges::begin(__r), ranges::end(__r),
1974 		       ranges::begin(__out), ranges::end(__out),
1975 		       std::move(__comp),
1976 		       std::move(__proj1), std::move(__proj2));
1977       }
1978   };
1979 
1980   inline constexpr __partial_sort_copy_fn partial_sort_copy{};
1981 
1982   struct __is_sorted_until_fn
1983   {
1984     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
1985 	     typename _Proj = identity,
1986 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
1987 	       _Comp = ranges::less>
1988       constexpr _Iter
1989       operator()(_Iter __first, _Sent __last,
1990 		 _Comp __comp = {}, _Proj __proj = {}) const
1991       {
1992 	if (__first == __last)
1993 	  return __first;
1994 
1995 	auto __next = __first;
1996 	for (++__next; __next != __last; __first = __next, (void)++__next)
1997 	  if (std::__invoke(__comp,
1998 			    std::__invoke(__proj, *__next),
1999 			    std::__invoke(__proj, *__first)))
2000 	    return __next;
2001 	return __next;
2002       }
2003 
2004     template<forward_range _Range, typename _Proj = identity,
2005 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
2006 	       _Comp = ranges::less>
2007       constexpr borrowed_iterator_t<_Range>
2008       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
2009       {
2010 	return (*this)(ranges::begin(__r), ranges::end(__r),
2011 		       std::move(__comp), std::move(__proj));
2012       }
2013   };
2014 
2015   inline constexpr __is_sorted_until_fn is_sorted_until{};
2016 
2017   struct __is_sorted_fn
2018   {
2019     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2020 	     typename _Proj = identity,
2021 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
2022 	       _Comp = ranges::less>
2023       constexpr bool
2024       operator()(_Iter __first, _Sent __last,
2025 		 _Comp __comp = {}, _Proj __proj = {}) const
2026       {
2027 	if (__first == __last)
2028 	  return true;
2029 
2030 	auto __next = __first;
2031 	for (++__next; __next != __last; __first = __next, (void)++__next)
2032 	  if (std::__invoke(__comp,
2033 			    std::__invoke(__proj, *__next),
2034 			    std::__invoke(__proj, *__first)))
2035 	    return false;
2036 	return true;
2037       }
2038 
2039     template<forward_range _Range, typename _Proj = identity,
2040 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
2041 	       _Comp = ranges::less>
2042       constexpr bool
2043       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
2044       {
2045 	return (*this)(ranges::begin(__r), ranges::end(__r),
2046 		       std::move(__comp), std::move(__proj));
2047       }
2048   };
2049 
2050   inline constexpr __is_sorted_fn is_sorted{};
2051 
2052   struct __nth_element_fn
2053   {
2054     template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent,
2055 	     typename _Comp = ranges::less, typename _Proj = identity>
2056       requires sortable<_Iter, _Comp, _Proj>
2057       constexpr _Iter
2058       operator()(_Iter __first, _Iter __nth, _Sent __last,
2059 		 _Comp __comp = {}, _Proj __proj = {}) const
2060       {
2061 	auto __lasti = ranges::next(__first, __last);
2062 	_GLIBCXX_STD_A::nth_element(std::move(__first), std::move(__nth),
2063 				    __lasti,
2064 				    __detail::__make_comp_proj(__comp, __proj));
2065 	return __lasti;
2066       }
2067 
2068     template<random_access_range _Range,
2069 	     typename _Comp = ranges::less, typename _Proj = identity>
2070       requires sortable<iterator_t<_Range>, _Comp, _Proj>
2071       constexpr borrowed_iterator_t<_Range>
2072       operator()(_Range&& __r, iterator_t<_Range> __nth,
2073 		 _Comp __comp = {}, _Proj __proj = {}) const
2074       {
2075 	return (*this)(ranges::begin(__r), std::move(__nth),
2076 		       ranges::end(__r), std::move(__comp), std::move(__proj));
2077       }
2078   };
2079 
2080   inline constexpr __nth_element_fn nth_element{};
2081 
2082   struct __lower_bound_fn
2083   {
2084     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2085 	     typename _Tp, typename _Proj = identity,
2086 	     indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
2087 	       _Comp = ranges::less>
2088       constexpr _Iter
2089       operator()(_Iter __first, _Sent __last,
2090 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2091       {
2092 	auto __len = ranges::distance(__first, __last);
2093 
2094 	while (__len > 0)
2095 	  {
2096 	    auto __half = __len / 2;
2097 	    auto __middle = __first;
2098 	    ranges::advance(__middle, __half);
2099 	    if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value))
2100 	      {
2101 		__first = __middle;
2102 		++__first;
2103 		__len = __len - __half - 1;
2104 	      }
2105 	    else
2106 	      __len = __half;
2107 	  }
2108 	return __first;
2109       }
2110 
2111     template<forward_range _Range, typename _Tp, typename _Proj = identity,
2112 	     indirect_strict_weak_order<const _Tp*,
2113 					projected<iterator_t<_Range>, _Proj>>
2114 	       _Comp = ranges::less>
2115       constexpr borrowed_iterator_t<_Range>
2116       operator()(_Range&& __r,
2117 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2118       {
2119 	return (*this)(ranges::begin(__r), ranges::end(__r),
2120 		       __value, std::move(__comp), std::move(__proj));
2121       }
2122   };
2123 
2124   inline constexpr __lower_bound_fn lower_bound{};
2125 
2126   struct __upper_bound_fn
2127   {
2128     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2129 	     typename _Tp, typename _Proj = identity,
2130 	     indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
2131 	       _Comp = ranges::less>
2132       constexpr _Iter
2133       operator()(_Iter __first, _Sent __last,
2134 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2135       {
2136 	auto __len = ranges::distance(__first, __last);
2137 
2138 	while (__len > 0)
2139 	  {
2140 	    auto __half = __len / 2;
2141 	    auto __middle = __first;
2142 	    ranges::advance(__middle, __half);
2143 	    if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle)))
2144 	      __len = __half;
2145 	    else
2146 	      {
2147 		__first = __middle;
2148 		++__first;
2149 		__len = __len - __half - 1;
2150 	      }
2151 	  }
2152 	return __first;
2153       }
2154 
2155     template<forward_range _Range, typename _Tp, typename _Proj = identity,
2156 	     indirect_strict_weak_order<const _Tp*,
2157 					projected<iterator_t<_Range>, _Proj>>
2158 	       _Comp = ranges::less>
2159       constexpr borrowed_iterator_t<_Range>
2160       operator()(_Range&& __r,
2161 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2162       {
2163 	return (*this)(ranges::begin(__r), ranges::end(__r),
2164 		       __value, std::move(__comp), std::move(__proj));
2165       }
2166   };
2167 
2168   inline constexpr __upper_bound_fn upper_bound{};
2169 
2170   struct __equal_range_fn
2171   {
2172     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2173 	     typename _Tp, typename _Proj = identity,
2174 	     indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
2175 	       _Comp = ranges::less>
2176       constexpr subrange<_Iter>
2177       operator()(_Iter __first, _Sent __last,
2178 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2179       {
2180 	auto __len = ranges::distance(__first, __last);
2181 
2182 	while (__len > 0)
2183 	  {
2184 	    auto __half = __len / 2;
2185 	    auto __middle = __first;
2186 	    ranges::advance(__middle, __half);
2187 	    if (std::__invoke(__comp,
2188 			      std::__invoke(__proj, *__middle),
2189 			      __value))
2190 	      {
2191 		__first = __middle;
2192 		++__first;
2193 		__len = __len - __half - 1;
2194 	      }
2195 	    else if (std::__invoke(__comp,
2196 				   __value,
2197 				   std::__invoke(__proj, *__middle)))
2198 	      __len = __half;
2199 	    else
2200 	      {
2201 		auto __left
2202 		  = ranges::lower_bound(__first, __middle,
2203 					__value, __comp, __proj);
2204 		ranges::advance(__first, __len);
2205 		auto __right
2206 		  = ranges::upper_bound(++__middle, __first,
2207 					__value, __comp, __proj);
2208 		return {__left, __right};
2209 	      }
2210 	  }
2211 	return {__first, __first};
2212       }
2213 
2214     template<forward_range _Range,
2215 	     typename _Tp, typename _Proj = identity,
2216 	     indirect_strict_weak_order<const _Tp*,
2217 					projected<iterator_t<_Range>, _Proj>>
2218 	       _Comp = ranges::less>
2219       constexpr borrowed_subrange_t<_Range>
2220       operator()(_Range&& __r, const _Tp& __value,
2221 		 _Comp __comp = {}, _Proj __proj = {}) const
2222       {
2223 	return (*this)(ranges::begin(__r), ranges::end(__r),
2224 		       __value, std::move(__comp), std::move(__proj));
2225       }
2226   };
2227 
2228   inline constexpr __equal_range_fn equal_range{};
2229 
2230   struct __binary_search_fn
2231   {
2232     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2233 	     typename _Tp, typename _Proj = identity,
2234 	     indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
2235 	       _Comp = ranges::less>
2236       constexpr bool
2237       operator()(_Iter __first, _Sent __last,
2238 		 const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const
2239       {
2240 	auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj);
2241 	if (__i == __last)
2242 	  return false;
2243 	return !(bool)std::__invoke(__comp, __value,
2244 				    std::__invoke(__proj, *__i));
2245       }
2246 
2247     template<forward_range _Range,
2248 	     typename _Tp, typename _Proj = identity,
2249 	     indirect_strict_weak_order<const _Tp*,
2250 					projected<iterator_t<_Range>, _Proj>>
2251 	       _Comp = ranges::less>
2252       constexpr bool
2253       operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {},
2254 		 _Proj __proj = {}) const
2255       {
2256 	return (*this)(ranges::begin(__r), ranges::end(__r),
2257 		       __value, std::move(__comp), std::move(__proj));
2258       }
2259   };
2260 
2261   inline constexpr __binary_search_fn binary_search{};
2262 
2263   struct __is_partitioned_fn
2264   {
2265     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
2266 	     typename _Proj = identity,
2267 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
2268       constexpr bool
2269       operator()(_Iter __first, _Sent __last,
2270 		 _Pred __pred, _Proj __proj = {}) const
2271       {
2272 	__first = ranges::find_if_not(std::move(__first), __last,
2273 				      __pred, __proj);
2274 	if (__first == __last)
2275 	  return true;
2276 	++__first;
2277 	return ranges::none_of(std::move(__first), std::move(__last),
2278 			       std::move(__pred), std::move(__proj));
2279       }
2280 
2281     template<input_range _Range, typename _Proj = identity,
2282 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
2283 	       _Pred>
2284       constexpr bool
2285       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
2286       {
2287 	return (*this)(ranges::begin(__r), ranges::end(__r),
2288 		       std::move(__pred), std::move(__proj));
2289       }
2290   };
2291 
2292   inline constexpr __is_partitioned_fn is_partitioned{};
2293 
2294   struct __partition_fn
2295   {
2296     template<permutable _Iter, sentinel_for<_Iter> _Sent,
2297 	     typename _Proj = identity,
2298 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
2299       constexpr subrange<_Iter>
2300       operator()(_Iter __first, _Sent __last,
2301 		 _Pred __pred, _Proj __proj = {}) const
2302       {
2303 	if constexpr (bidirectional_iterator<_Iter>)
2304 	  {
2305 	    auto __lasti = ranges::next(__first, __last);
2306 	    auto __tail = __lasti;
2307 	    for (;;)
2308 	      {
2309 		for (;;)
2310 		  if (__first == __tail)
2311 		    return {std::move(__first), std::move(__lasti)};
2312 		  else if (std::__invoke(__pred,
2313 					 std::__invoke(__proj, *__first)))
2314 		    ++__first;
2315 		  else
2316 		    break;
2317 		--__tail;
2318 		for (;;)
2319 		  if (__first == __tail)
2320 		    return {std::move(__first), std::move(__lasti)};
2321 		  else if (!(bool)std::__invoke(__pred,
2322 						std::__invoke(__proj, *__tail)))
2323 		    --__tail;
2324 		  else
2325 		    break;
2326 		ranges::iter_swap(__first, __tail);
2327 		++__first;
2328 	      }
2329 	  }
2330 	else
2331 	  {
2332 	    if (__first == __last)
2333 	      return {__first, __first};
2334 
2335 	    while (std::__invoke(__pred, std::__invoke(__proj, *__first)))
2336 	      if (++__first == __last)
2337 		return {__first, __first};
2338 
2339 	    auto __next = __first;
2340 	    while (++__next != __last)
2341 	      if (std::__invoke(__pred, std::__invoke(__proj, *__next)))
2342 		{
2343 		  ranges::iter_swap(__first, __next);
2344 		  ++__first;
2345 		}
2346 
2347 	    return {std::move(__first), std::move(__next)};
2348 	  }
2349       }
2350 
2351     template<forward_range _Range, typename _Proj = identity,
2352 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
2353 	       _Pred>
2354       requires permutable<iterator_t<_Range>>
2355       constexpr borrowed_subrange_t<_Range>
2356       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
2357       {
2358 	return (*this)(ranges::begin(__r), ranges::end(__r),
2359 		       std::move(__pred), std::move(__proj));
2360       }
2361   };
2362 
2363   inline constexpr __partition_fn partition{};
2364 
2365   struct __stable_partition_fn
2366   {
2367     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
2368 	     typename _Proj = identity,
2369 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
2370       requires permutable<_Iter>
2371       subrange<_Iter>
2372       operator()(_Iter __first, _Sent __last,
2373 		 _Pred __pred, _Proj __proj = {}) const
2374       {
2375 	auto __lasti = ranges::next(__first, __last);
2376 	auto __middle
2377 	  = std::stable_partition(std::move(__first), __lasti,
2378 				  __detail::__make_pred_proj(__pred, __proj));
2379 	return {std::move(__middle), std::move(__lasti)};
2380       }
2381 
2382     template<bidirectional_range _Range, typename _Proj = identity,
2383 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
2384 	       _Pred>
2385       requires permutable<iterator_t<_Range>>
2386       borrowed_subrange_t<_Range>
2387       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
2388       {
2389 	return (*this)(ranges::begin(__r), ranges::end(__r),
2390 		       std::move(__pred), std::move(__proj));
2391       }
2392   };
2393 
2394   inline constexpr __stable_partition_fn stable_partition{};
2395 
2396   template<typename _Iter, typename _Out1, typename _Out2>
2397     struct in_out_out_result
2398     {
2399       [[no_unique_address]] _Iter  in;
2400       [[no_unique_address]] _Out1 out1;
2401       [[no_unique_address]] _Out2 out2;
2402 
2403       template<typename _IIter, typename _OOut1, typename _OOut2>
2404 	requires convertible_to<const _Iter&, _IIter>
2405 	  && convertible_to<const _Out1&, _OOut1>
2406 	  && convertible_to<const _Out2&, _OOut2>
2407 	constexpr
2408 	operator in_out_out_result<_IIter, _OOut1, _OOut2>() const &
2409 	{ return {in, out1, out2}; }
2410 
2411       template<typename _IIter, typename _OOut1, typename _OOut2>
2412 	requires convertible_to<_Iter, _IIter>
2413 	  && convertible_to<_Out1, _OOut1>
2414 	  && convertible_to<_Out2, _OOut2>
2415 	constexpr
2416 	operator in_out_out_result<_IIter, _OOut1, _OOut2>() &&
2417 	{ return {std::move(in), std::move(out1), std::move(out2)}; }
2418     };
2419 
2420   template<typename _Iter, typename _Out1, typename _Out2>
2421     using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>;
2422 
2423   struct __partition_copy_fn
2424   {
2425     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
2426 	     weakly_incrementable _Out1, weakly_incrementable _Out2,
2427 	     typename _Proj = identity,
2428 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
2429       requires indirectly_copyable<_Iter, _Out1>
2430 	&& indirectly_copyable<_Iter, _Out2>
2431       constexpr partition_copy_result<_Iter, _Out1, _Out2>
2432       operator()(_Iter __first, _Sent __last,
2433 		 _Out1 __out_true, _Out2 __out_false,
2434 		 _Pred __pred, _Proj __proj = {}) const
2435       {
2436 	for (; __first != __last; ++__first)
2437 	  if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
2438 	    {
2439 	      *__out_true = *__first;
2440 	      ++__out_true;
2441 	    }
2442 	  else
2443 	    {
2444 	      *__out_false = *__first;
2445 	      ++__out_false;
2446 	    }
2447 
2448 	return {std::move(__first),
2449 		std::move(__out_true), std::move(__out_false)};
2450       }
2451 
2452     template<input_range _Range, weakly_incrementable _Out1,
2453 	     weakly_incrementable _Out2,
2454 	     typename _Proj = identity,
2455 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
2456 	       _Pred>
2457       requires indirectly_copyable<iterator_t<_Range>, _Out1>
2458 	&& indirectly_copyable<iterator_t<_Range>, _Out2>
2459       constexpr partition_copy_result<borrowed_iterator_t<_Range>, _Out1, _Out2>
2460       operator()(_Range&& __r, _Out1 __out_true, _Out2 __out_false,
2461 		 _Pred __pred, _Proj __proj = {}) const
2462       {
2463 	return (*this)(ranges::begin(__r), ranges::end(__r),
2464 		       std::move(__out_true), std::move(__out_false),
2465 		       std::move(__pred), std::move(__proj));
2466       }
2467   };
2468 
2469   inline constexpr __partition_copy_fn partition_copy{};
2470 
2471   struct __partition_point_fn
2472   {
2473     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
2474 	     typename _Proj = identity,
2475 	     indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
2476       constexpr _Iter
2477       operator()(_Iter __first, _Sent __last,
2478 		 _Pred __pred, _Proj __proj = {}) const
2479       {
2480 	auto __len = ranges::distance(__first, __last);
2481 
2482 	while (__len > 0)
2483 	  {
2484 	    auto __half = __len / 2;
2485 	    auto __middle = __first;
2486 	    ranges::advance(__middle, __half);
2487 	    if (std::__invoke(__pred, std::__invoke(__proj, *__middle)))
2488 	      {
2489 		__first = __middle;
2490 		++__first;
2491 		__len = __len - __half - 1;
2492 	      }
2493 	    else
2494 	      __len = __half;
2495 	  }
2496 	return __first;
2497       }
2498 
2499     template<forward_range _Range, typename _Proj = identity,
2500 	     indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
2501 	       _Pred>
2502       constexpr borrowed_iterator_t<_Range>
2503       operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const
2504       {
2505 	return (*this)(ranges::begin(__r), ranges::end(__r),
2506 		       std::move(__pred), std::move(__proj));
2507       }
2508   };
2509 
2510   inline constexpr __partition_point_fn partition_point{};
2511 
2512   template<typename _Iter1, typename _Iter2, typename _Out>
2513     using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>;
2514 
2515   struct __merge_fn
2516   {
2517     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2518 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2519 	     weakly_incrementable _Out, typename _Comp = ranges::less,
2520 	     typename _Proj1 = identity, typename _Proj2 = identity>
2521       requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
2522       constexpr merge_result<_Iter1, _Iter2, _Out>
2523       operator()(_Iter1 __first1, _Sent1 __last1,
2524 		 _Iter2 __first2, _Sent2 __last2, _Out __result,
2525 		 _Comp __comp = {},
2526 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2527       {
2528 	while (__first1 != __last1 && __first2 != __last2)
2529 	  {
2530 	    if (std::__invoke(__comp,
2531 			      std::__invoke(__proj2, *__first2),
2532 			      std::__invoke(__proj1, *__first1)))
2533 	      {
2534 		*__result = *__first2;
2535 		++__first2;
2536 	      }
2537 	    else
2538 	      {
2539 		*__result = *__first1;
2540 		++__first1;
2541 	      }
2542 	    ++__result;
2543 	  }
2544 	auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
2545 				    std::move(__result));
2546 	auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
2547 				    std::move(__copy1.out));
2548 	return { std::move(__copy1.in), std::move(__copy2.in),
2549 		 std::move(__copy2.out) };
2550       }
2551 
2552     template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
2553 	     typename _Comp = ranges::less,
2554 	     typename _Proj1 = identity, typename _Proj2 = identity>
2555       requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
2556 			 _Comp, _Proj1, _Proj2>
2557       constexpr merge_result<borrowed_iterator_t<_Range1>,
2558 			     borrowed_iterator_t<_Range2>,
2559 			     _Out>
2560       operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
2561 		 _Comp __comp = {},
2562 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2563       {
2564 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2565 		       ranges::begin(__r2), ranges::end(__r2),
2566 		       std::move(__result), std::move(__comp),
2567 		       std::move(__proj1), std::move(__proj2));
2568       }
2569   };
2570 
2571   inline constexpr __merge_fn merge{};
2572 
2573   struct __inplace_merge_fn
2574   {
2575     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
2576 	     typename _Comp = ranges::less,
2577 	     typename _Proj = identity>
2578       requires sortable<_Iter, _Comp, _Proj>
2579       _Iter
2580       operator()(_Iter __first, _Iter __middle, _Sent __last,
2581 		 _Comp __comp = {}, _Proj __proj = {}) const
2582       {
2583 	auto __lasti = ranges::next(__first, __last);
2584 	std::inplace_merge(std::move(__first), std::move(__middle), __lasti,
2585 			   __detail::__make_comp_proj(__comp, __proj));
2586 	return __lasti;
2587       }
2588 
2589     template<bidirectional_range _Range,
2590 	     typename _Comp = ranges::less, typename _Proj = identity>
2591       requires sortable<iterator_t<_Range>, _Comp, _Proj>
2592       borrowed_iterator_t<_Range>
2593       operator()(_Range&& __r, iterator_t<_Range> __middle,
2594 		 _Comp __comp = {}, _Proj __proj = {}) const
2595       {
2596 	return (*this)(ranges::begin(__r), std::move(__middle),
2597 		       ranges::end(__r),
2598 		       std::move(__comp), std::move(__proj));
2599       }
2600   };
2601 
2602   inline constexpr __inplace_merge_fn inplace_merge{};
2603 
2604   struct __includes_fn
2605   {
2606     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2607 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2608 	     typename _Proj1 = identity, typename _Proj2 = identity,
2609 	     indirect_strict_weak_order<projected<_Iter1, _Proj1>,
2610 					projected<_Iter2, _Proj2>>
2611 	       _Comp = ranges::less>
2612       constexpr bool
2613       operator()(_Iter1 __first1, _Sent1 __last1,
2614 		 _Iter2 __first2, _Sent2 __last2,
2615 		 _Comp __comp = {},
2616 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2617       {
2618 	while (__first1 != __last1 && __first2 != __last2)
2619 	  if (std::__invoke(__comp,
2620 			    std::__invoke(__proj2, *__first2),
2621 			    std::__invoke(__proj1, *__first1)))
2622 	    return false;
2623 	  else if (std::__invoke(__comp,
2624 				 std::__invoke(__proj1, *__first1),
2625 				 std::__invoke(__proj2, *__first2)))
2626 	    ++__first1;
2627 	  else
2628 	    {
2629 	      ++__first1;
2630 	      ++__first2;
2631 	    }
2632 
2633 	return __first2 == __last2;
2634       }
2635 
2636     template<input_range _Range1, input_range _Range2,
2637 	     typename _Proj1 = identity, typename _Proj2 = identity,
2638 	     indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
2639 					projected<iterator_t<_Range2>, _Proj2>>
2640 	       _Comp = ranges::less>
2641       constexpr bool
2642       operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
2643 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2644       {
2645 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2646 		       ranges::begin(__r2), ranges::end(__r2),
2647 		       std::move(__comp),
2648 		       std::move(__proj1), std::move(__proj2));
2649       }
2650   };
2651 
2652   inline constexpr __includes_fn includes{};
2653 
2654   template<typename _Iter1, typename _Iter2, typename _Out>
2655     using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>;
2656 
2657   struct __set_union_fn
2658   {
2659     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2660 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2661 	     weakly_incrementable _Out, typename _Comp = ranges::less,
2662 	     typename _Proj1 = identity, typename _Proj2 = identity>
2663       requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
2664       constexpr set_union_result<_Iter1, _Iter2, _Out>
2665       operator()(_Iter1 __first1, _Sent1 __last1,
2666 		 _Iter2 __first2, _Sent2 __last2,
2667 		 _Out __result, _Comp __comp = {},
2668 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2669       {
2670 	while (__first1 != __last1 && __first2 != __last2)
2671 	  {
2672 	    if (std::__invoke(__comp,
2673 			      std::__invoke(__proj1, *__first1),
2674 			      std::__invoke(__proj2, *__first2)))
2675 	      {
2676 		*__result = *__first1;
2677 		++__first1;
2678 	      }
2679 	    else if (std::__invoke(__comp,
2680 				   std::__invoke(__proj2, *__first2),
2681 				   std::__invoke(__proj1, *__first1)))
2682 	      {
2683 		*__result = *__first2;
2684 		++__first2;
2685 	      }
2686 	    else
2687 	      {
2688 		*__result = *__first1;
2689 		++__first1;
2690 		++__first2;
2691 	      }
2692 	    ++__result;
2693 	  }
2694 	auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
2695 				    std::move(__result));
2696 	auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
2697 				    std::move(__copy1.out));
2698 	return {std::move(__copy1.in), std::move(__copy2.in),
2699 		std::move(__copy2.out)};
2700       }
2701 
2702     template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
2703 	     typename _Comp = ranges::less,
2704 	     typename _Proj1 = identity, typename _Proj2 = identity>
2705       requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
2706 			 _Comp, _Proj1, _Proj2>
2707       constexpr set_union_result<borrowed_iterator_t<_Range1>,
2708 				 borrowed_iterator_t<_Range2>, _Out>
2709       operator()(_Range1&& __r1, _Range2&& __r2,
2710 		 _Out __result, _Comp __comp = {},
2711 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2712       {
2713 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2714 		       ranges::begin(__r2), ranges::end(__r2),
2715 		       std::move(__result), std::move(__comp),
2716 		       std::move(__proj1), std::move(__proj2));
2717       }
2718   };
2719 
2720   inline constexpr __set_union_fn set_union{};
2721 
2722   template<typename _Iter1, typename _Iter2, typename _Out>
2723     using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>;
2724 
2725   struct __set_intersection_fn
2726   {
2727     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2728 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2729 	     weakly_incrementable _Out, typename _Comp = ranges::less,
2730 	     typename _Proj1 = identity, typename _Proj2 = identity>
2731       requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
2732       constexpr set_intersection_result<_Iter1, _Iter2, _Out>
2733       operator()(_Iter1 __first1, _Sent1 __last1,
2734 		 _Iter2 __first2, _Sent2 __last2, _Out __result,
2735 		 _Comp __comp = {},
2736 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2737       {
2738 	while (__first1 != __last1 && __first2 != __last2)
2739 	  if (std::__invoke(__comp,
2740 			    std::__invoke(__proj1, *__first1),
2741 			    std::__invoke(__proj2, *__first2)))
2742 	    ++__first1;
2743 	  else if (std::__invoke(__comp,
2744 				 std::__invoke(__proj2, *__first2),
2745 				 std::__invoke(__proj1, *__first1)))
2746 	    ++__first2;
2747 	  else
2748 	    {
2749 	      *__result = *__first1;
2750 	      ++__first1;
2751 	      ++__first2;
2752 	      ++__result;
2753 	    }
2754 	// TODO: Eliminating these variables triggers an ICE.
2755 	auto __last1i = ranges::next(std::move(__first1), std::move(__last1));
2756 	auto __last2i = ranges::next(std::move(__first2), std::move(__last2));
2757 	return {std::move(__last1i), std::move(__last2i), std::move(__result)};
2758       }
2759 
2760     template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
2761 	     typename _Comp = ranges::less,
2762 	     typename _Proj1 = identity, typename _Proj2 = identity>
2763       requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
2764 			 _Comp, _Proj1, _Proj2>
2765       constexpr set_intersection_result<borrowed_iterator_t<_Range1>,
2766 					borrowed_iterator_t<_Range2>, _Out>
2767       operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
2768 		 _Comp __comp = {},
2769 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2770       {
2771 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2772 		       ranges::begin(__r2), ranges::end(__r2),
2773 		       std::move(__result), std::move(__comp),
2774 		       std::move(__proj1), std::move(__proj2));
2775       }
2776   };
2777 
2778   inline constexpr __set_intersection_fn set_intersection{};
2779 
2780   template<typename _Iter, typename _Out>
2781     using set_difference_result = in_out_result<_Iter, _Out>;
2782 
2783   struct __set_difference_fn
2784   {
2785     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2786 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2787 	     weakly_incrementable _Out, typename _Comp = ranges::less,
2788 	     typename _Proj1 = identity, typename _Proj2 = identity>
2789       requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
2790       constexpr set_difference_result<_Iter1, _Out>
2791       operator()(_Iter1 __first1, _Sent1 __last1,
2792 		 _Iter2 __first2, _Sent2 __last2, _Out __result,
2793 		 _Comp __comp = {},
2794 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2795       {
2796 	while (__first1 != __last1 && __first2 != __last2)
2797 	  if (std::__invoke(__comp,
2798 			    std::__invoke(__proj1, *__first1),
2799 			    std::__invoke(__proj2, *__first2)))
2800 	    {
2801 	      *__result = *__first1;
2802 	      ++__first1;
2803 	      ++__result;
2804 	    }
2805 	  else if (std::__invoke(__comp,
2806 				 std::__invoke(__proj2, *__first2),
2807 				 std::__invoke(__proj1, *__first1)))
2808 	    ++__first2;
2809 	  else
2810 	    {
2811 	      ++__first1;
2812 	      ++__first2;
2813 	    }
2814 	return ranges::copy(std::move(__first1), std::move(__last1),
2815 			    std::move(__result));
2816       }
2817 
2818     template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
2819 	     typename _Comp = ranges::less,
2820 	     typename _Proj1 = identity, typename _Proj2 = identity>
2821       requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
2822 			 _Comp, _Proj1, _Proj2>
2823       constexpr set_difference_result<borrowed_iterator_t<_Range1>, _Out>
2824       operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
2825 		 _Comp __comp = {},
2826 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2827       {
2828 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2829 		       ranges::begin(__r2), ranges::end(__r2),
2830 		       std::move(__result), std::move(__comp),
2831 		       std::move(__proj1), std::move(__proj2));
2832       }
2833   };
2834 
2835   inline constexpr __set_difference_fn set_difference{};
2836 
2837   template<typename _Iter1, typename _Iter2, typename _Out>
2838     using set_symmetric_difference_result
2839       = in_in_out_result<_Iter1, _Iter2, _Out>;
2840 
2841   struct __set_symmetric_difference_fn
2842   {
2843     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
2844 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
2845 	     weakly_incrementable _Out, typename _Comp = ranges::less,
2846 	     typename _Proj1 = identity, typename _Proj2 = identity>
2847       requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2>
2848       constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out>
2849       operator()(_Iter1 __first1, _Sent1 __last1,
2850 		 _Iter2 __first2, _Sent2 __last2,
2851 		 _Out __result, _Comp __comp = {},
2852 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2853       {
2854 	while (__first1 != __last1 && __first2 != __last2)
2855 	  if (std::__invoke(__comp,
2856 			    std::__invoke(__proj1, *__first1),
2857 			    std::__invoke(__proj2, *__first2)))
2858 	    {
2859 	      *__result = *__first1;
2860 	      ++__first1;
2861 	      ++__result;
2862 	    }
2863 	  else if (std::__invoke(__comp,
2864 				 std::__invoke(__proj2, *__first2),
2865 				 std::__invoke(__proj1, *__first1)))
2866 	    {
2867 	      *__result = *__first2;
2868 	      ++__first2;
2869 	      ++__result;
2870 	    }
2871 	  else
2872 	    {
2873 	      ++__first1;
2874 	      ++__first2;
2875 	    }
2876 	auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1),
2877 				    std::move(__result));
2878 	auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2),
2879 				    std::move(__copy1.out));
2880 	return {std::move(__copy1.in), std::move(__copy2.in),
2881 		std::move(__copy2.out)};
2882       }
2883 
2884     template<input_range _Range1, input_range _Range2, weakly_incrementable _Out,
2885 	     typename _Comp = ranges::less,
2886 	     typename _Proj1 = identity, typename _Proj2 = identity>
2887       requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _Out,
2888 			 _Comp, _Proj1, _Proj2>
2889       constexpr set_symmetric_difference_result<borrowed_iterator_t<_Range1>,
2890 						borrowed_iterator_t<_Range2>,
2891 						_Out>
2892       operator()(_Range1&& __r1, _Range2&& __r2, _Out __result,
2893 		 _Comp __comp = {},
2894 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
2895       {
2896 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
2897 		       ranges::begin(__r2), ranges::end(__r2),
2898 		       std::move(__result), std::move(__comp),
2899 		       std::move(__proj1), std::move(__proj2));
2900       }
2901   };
2902 
2903   inline constexpr __set_symmetric_difference_fn set_symmetric_difference{};
2904 
2905   struct __min_fn
2906   {
2907     template<typename _Tp, typename _Proj = identity,
2908 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
2909 	       _Comp = ranges::less>
2910       constexpr const _Tp&
2911       operator()(const _Tp& __a, const _Tp& __b,
2912 		 _Comp __comp = {}, _Proj __proj = {}) const
2913       {
2914 	if (std::__invoke(__comp,
2915 			  std::__invoke(__proj, __b),
2916 			  std::__invoke(__proj, __a)))
2917 	  return __b;
2918 	else
2919 	  return __a;
2920       }
2921 
2922     template<input_range _Range, typename _Proj = identity,
2923 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
2924 	       _Comp = ranges::less>
2925       requires indirectly_copyable_storable<iterator_t<_Range>,
2926 					    range_value_t<_Range>*>
2927       constexpr range_value_t<_Range>
2928       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
2929       {
2930 	auto __first = ranges::begin(__r);
2931 	auto __last = ranges::end(__r);
2932 	__glibcxx_assert(__first != __last);
2933 	auto __result = *__first;
2934 	while (++__first != __last)
2935 	  {
2936 	    auto __tmp = *__first;
2937 	    if (std::__invoke(__comp,
2938 			      std::__invoke(__proj, __tmp),
2939 			      std::__invoke(__proj, __result)))
2940 	      __result = std::move(__tmp);
2941 	  }
2942 	return __result;
2943       }
2944 
2945     template<copyable _Tp, typename _Proj = identity,
2946 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
2947 	       _Comp = ranges::less>
2948       constexpr _Tp
2949       operator()(initializer_list<_Tp> __r,
2950 		 _Comp __comp = {}, _Proj __proj = {}) const
2951       {
2952 	return (*this)(ranges::subrange(__r),
2953 		       std::move(__comp), std::move(__proj));
2954       }
2955   };
2956 
2957   inline constexpr __min_fn min{};
2958 
2959   struct __max_fn
2960   {
2961     template<typename _Tp, typename _Proj = identity,
2962 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
2963 	       _Comp = ranges::less>
2964       constexpr const _Tp&
2965       operator()(const _Tp& __a, const _Tp& __b,
2966 		 _Comp __comp = {}, _Proj __proj = {}) const
2967       {
2968 	if (std::__invoke(__comp,
2969 			  std::__invoke(__proj, __a),
2970 			  std::__invoke(__proj, __b)))
2971 	  return __b;
2972 	else
2973 	  return __a;
2974       }
2975 
2976     template<input_range _Range, typename _Proj = identity,
2977 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
2978 	       _Comp = ranges::less>
2979       requires indirectly_copyable_storable<iterator_t<_Range>,
2980 					    range_value_t<_Range>*>
2981       constexpr range_value_t<_Range>
2982       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
2983       {
2984 	auto __first = ranges::begin(__r);
2985 	auto __last = ranges::end(__r);
2986 	__glibcxx_assert(__first != __last);
2987 	auto __result = *__first;
2988 	while (++__first != __last)
2989 	  {
2990 	    auto __tmp = *__first;
2991 	    if (std::__invoke(__comp,
2992 			      std::__invoke(__proj, __result),
2993 			      std::__invoke(__proj, __tmp)))
2994 	      __result = std::move(__tmp);
2995 	  }
2996 	return __result;
2997       }
2998 
2999     template<copyable _Tp, typename _Proj = identity,
3000 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
3001 	       _Comp = ranges::less>
3002       constexpr _Tp
3003       operator()(initializer_list<_Tp> __r,
3004 		 _Comp __comp = {}, _Proj __proj = {}) const
3005       {
3006 	return (*this)(ranges::subrange(__r),
3007 		       std::move(__comp), std::move(__proj));
3008       }
3009   };
3010 
3011   inline constexpr __max_fn max{};
3012 
3013   struct __clamp_fn
3014   {
3015     template<typename _Tp, typename _Proj = identity,
3016 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp
3017 	       = ranges::less>
3018       constexpr const _Tp&
3019       operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi,
3020 		 _Comp __comp = {}, _Proj __proj = {}) const
3021       {
3022 	__glibcxx_assert(!(std::__invoke(__comp,
3023 					 std::__invoke(__proj, __hi),
3024 					 std::__invoke(__proj, __lo))));
3025 	auto&& __proj_val = std::__invoke(__proj, __val);
3026 	if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo)))
3027 	  return __lo;
3028 	else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val))
3029 	  return __hi;
3030 	else
3031 	  return __val;
3032       }
3033   };
3034 
3035   inline constexpr __clamp_fn clamp{};
3036 
3037   template<typename _Tp>
3038     struct min_max_result
3039     {
3040       [[no_unique_address]] _Tp min;
3041       [[no_unique_address]] _Tp max;
3042 
3043       template<typename _Tp2>
3044 	requires convertible_to<const _Tp&, _Tp2>
3045 	constexpr
3046 	operator min_max_result<_Tp2>() const &
3047 	{ return {min, max}; }
3048 
3049       template<typename _Tp2>
3050 	requires convertible_to<_Tp, _Tp2>
3051 	constexpr
3052 	operator min_max_result<_Tp2>() &&
3053 	{ return {std::move(min), std::move(max)}; }
3054     };
3055 
3056   template<typename _Tp>
3057     using minmax_result = min_max_result<_Tp>;
3058 
3059   struct __minmax_fn
3060   {
3061     template<typename _Tp, typename _Proj = identity,
3062 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
3063 	       _Comp = ranges::less>
3064       constexpr minmax_result<const _Tp&>
3065       operator()(const _Tp& __a, const _Tp& __b,
3066 		 _Comp __comp = {}, _Proj __proj = {}) const
3067       {
3068 	if (std::__invoke(__comp,
3069 			  std::__invoke(__proj, __b),
3070 			  std::__invoke(__proj, __a)))
3071 	  return {__b, __a};
3072 	else
3073 	  return {__a, __b};
3074       }
3075 
3076     template<input_range _Range, typename _Proj = identity,
3077 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
3078 	       _Comp = ranges::less>
3079       requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*>
3080       constexpr minmax_result<range_value_t<_Range>>
3081       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3082       {
3083 	auto __first = ranges::begin(__r);
3084 	auto __last = ranges::end(__r);
3085 	__glibcxx_assert(__first != __last);
3086 	auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
3087 	minmax_result<range_value_t<_Range>> __result = {*__first, *__first};
3088 	if (++__first == __last)
3089 	  return __result;
3090 	else
3091 	  {
3092 	    // At this point __result.min == __result.max, so a single
3093 	    // comparison with the next element suffices.
3094 	    auto&& __val = *__first;
3095 	    if (__comp_proj(__val, __result.min))
3096 	      __result.min = std::forward<decltype(__val)>(__val);
3097 	    else
3098 	      __result.max = std::forward<decltype(__val)>(__val);
3099 	  }
3100 	while (++__first != __last)
3101 	  {
3102 	    // Now process two elements at a time so that we perform at most
3103 	    // 1 + 3*(N-2)/2 comparisons in total (each of the (N-2)/2
3104 	    // iterations of this loop performs three comparisons).
3105 	    range_value_t<_Range> __val1 = *__first;
3106 	    if (++__first == __last)
3107 	      {
3108 		// N is odd; in this final iteration, we perform at most two
3109 		// comparisons, for a total of 1 + 3*(N-3)/2 + 2 comparisons,
3110 		// which is not more than 3*N/2, as required.
3111 		if (__comp_proj(__val1, __result.min))
3112 		  __result.min = std::move(__val1);
3113 		else if (!__comp_proj(__val1, __result.max))
3114 		  __result.max = std::move(__val1);
3115 		break;
3116 	      }
3117 	    auto&& __val2 = *__first;
3118 	    if (!__comp_proj(__val2, __val1))
3119 	      {
3120 		if (__comp_proj(__val1, __result.min))
3121 		  __result.min = std::move(__val1);
3122 		if (!__comp_proj(__val2, __result.max))
3123 		  __result.max = std::forward<decltype(__val2)>(__val2);
3124 	      }
3125 	    else
3126 	      {
3127 		if (__comp_proj(__val2, __result.min))
3128 		  __result.min = std::forward<decltype(__val2)>(__val2);
3129 		if (!__comp_proj(__val1, __result.max))
3130 		  __result.max = std::move(__val1);
3131 	      }
3132 	  }
3133 	return __result;
3134       }
3135 
3136     template<copyable _Tp, typename _Proj = identity,
3137 	     indirect_strict_weak_order<projected<const _Tp*, _Proj>>
3138 	       _Comp = ranges::less>
3139       constexpr minmax_result<_Tp>
3140       operator()(initializer_list<_Tp> __r,
3141 		 _Comp __comp = {}, _Proj __proj = {}) const
3142       {
3143 	return (*this)(ranges::subrange(__r),
3144 		       std::move(__comp), std::move(__proj));
3145       }
3146   };
3147 
3148   inline constexpr __minmax_fn minmax{};
3149 
3150   struct __min_element_fn
3151   {
3152     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
3153 	     typename _Proj = identity,
3154 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
3155 	       _Comp = ranges::less>
3156       constexpr _Iter
3157       operator()(_Iter __first, _Sent __last,
3158 		 _Comp __comp = {}, _Proj __proj = {}) const
3159       {
3160 	if (__first == __last)
3161 	  return __first;
3162 
3163 	auto __i = __first;
3164 	while (++__i != __last)
3165 	  {
3166 	    if (std::__invoke(__comp,
3167 			      std::__invoke(__proj, *__i),
3168 			      std::__invoke(__proj, *__first)))
3169 	      __first = __i;
3170 	  }
3171 	return __first;
3172       }
3173 
3174     template<forward_range _Range, typename _Proj = identity,
3175 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
3176 	       _Comp = ranges::less>
3177       constexpr borrowed_iterator_t<_Range>
3178       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3179       {
3180 	return (*this)(ranges::begin(__r), ranges::end(__r),
3181 		       std::move(__comp), std::move(__proj));
3182       }
3183   };
3184 
3185   inline constexpr __min_element_fn min_element{};
3186 
3187   struct __max_element_fn
3188   {
3189     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
3190 	     typename _Proj = identity,
3191 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
3192 	       _Comp = ranges::less>
3193       constexpr _Iter
3194       operator()(_Iter __first, _Sent __last,
3195 		 _Comp __comp = {}, _Proj __proj = {}) const
3196       {
3197 	if (__first == __last)
3198 	  return __first;
3199 
3200 	auto __i = __first;
3201 	while (++__i != __last)
3202 	  {
3203 	    if (std::__invoke(__comp,
3204 			      std::__invoke(__proj, *__first),
3205 			      std::__invoke(__proj, *__i)))
3206 	      __first = __i;
3207 	  }
3208 	return __first;
3209       }
3210 
3211     template<forward_range _Range, typename _Proj = identity,
3212 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
3213 	       _Comp = ranges::less>
3214       constexpr borrowed_iterator_t<_Range>
3215       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3216       {
3217 	return (*this)(ranges::begin(__r), ranges::end(__r),
3218 		       std::move(__comp), std::move(__proj));
3219       }
3220   };
3221 
3222   inline constexpr __max_element_fn max_element{};
3223 
3224   template<typename _Iter>
3225     using minmax_element_result = min_max_result<_Iter>;
3226 
3227   struct __minmax_element_fn
3228   {
3229     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
3230 	     typename _Proj = identity,
3231 	     indirect_strict_weak_order<projected<_Iter, _Proj>>
3232 	       _Comp = ranges::less>
3233       constexpr minmax_element_result<_Iter>
3234       operator()(_Iter __first, _Sent __last,
3235 		 _Comp __comp = {}, _Proj __proj = {}) const
3236       {
3237 	auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
3238 	minmax_element_result<_Iter> __result = {__first, __first};
3239 	if (__first == __last || ++__first == __last)
3240 	  return __result;
3241 	else
3242 	  {
3243 	    // At this point __result.min == __result.max, so a single
3244 	    // comparison with the next element suffices.
3245 	    if (__comp_proj(*__first, *__result.min))
3246 	      __result.min = __first;
3247 	    else
3248 	      __result.max = __first;
3249 	  }
3250 	while (++__first != __last)
3251 	  {
3252 	    // Now process two elements at a time so that we perform at most
3253 	    // 1 + 3*(N-2)/2 comparisons in total (each of the (N-2)/2
3254 	    // iterations of this loop performs three comparisons).
3255 	    auto __prev = __first;
3256 	    if (++__first == __last)
3257 	      {
3258 		// N is odd; in this final iteration, we perform at most two
3259 		// comparisons, for a total of 1 + 3*(N-3)/2 + 2 comparisons,
3260 		// which is not more than 3*N/2, as required.
3261 		if (__comp_proj(*__prev, *__result.min))
3262 		  __result.min = __prev;
3263 		else if (!__comp_proj(*__prev, *__result.max))
3264 		  __result.max = __prev;
3265 		break;
3266 	      }
3267 	    if (!__comp_proj(*__first, *__prev))
3268 	      {
3269 		if (__comp_proj(*__prev, *__result.min))
3270 		  __result.min = __prev;
3271 		if (!__comp_proj(*__first, *__result.max))
3272 		  __result.max = __first;
3273 	      }
3274 	    else
3275 	      {
3276 		if (__comp_proj(*__first, *__result.min))
3277 		  __result.min = __first;
3278 		if (!__comp_proj(*__prev, *__result.max))
3279 		  __result.max = __prev;
3280 	      }
3281 	  }
3282 	return __result;
3283       }
3284 
3285     template<forward_range _Range, typename _Proj = identity,
3286 	     indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>>
3287 	       _Comp = ranges::less>
3288       constexpr minmax_element_result<borrowed_iterator_t<_Range>>
3289       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3290       {
3291 	return (*this)(ranges::begin(__r), ranges::end(__r),
3292 		       std::move(__comp), std::move(__proj));
3293       }
3294   };
3295 
3296   inline constexpr __minmax_element_fn minmax_element{};
3297 
3298   struct __lexicographical_compare_fn
3299   {
3300     template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
3301 	     input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
3302 	     typename _Proj1 = identity, typename _Proj2 = identity,
3303 	     indirect_strict_weak_order<projected<_Iter1, _Proj1>,
3304 					projected<_Iter2, _Proj2>>
3305 	       _Comp = ranges::less>
3306       constexpr bool
3307       operator()(_Iter1 __first1, _Sent1 __last1,
3308 		 _Iter2 __first2, _Sent2 __last2,
3309 		 _Comp __comp = {},
3310 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
3311       {
3312 	if constexpr (__detail::__is_normal_iterator<_Iter1>
3313 		      && same_as<_Iter1, _Sent1>)
3314 	  return (*this)(__first1.base(), __last1.base(),
3315 			 std::move(__first2), std::move(__last2),
3316 			 std::move(__comp),
3317 			 std::move(__proj1), std::move(__proj2));
3318 	else if constexpr (__detail::__is_normal_iterator<_Iter2>
3319 			   && same_as<_Iter2, _Sent2>)
3320 	  return (*this)(std::move(__first1), std::move(__last1),
3321 			 __first2.base(), __last2.base(),
3322 			 std::move(__comp),
3323 			 std::move(__proj1), std::move(__proj2));
3324 	else
3325 	  {
3326 	    constexpr bool __sized_iters
3327 	      = (sized_sentinel_for<_Sent1, _Iter1>
3328 		 && sized_sentinel_for<_Sent2, _Iter2>);
3329 	    if constexpr (__sized_iters)
3330 	      {
3331 		using _ValueType1 = iter_value_t<_Iter1>;
3332 		using _ValueType2 = iter_value_t<_Iter2>;
3333 		// This condition is consistent with the one in
3334 		// __lexicographical_compare_aux in <bits/stl_algobase.h>.
3335 		constexpr bool __use_memcmp
3336 		  = (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value
3337 		     && __ptr_to_nonvolatile<_Iter1>
3338 		     && __ptr_to_nonvolatile<_Iter2>
3339 		     && (is_same_v<_Comp, ranges::less>
3340 			 || is_same_v<_Comp, ranges::greater>)
3341 		     && is_same_v<_Proj1, identity>
3342 		     && is_same_v<_Proj2, identity>);
3343 		if constexpr (__use_memcmp)
3344 		  {
3345 		    const auto __d1 = __last1 - __first1;
3346 		    const auto __d2 = __last2 - __first2;
3347 
3348 		    if (const auto __len = std::min(__d1, __d2))
3349 		      {
3350 			const auto __c
3351 			  = std::__memcmp(__first1, __first2, __len);
3352 			if constexpr (is_same_v<_Comp, ranges::less>)
3353 			  {
3354 			    if (__c < 0)
3355 			      return true;
3356 			    if (__c > 0)
3357 			      return false;
3358 			  }
3359 			else if constexpr (is_same_v<_Comp, ranges::greater>)
3360 			  {
3361 			    if (__c > 0)
3362 			      return true;
3363 			    if (__c < 0)
3364 			      return false;
3365 			  }
3366 		      }
3367 		    return __d1 < __d2;
3368 		  }
3369 	      }
3370 
3371 	    for (; __first1 != __last1 && __first2 != __last2;
3372 		 ++__first1, (void) ++__first2)
3373 	      {
3374 		if (std::__invoke(__comp,
3375 				  std::__invoke(__proj1, *__first1),
3376 				  std::__invoke(__proj2, *__first2)))
3377 		  return true;
3378 		if (std::__invoke(__comp,
3379 				  std::__invoke(__proj2, *__first2),
3380 				  std::__invoke(__proj1, *__first1)))
3381 		  return false;
3382 	      }
3383 	    return __first1 == __last1 && __first2 != __last2;
3384 	  }
3385       }
3386 
3387     template<input_range _Range1, input_range _Range2,
3388 	     typename _Proj1 = identity, typename _Proj2 = identity,
3389 	     indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
3390 					projected<iterator_t<_Range2>, _Proj2>>
3391 	       _Comp = ranges::less>
3392       constexpr bool
3393       operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {},
3394 		 _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
3395       {
3396 	return (*this)(ranges::begin(__r1), ranges::end(__r1),
3397 		       ranges::begin(__r2), ranges::end(__r2),
3398 		       std::move(__comp),
3399 		       std::move(__proj1), std::move(__proj2));
3400       }
3401 
3402   private:
3403     template<typename _Iter, typename _Ref = iter_reference_t<_Iter>>
3404       static constexpr bool __ptr_to_nonvolatile
3405 	= is_pointer_v<_Iter> && !is_volatile_v<remove_reference_t<_Ref>>;
3406   };
3407 
3408   inline constexpr __lexicographical_compare_fn lexicographical_compare;
3409 
3410   template<typename _Iter>
3411     struct in_found_result
3412     {
3413       [[no_unique_address]] _Iter in;
3414       bool found;
3415 
3416       template<typename _Iter2>
3417 	requires convertible_to<const _Iter&, _Iter2>
3418 	constexpr
3419 	operator in_found_result<_Iter2>() const &
3420 	{ return {in, found}; }
3421 
3422       template<typename _Iter2>
3423 	requires convertible_to<_Iter, _Iter2>
3424 	constexpr
3425 	operator in_found_result<_Iter2>() &&
3426 	{ return {std::move(in), found}; }
3427     };
3428 
3429   template<typename _Iter>
3430     using next_permutation_result = in_found_result<_Iter>;
3431 
3432   struct __next_permutation_fn
3433   {
3434     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
3435 	     typename _Comp = ranges::less, typename _Proj = identity>
3436       requires sortable<_Iter, _Comp, _Proj>
3437       constexpr next_permutation_result<_Iter>
3438       operator()(_Iter __first, _Sent __last,
3439 		 _Comp __comp = {}, _Proj __proj = {}) const
3440       {
3441 	if (__first == __last)
3442 	  return {std::move(__first), false};
3443 
3444 	auto __i = __first;
3445 	++__i;
3446 	if (__i == __last)
3447 	  return {std::move(__i), false};
3448 
3449 	auto __lasti = ranges::next(__first, __last);
3450 	__i = __lasti;
3451 	--__i;
3452 
3453 	for (;;)
3454 	  {
3455 	    auto __ii = __i;
3456 	    --__i;
3457 	    if (std::__invoke(__comp,
3458 			      std::__invoke(__proj, *__i),
3459 			      std::__invoke(__proj, *__ii)))
3460 	      {
3461 		auto __j = __lasti;
3462 		while (!(bool)std::__invoke(__comp,
3463 					    std::__invoke(__proj, *__i),
3464 					    std::__invoke(__proj, *--__j)))
3465 		  ;
3466 		ranges::iter_swap(__i, __j);
3467 		ranges::reverse(__ii, __last);
3468 		return {std::move(__lasti), true};
3469 	      }
3470 	    if (__i == __first)
3471 	      {
3472 		ranges::reverse(__first, __last);
3473 		return {std::move(__lasti), false};
3474 	      }
3475 	  }
3476       }
3477 
3478     template<bidirectional_range _Range, typename _Comp = ranges::less,
3479 	     typename _Proj = identity>
3480       requires sortable<iterator_t<_Range>, _Comp, _Proj>
3481       constexpr next_permutation_result<borrowed_iterator_t<_Range>>
3482       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3483       {
3484 	return (*this)(ranges::begin(__r), ranges::end(__r),
3485 		       std::move(__comp), std::move(__proj));
3486       }
3487   };
3488 
3489   inline constexpr __next_permutation_fn next_permutation{};
3490 
3491   template<typename _Iter>
3492     using prev_permutation_result = in_found_result<_Iter>;
3493 
3494   struct __prev_permutation_fn
3495   {
3496     template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
3497 	     typename _Comp = ranges::less, typename _Proj = identity>
3498       requires sortable<_Iter, _Comp, _Proj>
3499       constexpr prev_permutation_result<_Iter>
3500       operator()(_Iter __first, _Sent __last,
3501 		 _Comp __comp = {}, _Proj __proj = {}) const
3502       {
3503 	if (__first == __last)
3504 	  return {std::move(__first), false};
3505 
3506 	auto __i = __first;
3507 	++__i;
3508 	if (__i == __last)
3509 	  return {std::move(__i), false};
3510 
3511 	auto __lasti = ranges::next(__first, __last);
3512 	__i = __lasti;
3513 	--__i;
3514 
3515 	for (;;)
3516 	  {
3517 	    auto __ii = __i;
3518 	    --__i;
3519 	    if (std::__invoke(__comp,
3520 			      std::__invoke(__proj, *__ii),
3521 			      std::__invoke(__proj, *__i)))
3522 	      {
3523 		auto __j = __lasti;
3524 		while (!(bool)std::__invoke(__comp,
3525 					    std::__invoke(__proj, *--__j),
3526 					    std::__invoke(__proj, *__i)))
3527 		  ;
3528 		ranges::iter_swap(__i, __j);
3529 		ranges::reverse(__ii, __last);
3530 		return {std::move(__lasti), true};
3531 	      }
3532 	    if (__i == __first)
3533 	      {
3534 		ranges::reverse(__first, __last);
3535 		return {std::move(__lasti), false};
3536 	      }
3537 	  }
3538       }
3539 
3540     template<bidirectional_range _Range, typename _Comp = ranges::less,
3541 	     typename _Proj = identity>
3542       requires sortable<iterator_t<_Range>, _Comp, _Proj>
3543       constexpr prev_permutation_result<borrowed_iterator_t<_Range>>
3544       operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
3545       {
3546 	return (*this)(ranges::begin(__r), ranges::end(__r),
3547 		       std::move(__comp), std::move(__proj));
3548       }
3549   };
3550 
3551   inline constexpr __prev_permutation_fn prev_permutation{};
3552 
3553 } // namespace ranges
3554 
3555 #define __cpp_lib_shift 201806L
3556   template<typename _ForwardIterator>
3557     constexpr _ForwardIterator
3558     shift_left(_ForwardIterator __first, _ForwardIterator __last,
3559 	       typename iterator_traits<_ForwardIterator>::difference_type __n)
3560     {
3561       __glibcxx_assert(__n >= 0);
3562       if (__n == 0)
3563 	return __last;
3564 
3565       auto __mid = ranges::next(__first, __n, __last);
3566       if (__mid == __last)
3567 	return __first;
3568       return std::move(std::move(__mid), std::move(__last), std::move(__first));
3569     }
3570 
3571   template<typename _ForwardIterator>
3572     constexpr _ForwardIterator
3573     shift_right(_ForwardIterator __first, _ForwardIterator __last,
3574 		typename iterator_traits<_ForwardIterator>::difference_type __n)
3575     {
3576       __glibcxx_assert(__n >= 0);
3577       if (__n == 0)
3578 	return __first;
3579 
3580       using _Cat
3581 	= typename iterator_traits<_ForwardIterator>::iterator_category;
3582       if constexpr (derived_from<_Cat, bidirectional_iterator_tag>)
3583 	{
3584 	  auto __mid = ranges::next(__last, -__n, __first);
3585 	  if (__mid == __first)
3586 	    return __last;
3587 
3588 	  return std::move_backward(std::move(__first), std::move(__mid),
3589 				    std::move(__last));
3590 	}
3591       else
3592 	{
3593 	  auto __result = ranges::next(__first, __n, __last);
3594 	  if (__result == __last)
3595 	    return __last;
3596 
3597 	  auto __dest_head = __first, __dest_tail = __result;
3598 	  while (__dest_head != __result)
3599 	    {
3600 	      if (__dest_tail == __last)
3601 		{
3602 		  // If we get here, then we must have
3603 		  //     2*n >= distance(__first, __last)
3604 		  // i.e. we are shifting out at least half of the range.  In
3605 		  // this case we can safely perform the shift with a single
3606 		  // move.
3607 		  std::move(std::move(__first), std::move(__dest_head), __result);
3608 		  return __result;
3609 		}
3610 	      ++__dest_head;
3611 	      ++__dest_tail;
3612 	    }
3613 
3614 	  for (;;)
3615 	    {
3616 	      // At the start of each iteration of this outer loop, the range
3617 	      // [__first, __result) contains those elements that after shifting
3618 	      // the whole range right by __n, should end up in
3619 	      // [__dest_head, __dest_tail) in order.
3620 
3621 	      // The below inner loop swaps the elements of [__first, __result)
3622 	      // and [__dest_head, __dest_tail), while simultaneously shifting
3623 	      // the latter range by __n.
3624 	      auto __cursor = __first;
3625 	      while (__cursor != __result)
3626 		{
3627 		  if (__dest_tail == __last)
3628 		    {
3629 		      // At this point the ranges [__first, result) and
3630 		      // [__dest_head, dest_tail) are disjoint, so we can safely
3631 		      // move the remaining elements.
3632 		      __dest_head = std::move(__cursor, __result,
3633 					      std::move(__dest_head));
3634 		      std::move(std::move(__first), std::move(__cursor),
3635 				std::move(__dest_head));
3636 		      return __result;
3637 		    }
3638 		  std::iter_swap(__cursor, __dest_head);
3639 		  ++__dest_head;
3640 		  ++__dest_tail;
3641 		  ++__cursor;
3642 		}
3643 	    }
3644 	}
3645     }
3646 
3647 _GLIBCXX_END_NAMESPACE_VERSION
3648 } // namespace std
3649 #endif // concepts
3650 #endif // C++20
3651 #endif // _RANGES_ALGO_H
3652