Latest implementation

This commit is contained in:
John Wellbelove 2020-12-27 11:59:14 +00:00
parent faed3231bf
commit aa148ac424
4 changed files with 458 additions and 70 deletions

View File

@ -118,6 +118,18 @@ namespace etl
}
};
//***************************************************************************
template <typename T = void>
struct less_equal
{
typedef T value_type;
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
{
return lhs <= rhs;
}
};
//***************************************************************************
template <typename T = void>
struct greater
@ -130,6 +142,18 @@ namespace etl
}
};
//***************************************************************************
template <typename T = void>
struct greater_equal
{
typedef T value_type;
ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const
{
return lhs >= rhs;
}
};
//***************************************************************************
template <typename T = void>
struct equal_to
@ -238,6 +262,187 @@ namespace etl
return binder2nd<F>(f, x);
}
//***************************************************************************
template <typename T = void>
struct plus
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs + rhs;
}
};
//***************************************************************************
template <typename T = void>
struct minus
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs - rhs;
}
};
//***************************************************************************
template <typename T = void>
struct negate
{
typedef T argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs) const
{
return -lhs;
}
};
//***************************************************************************
template <typename T = void>
struct multiplies
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs * rhs;
}
};
//***************************************************************************
template <typename T = void>
struct divides
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs / rhs;
}
};
//***************************************************************************
template <typename T = void>
struct modulus
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs % rhs;
}
};
//***************************************************************************
template <typename T = void>
struct logical_and
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs && rhs;
}
};
//***************************************************************************
template <typename T = void>
struct logical_or
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs || rhs;
}
};
//***************************************************************************
template <typename T = void>
struct logical_not
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs) const
{
return !lhs;
}
};
//***************************************************************************
template <typename T = void>
struct bit_and
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs & rhs;
}
};
//***************************************************************************
template <typename T = void>
struct bit_or
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs | rhs;
}
};
//***************************************************************************
template <typename T = void>
struct bit_xor
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const
{
return lhs ^ rhs;
}
};
//***************************************************************************
template <typename T = void>
struct bit_not
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
ETL_CONSTEXPR T operator()(const T& lhs) const
{
return ~lhs;
}
};
//***************************************************************************
template <typename T>
@ -246,11 +451,12 @@ namespace etl
T operator()(T& value)
{
++value;
return value;
}
};
//***************************************************************************
template <typename T>
struct post_increment
{
@ -262,22 +468,27 @@ namespace etl
}
};
//***************************************************************************
template <typename T>
struct increment : etl::pre_increment<T>
{
};
//***************************************************************************
template <typename T>
struct pre_decrement
{
T operator()(T& value)
{
--value;
return value;
}
};
//***************************************************************************
template <typename T>
struct post_decrement
{
@ -289,6 +500,8 @@ namespace etl
}
};
//***************************************************************************
template <typename T>
struct decrement : etl::pre_decrement<T>
{

View File

@ -115,12 +115,23 @@ namespace etl
//***************************************************************************
/// Unlinks this loop from its inner.
/// Re-starts the loop.
//***************************************************************************
void clear()
void detach()
{
inner = ETL_NULLPTR;
start();
}
//***************************************************************************
/// Unlinks this and all inner loops.
//***************************************************************************
void detach_all()
{
if (inner != ETL_NULLPTR)
{
inner->detach_all();
}
detach();
}
//***************************************************************************
@ -225,10 +236,14 @@ namespace etl
//***************************************************************************
/// multi_loop
/// \tparam T The type to loop over.
/// \tparam TIncrementor The incrementor type that implements operator() to increment.
/// \tparam TStepper The type that implements operator() to step.
/// Default = etl::increment, which calls operator ++() for the type.
/// \tparam TContinue The type that implements operator() to test for loop continuation.
/// Default = etl::not_equal_to, which calls operator !=() for the type.
//***************************************************************************
template <typename T, template <typename U> class TIncrementor = etl::increment>
template <typename T,
typename TStepper = etl::increment<T>,
typename TContinue = etl::not_equal_to<T> >
class multi_loop : public imulti_loop
{
public:
@ -241,10 +256,15 @@ namespace etl
/// \param first The starting value of the loop.
/// \param last The terminating value of the loop. Equal to the last required value + 1.
//***************************************************************************
multi_loop(value_type first_, value_type last_)
multi_loop(value_type first_,
value_type last_,
TStepper stepper_ = TStepper(),
TContinue continue_loop_ = TContinue())
: first(first_)
, last(last_)
, current(first_)
, stepper(stepper_)
, continue_loop(continue_loop_)
{
}
@ -276,7 +296,7 @@ namespace etl
}
current = first;
has_completed = false;
has_completed = !continue_loop(current, last); // Check for null loop.
}
//***************************************************************************
@ -292,12 +312,12 @@ namespace etl
if (inner->completed())
{
has_completed = increment();
has_completed = step();
}
}
else
{
has_completed = increment();
has_completed = step();
}
}
@ -314,11 +334,11 @@ namespace etl
//***************************************************************************
/// Increments the current loop value.
//***************************************************************************
bool increment()
bool step()
{
incrementor(current);
current = stepper(current);
const bool has_rolled_over = (current == last);
const bool has_rolled_over = !continue_loop(current, last);
if (has_rolled_over)
{
@ -327,12 +347,13 @@ namespace etl
return has_rolled_over;
}
TIncrementor<value_type> incrementor; ///< The incrementor type.
value_type first; ///< The first value of the loop.
value_type last; ///< The terminating value of the loop.
value_type current; ///< The current value of the loop.
TStepper stepper; ///< The type to step the value to the next.
TContinue continue_loop; ///< The type to determine if the loop should continue.
};
}

