Skip to content
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

Extend range of min max optimization #2825

Merged
merged 7 commits into from Jul 1, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions stl/inc/algorithm
Expand Up @@ -9442,6 +9442,22 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>);

#if _USE_STD_VECTOR_ALGORITHMS
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> //
&& sized_sentinel_for<_Se, _It>) {
if (!_STD is_constant_evaluated()) {
const auto _First_ptr = _STD to_address(_First);
const auto _Last_ptr = _First_ptr + (_Last - _First);
const auto _Result = __std_max_element(_First_ptr, _Last_ptr);
if constexpr (is_pointer_v<_It>) {
return _Result;
} else {
return _First + (_Result - _First_ptr);
}
}
}
#endif // _USE_STD_VECTOR_ALGORITHMS

auto _Found = _First;
if (_First == _Last) {
return _Found;
Expand Down Expand Up @@ -9547,6 +9563,22 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>);

#if _USE_STD_VECTOR_ALGORITHMS
if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> //
&& sized_sentinel_for<_Se, _It>) {
if (!_STD is_constant_evaluated()) {
const auto _First_ptr = _STD to_address(_First);
const auto _Last_ptr = _First_ptr + (_Last - _First);
const auto _Result = __std_min_element(_First_ptr, _Last_ptr);
if constexpr (is_pointer_v<_It>) {
return _Result;
} else {
return _First + (_Result - _First_ptr);
}
}
}
#endif // _USE_STD_VECTOR_ALGORITHMS

auto _Found = _First;
if (_First == _Last) {
return _Found;
Expand Down Expand Up @@ -9686,6 +9718,22 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>);

#if _USE_STD_VECTOR_ALGORITHMS
if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> //
&& sized_sentinel_for<_Se, _It>) {
if (!_STD is_constant_evaluated()) {
const auto _First_ptr = _STD to_address(_First);
const auto _Last_ptr = _First_ptr + (_Last - _First);
const auto _Result = __std_minmax_element(_First_ptr, _Last_ptr);
if constexpr (is_pointer_v<_It>) {
return {_Result.first, _Result.second};
} else {
return {_First + (_Result.first - _First_ptr), _First + (_Result.second - _First_ptr)};
}
}
}
#endif // _USE_STD_VECTOR_ALGORITHMS

min_max_result<_It> _Found{_First, _First};

if (_First == _Last) {
Expand Down
22 changes: 22 additions & 0 deletions tests/std/tests/VSO_0000000_vector_algorithms/test.cpp
Expand Up @@ -15,6 +15,10 @@
#include <type_traits>
#include <vector>

#ifdef __cpp_lib_concepts
#include <ranges>
#endif

using namespace std;

#pragma warning(disable : 4984) // 'if constexpr' is a C++17 language extension
Expand Down Expand Up @@ -194,6 +198,24 @@ void test_case_min_max_element(const vector<T>& input) {
assert(expected_min == actual_min);
assert(expected_max == actual_max);
assert(expected_minmax == actual_minmax);
#ifdef __cpp_lib_concepts
using ranges::views::take;

auto actual_min_range = ranges::min_element(input);
auto actual_max_range = ranges::max_element(input);
auto actual_minmax_range = ranges::minmax_element(input);
auto actual_min_sized_range = ranges::min_element(take(input, static_cast<ptrdiff_t>(input.size())));
auto actual_max_sized_range = ranges::max_element(take(input, static_cast<ptrdiff_t>(input.size())));
auto actual_minmax_sized_range = ranges::minmax_element(take(input, static_cast<ptrdiff_t>(input.size())));
assert(expected_min == actual_min_range);
assert(expected_max == actual_max_range);
assert(expected_minmax.first == actual_minmax_range.min);
assert(expected_minmax.second == actual_minmax_range.max);
assert(expected_min == actual_min_sized_range);
assert(expected_max == actual_max_sized_range);
assert(expected_minmax.first == actual_minmax_sized_range.min);
assert(expected_minmax.second == actual_minmax_sized_range.max);
#endif // __cpp_lib_concepts
}

template <class T>
Expand Down