1*1d1a191eSNikolas Klauser //===----------------------------------------------------------------------===//
2*1d1a191eSNikolas Klauser //
3*1d1a191eSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*1d1a191eSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5*1d1a191eSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*1d1a191eSNikolas Klauser //
7*1d1a191eSNikolas Klauser //===----------------------------------------------------------------------===//
8*1d1a191eSNikolas Klauser 
9*1d1a191eSNikolas Klauser #ifndef _LIBCPP___ALGORITHM_RANGES_REVERSE_H
10*1d1a191eSNikolas Klauser #define _LIBCPP___ALGORITHM_RANGES_REVERSE_H
11*1d1a191eSNikolas Klauser 
12*1d1a191eSNikolas Klauser #include <__config>
13*1d1a191eSNikolas Klauser #include <__iterator/concepts.h>
14*1d1a191eSNikolas Klauser #include <__iterator/iter_swap.h>
15*1d1a191eSNikolas Klauser #include <__iterator/next.h>
16*1d1a191eSNikolas Klauser #include <__iterator/permutable.h>
17*1d1a191eSNikolas Klauser #include <__ranges/access.h>
18*1d1a191eSNikolas Klauser #include <__ranges/concepts.h>
19*1d1a191eSNikolas Klauser #include <__ranges/dangling.h>
20*1d1a191eSNikolas Klauser 
21*1d1a191eSNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22*1d1a191eSNikolas Klauser #  pragma GCC system_header
23*1d1a191eSNikolas Klauser #endif
24*1d1a191eSNikolas Klauser 
25*1d1a191eSNikolas Klauser #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
26*1d1a191eSNikolas Klauser 
27*1d1a191eSNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
28*1d1a191eSNikolas Klauser 
29*1d1a191eSNikolas Klauser namespace ranges {
30*1d1a191eSNikolas Klauser namespace __reverse {
31*1d1a191eSNikolas Klauser struct __fn {
32*1d1a191eSNikolas Klauser 
33*1d1a191eSNikolas Klauser   template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent>
34*1d1a191eSNikolas Klauser     requires permutable<_Iter>
35*1d1a191eSNikolas Klauser   _LIBCPP_HIDE_FROM_ABI constexpr
operator__fn36*1d1a191eSNikolas Klauser   _Iter operator()(_Iter __first, _Sent __last) const {
37*1d1a191eSNikolas Klauser     if constexpr (random_access_iterator<_Iter>) {
38*1d1a191eSNikolas Klauser       if (__first == __last)
39*1d1a191eSNikolas Klauser         return __first;
40*1d1a191eSNikolas Klauser 
41*1d1a191eSNikolas Klauser       auto __end = ranges::next(__first, __last);
42*1d1a191eSNikolas Klauser       auto __ret = __end;
43*1d1a191eSNikolas Klauser 
44*1d1a191eSNikolas Klauser       while (__first < --__end) {
45*1d1a191eSNikolas Klauser         ranges::iter_swap(__first, __end);
46*1d1a191eSNikolas Klauser         ++__first;
47*1d1a191eSNikolas Klauser       }
48*1d1a191eSNikolas Klauser       return __ret;
49*1d1a191eSNikolas Klauser     } else {
50*1d1a191eSNikolas Klauser       auto __end = ranges::next(__first, __last);
51*1d1a191eSNikolas Klauser       auto __ret = __end;
52*1d1a191eSNikolas Klauser 
53*1d1a191eSNikolas Klauser       while (__first != __end) {
54*1d1a191eSNikolas Klauser         if (__first == --__end)
55*1d1a191eSNikolas Klauser           break;
56*1d1a191eSNikolas Klauser 
57*1d1a191eSNikolas Klauser         ranges::iter_swap(__first, __end);
58*1d1a191eSNikolas Klauser         ++__first;
59*1d1a191eSNikolas Klauser       }
60*1d1a191eSNikolas Klauser       return __ret;
61*1d1a191eSNikolas Klauser     }
62*1d1a191eSNikolas Klauser   }
63*1d1a191eSNikolas Klauser 
64*1d1a191eSNikolas Klauser   template <bidirectional_range _Range>
65*1d1a191eSNikolas Klauser     requires permutable<iterator_t<_Range>>
66*1d1a191eSNikolas Klauser   _LIBCPP_HIDE_FROM_ABI constexpr
operator__fn67*1d1a191eSNikolas Klauser   borrowed_iterator_t<_Range> operator()(_Range&& __range) const {
68*1d1a191eSNikolas Klauser     return (*this)(ranges::begin(__range), ranges::end(__range));
69*1d1a191eSNikolas Klauser   }
70*1d1a191eSNikolas Klauser 
71*1d1a191eSNikolas Klauser };
72*1d1a191eSNikolas Klauser } // namespace __reverse
73*1d1a191eSNikolas Klauser 
74*1d1a191eSNikolas Klauser inline namespace __cpo {
75*1d1a191eSNikolas Klauser   inline constexpr auto reverse = __reverse::__fn{};
76*1d1a191eSNikolas Klauser } // namespace __cpo
77*1d1a191eSNikolas Klauser } // namespace ranges
78*1d1a191eSNikolas Klauser 
79*1d1a191eSNikolas Klauser _LIBCPP_END_NAMESPACE_STD
80*1d1a191eSNikolas Klauser 
81*1d1a191eSNikolas Klauser #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
82*1d1a191eSNikolas Klauser 
83*1d1a191eSNikolas Klauser #endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_H
84