Skip to content

Commit

Permalink
[libc++][ranges] implement std::ranges::unique{_copy}
Browse files Browse the repository at this point in the history
implement `std::ranges::unique` and `std::ranges::unique_copy`

Differential Revision: https://reviews.llvm.org/D130404
  • Loading branch information
huixie90 committed Jul 29, 2022
1 parent bf37148 commit 72f57e3
Show file tree
Hide file tree
Showing 19 changed files with 889 additions and 174 deletions.
4 changes: 2 additions & 2 deletions libcxx/docs/Status/RangesAlgorithms.csv
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Write,swap_ranges,Nikolas Klauser,`D116303 <https://llvm.org/D116303>`_,✅
Write,reverse_copy,Nikolas Klauser,`D127211 <https://llvm.org/D127211>`_,✅
Write,rotate_copy,Nikolas Klauser,`D127211 <https://llvm.org/D127211>`_,✅
Write,sample,Not assigned,n/a,Not started
Write,unique_copy,Not assigned,n/a,Not started
Write,unique_copy,Hui Xie,`D130404 <https://llvm.org/D130404>`,✅
Write,partition_copy,Konstantin Varlamov,`D130070 <https://llvm.org/D130070>`_,✅
Write,partial_sort_copy,Konstantin Varlamov,n/a,In progress
Merge,merge,Hui Xie,`D128611 <https://llvm.org/D128611>`_,✅
Expand All @@ -70,7 +70,7 @@ Permutation,remove_if,Nikolas Klauser,`D128618 <https://llvm.org/D128618>`_,✅
Permutation,reverse,Nikolas Klauser,`D125752 <https://llvm.org/D125752>`_,✅
Permutation,rotate,Nikolas Klauser,`D124122 <https://llvm.org/D124122>`_,Under review
Permutation,shuffle,Konstantin Varlamov,`D130321 <https://llvm.org/D130321>`_,✅
Permutation,unique,Not assigned,n/a,Not started
Permutation,unique,Hui Xie,`D130404 <https://llvm.org/D130404>`,✅
Permutation,partition,Konstantin Varlamov,`D129624 <https://llvm.org/D129624>`_,✅
Permutation,stable_partition,Konstantin Varlamov,`D129624 <https://llvm.org/D129624>`_,✅
Permutation,sort,Konstantin Varlamov,`D127557 <https://llvm.org/D127557>`_,✅
Expand Down
32 changes: 20 additions & 12 deletions libcxx/include/__algorithm/adjacent_find.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,42 @@
#define _LIBCPP___ALGORITHM_ADJACENT_FIND_H

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

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

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Iter, class _Sent, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter
__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
if (__first == __last)
return __first;
_Iter __i = __first;
while (++__i != __last) {
if (__pred(*__first, *__i))
return __first;
__first = __i;
}
return __i;
}

template <class _ForwardIterator, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
if (__first != __last) {
_ForwardIterator __i = __first;
while (++__i != __last) {
if (__pred(*__first, *__i))
return __first;
__first = __i;
}
}
return __last;
return std::__adjacent_find(std::move(__first), std::move(__last), __pred);
}

template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last) {
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
return _VSTD::adjacent_find(__first, __last, __equal_to<__v>());
return std::adjacent_find(std::move(__first), std::move(__last), __equal_to<__v>());
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/__algorithm/iterator_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <__iterator/iter_swap.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
#include <__iterator/readable_traits.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/move.h>
Expand All @@ -35,6 +36,10 @@ struct _RangeAlgPolicy {};

template <>
struct _IterOps<_RangeAlgPolicy> {

template <class _Iter>
using __value_type = iter_value_t<_Iter>;

static constexpr auto advance = ranges::advance;
static constexpr auto distance = ranges::distance;
static constexpr auto __iter_move = ranges::iter_move;
Expand All @@ -50,6 +55,9 @@ struct _ClassicAlgPolicy {};
template <>
struct _IterOps<_ClassicAlgPolicy> {

template <class _Iter>
using __value_type = typename iterator_traits<_Iter>::value_type;

// advance
template <class _Iter, class _Distance>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
Expand Down
46 changes: 25 additions & 21 deletions libcxx/include/__algorithm/ranges_unique.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H

#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique.h>
#include <__config>
Expand Down Expand Up @@ -37,28 +38,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __unique {

struct __fn {
struct __fn {
template <
permutable _Iter,
sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__unique<_RangeAlgPolicy>(
std::move(__first), std::move(__last), ranges::__make_projected_comp(__comp, __proj));
return {std::move(__ret.first), std::move(__ret.second)};
}

template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
_LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__first; (void)__last; (void)__comp; (void)__proj;
return {};
}

template <forward_range _Range, class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
_LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__range; (void)__comp; (void)__proj;
return {};
}

};
template <
forward_range _Range,
class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires permutable<iterator_t<_Range>>
_LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__unique<_RangeAlgPolicy>(
ranges::begin(__range), ranges::end(__range), ranges::__make_projected_comp(__comp, __proj));
return {std::move(__ret.first), std::move(__ret.second)};
}
};

} // namespace __unique

