Skip to content
Merged
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
41 changes: 41 additions & 0 deletions libcxx/include/__algorithm/swap_ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,47 @@ __swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2
template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2>
__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) {
#if _LIBCPP_STD_VER >= 26
if ! consteval {
using _V1Type = iterator_traits<_ForwardIterator1>::value_type;
using _V2Type = iterator_traits<_ForwardIterator2>::value_type;
if constexpr(__libcpp_is_contiguous_iterator<_ForwardIterator1>::value &&
__libcpp_is_contiguous_iterator<_ForwardIterator2>::value &&
is_same_v<_V1Type, _V2Type> &&
is_trivially_relocatable_v<_V1Type> && is_replaceable_v<_V1Type>) {
size_t __distance = distance(__first1, __last1);
if (__distance == 1)
iter_swap(__first1, __first2);
else if (__distance > 0) {
size_t __numBytes = __distance * sizeof(_V1Type);
byte *__aptr = reinterpret_cast<byte *> (addressof(*__first1));
byte *__bptr = reinterpret_cast<byte *> (addressof(*__first2));

size_t __size = __numBytes < 512 ? __numBytes : 512;
size_t __chunk = __numBytes / __size;
size_t __rem = __numBytes % __size;

char __buffer[__size];
if (__chunk > 0) {
for (std::size_t __n = 0; __n < __chunk; __n++, __aptr += __size, __bptr += __size) {
__builtin_memcpy(__buffer, __aptr, __size);
__builtin_memcpy(__aptr, __bptr, __size);
__builtin_memcpy(__bptr, __buffer, __size);
}
}

if (__rem > 0) {
__builtin_memcpy(__buffer, __aptr, __rem);
__builtin_memcpy(__aptr, __bptr, __rem);
__builtin_memcpy(__bptr, __buffer, __rem);
}
}
return pair<_ForwardIterator1, _ForwardIterator2>(__first1 + __distance, __first2 + __distance);
}
}
#endif

// else not replaceable, not contiguous, or constexpr
while (__first1 != __last1) {
_IterOps<_AlgPolicy>::iter_swap(__first1, __first2);
++__first1;
Expand Down