Skip to content

[libc++][ranges] implement ranges::shift_left #83231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e0800f1
[libc++][ranges] implement ranges::shift_left
Feb 28, 2024
68a8635
[libc++][ranges] format code with 'clang-format'
Feb 28, 2024
ade1707
[libc++][ranges] check '_LIBCPP_STD_VER' in 'algorithm.inc'
Feb 28, 2024
c847929
[libc++][ranges] add missing headers to 'shift_left.h' and 'ranges_sh…
Feb 28, 2024
40691ad
[libc++][ranges] add missing headers to 'shift_left.h'
Feb 28, 2024
4de1787
[libc++][ranges] add missing constraints to 'ranges_shift_left.h'
Feb 28, 2024
02a20d9
[libc++][ranges] format code with 'clang-format'
Feb 28, 2024
9bd0eac
[libc++][ranges] add missing headers to 'ranges_shift_left.h'
Feb 29, 2024
7747973
[libc++][ranges] implement 'ranges.shift_left.pass.cpp' to test 'rang…
Feb 29, 2024
aa1f598
[libc++][ranges] update the implementation status of 'P2440R1'
Feb 29, 2024
a68eb02
[libc++][ranges] attempt to reduce the steps required for 'constexpr'…
Feb 29, 2024
020a097
[libc++][ranges] fix an out-of-bounds access in 'ranges.shift_left.pa…
Feb 29, 2024
e79f643
[libc++][ranges] refactor '__shift_left' to avoid redundant iteration
Mar 4, 2024
357f4eb
[libc++][ranges] refactor 'ranges::shift_left'
Mar 4, 2024
c2fc0dc
[libc++][ranges] check the precondition in '__shift_left'
Mar 5, 2024
e2aa538
[libc++][ranges] refactor 'ranges.shift_left.pass.cpp'
Mar 5, 2024
424c31b
[libc++][ranges] merge branch 'main'
Mar 5, 2024
7cde586
[libc++][ranges] add missing headers to 'shift_left.h'
Mar 6, 2024
ead91b5
[libc++][ranges] add benchmark for 'ranges::shift_left'
Mar 6, 2024
e1360e0
[libc++][ranges] add benchmark for 'ranges::shift_left'
Mar 6, 2024
956b915
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
be2162d
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
f61bc69
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
219655c
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
cdf0c94
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
ac2e129
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
20b1cce
[libc++][ranges] implement 'ranges::shift_left'
Dec 24, 2024
dfeaf68
[libc++][ranges] implement 'ranges::shift_left'
Dec 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"`P2255R2 <https://wg21.link/P2255R2>`__","LWG","A type trait to detect reference binding to temporary","February 2022","",""
"`P2273R3 <https://wg21.link/P2273R3>`__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0"
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","|In progress|","","|ranges|"
"`P2441R2 <https://wg21.link/P2441R2>`__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|"
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"
"`P2443R1 <https://wg21.link/P2443R1>`__","LWG","``views::chunk_by``","February 2022","|Complete|","18.0","|ranges|"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/RangesAlgorithms.csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ C++23,`find_last_if <https://wg21.link/P1223R5>`_,Unassigned,No patch yet,Not st
C++23,`find_last_if_not <https://wg21.link/P1223R5>`_,Unassigned,No patch yet,Not started
C++23,`starts_with <https://wg21.link/P1659R3>`_,Zijun Zhao,`D150735 <https://llvm.org/D150735>`_,Complete
C++23,`ends_with <https://wg21.link/P1659R3>`_,Zijun Zhao, `D150831 <https://llvm.org/D150831>`_,Complete
C++23,`shift_left <https://wg21.link/p2440r1>`_,Unassigned,No patch yet,Not started
C++23,`shift_left <https://wg21.link/p2440r1>`_,Xiaoyang Liu,`83231 <https://github.com/llvm/llvm-project/pull/83231>`,✅
C++23,`shift_right <https://wg21.link/p2440r1>`_,Unassigned,No patch yet,Not started
C++23,`iota (algorithm) <https://wg21.link/p2440r1>`_,Unassigned,No patch yet,Not started
C++23,`fold <https://wg21.link/p2322r5>`_,Unassigned,No patch yet,Not started
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ set(files
__algorithm/ranges_set_intersection.h
__algorithm/ranges_set_symmetric_difference.h
__algorithm/ranges_set_union.h
__algorithm/ranges_shift_left.h
__algorithm/ranges_shuffle.h
__algorithm/ranges_sort.h
__algorithm/ranges_sort_heap.h
Expand Down
73 changes: 73 additions & 0 deletions libcxx/include/__algorithm/ranges_shift_left.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___ALGORITHM_RANGES_SHIFT_LEFT_H
#define _LIBCPP___ALGORITHM_RANGES_SHIFT_LEFT_H

#include <__algorithm/iterator_operations.h>
#include <__algorithm/shift_left.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
#include <__iterator/permutable.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/subrange.h>
#include <__utility/move.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#if _LIBCPP_STD_VER >= 23

_LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {
namespace __shift_left {

struct __fn {
template <class _Iter, class _Sent>
_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> static __shift_left_impl(
_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) {
auto __ret = std::__shift_left<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__n));
return {std::move(__ret.first), std::move(__ret.second)};
}

template <permutable _Iter, sentinel_for<_Iter> _Sent>
_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const {
return __shift_left_impl(std::move(__first), std::move(__last), std::move(__n));
}

template <forward_range _Range>
requires permutable<iterator_t<_Range>>
_LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __range, range_difference_t<_Range> __n) const {
return __shift_left_impl(ranges::begin(__range), ranges::end(__range), std::move(__n));
}
};

} // namespace __shift_left

