mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 14:49:53 +08:00
Added specialisations of etl::rotate for different iterator types
This commit is contained in:
parent
17a4e8d934
commit
384c08f25b
@ -43,6 +43,7 @@ SOFTWARE.
|
||||
#include "iterator.h"
|
||||
#include "functional.h"
|
||||
#include "utility.h"
|
||||
#include "gcd.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -1157,20 +1158,94 @@ namespace etl
|
||||
namespace private_algorithm
|
||||
{
|
||||
//*********************************
|
||||
// For random access iterators
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TIterator rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
typename etl::enable_if<etl::is_random_access_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
int n = last - first;
|
||||
int m = middle - first;
|
||||
int gcd_nm = etl::gcd(n, m);
|
||||
|
||||
TIterator result = first + (last - middle);
|
||||
|
||||
for (int i = 0; i < gcd_nm; i++)
|
||||
{
|
||||
auto temp = *(first + i);
|
||||
int j = i;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int k = j + m;
|
||||
|
||||
if (k >= n)
|
||||
{
|
||||
k = k - n;
|
||||
}
|
||||
|
||||
if (k == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*(first + j) = *(first + k);
|
||||
j = k;
|
||||
}
|
||||
|
||||
*(first + j) = temp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
// For bidirectional iterators
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_bidirectional_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
TIterator result = first;
|
||||
etl::advance(result, etl::distance(middle, last));
|
||||
|
||||
reverse(first, middle);
|
||||
reverse(middle, last);
|
||||
reverse(first, last);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
// For forward iterators
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<etl::is_forward_iterator<TIterator>::value, TIterator>::type
|
||||
rotate_general(TIterator first, TIterator middle, TIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
TIterator next = middle;
|
||||
TIterator result = first;
|
||||
std::advance(result, std::distance(middle, last));
|
||||
|
||||
while (first != next)
|
||||
{
|
||||
using ETL_OR_STD::swap; // Allow ADL
|
||||
|
||||
swap(*first, *next);
|
||||
|
||||
++first;
|
||||
++next;
|
||||
using ETL_OR_STD::swap;
|
||||
swap(*first++, *next++);
|
||||
|
||||
if (next == last)
|
||||
{
|
||||
@ -1182,10 +1257,11 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
// Simplified algorithm for rotate left by one
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TIterator rotate_left_by_one(TIterator first, TIterator last)
|
||||
@ -1206,6 +1282,7 @@ namespace etl
|
||||
}
|
||||
|
||||
//*********************************
|
||||
// Simplified for algorithm rotate right by one
|
||||
template <typename TIterator>
|
||||
ETL_CONSTEXPR14
|
||||
TIterator rotate_right_by_one(TIterator first, TIterator last)
|
||||
@ -1239,7 +1316,18 @@ namespace etl
|
||||
|
||||
if (etl::next(middle) == last)
|
||||
{
|
||||
return private_algorithm::rotate_right_by_one(first, last);
|
||||
#if ETL_USING_CPP20
|
||||
if ETL_IF_CONSTEXPR(etl::is_forward_iterator<TIterator>::value)
|
||||
{
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
}
|
||||
else
|
||||
{
|
||||
return private_algorithm::rotate_right_by_one(first, last);
|
||||
}
|
||||
#else
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
#endif
|
||||
}
|
||||
|
||||
return private_algorithm::rotate_general(first, middle, last);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user