diff --git a/stl/inc/algorithm b/stl/inc/algorithm index e4214cb42ef..6d7e76ed4af 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -720,7 +720,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, if constexpr (is_pointer_v) { _ULast = _Result; } else { - _ULast = _UFirst + (_Result - _First_ptr); + _ULast = _UFirst + static_cast<_Iter_diff_t>(_Result - _First_ptr); } _STD _Seek_wrapped(_Last, _ULast); @@ -794,7 +794,7 @@ namespace ranges { } const auto _First_ptr = _STD _To_address(_First); - const auto _Last_ptr = _First_ptr + (_Last - _First); + const auto _Last_ptr = _First_ptr + static_cast(_Last - _First); return static_cast>(_STD _Count_vectorized(_First_ptr, _Last_ptr, _Val)); } @@ -2328,7 +2328,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays if constexpr (is_pointer_v) { _UFirst1 = _Ptr_res1; } else { - _UFirst1 += _Ptr_res1 - _Ptr1; + _UFirst1 += static_cast<_Iter_diff_t>(_Ptr_res1 - _Ptr1); } _STD _Seek_wrapped(_Last1, _UFirst1); @@ -2440,7 +2440,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( if constexpr (is_pointer_v) { _UFirst = _Result; } else { - _UFirst += _Result - _First_ptr; + _UFirst += static_cast<_Iter_diff_t>(_Result - _First_ptr); } _STD _Seek_wrapped(_Last, _UFirst); @@ -2630,7 +2630,7 @@ namespace ranges { } const auto _First_ptr = _STD _To_address(_First); - const auto _Last_ptr = _First_ptr + _Dist; + const auto _Last_ptr = _First_ptr + static_cast(_Dist); const auto _Result = _STD _Search_n_vectorized(_First_ptr, _Last_ptr, static_cast(_Count), _Val); @@ -2642,7 +2642,7 @@ namespace ranges { } } else { if (_Result != _Last_ptr) { - _First += _Result - _First_ptr; + _First += static_cast>(_Result - _First_ptr); return {_First, _First + _Count}; } else { _First += _Dist; @@ -3322,13 +3322,13 @@ namespace ranges { } const auto _First_ptr = _STD _To_address(_First); - const auto _Last_ptr = _First_ptr + _Count; + const auto _Last_ptr = _First_ptr + static_cast(_Count); const auto _Result = _STD _Find_last_vectorized(_First_ptr, _Last_ptr, _Value); if constexpr (is_pointer_v<_It>) { return {_Result, _Last_ptr}; } else { - return {_First + (_Result - _First_ptr), _First + _Count}; + return {_First + static_cast>(_Result - _First_ptr), _First + _Count}; } } } @@ -3483,7 +3483,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( if constexpr (is_pointer_v) { _UFirst1 = _Ptr_res1; } else { - _UFirst1 += _Ptr_res1 - _Ptr1; + _UFirst1 += static_cast<_Iter_diff_t>(_Ptr_res1 - _Ptr1); } _STD _Seek_wrapped(_First1, _UFirst1); @@ -3601,7 +3601,7 @@ namespace ranges { if (!_STD is_constant_evaluated()) { const auto _Ptr1 = _STD to_address(_First1); const auto _Ptr2 = _STD to_address(_First2); - const auto _Ptr_last1 = _Ptr1 + _Count1; + const auto _Ptr_last1 = _Ptr1 + static_cast(_Count1); const auto _Ptr_res1 = _STD _Find_end_vectorized(_Ptr1, _Ptr_last1, _Ptr2, static_cast(_Count2)); @@ -3613,7 +3613,7 @@ namespace ranges { return {_Ptr_res1, _Ptr_res1}; } } else { - _First1 += _Ptr_res1 - _Ptr1; + _First1 += static_cast>(_Ptr_res1 - _Ptr1); if (_Ptr_res1 != _Ptr_last1) { return {_First1, _First1 + _Count2_as1}; } else { @@ -3805,7 +3805,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( if constexpr (is_pointer_v) { _UFirst1 = _Result; } else { - _UFirst1 += _Result - _First1_ptr; + _UFirst1 += static_cast<_Iter_diff_t>(_Result - _First1_ptr); } _STD _Seek_wrapped(_First1, _UFirst1); return _First1; @@ -3903,11 +3903,11 @@ namespace ranges { if constexpr (_Vector_alg_in_find_first_of_is_safe<_It1, _It2, _Pr> && sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated() && _Last1 - _First1 >= _Threshold_find_first_of) { - const auto _Count1 = _Last1 - _First1; + const auto _Count1 = static_cast(_Last1 - _First1); const auto _First1_ptr = _STD _To_address(_First1); const auto _Last1_ptr = _First1_ptr + _Count1; - const auto _Count2 = _Last2 - _First2; + const auto _Count2 = static_cast(_Last2 - _First2); const auto _First2_ptr = _STD _To_address(_First2); const auto _Last2_ptr = _First2_ptr + _Count2; @@ -3917,7 +3917,7 @@ namespace ranges { if constexpr (is_pointer_v<_It1>) { return _Result; } else { - return _First1 + (_Result - _First1_ptr); + return _First1 + static_cast>(_Result - _First1_ptr); } } } @@ -3974,17 +3974,18 @@ namespace ranges { (_STD min)(static_cast(_Last1 - _First1), static_cast(_Last2 - _First2)); const auto _Last1_addr = _First1_addr + _Count; ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); - return {_First1 + _Count, _First2 + _Count}; + return {_First1 + static_cast>(_Count), + _First2 + static_cast>(_Count)}; } else if constexpr (_Is_sized1) { const auto _Final1 = _RANGES next(_First1, _Last1); const auto _Last1_addr = _STD to_address(_Final1); ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); - return {_Final1, _First2 + (_Last1 - _First1)}; + return {_Final1, _First2 + static_cast>(_Last1 - _First1)}; } else if constexpr (_Is_sized2) { const auto _Final2 = _RANGES next(_First2, _Last2); const auto _Last2_addr = _STD to_address(_Final2); ::__std_swap_ranges_trivially_swappable_noalias(_First2_addr, _Last2_addr, _First1_addr); - return {_First1 + (_Last2 - _First2), _Final2}; + return {_First1 + static_cast>(_Last2 - _First2), _Final2}; } else { _STL_ASSERT(false, "Tried to swap_ranges with two unreachable sentinels"); } @@ -4343,7 +4344,7 @@ namespace ranges { if (_STD _Could_compare_equal_to_value_type<_It>(_Oldval)) { const auto _First_ptr = _STD to_address(_First); - const auto _Last_ptr = _First_ptr + _Count; + const auto _Last_ptr = _First_ptr + static_cast(_Count); _STD _Replace_vectorized(_First_ptr, _Last_ptr, _Oldval, _Newval); } @@ -4841,7 +4842,7 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _ if constexpr (is_pointer_v) { _UDest = _Result; } else { - _UDest += _Result - _Dest_ptr; + _UDest += static_cast<_Iter_diff_t>(_Result - _Dest_ptr); } _STD _Seek_wrapped(_Dest, _UDest); @@ -4959,7 +4960,7 @@ namespace ranges { if constexpr (is_pointer_v<_It>) { return {_Result, _Last_ptr}; } else { - return {_First + (_Result - _First_ptr), _First + _Size}; + return {_First + static_cast>(_Result - _First_ptr), _First + _Size}; } } } @@ -5094,7 +5095,8 @@ namespace ranges { if constexpr (is_pointer_v<_Out>) { return {_STD move(_End), _Result}; } else { - return {_STD move(_End), _STD move(_Output) + (_Result - _Dest_ptr)}; + return {_STD move(_End), + _STD move(_Output) + static_cast>(_Result - _Dest_ptr)}; } } } @@ -5190,7 +5192,7 @@ _NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _P if constexpr (is_pointer_v) { _UFirst = _Result; } else { - _UFirst += _Result - _First_ptr; + _UFirst += static_cast<_Iter_diff_t>(_Result - _First_ptr); } _STD _Seek_wrapped(_Last, _UFirst); @@ -5287,7 +5289,7 @@ namespace ranges { if constexpr (is_pointer_v<_It>) { return {_Result, _Last_ptr}; } else { - return {_First + (_Result - _First_ptr), _First + _Size}; + return {_First + static_cast>(_Result - _First_ptr), _First + _Size}; } } } @@ -5358,7 +5360,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr if constexpr (is_pointer_v) { _UDest = _Result; } else { - _UDest += _Result - _Dest_ptr; + _UDest += static_cast<_Iter_diff_t>(_Result - _Dest_ptr); } _STD _Seek_wrapped(_Dest, _UDest); @@ -5508,7 +5510,8 @@ namespace ranges { if constexpr (is_pointer_v<_It> && is_pointer_v<_Out>) { return {_Last_ptr, _Result}; } else { - return {_STD move(_First) + _Size, _STD move(_Output) + (_Result - _Output_ptr)}; + return {_STD move(_First) + _Size, + _STD move(_Output) + static_cast>(_Result - _Output_ptr)}; } } } @@ -10812,7 +10815,8 @@ constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _ if constexpr (is_pointer_v<_FwdIt>) { return _Result; } else { - return {_First + (_Result.first - _First_ptr), _First + (_Result.second - _First_ptr)}; + return {_First + static_cast<_Iter_diff_t<_FwdIt>>(_Result.first - _First_ptr), + _First + static_cast<_Iter_diff_t<_FwdIt>>(_Result.second - _First_ptr)}; } } } @@ -10934,12 +10938,13 @@ namespace ranges { && 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 _Last_ptr = _First_ptr + static_cast(_Last - _First); const auto _Result = _STD _Minmax_element_vectorized(_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)}; + return {_First + static_cast>(_Result.first - _First_ptr), + _First + static_cast>(_Result.second - _First_ptr)}; } } } @@ -11101,14 +11106,14 @@ namespace ranges { if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); const auto _Result = _STD _Minmax_vectorized(_First_ptr, _Last_ptr); return {static_cast<_Vty>(_Result._Min), static_cast<_Vty>(_Result._Max)}; } } else if constexpr (_Is_min_max_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); const auto _Result = _STD _Minmax_element_vectorized(_First_ptr, _Last_ptr); return {*static_cast(_Result.first), *static_cast(_Result.second)}; } diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 80041fc71bc..8e430d91755 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -2329,7 +2329,7 @@ _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _La if constexpr (is_pointer_v) { _UNext = _Result; } else { - _UNext += _Result - _First_ptr; + _UNext += static_cast<_Iter_diff_t>(_Result - _First_ptr); } _STD _Seek_wrapped(_First, _UNext); diff --git a/stl/inc/xutility b/stl/inc/xutility index 1cbbc5a817f..f3660728b5f 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4737,7 +4737,7 @@ _CONSTEXPR20 void _Verify_ranges_do_not_overlap(const _Iter1& _First1, const _Se } #endif // _HAS_CXX20 - const auto _Offset = _Last1 - _First1; + const auto _Offset = static_cast(_Last1 - _First1); const auto _Ptr1Offset = _Offset * sizeof(*_STD _To_address(_First1)); const auto _Ptr2Offset = _Offset * sizeof(*_STD _To_address(_First2)); // This cast to `cv char*` allows us to compare pointers to distinct types, @@ -5357,7 +5357,7 @@ _CONSTEXPR20 _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val } else if constexpr (_Fill_zero_memset_is_safe) { if (_STD _Is_all_bits_zero(_Val)) { _STD _Fill_zero_memset(_UDest, static_cast(_Count)); - _STD _Seek_wrapped(_Dest, _UDest + _Count); + _STD _Seek_wrapped(_Dest, _UDest + static_cast<_Iter_diff_t>(_Count)); return _Dest; } } @@ -6141,7 +6141,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c if constexpr (is_pointer_v<_InIt>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast<_Iter_diff_t<_InIt>>(_Result - _First_ptr); } #else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv if constexpr (sizeof(_Iter_value_t<_InIt>) <= 2) { @@ -6231,7 +6231,7 @@ namespace ranges { #if _USE_STD_VECTOR_ALGORITHMS if constexpr (_Is_sized) { // When _Is_sized && _Elements_are_1_byte, prefer this over memchr() for performance - const auto _Last_ptr = _First_ptr + (_Last - _First); + const auto _Last_ptr = _First_ptr + static_cast(_Last - _First); _Result = _STD _Find_vectorized(_First_ptr, _Last_ptr, _Val); } else #endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ @@ -6804,13 +6804,13 @@ namespace ranges { && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); - const auto _Last_ptr = _First_ptr + (_Last - _First); + const auto _Last_ptr = _First_ptr + static_cast(_Last - _First); const auto _Result = _STD _Adjacent_find_vectorized(_First_ptr, _Last_ptr); if constexpr (is_pointer_v<_It>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast>(_Result - _First_ptr); } } } @@ -6927,7 +6927,7 @@ namespace ranges { return {_Ptr_res1, _Ptr_res1}; } } else { - _First1 += _Ptr_res1 - _Ptr1; + _First1 += static_cast>(_Ptr_res1 - _Ptr1); if (_First1 != _Last1) { return {_First1, _First1 + static_cast>(_Count2)}; } else { @@ -7041,7 +7041,7 @@ constexpr _FwdIt _Max_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) if constexpr (is_pointer_v<_FwdIt>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast<_Iter_diff_t<_FwdIt>>(_Result - _First_ptr); } } } @@ -7102,12 +7102,12 @@ namespace ranges { && 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 _Last_ptr = _First_ptr + static_cast(_Last - _First); const auto _Result = _STD _Max_element_vectorized(_First_ptr, _Last_ptr); if constexpr (is_pointer_v<_It>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast>(_Result - _First_ptr); } } } @@ -7230,7 +7230,7 @@ namespace ranges { && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); return static_cast>(_STD _Max_vectorized(_First_ptr, _Last_ptr)); } } @@ -7265,7 +7265,7 @@ constexpr _FwdIt _Min_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) if constexpr (is_pointer_v<_FwdIt>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast<_Iter_diff_t<_FwdIt>>(_Result - _First_ptr); } } } @@ -7326,12 +7326,12 @@ namespace ranges { && 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 _Last_ptr = _First_ptr + static_cast(_Last - _First); const auto _Result = _STD _Min_element_vectorized(_First_ptr, _Last_ptr); if constexpr (is_pointer_v<_It>) { return _Result; } else { - return _First + (_Result - _First_ptr); + return _First + static_cast>(_Result - _First_ptr); } } } @@ -7448,7 +7448,7 @@ namespace ranges { && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); return static_cast>(_STD _Min_vectorized(_First_ptr, _Last_ptr)); } } diff --git a/tests/std/test.lst b/tests/std/test.lst index 7489fd82a95..32e116d37d3 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -262,6 +262,7 @@ tests\GH_005244_regex_escape_sequences tests\GH_005276_system_error_heap_use_after_free tests\GH_005315_destructor_tombstones tests\GH_005402_string_with_volatile_range +tests\GH_005421_vector_algorithms_integer_class_type_iterator tests\LWG2381_num_get_floating_point tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function diff --git a/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/env.lst b/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/env.lst new file mode 100644 index 00000000000..351a8293d9d --- /dev/null +++ b/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_20_matrix.lst diff --git a/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/test.cpp b/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/test.cpp new file mode 100644 index 00000000000..fcd796d73a1 --- /dev/null +++ b/tests/std/tests/GH_005421_vector_algorithms_integer_class_type_iterator/test.cpp @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include <__msvc_int128.hpp> +#include +#include +#include +#include +#include + +#include "range_algorithm_support.hpp" + +using namespace std; + +template +using picky_contiguous_iterator = test::redifference_iterator<_Signed128, T*>; + +static_assert(contiguous_iterator>); + +int main() { + const int arr[] = { + 200, 210, 220, 250, 240, 250, 250, 270, 280, 290, 300, 310, 320, 250, 340, 250, 250, 370, 380, 390}; + constexpr auto arr_size = size(arr); + + picky_contiguous_iterator arr_begin(begin(arr)); + picky_contiguous_iterator arr_end(end(arr)); + + assert(find(arr_begin, arr_end, 250) == arr_begin + _Signed128{3}); + assert(ranges::find(arr_begin, arr_end, 250) == arr_begin + _Signed128{3}); +#if _HAS_CXX23 + assert(begin(ranges::find_last(arr_begin, arr_end, 250)) == arr_begin + _Signed128{16}); +#endif + assert(search_n(arr_begin, arr_end, 2, 250) == arr_begin + _Signed128{5}); + assert(begin(ranges::search_n(arr_begin, arr_end, 2, 250)) == arr_begin + _Signed128{5}); + + { + const int needle[] = {100, 300, 500, 700, 900}; + picky_contiguous_iterator needle_begin(begin(needle)); + picky_contiguous_iterator needle_end(end(needle)); + + assert(find_first_of(arr_begin, arr_end, needle_begin, needle_end) == arr_begin + _Signed128{10}); + assert(ranges::find_first_of(arr_begin, arr_end, needle_begin, needle_end) == arr_begin + _Signed128{10}); + } + + assert(adjacent_find(arr_begin, arr_end) == arr_begin + _Signed128{5}); + assert(ranges::adjacent_find(arr_begin, arr_end) == arr_begin + _Signed128{5}); + + { + // As of 2025-05-09, 'search' and 'find_end' are manually vectorized for 8-bit and 16-bit elements only. + short short_arr[arr_size]; + picky_contiguous_iterator short_arr_begin(begin(short_arr)); + picky_contiguous_iterator short_arr_end(end(short_arr)); + + transform(arr_begin, arr_end, short_arr_begin, [](int v) { return static_cast(v); }); + + const short short_needle[] = {300, 310, 320}; + + picky_contiguous_iterator short_needle_begin(begin(short_needle)); + picky_contiguous_iterator short_needle_end(end(short_needle)); + + assert(search(short_arr_begin, short_arr_end, short_needle_begin, short_needle_end) + == short_arr_begin + _Signed128{10}); + assert(begin(ranges::search(short_arr_begin, short_arr_end, short_needle_begin, short_needle_end)) + == short_arr_begin + _Signed128{10}); + + assert(find_end(short_arr_begin, short_arr_end, short_needle_begin, short_needle_end) + == short_arr_begin + _Signed128{10}); + assert(begin(ranges::find_end(short_arr_begin, short_arr_end, short_needle_begin, short_needle_end)) + == short_arr_begin + _Signed128{10}); + } + + assert(count(arr_begin, arr_end, 250) == 6); + assert(ranges::count(arr_begin, arr_end, 250) == 6); + + { + const int arr_cmp[] = {200, 210, 220, 230, 240, 250}; + + picky_contiguous_iterator arr_cmp_begin(begin(arr_cmp)); + picky_contiguous_iterator arr_cmp_end(end(arr_cmp)); + + assert(!equal(arr_cmp_begin, arr_cmp_end, arr_begin)); + assert(!equal(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end)); + assert(!ranges::equal(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end)); + assert(mismatch(arr_cmp_begin, arr_cmp_end, arr_begin).first == arr_cmp_begin + _Signed128{3}); + assert(mismatch(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end).first == arr_cmp_begin + _Signed128{3}); + assert(ranges::mismatch(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end).in1 == arr_cmp_begin + _Signed128{3}); + + assert(lexicographical_compare(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end)); + assert(ranges::lexicographical_compare(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end)); + assert( + lexicographical_compare_three_way(arr_cmp_begin, arr_cmp_end, arr_begin, arr_end) == strong_ordering::less); + } + + assert(min_element(arr_begin, arr_end) == arr_begin); + assert(max_element(arr_begin, arr_end) == arr_end - _Signed128{1}); + assert(minmax_element(arr_begin, arr_end) == pair(arr_begin, arr_end - _Signed128{1})); + + assert(ranges::min_element(arr_begin, arr_end) == arr_begin); + assert(ranges::max_element(arr_begin, arr_end) == arr_end - _Signed128{1}); + assert(ranges::minmax_element(arr_begin, arr_end).max == arr_end - _Signed128{1}); + + assert(ranges::min(ranges::subrange(arr_begin, arr_end)) == 200); + assert(ranges::max(ranges::subrange(arr_begin, arr_end)) == 390); + assert(ranges::minmax(ranges::subrange(arr_begin, arr_end)).max == 390); + + { + // floating minmax is distinct codepath unless /fp:fast + float float_arr[arr_size]; + picky_contiguous_iterator float_arr_begin(begin(float_arr)); + picky_contiguous_iterator float_arr_end(end(float_arr)); + + transform(arr_begin, arr_end, float_arr_begin, [](int v) { return static_cast(v); }); + + assert(ranges::min(ranges::subrange(float_arr_begin, float_arr_end)) == 200.0); + assert(ranges::max(ranges::subrange(float_arr_begin, float_arr_end)) == 390.0); + assert(ranges::minmax(ranges::subrange(float_arr_begin, float_arr_end)).max == 390.0); + } + + assert(is_sorted_until(arr_begin, arr_end) == arr_begin + _Signed128{4}); + assert(ranges::is_sorted_until(arr_begin, arr_end) == arr_begin + _Signed128{4}); + + { + int arr_copy[arr_size]; + picky_contiguous_iterator arr_copy_begin(begin(arr_copy)); + picky_contiguous_iterator arr_copy_end(end(arr_copy)); + + copy(arr_begin, arr_end, arr_copy_begin); + assert(equal(arr_begin, arr_end, arr_copy_begin, arr_copy_end)); + fill(arr_copy_begin, arr_copy_end, 0); + assert(count(arr_copy_begin, arr_copy_end, 0) == arr_size); + + ranges::copy(arr_begin, arr_end, arr_copy_begin); + assert(ranges::equal(arr_begin, arr_end, arr_copy_begin, arr_copy_end)); + ranges::fill(arr_copy_begin, arr_copy_end, 0); + assert(ranges::count(arr_copy_begin, arr_copy_end, 0) == arr_size); + + copy_n(arr_begin, arr_size, arr_copy_begin); + assert(equal(arr_begin, arr_end, arr_copy_begin, arr_copy_end)); + fill_n(arr_copy_begin, arr_size, 0); + assert(count(arr_copy_begin, arr_copy_end, 0) == arr_size); + + ranges::copy_n(arr_begin, arr_size, arr_copy_begin); + assert(ranges::equal(arr_begin, arr_end, arr_copy_begin, arr_copy_end)); + ranges::fill_n(arr_copy_begin, arr_size, 0); + assert(ranges::count(arr_copy_begin, arr_copy_end, 0) == arr_size); + } + + { + int temp[arr_size]; + picky_contiguous_iterator temp_begin(begin(temp)); + picky_contiguous_iterator temp_end(end(temp)); + + { + const int remove_expected[] = {200, 210, 220, 240, 270, 280, 290, 300, 310, 320, 340, 370, 380, 390}; + + fill(temp_begin, temp_end, 0); + auto rem_copy_it = remove_copy(arr_begin, arr_end, temp_begin, 250); + assert(equal(temp_begin, rem_copy_it, begin(remove_expected), end(remove_expected))); + + copy(arr_begin, arr_end, temp_begin); + auto rem_it = remove(temp_begin, temp_end, 250); + assert(equal(temp_begin, rem_it, begin(remove_expected), end(remove_expected))); + + ranges::fill(temp_begin, temp_end, 0); + auto r_rem_copy_it = ranges::remove_copy(arr_begin, arr_end, temp_begin, 250); + assert(ranges::equal(temp_begin, r_rem_copy_it.out, begin(remove_expected), end(remove_expected))); + + ranges::copy(arr_begin, arr_end, temp_begin); + auto r_rem_it = ranges::remove(temp_begin, temp_end, 250); + assert(ranges::equal(temp_begin, begin(r_rem_it), begin(remove_expected), end(remove_expected))); + } + { + const int unique_expected[] = { + 200, 210, 220, 250, 240, 250, 270, 280, 290, 300, 310, 320, 250, 340, 250, 370, 380, 390}; + + fill(temp_begin, temp_end, 0); + auto un_copy_it = unique_copy(arr_begin, arr_end, temp_begin); + assert(equal(temp_begin, un_copy_it, begin(unique_expected), end(unique_expected))); + + copy(arr_begin, arr_end, temp_begin); + auto un_it = unique(temp_begin, temp_end); + assert(equal(temp_begin, un_it, begin(unique_expected), end(unique_expected))); + + ranges::fill(temp_begin, temp_end, 0); + auto r_un_copy_it = ranges::unique_copy(arr_begin, arr_end, temp_begin); + assert(ranges::equal(temp_begin, r_un_copy_it.out, begin(unique_expected), end(unique_expected))); + + ranges::copy(arr_begin, arr_end, temp_begin); + auto r_un_it = ranges::unique(temp_begin, temp_end); + assert(ranges::equal(temp_begin, begin(r_un_it), begin(unique_expected), end(unique_expected))); + } + { + const int reverse_expected[] = { + 390, 380, 370, 250, 250, 340, 250, 320, 310, 300, 290, 280, 270, 250, 250, 240, 250, 220, 210, 200}; + + reverse_copy(arr_begin, arr_end, temp_begin); + assert(equal(temp_begin, temp_end, begin(reverse_expected), end(reverse_expected))); + + copy(arr_begin, arr_end, temp_begin); + reverse(temp_begin, temp_end); + assert(equal(temp_begin, temp_end, begin(reverse_expected), end(reverse_expected))); + + ranges::reverse_copy(arr_begin, arr_end, temp_begin); + assert(ranges::equal(temp_begin, temp_end, begin(reverse_expected), end(reverse_expected))); + + ranges::copy(arr_begin, arr_end, temp_begin); + ranges::reverse(temp_begin, temp_end); + assert(ranges::equal(temp_begin, temp_end, begin(reverse_expected), end(reverse_expected))); + } + { + // Out of replace family, only replace for 32-bit and 64-bit elements is manually vectorized, + // replace_copy is auto vectorized (along with replace_copy_if) + const int replace_expected[] = { + 200, 210, 220, 333, 240, 333, 333, 270, 280, 290, 300, 310, 320, 333, 340, 333, 333, 370, 380, 390}; + + copy(arr_begin, arr_end, temp_begin); + replace(temp_begin, temp_end, 250, 333); + assert(equal(temp_begin, temp_end, begin(replace_expected), end(replace_expected))); + + ranges::copy(arr_begin, arr_end, temp_begin); + ranges::replace(temp_begin, temp_end, 250, 333); + assert(ranges::equal(temp_begin, temp_end, begin(replace_expected), end(replace_expected))); + } + { + const int swap_ranges_expected[] = { + 300, 310, 320, 250, 340, 250, 250, 370, 380, 390, 200, 210, 220, 250, 240, 250, 250, 270, 280, 290}; + + const auto temp_mid = temp_begin + _Signed128{10}; + + copy(arr_begin, arr_end, temp_begin); + swap_ranges(temp_begin, temp_mid, temp_mid); + assert(equal(temp_begin, temp_end, begin(swap_ranges_expected), end(swap_ranges_expected))); + + ranges::copy(arr_begin, arr_end, temp_begin); + ranges::swap_ranges(temp_begin, temp_mid, temp_mid, temp_end); + assert(ranges::equal(temp_begin, temp_end, begin(swap_ranges_expected), end(swap_ranges_expected))); + } + } +}