@@ -85,10 +85,20 @@ const void* __stdcall __std_search_n_2(const void* _First, const void* _Last, si
85
85
const void* __stdcall __std_search_n_4(const void* _First, const void* _Last, size_t _Count, uint32_t _Value) noexcept;
86
86
const void* __stdcall __std_search_n_8(const void* _First, const void* _Last, size_t _Count, uint64_t _Value) noexcept;
87
87
88
+ void* __stdcall __std_remove_copy_1(const void* _First, const void* _Last, void* _Out, uint8_t _Val) noexcept;
89
+ void* __stdcall __std_remove_copy_2(const void* _First, const void* _Last, void* _Out, uint16_t _Val) noexcept;
90
+ void* __stdcall __std_remove_copy_4(const void* _First, const void* _Last, void* _Out, uint32_t _Val) noexcept;
91
+ void* __stdcall __std_remove_copy_8(const void* _First, const void* _Last, void* _Out, uint64_t _Val) noexcept;
92
+
88
93
void* __stdcall __std_unique_1(void* _First, void* _Last) noexcept;
89
94
void* __stdcall __std_unique_2(void* _First, void* _Last) noexcept;
90
95
void* __stdcall __std_unique_4(void* _First, void* _Last) noexcept;
91
96
void* __stdcall __std_unique_8(void* _First, void* _Last) noexcept;
97
+
98
+ void* __stdcall __std_unique_copy_1(const void* _First, const void* _Last, void* _Dest) noexcept;
99
+ void* __stdcall __std_unique_copy_2(const void* _First, const void* _Last, void* _Dest) noexcept;
100
+ void* __stdcall __std_unique_copy_4(const void* _First, const void* _Last, void* _Dest) noexcept;
101
+ void* __stdcall __std_unique_copy_8(const void* _First, const void* _Last, void* _Dest) noexcept;
92
102
} // extern "C"
93
103
94
104
_STD_BEGIN
@@ -257,6 +267,43 @@ _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept {
257
267
}
258
268
}
259
269
270
+ template <class _Ty, class _TVal>
271
+ _Ty* _Remove_copy_vectorized(
272
+ const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest, const _TVal _Val) noexcept {
273
+ if constexpr (is_pointer_v<_Ty>) {
274
+ #ifdef _WIN64
275
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_8(_First, _Last, _Dest, reinterpret_cast<uint64_t>(_Val)));
276
+ #else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
277
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_4(_First, _Last, _Dest, reinterpret_cast<uint32_t>(_Val)));
278
+ #endif // ^^^ !defined(_WIN64) ^^^
279
+ } else if constexpr (sizeof(_Ty) == 1) {
280
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_1(_First, _Last, _Dest, static_cast<uint8_t>(_Val)));
281
+ } else if constexpr (sizeof(_Ty) == 2) {
282
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_2(_First, _Last, _Dest, static_cast<uint16_t>(_Val)));
283
+ } else if constexpr (sizeof(_Ty) == 4) {
284
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_4(_First, _Last, _Dest, static_cast<uint32_t>(_Val)));
285
+ } else if constexpr (sizeof(_Ty) == 8) {
286
+ return reinterpret_cast<_Ty*>(::__std_remove_copy_8(_First, _Last, _Dest, static_cast<uint64_t>(_Val)));
287
+ } else {
288
+ _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size
289
+ }
290
+ }
291
+
292
+ template <class _Ty>
293
+ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest) noexcept {
294
+ if constexpr (sizeof(_Ty) == 1) {
295
+ return reinterpret_cast<_Ty*>(::__std_unique_copy_1(_First, _Last, _Dest));
296
+ } else if constexpr (sizeof(_Ty) == 2) {
297
+ return reinterpret_cast<_Ty*>(::__std_unique_copy_2(_First, _Last, _Dest));
298
+ } else if constexpr (sizeof(_Ty) == 4) {
299
+ return reinterpret_cast<_Ty*>(::__std_unique_copy_4(_First, _Last, _Dest));
300
+ } else if constexpr (sizeof(_Ty) == 8) {
301
+ return reinterpret_cast<_Ty*>(::__std_unique_copy_8(_First, _Last, _Dest));
302
+ } else {
303
+ _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size
304
+ }
305
+ }
306
+
260
307
// Can we activate the vector algorithms for find_first_of?
261
308
template <class _It1, class _It2, class _Pr>
262
309
constexpr bool _Vector_alg_in_find_first_of_is_safe = _Equal_memcmp_is_safe<_It1, _It2, _Pr>;
@@ -282,6 +329,17 @@ constexpr bool _Vector_alg_in_search_n_is_safe = _Vector_alg_in_find_is_safe<_It
282
329
// Can we activate the vector algorithms for unique?
283
330
template <class _Iter, class _Pr>
284
331
constexpr bool _Vector_alg_in_unique_is_safe = _Equal_memcmp_is_safe<_Iter, _Iter, _Pr>;
332
+
333
+ // Can we use this output iterator for remove_copy or unique_copy?
334
+ template <class _Out, class _In>
335
+ constexpr bool _Output_iterator_for_vector_alg_is_safe() {
336
+ if constexpr (_Iterator_is_contiguous<_Out>) {
337
+ return is_same_v<_Iter_value_t<_Out>, remove_const_t<_Iter_value_t<_In>>>;
338
+ } else {
339
+ return false;
340
+ }
341
+ }
342
+
285
343
_STD_END
286
344
#endif // _USE_STD_VECTOR_ALGORITHMS
287
345
@@ -4718,6 +4776,33 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _
4718
4776
auto _UFirst = _STD _Get_unwrapped(_First);
4719
4777
const auto _ULast = _STD _Get_unwrapped(_Last);
4720
4778
auto _UDest = _STD _Get_unwrapped_unverified(_Dest);
4779
+
4780
+ #if _USE_STD_VECTOR_ALGORITHMS
4781
+ if constexpr (_Vector_alg_in_find_is_safe<decltype(_UFirst), _Ty>
4782
+ && _Output_iterator_for_vector_alg_is_safe<decltype(_UDest), decltype(_UFirst)>()) {
4783
+ if (!_STD _Is_constant_evaluated()) {
4784
+ if (!_STD _Could_compare_equal_to_value_type<decltype(_UFirst)>(_Val)) {
4785
+ _UDest = _STD _Copy_unchecked(_UFirst, _ULast, _UDest);
4786
+ _STD _Seek_wrapped(_Dest, _UDest);
4787
+ return _Dest;
4788
+ }
4789
+
4790
+ const auto _Dest_ptr = _STD _To_address(_UDest);
4791
+ const auto _Result =
4792
+ _STD _Remove_copy_vectorized(_STD _To_address(_UFirst), _STD _To_address(_ULast), _Dest_ptr, _Val);
4793
+
4794
+ if constexpr (is_pointer_v<decltype(_UDest)>) {
4795
+ _UDest = _Result;
4796
+ } else {
4797
+ _UDest += _Result - _Dest_ptr;
4798
+ }
4799
+
4800
+ _STD _Seek_wrapped(_Dest, _UDest);
4801
+ return _Dest;
4802
+ }
4803
+ }
4804
+ #endif // _USE_STD_VECTOR_ALGORITHMS
4805
+
4721
4806
for (; _UFirst != _ULast; ++_UFirst) {
4722
4807
if (!(*_UFirst == _Val)) {
4723
4808
*_UDest = *_UFirst;
@@ -4943,6 +5028,31 @@ namespace ranges {
4943
5028
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>);
4944
5029
_STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate<ranges::equal_to, projected<_It, _Pj>, const _Ty*>);
4945
5030
5031
+ #if _USE_STD_VECTOR_ALGORITHMS
5032
+ if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && _Output_iterator_for_vector_alg_is_safe<_Out, _It>()
5033
+ && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) {
5034
+ if (!_STD is_constant_evaluated()) {
5035
+ const auto _Size = _Last - _First;
5036
+ auto _End = _First + _Size;
5037
+
5038
+ if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) {
5039
+ _Output = _STD _Copy_unchecked(_First, _Last, _Output);
5040
+ return {_STD move(_End), _STD move(_Output)};
5041
+ }
5042
+
5043
+ const auto _Dest_ptr = _STD to_address(_Output);
5044
+ const auto _Result =
5045
+ _STD _Remove_copy_vectorized(_STD to_address(_First), _STD to_address(_End), _Dest_ptr, _Val);
5046
+
5047
+ if constexpr (is_pointer_v<_Out>) {
5048
+ return {_STD move(_End), _Result};
5049
+ } else {
5050
+ return {_STD move(_End), _STD move(_Output) + (_Result - _Dest_ptr)};
5051
+ }
5052
+ }
5053
+ }
5054
+ #endif // _USE_STD_VECTOR_ALGORITHMS
5055
+
4946
5056
for (; _First != _Last; ++_First) {
4947
5057
if (_STD invoke(_Proj, *_First) != _Val) {
4948
5058
*_Output = *_First;
@@ -5190,6 +5300,26 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr
5190
5300
5191
5301
auto _UDest = _STD _Get_unwrapped_unverified(_Dest);
5192
5302
5303
+ #if _USE_STD_VECTOR_ALGORITHMS
5304
+ if constexpr (_Vector_alg_in_unique_is_safe<decltype(_UFirst), _Pr>
5305
+ && _Output_iterator_for_vector_alg_is_safe<decltype(_UDest), decltype(_UFirst)>()) {
5306
+ if (!_STD _Is_constant_evaluated()) {
5307
+ const auto _First_ptr = _STD _To_address(_UFirst);
5308
+ const auto _Dest_ptr = _STD _To_address(_UDest);
5309
+ const auto _Result = _STD _Unique_copy_vectorized(_First_ptr, _STD _To_address(_ULast), _Dest_ptr);
5310
+
5311
+ if constexpr (is_pointer_v<decltype(_UDest)>) {
5312
+ _UDest = _Result;
5313
+ } else {
5314
+ _UDest += _Result - _Dest_ptr;
5315
+ }
5316
+
5317
+ _STD _Seek_wrapped(_Dest, _UDest);
5318
+ return _Dest;
5319
+ }
5320
+ }
5321
+ #endif // _USE_STD_VECTOR_ALGORITHMS
5322
+
5193
5323
if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { // can reread the source for comparison
5194
5324
auto _Firstb = _UFirst;
5195
5325
@@ -5317,6 +5447,26 @@ namespace ranges {
5317
5447
return {_STD move(_First), _STD move(_Output)};
5318
5448
}
5319
5449
5450
+ #if _USE_STD_VECTOR_ALGORITHMS
5451
+ if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It>
5452
+ && _Vector_alg_in_unique_is_safe<_It, _Pr>
5453
+ && _Output_iterator_for_vector_alg_is_safe<_Out, _It>()) {
5454
+ if (!_STD is_constant_evaluated()) {
5455
+ const auto _Size = _Last - _First;
5456
+ const auto _First_ptr = _STD to_address(_First);
5457
+ const auto _Last_ptr = _First_ptr + static_cast<size_t>(_Size);
5458
+ const auto _Output_ptr = _STD to_address(_Output);
5459
+ const auto _Result = _STD _Unique_copy_vectorized(_First_ptr, _Last_ptr, _Output_ptr);
5460
+
5461
+ if constexpr (is_pointer_v<_It> && is_pointer_v<_Out>) {
5462
+ return {_Last_ptr, _Result};
5463
+ } else {
5464
+ return {_STD move(_First) + _Size, _STD move(_Output) + (_Result - _Output_ptr)};
5465
+ }
5466
+ }
5467
+ }
5468
+ #endif // _USE_STD_VECTOR_ALGORITHMS
5469
+
5320
5470
if constexpr (_Is_input_with_value_type<_Out, iter_value_t<_It>>) {
5321
5471
// Can reread _Output
5322
5472
*_Output = *_First;
0 commit comments