Expand Down
73 changes: 50 additions & 23 deletions libcxx/include/__algorithm/ranges_unique_copy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H

#include <__algorithm/in_out_result.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique_copy.h>
#include <__concepts/same_as.h>
Expand All @@ -19,8 +20,8 @@
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/readable_traits.h>
#include <__iterator/projected.h>
#include <__iterator/readable_traits.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
Expand All @@ -42,42 +43,68 @@ using unique_copy_result = in_out_result<_InIter, _OutIter>;

namespace __unique_copy {

template <class _InIter, class _OutIter>
concept __can_reread_from_output = (input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>);

struct __fn {
template <class _InIter, class _OutIter>
static consteval auto __get_algo_tag() {
if constexpr (forward_iterator<_InIter>) {
return __unique_copy_tags::__reread_from_input_tag{};
} else if constexpr (__can_reread_from_output<_InIter, _OutIter>) {
return __unique_copy_tags::__reread_from_output_tag{};
} else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) {
return __unique_copy_tags::__read_from_tmp_value_tag{};
}
}

template <class _InIter, class _OutIter>
using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>());

template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter, class _Proj = identity,
template <input_iterator _InIter,
sentinel_for<_InIter> _Sent,
weakly_incrementable _OutIter,
class _Proj = identity,
indirect_equivalence_relation<projected<_InIter, _Proj>> _Comp = ranges::equal_to>
requires indirectly_copyable<_InIter, _OutIter> &&
(forward_iterator<_InIter> ||
(input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<_InIter, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr
unique_copy_result<_InIter, _OutIter>
requires indirectly_copyable<_InIter, _OutIter> &&
(forward_iterator<_InIter> ||
(input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<_InIter, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter>
operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__first; (void)__last; (void)__result; (void)__comp; (void)__proj;
return {};
auto __ret = std::__unique_copy<_RangeAlgPolicy>(
std::move(__first),
std::move(__last),
std::move(__result),
__make_projected_comp(__comp, __proj),
__algo_tag_t<_InIter, _OutIter>());
return {std::move(__ret.first), std::move(__ret.second)};
}

template <input_range _Range, weakly_incrementable _OutIter, class _Proj = identity,
template <input_range _Range,
weakly_incrementable _OutIter,
class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
(forward_iterator<iterator_t<_Range>> ||
(input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr
unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
(forward_iterator<iterator_t<_Range>> ||
(input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
_LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
// TODO: implement
(void)__range; (void)__result; (void)__comp; (void)__proj;
return {};
auto __ret = std::__unique_copy<_RangeAlgPolicy>(
ranges::begin(__range),
ranges::end(__range),
std::move(__result),
__make_projected_comp(__comp, __proj),
__algo_tag_t<iterator_t<_Range>, _OutIter>());
return {std::move(__ret.first), std::move(__ret.second)};
}

};

} // namespace __unique_copy

inline namespace __cpo {
inline constexpr auto unique_copy = __unique_copy::__fn{};
inline constexpr auto unique_copy = __unique_copy::__fn{};
} // namespace __cpo
} // namespace ranges

Expand Down
48 changes: 26 additions & 22 deletions libcxx/include/__algorithm/unique.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

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

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -23,32 +25,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// unique

template <class _AlgPolicy, class _Iter, class _Sent, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 std::pair<_Iter, _Iter>
__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
__first = std::__adjacent_find(__first, __last, __pred);
if (__first != __last) {
// ... a a ? ...
// f i
_Iter __i = __first;
for (++__i; ++__i != __last;)
if (!__pred(*__first, *__i))
*++__first = _IterOps<_AlgPolicy>::__iter_move(__i);
++__first;
return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i));
}
return std::pair<_Iter, _Iter>(__first, __first);
}

template <class _ForwardIterator, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
{
__first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred);
if (__first != __last)
{
// ... a a ? ...
// f i
_ForwardIterator __i = __first;
for (++__i; ++__i != __last;)
if (!__pred(*__first, *__i))
*++__first = _VSTD::move(*__i);
++__first;
}
return __first;
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first;
}

template <class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last)
{
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
return _VSTD::unique(__first, __last, __equal_to<__v>());
_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last) {
typedef typename iterator_traits<_ForwardIterator>::value_type __v;
return std::unique(__first, __last, __equal_to<__v>());
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
Loading

0 comments on commit 72f57e3

Please sign in to comment.