View File

@ -60,6 +60,14 @@ namespace
CHECK(!(compare<etl::less<int>>(1, 1)));
}
//*************************************************************************
TEST(test_less_equal)
{
CHECK((compare<etl::less_equal<int>>(1, 2)));
CHECK(!(compare<etl::less_equal<int>>(2, 1)));
CHECK((compare<etl::less_equal<int>>(1, 1)));
}
//*************************************************************************
TEST(test_greater)
{
@ -68,6 +76,14 @@ namespace
CHECK(!(compare<etl::greater<int>>(1, 1)));
}
//*************************************************************************
TEST(test_greater_equal)
{
CHECK(!(compare<etl::greater_equal<int>>(1, 2)));
CHECK((compare<etl::greater_equal<int>>(2, 1)));
CHECK((compare<etl::greater_equal<int>>(1, 1)));
}
//*************************************************************************
TEST(test_equal_to)
{
@ -186,13 +202,13 @@ namespace
//*************************************************************************
TEST(test_pre_decrement)
{
etl::pre_decrement<int> pi;
etl::pre_decrement<int> pd;
int i = 0;
int j = 0;
pi(i);
j = pi(i);
pd(i);
j = pd(i);
CHECK_EQUAL(-2, i);
CHECK_EQUAL(-2, j);
@ -201,16 +217,126 @@ namespace
//*************************************************************************
TEST(test_post_decrement)
{
etl::post_decrement<int> pi;
etl::post_decrement<int> pd;
int i = 0;
int j = 0;
pi(i);
j = pi(i);
pd(i);
j = pd(i);
CHECK_EQUAL(-2, i);
CHECK_EQUAL(-1, j);
}
//*************************************************************************
TEST(test_plus)
{
auto f = etl::plus<int>();
CHECK_EQUAL(2 + 4, f(2, 4));
}
//*************************************************************************
TEST(test_minus)
{
auto f = etl::minus<int>();
CHECK_EQUAL(2 - 4, f(2, 4));
}
//*************************************************************************
TEST(test_negate)
{
auto f = etl::negate<int>();
CHECK_EQUAL(-2, f(2));
}
//*************************************************************************
TEST(test_multiplies)
{
auto f = etl::multiplies<int>();
CHECK_EQUAL(2 * 4, f(2, 4));
}
//*************************************************************************
TEST(test_divides)
{
auto f = etl::divides<int>();
CHECK_EQUAL(4 / 2, f(4, 2));
}
//*************************************************************************
TEST(test_modulus)
{
auto f = etl::modulus<int>();
CHECK_EQUAL(5 % 2, f(5, 2));
}
//*************************************************************************
TEST(test_logical_and)
{
auto f = etl::logical_and<bool>();
CHECK_EQUAL(false && false, f(false, false));
CHECK_EQUAL(false && true, f(false, true));
CHECK_EQUAL(true && false, f(true, false));
CHECK_EQUAL(true && true, f(true, true));
}
//*************************************************************************
TEST(test_logical_or)
{
auto f = etl::logical_or<bool>();
CHECK_EQUAL(false || false, f(false, false));
CHECK_EQUAL(false || true, f(false, true));
CHECK_EQUAL(true || false, f(true, false));
CHECK_EQUAL(true || true, f(true, true));
}
//*************************************************************************
TEST(test_logical_not)
{
auto f = etl::logical_not<bool>();
CHECK_EQUAL(!false, f(false));
CHECK_EQUAL(!true, f(true));
}
//*************************************************************************
TEST(test_bit_and)
{
auto f = etl::bit_and<uint8_t>();
CHECK_EQUAL(0x00 & 0xFF, f(0x00, 0xFF));
CHECK_EQUAL(0xAA & 0xFF, f(0xAA, 0xFF));
CHECK_EQUAL(0x55 & 0xFF, f(0x55, 0xFF));
CHECK_EQUAL(0xFF & 0xFF, f(0xFF, 0xFF));
}
//*************************************************************************
TEST(test_bit_or)
{
auto f = etl::bit_or<uint8_t>();
CHECK_EQUAL(0xFF | 0x00, f(0xFF, 0x00));
CHECK_EQUAL(0xAA | 0x00, f(0xAA, 0x00));
CHECK_EQUAL(0x55 | 0x00, f(0x55, 0x00));
CHECK_EQUAL(0x55 | 0xAA, f(0x55, 0xAA));
}
//*************************************************************************
TEST(test_bit_xor)
{
auto f = etl::bit_xor<uint8_t>();
CHECK_EQUAL(0xFF ^ 0x00, f(0xFF, 0x00));
CHECK_EQUAL(0xAA ^ 0x00, f(0xAA, 0x00));
CHECK_EQUAL(0x55 ^ 0x00, f(0x55, 0x00));
CHECK_EQUAL(0x55 ^ 0xAA, f(0x55, 0xAA));
}
//*************************************************************************
TEST(test_bit_not)
{
auto f = etl::bit_not<uint8_t>();
CHECK_EQUAL(uint8_t(~0x00), f(0x00));
CHECK_EQUAL(uint8_t(~0x55), f(0x55));
CHECK_EQUAL(uint8_t(~0xAA), f(0xAA));
CHECK_EQUAL(uint8_t(~0xFF), f(0xFF));
}
};
}