inline namespace __cpo {
inline constexpr auto shift_left = __shift_left::__fn{};
} // namespace __cpo
} // namespace ranges

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP_STD_VER >= 23

_LIBCPP_POP_MACROS

#endif // _LIBCPP___ALGORITHM_RANGES_SHIFT_LEFT_H
38 changes: 25 additions & 13 deletions libcxx/include/__algorithm/shift_left.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
#ifndef _LIBCPP___ALGORITHM_SHIFT_LEFT_H
#define _LIBCPP___ALGORITHM_SHIFT_LEFT_H

#include <__algorithm/iterator_operations.h>
#include <__algorithm/move.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__utility/pair.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -24,30 +26,40 @@ _LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20

template <class _ForwardIterator>
inline _LIBCPP_HIDE_FROM_ABI constexpr _ForwardIterator
shift_left(_ForwardIterator __first,
_ForwardIterator __last,
typename iterator_traits<_ForwardIterator>::difference_type __n) {
template <class _AlgPolicy, class _Iter, class _Sent>
inline _LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter, _Iter>
__shift_left(_Iter __first, _Sent __last, typename iterator_traits<_Iter>::difference_type __n) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__shift_left(_Iter __first, _Sent __last, typename iterator_traits<_Iter>::difference_type __n) {
__shift_left(_Iter __first, _Sent __last, _IterOps<_AlgPolicy>::template __difference_type<_Iter> __n) {

Please add a test!

Copy link
Member Author

@xiaoyang-sde xiaoyang-sde Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Could you please provide more details about the tests I should consider adding?

_Iter __end = _IterOps<_AlgPolicy>::next(__first, __last);

if (__n == 0) {
return __last;
return {std::move(__first), std::move(__end)};
}

_ForwardIterator __m = __first;
if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) {
if (__n >= __last - __first) {
return __first;
_Iter __m = __first;
if constexpr (__has_random_access_iterator_category<_Iter>::value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check _IterOps<_AlgPolicy>::template __iterator_category. We should also make sure [__first, __last) is a sized range to avoid having to iterate linearly through the range twice. Could you add a benchmark for these cases too?

Copy link
Member Author

@xiaoyang-sde xiaoyang-sde Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! I refactored this function.

if (__n >= __end - __first) {
return {std::move(__first), std::move(__first)};
}
__m += __n;
} else {
for (; __n > 0; --__n) {
if (__m == __last) {
return __first;
if (__m == __end) {
return {std::move(__first), std::move(__first)};
}
++__m;
}
}
return std::move(__m, __last, __first);

_Iter __result = std::__move<_AlgPolicy>(__m, __end, __first).second;
return {std::move(__first), std::move(__result)};
}

template <class _ForwardIterator>
inline _LIBCPP_HIDE_FROM_ABI constexpr _ForwardIterator
shift_left(_ForwardIterator __first,
_ForwardIterator __last,
typename iterator_traits<_ForwardIterator>::difference_type __n) {
return std::__shift_left<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __n).second;
}

#endif // _LIBCPP_STD_VER >= 20
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,13 @@ namespace ranges {
uniform_random_bit_generator<remove_reference_t<Gen>>
O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); // since C++20

template<permutable I, sentinel_for<I> S>
constexpr subrange<I> ranges::shift_left(I first, S last, iter_difference_t<I> n); // since C++23

template<forward_range R>
requires permutable<iterator_t<R>>
constexpr borrowed_subrange_t<R> ranges::shift_left(R&& r, range_difference_t<R> n) // since C++23

template<random_access_iterator I, sentinel_for<I> S, class Gen>
requires permutable<I> &&
uniform_random_bit_generator<remove_reference_t<Gen>>
Expand Down Expand Up @@ -1960,6 +1967,7 @@ template <class BidirectionalIterator, class Compare>
#include <__algorithm/ranges_set_intersection.h>
#include <__algorithm/ranges_set_symmetric_difference.h>
#include <__algorithm/ranges_set_union.h>
#include <__algorithm/ranges_shift_left.h>
#include <__algorithm/ranges_shuffle.h>
#include <__algorithm/ranges_sort.h>
#include <__algorithm/ranges_sort_heap.h>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/libcxx.imp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@
{ include: [ "<__algorithm/ranges_set_intersection.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_set_symmetric_difference.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_set_union.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_shift_left.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_shuffle.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_sort.h>", "private", "<algorithm>", "public" ] },
{ include: [ "<__algorithm/ranges_sort_heap.h>", "private", "<algorithm>", "public" ] },
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap.in
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,7 @@ module std_private_algorithm_ranges_set_union [system
export std_private_algorithm_in_in_out_result
export std_private_functional_ranges_operations
}
module std_private_algorithm_ranges_shift_left [system] { header "__algorithm/ranges_shift_left.h" }
module std_private_algorithm_ranges_shuffle [system] { header "__algorithm/ranges_shuffle.h" }
module std_private_algorithm_ranges_sort [system] {
header "__algorithm/ranges_sort.h"
Expand Down
4 changes: 3 additions & 1 deletion libcxx/modules/std/algorithm.inc
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,11 @@ export namespace std {
// [alg.shift], shift
using std::shift_left;

#if _LIBCPP_STD_VER >= 23
namespace ranges {
// using std::ranges::shift_left;
using std::ranges::shift_left;
}
#endif // _LIBCPP_STD_VER >= 23

using std::shift_right;

Expand Down
Loading