Additional algorithms.

This commit is contained in:
John Wellbelove 2017-06-28 19:13:12 +01:00
parent 6e04c8b190
commit 14074ade05
2 changed files with 175 additions and 19 deletions

View File

@ -258,21 +258,40 @@ namespace etl
}
//***************************************************************************
/// copy_n
/// copy_n (Random input iterators)
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/copy_n"></a>
//***************************************************************************
template <typename TInputIterator,
typename TSize,
typename TOutputIterator>
TOutputIterator copy_n(TInputIterator i_begin,
TSize n,
TOutputIterator o_begin)
typename etl::enable_if<etl::is_random_iterator<TInputIterator>::value, TOutputIterator>::type
copy_n(TInputIterator i_begin,
TSize n,
TOutputIterator o_begin)
{
TInputIterator i_end(i_begin);
std::advance(i_end, n);
return std::copy(i_begin, i_begin + n, o_begin);
}
return std::copy(i_begin, i_end, o_begin);
//***************************************************************************
/// copy_n (Non-random input iterators)
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/copy_n"></a>
//***************************************************************************
template <typename TInputIterator,
typename TSize,
typename TOutputIterator>
typename etl::enable_if<!etl::is_random_iterator<TInputIterator>::value, TOutputIterator>::type
copy_n(TInputIterator i_begin,
TSize n,
TOutputIterator o_begin)
{
while (n-- > 0)
{
*o_begin++ = *i_begin++;
}
return o_begin;
}
//***************************************************************************
@ -288,10 +307,34 @@ namespace etl
TOutputIterator o_begin,
TOutputIterator o_end)
{
TInputIterator i_end(i_begin);
std::advance(i_end, n);
while ((n-- > 0) && (o_begin != o_end))
{
*o_begin++ = *i_begin++;
}
return etl::copy(i_begin, i_end, o_begin, o_end);;
return o_begin;
}
//***************************************************************************
/// copy_n
/// A form of copy_n where the smallest of the two ranges is used.
///\ingroup algorithm
//***************************************************************************
template <typename TInputIterator,
typename TSize1,
typename TOutputIterator,
typename TSize2>
TOutputIterator copy_n(TInputIterator i_begin,
TSize1 n1,
TOutputIterator o_begin,
TSize2 n2)
{
while ((n1-- > 0) && (n2-- > 0))
{
*o_begin++ = *i_begin++;
}
return o_begin;
}
//***************************************************************************
@ -357,12 +400,12 @@ namespace etl
typename TSize,
typename TOutputIterator,
typename TUnaryPredicate>
TOutputIterator copy_n_if(TInputIterator begin,
TOutputIterator copy_n_if(TInputIterator i_begin,
TSize n,
TOutputIterator result,
TOutputIterator o_begin,
TUnaryPredicate predicate)
{
while (n > 0)
while (n-- > 0)
{
if (predicate(*i_begin))
{
@ -370,7 +413,6 @@ namespace etl
}
++i_begin;
--n;
}
return o_begin;
@ -697,10 +739,9 @@ namespace etl
TSize n,
TUnaryFunction function)
{
while (n > 0)
while (n-- > 0)
{
function(*begin++);
--n;
}
return begin;
@ -719,7 +760,7 @@ namespace etl
TUnaryFunction function,
TUnaryPredicate predicate)
{
while (n > 0)
while (n-- > 0)
{
if (predicate(*begin))
{
@ -727,7 +768,6 @@ namespace etl
}
++begin;
--n;
}
return begin;

View File

@ -219,7 +219,7 @@ namespace
}
//=========================================================================
TEST(copy_n)
TEST(copy_n_random_iterator)
{
int data1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int data2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@ -236,6 +236,24 @@ namespace
CHECK(is_same);
}
//=========================================================================
TEST(copy_n_non_random_iterator)
{
std::list<int> data1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int data2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int data3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int* result;
std::copy_n(std::begin(data1), 4, std::begin(data2));
result = etl::copy_n(std::begin(data1), 4, std::begin(data3));
CHECK_EQUAL(std::begin(data3) + 4, result);
bool is_same = std::equal(std::begin(data2), std::end(data2), std::begin(data3));
CHECK(is_same);
}
//=========================================================================
TEST(copy_n_4_parameter)
{
@ -272,6 +290,42 @@ namespace
CHECK(is_same);
}
//=========================================================================
TEST(copy_2n_4_parameter)
{
int data1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int out1[10];
int out2[5];
int check1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int check2[] = { 1, 2, 3, 4, 5 };
int check3[] = { 1, 2, 3, 4, 5, 0, 0, 0, 0, 0 };
int* result;
// Same size.
std::fill(std::begin(out1), std::end(out1), 0);
result = etl::copy_n(std::begin(data1), 10, std::begin(out1), 10);
CHECK_EQUAL(std::end(out1), result);
bool is_same = std::equal(std::begin(out1), std::end(out1), std::begin(check1));
CHECK(is_same);
// Destination smaller.
std::fill(std::begin(out2), std::end(out2), 0);
result = etl::copy_n(std::begin(data1), 10, std::begin(out2), 5);
CHECK_EQUAL(std::end(out2), result);
is_same = std::equal(std::begin(out2), std::end(out2), std::begin(check2));
CHECK(is_same);
// Source smaller.
std::fill(std::begin(out1), std::end(out1), 0);
result = etl::copy_n(std::begin(data1), 5, std::begin(out1), 10);
CHECK_EQUAL(std::begin(out1) + 5, result);
is_same = std::equal(std::begin(out1), std::end(out1), std::begin(check3));
CHECK(is_same);
}
//=========================================================================
TEST(copy_if)
{
@ -287,6 +341,28 @@ namespace
CHECK(is_same);
}
//=========================================================================
TEST(copy_n_if)
{
int data1[] = { 1, 8, 2, 7, 3, 6, 4, 5, 10, 9 };
int data2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int data3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Copy everything less than 5.
int *pout = data2;
for (int* pin = std::begin(data1); pin != std::begin(data1) + 6; ++pin)
{
if (*pin < 5)
{
*pout++ = *pin;
}
}
etl::copy_n_if(std::begin(data1), 6, std::begin(data3), std::bind2nd(std::less<int>(), 5));
bool is_same = std::equal(std::begin(data2), std::end(data2), std::begin(data3));
CHECK(is_same);
}
//=========================================================================
TEST(copy_if_4_parameter)
{
@ -499,6 +575,46 @@ namespace
CHECK_EQUAL(10, accumulator.sum);
}
//=========================================================================
TEST(for_each_n)
{
int data1[] = { 1, 8, 2, 7, 3, 6, 4, 5, 10, 9 };
int data2[] = { 2, 16, 4, 14, 6, 6, 4, 5, 10, 9 };
struct Multiply
{
void operator()(int& i)
{
i *= 2;
}
} multiplier;
etl::for_each_n(std::begin(data1), 5, multiplier);
bool are_equal = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
CHECK(are_equal);
}
//=========================================================================
TEST(for_each_n_if)
{
int data1[] = { 1, 8, 2, 7, 3, 6, 4, 5, 10, 9 };
int data2[] = { 2, 8, 4, 7, 6, 6, 4, 5, 10, 9 };
struct Multiply
{
void operator()(int& i)
{
i *= 2;
}
} multiplier;
etl::for_each_n_if(std::begin(data1), 5, multiplier, std::bind2nd(std::less<int>(), 5));
bool are_equal = std::equal(std::begin(data1), std::end(data1), std::begin(data2));
CHECK(are_equal);
}
//=========================================================================
TEST(transform_4_parameter)
{