View File

@ -29,11 +29,13 @@ SOFTWARE.
#include "UnitTest++/UnitTest++.h"
#include "etl/multi_loop.h"
#include "etl/functional.h"
#include <iterator>
#include <string>
#include <forward_list>
#include <array>
#include <functional>
namespace
{
@ -107,8 +109,28 @@ namespace
using Iterator = std::forward_list<std::string>::const_iterator;
using Outer = etl::multi_loop<int>;
using Middle = etl::multi_loop<Index, etl::decrement>;
struct Adder
{
Adder()
: value(0)
{
}
Adder(int value_)
: value(value_)
{
}
int operator()(int i)
{
return i + value;
}
int value;
};
using Outer = etl::multi_loop<int, Adder>;
using Middle = etl::multi_loop<Index, etl::decrement<Index>, etl::greater<Index>>;
using Inner = etl::multi_loop<Iterator>;
std::forward_list<std::string> strings =
@ -116,7 +138,7 @@ namespace
"zero", "one", "two", "three"
};
Outer outer(0, 4);
Outer outer(0, 8, Adder(2));
Middle middle(Index(2), Index(-2));
Inner inner(strings.begin(), strings.end());
@ -125,16 +147,12 @@ namespace
//*************************************************************************
TEST(create_three_loops)
{
outer.clear();
middle.clear();
inner.clear();
outer.append(middle);
middle.insert(inner);
CHECK(!outer.completed());
CHECK(!middle.completed());
CHECK(!inner.completed());
CHECK(outer.completed());
CHECK(middle.completed());
CHECK(inner.completed());
CHECK_EQUAL(3U, outer.number_of_loops());
CHECK_EQUAL(2U, middle.number_of_loops());
@ -145,7 +163,7 @@ namespace
CHECK_EQUAL(4U, inner.number_of_iterations());
CHECK_EQUAL(0, outer.begin());
CHECK_EQUAL(4, outer.end());
CHECK_EQUAL(8, outer.end());
CHECK_EQUAL(outer.begin(), outer.value());
CHECK_EQUAL(Index(2), middle.begin());
@ -155,21 +173,19 @@ namespace
CHECK(strings.begin() == inner.begin());
CHECK(strings.end() == inner.end());
CHECK(inner.begin() == inner.value());
outer.detach_all();
}
//*************************************************************************
TEST(create_three_loops_different_order)
{
outer.clear();
middle.clear();
inner.clear();
middle.append(inner);
outer.insert(middle);
CHECK(!outer.completed());
CHECK(!middle.completed());
CHECK(!inner.completed());
CHECK(outer.completed());
CHECK(middle.completed());
CHECK(inner.completed());
CHECK_EQUAL(3U, outer.number_of_loops());
CHECK_EQUAL(2U, middle.number_of_loops());
@ -180,7 +196,7 @@ namespace
CHECK_EQUAL(4U, inner.number_of_iterations());
CHECK_EQUAL(0, outer.begin());
CHECK_EQUAL(4, outer.end());
CHECK_EQUAL(8, outer.end());
CHECK_EQUAL(outer.begin(), outer.value());
CHECK_EQUAL(Index(2), middle.begin());
@ -190,20 +206,18 @@ namespace
CHECK(strings.begin() == inner.begin());
CHECK(strings.end() == inner.end());
CHECK(inner.begin() == inner.value());
outer.detach_all();
}
//*************************************************************************
TEST(create_three_loops_functional_style)
{
outer.clear();
middle.clear();
inner.clear();
outer.append(inner).insert(middle);
CHECK(!outer.completed());
CHECK(!middle.completed());
CHECK(!inner.completed());
CHECK(outer.completed());
CHECK(middle.completed());
CHECK(inner.completed());
CHECK_EQUAL(3U, outer.number_of_loops());
CHECK_EQUAL(2U, middle.number_of_loops());
@ -214,7 +228,7 @@ namespace
CHECK_EQUAL(4U, inner.number_of_iterations());
CHECK_EQUAL(0, outer.begin());
CHECK_EQUAL(4, outer.end());
CHECK_EQUAL(8, outer.end());
CHECK_EQUAL(outer.begin(), outer.value());
CHECK_EQUAL(Index(2), middle.begin());
@ -224,28 +238,42 @@ namespace
CHECK(strings.begin() == inner.begin());
CHECK(strings.end() == inner.end());
CHECK(inner.begin() == inner.value());
outer.detach_all();
}
//*************************************************************************
TEST(create_three_loops_circular_links)
{
outer.clear();
middle.clear();
inner.clear();
middle.append(outer);
CHECK_THROW(outer.append(middle), etl::multi_loop_circular_reference);
CHECK_THROW(inner.append(inner), etl::multi_loop_circular_reference);
outer.detach();
middle.detach();
inner.detach();
}
//*************************************************************************
TEST(null_loop)
{
Outer null_loop(2, 2);
CHECK(null_loop.completed());
CHECK_EQUAL(1U, null_loop.number_of_loops());
CHECK_EQUAL(0U, null_loop.number_of_iterations());
CHECK_EQUAL(2, null_loop.begin());
CHECK_EQUAL(2, null_loop.end());
CHECK_EQUAL(null_loop.begin(), null_loop.value());
}
//*************************************************************************
TEST(run_three_loops)
{
outer.clear();
middle.clear();
inner.clear();
outer.append(middle).append(inner);
struct result
@ -261,18 +289,18 @@ namespace
result{ 0, 1, "zero" }, result{ 0, 1, "one" }, result{ 0, 1, "two" }, result{ 0, 1, "three" },
result{ 0, 0, "zero" }, result{ 0, 0, "one" }, result{ 0, 0, "two" }, result{ 0, 0, "three" },
result{ 0, -1, "zero" }, result{ 0, -1, "one" }, result{ 0, -1, "two" }, result{ 0, -1, "three" },
result{ 1, 2, "zero" }, result{ 1, 2, "one" }, result{ 1, 2, "two" }, result{ 1, 2, "three" },
result{ 1, 1, "zero" }, result{ 1, 1, "one" }, result{ 1, 1, "two" }, result{ 1, 1, "three" },
result{ 1, 0, "zero" }, result{ 1, 0, "one" }, result{ 1, 0, "two" }, result{ 1, 0, "three" },
result{ 1, -1, "zero" }, result{ 1, -1, "one" }, result{ 1, -1, "two" }, result{ 1, -1, "three" },
result{ 2, 2, "zero" }, result{ 2, 2, "one" }, result{ 2, 2, "two" }, result{ 2, 2, "three" },
result{ 2, 1, "zero" }, result{ 2, 1, "one" }, result{ 2, 1, "two" }, result{ 2, 1, "three" },
result{ 2, 0, "zero" }, result{ 2, 0, "one" }, result{ 2, 0, "two" }, result{ 2, 0, "three" },
result{ 2, -1, "zero" }, result{ 2, -1, "one" }, result{ 2, -1, "two" }, result{ 2, -1, "three" },
result{ 3, 2, "zero" }, result{ 3, 2, "one" }, result{ 3, 2, "two" }, result{ 3, 2, "three" },
result{ 3, 1, "zero" }, result{ 3, 1, "one" }, result{ 3, 1, "two" }, result{ 3, 1, "three" },
result{ 3, 0, "zero" }, result{ 3, 0, "one" }, result{ 3, 0, "two" }, result{ 3, 0, "three" },
result{ 3, -1, "zero" }, result{ 3, -1, "one" }, result{ 3, -1, "two" }, result{ 3, -1, "three" }
result{ 4, 2, "zero" }, result{ 4, 2, "one" }, result{ 4, 2, "two" }, result{ 4, 2, "three" },
result{ 4, 1, "zero" }, result{ 4, 1, "one" }, result{ 4, 1, "two" }, result{ 4, 1, "three" },
result{ 4, 0, "zero" }, result{ 4, 0, "one" }, result{ 4, 0, "two" }, result{ 4, 0, "three" },
result{ 4, -1, "zero" }, result{ 4, -1, "one" }, result{ 4, -1, "two" }, result{ 4, -1, "three" },
result{ 6, 2, "zero" }, result{ 6, 2, "one" }, result{ 6, 2, "two" }, result{ 6, 2, "three" },
result{ 6, 1, "zero" }, result{ 6, 1, "one" }, result{ 6, 1, "two" }, result{ 6, 1, "three" },
result{ 6, 0, "zero" }, result{ 6, 0, "one" }, result{ 6, 0, "two" }, result{ 6, 0, "three" },
result{ 6, -1, "zero" }, result{ 6, -1, "one" }, result{ 6, -1, "two" }, result{ 6, -1, "three" }
};
size_t i = 0U;
@ -322,15 +350,13 @@ namespace
}
CHECK(outer.completed());
outer.detach_all();
}
//*************************************************************************
TEST(create_three_loops_but_just_run_the_inner_two)
{
outer.clear();
middle.clear();
inner.clear();
outer.append(middle).append(inner);
struct result
@ -395,6 +421,8 @@ namespace
}
CHECK(middle.completed());
outer.detach_all();
}
};
}