Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
146 changes: 146 additions & 0 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -9133,6 +9133,79 @@ _CONSTEXPR20 bool next_permutation(_BidIt _First, _BidIt _Last) {
return _STD next_permutation(_First, _Last, less<>{});
}

#ifdef __cpp_lib_concepts
namespace ranges {
// ALIAS TEMPLATE next_permutation_result
template <class _In>
using next_permutation_result = in_found_result<_In>;

// VARIABLE ranges::next_permutation
class _Next_permutation_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <bidirectional_iterator _It, sentinel_for<_It> _Se, class _Pr = ranges::less, class _Pj = identity>
requires sortable<_It, _Pr, _Pj>
constexpr next_permutation_result<_It> operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_STD move(_First));
auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last));
_Seek_wrapped(_First, _ULast);
const bool _Found =
_Next_permutation_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
return {_STD move(_First), _Found};
}

// clang-format off
template <bidirectional_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
constexpr next_permutation_result<borrowed_iterator_t<_Rng>> operator()(
_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
auto _ULast = _Get_final_iterator_unwrapped(_Range);
const bool _Found = _Next_permutation_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
return {_Rewrap_iterator(_Range, _STD move(_ULast)), _Found};
}

private:
template <class _It, class _Pr, class _Pj>
_NODISCARD static constexpr bool _Next_permutation_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
_STL_INTERNAL_STATIC_ASSERT(bidirectional_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);

auto _Next = _Last;
if (_First == _Last || _First == --_Next) {
return false;
}

for (;;) { // find rightmost element smaller than successor
auto _Next1 = _Next;
if (_STD invoke(_Pred, _STD invoke(_Proj, *--_Next), _STD invoke(_Proj, *_Next1))) {
// swap with rightmost element that's smaller, flip suffix
auto _Mid = _Last;
do {
--_Mid;
} while (!_STD invoke(_Pred, _STD invoke(_Proj, *_Next), _STD invoke(_Proj, *_Mid)));

_RANGES iter_swap(_Next, _Mid);
_Reverse_common(_STD move(_Next1), _STD move(_Last));
return true;
}

if (_Next == _First) { // pure descending, flip all
_Reverse_common(_STD move(_First), _STD move(_Last));
return false;
}
}
}
};

inline constexpr _Next_permutation_fn next_permutation{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATE prev_permutation
template <class _BidIt, class _Pr>
_CONSTEXPR20 bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred) {
Expand Down Expand Up @@ -9171,6 +9244,79 @@ _CONSTEXPR20 bool prev_permutation(_BidIt _First, _BidIt _Last) {
return _STD prev_permutation(_First, _Last, less<>{});
}

#ifdef __cpp_lib_concepts
namespace ranges {
// ALIAS TEMPLATE prev_permutation_result
template <class _In>
using prev_permutation_result = in_found_result<_In>;

// VARIABLE ranges::prev_permutation
class _Prev_permutation_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <bidirectional_iterator _It, sentinel_for<_It> _Se, class _Pr = ranges::less, class _Pj = identity>
requires sortable<_It, _Pr, _Pj>
constexpr prev_permutation_result<_It> operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_STD move(_First));
auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last));
_Seek_wrapped(_First, _ULast);
const bool _Found =
_Prev_permutation_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
return {_STD move(_First), _Found};
}

// clang-format off
template <bidirectional_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
constexpr prev_permutation_result<borrowed_iterator_t<_Rng>> operator()(
_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
auto _ULast = _Get_final_iterator_unwrapped(_Range);
const bool _Found = _Prev_permutation_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
return {_Rewrap_iterator(_Range, _STD move(_ULast)), _Found};
}

private:
template <class _It, class _Pr, class _Pj>
_NODISCARD static constexpr bool _Prev_permutation_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
_STL_INTERNAL_STATIC_ASSERT(bidirectional_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);

auto _Next = _Last;
if (_First == _Last || _First == --_Next) {
return false;
}

for (;;) { // find rightmost element not smaller than successor
auto _Next1 = _Next;
if (_STD invoke(_Pred, _STD invoke(_Proj, *_Next1), _STD invoke(_Proj, *--_Next))) {
// swap with rightmost element that's not smaller, flip suffix
auto _Mid = _Last;
do {
--_Mid;
} while (!_STD invoke(_Pred, _STD invoke(_Proj, *_Mid), _STD invoke(_Proj, *_Next)));

_RANGES iter_swap(_Next, _Mid);
_Reverse_common(_STD move(_Next1), _STD move(_Last));
return true;
}

if (_Next == _First) { // pure ascending, flip all
_Reverse_common(_STD move(_First), _STD move(_Last));
return false;
}
}
}
};

inline constexpr _Prev_permutation_fn prev_permutation{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATES is_sorted AND is_sorted_until
template <class _FwdIt, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) {
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ tests\P0896R4_ranges_alg_none_of
tests\P0896R4_ranges_alg_partition
tests\P0896R4_ranges_alg_partition_copy
tests\P0896R4_ranges_alg_partition_point
tests\P0896R4_ranges_alg_permutations
tests\P0896R4_ranges_alg_remove
tests\P0896R4_ranges_alg_remove_copy
tests\P0896R4_ranges_alg_remove_copy_if
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_permutations/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_matrix.lst
Loading