diff --git a/include/etl/functional.h b/include/etl/functional.h index d9258262..6cd2fd3c 100644 --- a/include/etl/functional.h +++ b/include/etl/functional.h @@ -114,7 +114,19 @@ namespace etl ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const { - return lhs < rhs; + return (lhs < rhs); + } + }; + + //*************************************************************************** + template + struct less_equal + { + typedef T value_type; + + ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const + { + return !(rhs < lhs); } }; @@ -126,7 +138,19 @@ namespace etl ETL_CONSTEXPR bool operator()(const T &lhs, const T &rhs) const { - return lhs > rhs; + return (rhs < lhs); + } + }; + + //*************************************************************************** + template + struct greater_equal + { + typedef T value_type; + + ETL_CONSTEXPR bool operator()(const T& lhs, const T& rhs) const + { + return !(lhs < rhs); } }; @@ -239,59 +263,184 @@ namespace etl } //*************************************************************************** - - template - struct pre_increment + template + struct plus { - T operator()(T& value) - { - ++value; + typedef T first_argument_type; + typedef T second_argument_type; + typedef T result_type; - return value; + ETL_CONSTEXPR T operator()(const T& lhs, const T& rhs) const + { + return lhs + rhs; } }; - template - struct post_increment + //*************************************************************************** + template + struct minus { - T operator()(T& value) + 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 { - T temp(value); - ++value; - return temp; + return lhs - rhs; } }; - template - struct increment : etl::pre_increment + //*************************************************************************** + template + struct negate { - }; + typedef T argument_type; + typedef T result_type; - template - struct pre_decrement - { - T operator()(T& value) + ETL_CONSTEXPR T operator()(const T& lhs) const { - --value; - - return value; + return -lhs; } }; - template - struct post_decrement + //*************************************************************************** + template + struct multiplies { - T operator()(T& value) + 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 { - T temp(value); - --value; - return temp; + return lhs * rhs; } }; - template - struct decrement : etl::pre_decrement + //*************************************************************************** + template + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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; + } }; } diff --git a/include/etl/multi_loop.h b/include/etl/multi_loop.h deleted file mode 100644 index 1bf82fad..00000000 --- a/include/etl/multi_loop.h +++ /dev/null @@ -1,341 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2020 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef ETL_MULTI_LOOP_INCLUDED -#define ETL_MULTI_LOOP_INCLUDED - -#include "platform.h" -#include "nullptr.h" -#include "functional.h" -#include "exception.h" -#include "error_handler.h" - -#undef ETL_FILE -#define ETL_FILE "57" - -namespace etl -{ - //*************************************************************************** - /// Exception for the multi_loop. - //*************************************************************************** - class multi_loop_exception : public etl::exception - { - public: - - multi_loop_exception(string_type reason_, string_type file_name_, numeric_type line_number_) - : exception(reason_, file_name_, line_number_) - { - } - }; - - //*************************************************************************** - /// Circular reference exception. - //*************************************************************************** - class multi_loop_circular_reference : public etl::multi_loop_exception - { - public: - - multi_loop_circular_reference(string_type file_name_, numeric_type line_number_) - : etl::multi_loop_exception(ETL_ERROR_TEXT("multi_loop:circular reference", ETL_FILE"A"), file_name_, line_number_) - { - } - }; - - //*************************************************************************** - /// The base class for multi_loop. - //*************************************************************************** - class imulti_loop - { - public: - - //*************************************************************************** - /// Insert after this loop. - //*************************************************************************** - imulti_loop& insert(imulti_loop& inner_loop) - { - ETL_ASSERT(is_valid(inner_loop), ETL_ERROR(multi_loop_circular_reference)); - - // Remember what the next loop was. - imulti_loop* next = inner; - - // Append the new loop - inner = &inner_loop; - - // Link to the original next loop. - inner_loop.set_last(next); - - return *this; - } - - //*************************************************************************** - /// Append to the most inner loop. - //*************************************************************************** - imulti_loop& append(imulti_loop& inner_loop) - { - ETL_ASSERT(is_valid(inner_loop), ETL_ERROR(multi_loop_circular_reference)); - - if (inner != nullptr) - { - inner->append(inner_loop); - } - else - { - inner = &inner_loop; - } - - return *this; - } - - //*************************************************************************** - /// Unlinks this loop from its inner. - /// Re-starts the loop. - //*************************************************************************** - void clear() - { - inner = ETL_NULLPTR; - start(); - } - - //*************************************************************************** - /// - //*************************************************************************** - bool completed() const - { - return has_completed; - } - - //*************************************************************************** - /// Gets the total number of loops, from this loop inclusive. - //*************************************************************************** - size_t number_of_loops() const - { - size_t count = 1U; - - imulti_loop* p_loop = inner; - - while (p_loop != ETL_NULLPTR) - { - ++count; - p_loop = p_loop->inner; - } - - return count; - } - - //*************************************************************************** - /// Gets the total number of iterations over all loops, from this loop inclusive. - //*************************************************************************** - size_t number_of_iterations() - { - size_t count = 0U; - - for (start(); !completed(); next()) - { - ++count; - } - - return count; - } - - //*************************************************************************** - /// Pure virtual functions. - //*************************************************************************** - virtual void next() = 0; - virtual void start() = 0; - - protected: - - //*************************************************************************** - /// Constructor - //*************************************************************************** - imulti_loop() - : has_completed(true) - , inner(ETL_NULLPTR) - { - } - - //*************************************************************************** - /// Checks that there are no circular references by making sure that the - /// inner loop does not link to this loop. - //*************************************************************************** - bool is_valid(imulti_loop& inner_loop) - { - imulti_loop* loop = &inner_loop; - - while (loop != ETL_NULLPTR) - { - if (loop == this) - { - return false; - } - - loop = loop->inner; - } - - return true; - } - - //*************************************************************************** - /// Set the inner loop of the last linked loop. - //*************************************************************************** - void set_last(imulti_loop* next) - { - // Find the last loop. - imulti_loop* loop = this; - - while (loop->inner != ETL_NULLPTR) - { - loop = loop->inner; - } - - loop->inner = next; - } - - bool has_completed; - imulti_loop* inner; - }; - - //*************************************************************************** - /// multi_loop - /// \tparam T The type to loop over. - /// \tparam TIncrementor The incrementor type that implements operator() to increment. - /// Default = etl::increment, which calls operator ++() for the type. - //*************************************************************************** - template class TIncrementor = etl::increment> - class multi_loop : public imulti_loop - { - public: - - typedef T value_type; - typedef const T& const_reference; - - //*************************************************************************** - /// Constructor - /// \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_) - : first(first_) - , last(last_) - , current(first_) - { - } - - //*************************************************************************** - /// Get a const reference to the starting value of the loop. - //*************************************************************************** - const_reference begin() - { - return first; - } - - //*************************************************************************** - /// Get a const reference to the terminating value of the loop. - /// Equal to the last required value + 1. - //*************************************************************************** - const_reference end() - { - return last; - } - - //*************************************************************************** - /// Initialises the loops to the starting values. - //*************************************************************************** - void start() ETL_OVERRIDE - { - if (inner != ETL_NULLPTR) - { - inner->start(); - } - - current = first; - has_completed = false; - } - - //*************************************************************************** - /// Step to the next logical values in the loops. - //*************************************************************************** - void next() ETL_OVERRIDE - { - has_completed = false; - - if (inner != ETL_NULLPTR) - { - inner->next(); - - if (inner->completed()) - { - has_completed = increment(); - } - } - else - { - has_completed = increment(); - } - } - - //*************************************************************************** - /// Returns a const reference to the current loop value. - //*************************************************************************** - const_reference value() const - { - return current; - } - - private: - - //*************************************************************************** - /// Increments the current loop value. - //*************************************************************************** - bool increment() - { - incrementor(current); - - const bool has_rolled_over = (current == last); - - if (has_rolled_over) - { - current = first; - } - - return has_rolled_over; - } - - TIncrementor 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. - }; -} - -#undef ETL_FILE - -#endif \ No newline at end of file diff --git a/include/etl/multi_range.h b/include/etl/multi_range.h new file mode 100644 index 00000000..e0b3e41a --- /dev/null +++ b/include/etl/multi_range.h @@ -0,0 +1,534 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_MULTI_LOOP_INCLUDED +#define ETL_MULTI_LOOP_INCLUDED + +#include "platform.h" +#include "nullptr.h" +#include "functional.h" +#include "exception.h" +#include "error_handler.h" + +#undef ETL_FILE +#define ETL_FILE "57" + +namespace etl +{ + //*************************************************************************** + /// Exception for the multi_range. + //*************************************************************************** + class multi_range_exception : public etl::exception + { + public: + + multi_range_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// Circular reference exception. + //*************************************************************************** + class multi_range_circular_reference : public etl::multi_range_exception + { + public: + + multi_range_circular_reference(string_type file_name_, numeric_type line_number_) + : etl::multi_range_exception(ETL_ERROR_TEXT("multi_range:circular reference", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// The base class for multi_range. + //*************************************************************************** + class imulti_range + { + public: + + //*************************************************************************** + /// Insert after this range. + //*************************************************************************** + imulti_range& insert(imulti_range& inner_range) + { + ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference)); + + // Remember what the next range was. + imulti_range* next = inner; + + // Append the new range + inner = &inner_range; + + // Link to the original next range. + inner_range.set_last(next); + + return *this; + } + + //*************************************************************************** + /// Append to the most inner range. + //*************************************************************************** + imulti_range& append(imulti_range& inner_range) + { + ETL_ASSERT(is_valid(inner_range), ETL_ERROR(multi_range_circular_reference)); + + if (inner != nullptr) + { + inner->append(inner_range); + } + else + { + inner = &inner_range; + } + + return *this; + } + + //*************************************************************************** + /// Unlinks this range from its inner. + //*************************************************************************** + void detach() + { + inner = ETL_NULLPTR; + } + + //*************************************************************************** + /// Unlinks this and all inner ranges. + //*************************************************************************** + void detach_all() + { + if (inner != ETL_NULLPTR) + { + inner->detach_all(); + } + + detach(); + } + + //*************************************************************************** + /// + //*************************************************************************** + bool completed() const + { + return has_completed; + } + + //*************************************************************************** + /// Gets the total number of ranges, from this range inclusive. + //*************************************************************************** + size_t number_of_ranges() const + { + size_t count = 1U; + + imulti_range* p_range = inner; + + while (p_range != ETL_NULLPTR) + { + ++count; + p_range = p_range->inner; + } + + return count; + } + + //*************************************************************************** + /// Gets the total number of iterations over all ranges, from this range inclusive. + //*************************************************************************** + size_t number_of_iterations() + { + size_t count = 0U; + + for (start(); !completed(); next()) + { + ++count; + } + + return count; + } + + //*************************************************************************** + /// Pure virtual functions. + //*************************************************************************** + virtual void next() = 0; + virtual void start() = 0; + + protected: + + //*************************************************************************** + /// Constructor + //*************************************************************************** + imulti_range() + : has_completed(true) + , inner(ETL_NULLPTR) + { + } + + //*************************************************************************** + /// Checks that there are no circular references. + //*************************************************************************** + bool is_valid(imulti_range& inner_range) + { + imulti_range* range = &inner_range; + + while (range != ETL_NULLPTR) + { + if (range == this) + { + return false; + } + + range = range->inner; + } + + return true; + } + + //*************************************************************************** + /// Set the inner range of the last linked range. + //*************************************************************************** + void set_last(imulti_range* next) + { + // Find the last range. + imulti_range* range = this; + + while (range->inner != ETL_NULLPTR) + { + range = range->inner; + } + + range->inner = next; + } + + bool has_completed; + imulti_range* inner; + }; + + //*************************************************************************** + /// multi_range + /// \tparam T The type to range over. + //*************************************************************************** + template + class multi_range : public imulti_range + { + public: + + typedef T value_type; + typedef const T& const_reference; + + //*************************************************************************** + /// + //*************************************************************************** + struct step_type + { + typedef T value_type; + + virtual void operator()(value_type& value) = 0; + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct forward_step : public step_type + { + typedef T value_type; + + virtual void operator()(value_type& value) + { + ++value; + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct forward_step_by : public step_type + { + typedef T value_type; + + explicit forward_step_by(const value_type& step_value_) + : step_value(step_value_) + { + } + + virtual void operator()(value_type& value) + { + value += step_value; + } + + const value_type step_value; + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct reverse_step : public step_type + { + typedef T value_type; + + virtual void operator()(value_type& value) + { + --value; + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct reverse_step_by : public step_type + { + typedef T value_type; + + explicit reverse_step_by(const value_type& step_value_) + : step_value(step_value_) + { + } + + virtual void operator()(value_type& value) + { + value -= step_value; + } + + const value_type step_value; + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct compare_type + { + typedef T value_type; + + virtual bool operator()(const value_type& current, const value_type& last) const = 0; + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct not_equal_compare : public compare_type + { + typedef T value_type; + + virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE + { + return etl::not_equal_to()(current, last); + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct less_than_compare : public compare_type + { + typedef T value_type; + + virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE + { + return etl::less()(current, last); + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + struct greater_than_compare : public compare_type + { + typedef T value_type; + + virtual bool operator()(const value_type& current, const value_type& last) const ETL_OVERRIDE + { + return etl::greater()(current, last); + } + }; + + //*************************************************************************** + /// Constructor + /// \param first The starting value of the range. + /// \param last The terminating value of the range. Equal to the last required value + 1. + //*************************************************************************** + multi_range(value_type first_, + value_type last_) + : first(first_) + , last(last_) + , current(first_) + , p_stepper(&default_stepper) + , p_compare(&default_compare) + { + } + + //*************************************************************************** + /// Constructor + /// \param first The starting value of the range. + /// \param last The terminating value of the range. Equal to the last required value + 1. + //*************************************************************************** + multi_range(value_type first_, + value_type last_, + step_type& stepper_) + : first(first_) + , last(last_) + , current(first_) + , p_stepper(&stepper_) + , p_compare(&default_compare) + { + } + + //*************************************************************************** + /// Constructor + /// \param first The starting value of the range. + /// \param last The terminating value of the range. + //*************************************************************************** + multi_range(value_type first_, + value_type last_, + compare_type& compare_) + : first(first_) + , last(last_) + , current(first_) + , p_stepper(&default_stepper) + , p_compare(&compare_) + { + } + + //*************************************************************************** + /// Constructor + /// \param first The starting value of the range. + /// \param last The terminating value of the range. Equal to the last required value + 1. + //*************************************************************************** + multi_range(value_type first_, + value_type last_, + step_type& stepper_, + compare_type& compare_) + : first(first_) + , last(last_) + , current(first_) + , p_stepper(&stepper_) + , p_compare(&compare_) + { + } + + //*************************************************************************** + /// Get a const reference to the starting value of the range. + //*************************************************************************** + const_reference begin() + { + return first; + } + + //*************************************************************************** + /// Get a const reference to the terminating value of the range. + /// Equal to the last required value + 1. + //*************************************************************************** + const_reference end() + { + return last; + } + + //*************************************************************************** + /// Initialises the ranges to the starting values. + //*************************************************************************** + void start() ETL_OVERRIDE + { + if (inner != ETL_NULLPTR) + { + inner->start(); + } + + current = first; + has_completed = !(*p_compare)(current, last); // Check for null range. + } + + //*************************************************************************** + /// Step to the next logical values in the ranges. + //*************************************************************************** + void next() ETL_OVERRIDE + { + has_completed = false; + + if (inner != ETL_NULLPTR) + { + inner->next(); + + if (inner->completed()) + { + has_completed = step(); + } + } + else + { + has_completed = step(); + } + } + + //*************************************************************************** + /// Returns a const reference to the current range value. + //*************************************************************************** + const_reference value() const + { + return current; + } + + private: + + //*************************************************************************** + /// Increments the current range value. + //*************************************************************************** + bool step() + { + (*p_stepper)(current); + + const bool has_rolled_over = !(*p_compare)(current, last); + + if (has_rolled_over) + { + current = first; + } + + return has_rolled_over; + } + + multi_range() ETL_DELETE; + multi_range(const multi_range&) ETL_DELETE; + multi_range& operator =(const multi_range&) ETL_DELETE; + + value_type first; ///< The first value of the range. + value_type last; ///< The terminating value of the range. + value_type current; ///< The current value of the range. + + step_type* p_stepper; + forward_step default_stepper; + + compare_type* p_compare; + not_equal_compare default_compare; + }; +} + +#undef ETL_FILE + +#endif \ No newline at end of file diff --git a/test/test_functional.cpp b/test/test_functional.cpp index 3e9856db..0958d1cf 100644 --- a/test/test_functional.cpp +++ b/test/test_functional.cpp @@ -154,63 +154,113 @@ namespace } //************************************************************************* - TEST(test_pre_increment) + TEST(test_plus) { - etl::pre_increment pi; - - int i = 0; - int j = 0; - - pi(i); - j = pi(i); - - CHECK_EQUAL(2, i); - CHECK_EQUAL(2, j); + auto f = etl::plus(); + CHECK_EQUAL(2 + 4, f(2, 4)); } //************************************************************************* - TEST(test_post_increment) + TEST(test_minus) { - etl::post_increment pi; - - int i = 0; - int j = 0; - - pi(i); - j = pi(i); - - CHECK_EQUAL(2, i); - CHECK_EQUAL(1, j); + auto f = etl::minus(); + CHECK_EQUAL(2 - 4, f(2, 4)); } //************************************************************************* - TEST(test_pre_decrement) + TEST(test_negate) { - etl::pre_decrement pi; - - int i = 0; - int j = 0; - - pi(i); - j = pi(i); - - CHECK_EQUAL(-2, i); - CHECK_EQUAL(-2, j); + auto f = etl::negate(); + CHECK_EQUAL(-2, f(2)); } //************************************************************************* - TEST(test_post_decrement) + TEST(test_multiplies) { - etl::post_decrement pi; + auto f = etl::multiplies(); + CHECK_EQUAL(2 * 4, f(2, 4)); + } - int i = 0; - int j = 0; + //************************************************************************* + TEST(test_divides) + { + auto f = etl::divides(); + CHECK_EQUAL(4 / 2, f(4, 2)); + } - pi(i); - j = pi(i); + //************************************************************************* + TEST(test_modulus) + { + auto f = etl::modulus(); + CHECK_EQUAL(5 % 2, f(5, 2)); + } - CHECK_EQUAL(-2, i); - CHECK_EQUAL(-1, j); + //************************************************************************* + TEST(test_logical_and) + { + auto f = etl::logical_and(); + 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(); + 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(); + CHECK_EQUAL(!false, f(false)); + CHECK_EQUAL(!true, f(true)); + } + + //************************************************************************* + TEST(test_bit_and) + { + auto f = etl::bit_and(); + 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(); + 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(); + 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(); + 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)); } }; } diff --git a/test/test_multi_loop.cpp b/test/test_multi_range.cpp similarity index 71% rename from test/test_multi_loop.cpp rename to test/test_multi_range.cpp index b6c5f231..16646c4b 100644 --- a/test/test_multi_loop.cpp +++ b/test/test_multi_range.cpp @@ -28,12 +28,14 @@ SOFTWARE. #include "UnitTest++/UnitTest++.h" -#include "etl/multi_loop.h" +#include "etl/multi_range.h" +#include "etl/functional.h" #include #include #include #include +#include namespace { @@ -107,45 +109,63 @@ namespace using Iterator = std::forward_list::const_iterator; - using Outer = etl::multi_loop; - using Middle = etl::multi_loop; - using Inner = etl::multi_loop; + //************************************************************************* + using StepperOuter = etl::multi_range::forward_step_by; + //************************************************************************* + using StepperMiddle = etl::multi_range::reverse_step; + + //************************************************************************* + using CompareMiddle = etl::multi_range::greater_than_compare; + + // Declare the loops. + using Outer = etl::multi_range; + using Middle = etl::multi_range; + using Inner = etl::multi_range; + + // A list of strings. std::forward_list strings = { "zero", "one", "two", "three" }; - Outer outer(0, 4); - Middle middle(Index(2), Index(-2)); - Inner inner(strings.begin(), strings.end()); + // Outer loop : Iterate from 0 to 6 in steps of 2. + // Keep looping while the value is not equal to 8. + StepperOuter stepperOuter(2); + Outer outer(0, 8, stepperOuter); - SUITE(test_multi_loop) + // Middle loop : Iterate from Index(2) to Index(-1). + // Keep looping while the value is greater than Index(-2). + StepperMiddle stepperMiddle; + CompareMiddle compareMiddle; + Middle middle(Index(2), Index(-2), stepperMiddle, compareMiddle); + + // Inner loop : Iterate from the first to the last string in the forward_list of strings. + // Keep looping while the iterator is not equal to strings.end(). + Inner inner(strings.begin(), strings.end()); + + SUITE(test_multi_range) { //************************************************************************* 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()); - CHECK_EQUAL(1U, inner.number_of_loops()); + CHECK_EQUAL(3U, outer.number_of_ranges()); + CHECK_EQUAL(2U, middle.number_of_ranges()); + CHECK_EQUAL(1U, inner.number_of_ranges()); CHECK_EQUAL(64U, outer.number_of_iterations()); CHECK_EQUAL(16U, middle.number_of_iterations()); 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,32 +175,30 @@ 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()); - CHECK_EQUAL(1U, inner.number_of_loops()); + CHECK_EQUAL(3U, outer.number_of_ranges()); + CHECK_EQUAL(2U, middle.number_of_ranges()); + CHECK_EQUAL(1U, inner.number_of_ranges()); CHECK_EQUAL(64U, outer.number_of_iterations()); CHECK_EQUAL(16U, middle.number_of_iterations()); 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,31 +208,29 @@ 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()); - CHECK_EQUAL(1U, inner.number_of_loops()); + CHECK_EQUAL(3U, outer.number_of_ranges()); + CHECK_EQUAL(2U, middle.number_of_ranges()); + CHECK_EQUAL(1U, inner.number_of_ranges()); CHECK_EQUAL(64U, outer.number_of_iterations()); CHECK_EQUAL(16U, middle.number_of_iterations()); 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 +240,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); + CHECK_THROW(outer.append(middle), etl::multi_range_circular_reference); + CHECK_THROW(inner.append(inner), etl::multi_range_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_ranges()); + + 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 +291,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 +352,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 +423,8 @@ namespace } CHECK(middle.completed()); + + outer.detach_all(); } }; } diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 45e2c03a..7defeade 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1292,7 +1292,7 @@ - + @@ -1863,7 +1863,7 @@ - + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index c59580dd..1a73bbcd 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -906,9 +906,9 @@ ETL\Arduino - + ETL\Utilities - + @@ -1442,7 +1442,7 @@ Source Files - + Source Files @@ -1563,4 +1563,4 @@ Resource Files\Images - + \ No newline at end of file