From d4ca11f9667f3287a5e7d676dc9966a32f41beb2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Sep 2026 18:41:49 +0100 Subject: [PATCH] Further optimsed advance Updated docs and tests --- docs/_index.md | 5 +- docs/utilities/cyclic-value.md | 179 ++++++++++++++----- include/etl/cyclic_value.h | 89 +++++++--- test/run-syntax-checks.sh | 37 ++-- test/test_cyclic_value.cpp | 312 ++++++++++++++++++++++++++++++++- 5 files changed, 525 insertions(+), 97 deletions(-) diff --git a/docs/_index.md b/docs/_index.md index 472fb0ac..b05ae026 100644 --- a/docs/_index.md +++ b/docs/_index.md @@ -118,9 +118,9 @@ CRC calculations (8, 16, 32 & 64-bit) Checksums and hash functions - Variants (type-safe unions) - Extensive template support utilities -- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; user’s choice. +- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; user's choice. - Thoroughly Tested: -Over 10,000 unit tests +Over **14,000** tests Tested with Visual Studio 2022, GCC 12, and Clang 14 Continuous integration via GitHub Actions. - Readable and Well-Documented: Clean, maintainable source code with clear documentation. @@ -128,6 +128,7 @@ Continuous integration via GitHub Actions. - Archived: A snapshot of the ETL is preserved in the Arctic Code Vault for long-term digital preservation. ## Support the ETL + Maintaining the ETL can take a lot of man-hours of work, but unfortunately it doesn't pay the bills. When I have to take on paying work, the ETL gets a lot less attention. So if you have found the library is an important component in your work and you would like to help out, then please consider by supporting the project. --- diff --git a/docs/utilities/cyclic-value.md b/docs/utilities/cyclic-value.md index 37a92b65..6b31c624 100644 --- a/docs/utilities/cyclic-value.md +++ b/docs/utilities/cyclic-value.md @@ -16,6 +16,8 @@ template class cyclic_value ``` +**Example** + ```cpp etl::cyclic_value value_ct; // Compile time. Fixed range of 2 to 7 inclusive. @@ -25,125 +27,172 @@ value_rt.set(3, 8); ## Constructor ```cpp -cyclic_value value; +cyclic_value() noexcept; ``` -Creates a runtime cyclic value of type int with default constructed initial defined limits. +Creates a *run time* cyclic value of type `T` default constructed with the `first` limit. +`constexpr` from C++11. --- ```cpp -cyclic_value value; +cyclic_value(T initial) noexcept; ``` -Creates a compile time cyclic value of type int with fixed limits of N and M. +Creates a *run time* cyclic value of type `T` default constructed with the `initial`. +`initial` will be clamped to be in the range `(First, Last)`. +`constexpr` from C++11. + +--- -**Example** ```cpp -cyclic_value value(N, M); +cyclic_value(T first, T last) noexcept; ``` -Creates a runtime cyclic value of type int with initial defined limits of N and M. +Creates a *compile time* cyclic value of type `T` with limits of `first` and `fast` and default constructed with `first`. +`constexpr` from C++11. + +--- + +```cpp +cyclic_value(T first, T last, T initial) noexcept; +``` +Creates a *run time* cyclic value of type `T` with limits of `first` and `fast` and default constructed with `initial`. +`constexpr` from C++11. + +--- + +```cpp +cyclic_value() noexcept; +``` +Creates a *compile time* cyclic value of type `T` with fixed limits of `First` and `Last` and default constructed with `First`. +`constexpr` from C++11. ## Modifiers ```cpp -cyclic_value& operator ++(); -cyclic_value& operator ++(int); +cyclic_value& operator ++() noexcept; +cyclic_value& operator ++(int) noexcept; ``` -Increments the value. If the value is at the last value then is set to the first. +Increments the value. If the value is at the last value then is set to the first. +`constexpr` from C++14. --- ```cpp -cyclic_value& operator --(); -cyclic_value& operator --(int); +cyclic_value& operator --() noexcept; +cyclic_value& operator --(int) noexcept; ``` -Decrements the value. If the value is at the first value then is set to the last. +Decrements the value. If the value is at the first value then is set to the last. +`constexpr` from C++14. --- ```cpp -void advance(int n); +template +void advance(TStep n) noexcept; ``` -Advances the value by the specified amount, wrapping if necessary. +Advances the value by the specified amount, wrapping if necessary. +`constexpr` from C++14. + +--- + +```cpp +template +cyclic_value& operator +=(TSTep n) noexcept; +``` +Advances the value by the specified amount, wrapping if necessary. +`constexpr` from C++14. + +--- + +```cpp +template +cyclic_value& operator -=(TSTep n) noexcept; +``` +Decrements the value by the specified amount, wrapping if necessary. +`constexpr` from C++14. ## Access ```cpp T get() const; ``` -Gets the current value +Gets the current value. +`constexpr` from C++11. --- ```cpp -T first() const; +T first() const noexcept; ``` -Sets the current value to the first value +Gets the first value. +`constexpr` from C++11. --- ```cpp -T last() const; +T last() const noexcept; ``` -Sets the current value to the last value +Gets the last value. +`constexpr` from C++11. --- ```cpp -void set(T first, T last); +void set(T first, T last) noexcept; ``` -Sets the new first and last values. Sets the current value to first. +Sets the new *run time* `first` and `last` values. Sets the current value to `first`. +`constexpr` from C++14. --- ```cpp -void set(T value); +void set(T value) noexcept; ``` -Sets the current value. +Sets the current value. +`constexpr` from C++14. --- ```cpp -void to_first(); +void to_first() noexcept; ``` -Sets the current value to the first value +Sets the current value to the first value. +`constexpr` from C++14. --- ```cpp -void to_last(); +void to_last() noexcept; ``` -Sets the current value to the last value +Sets the current value to the last value. +`constexpr` from C++14. ## Operations ```cpp -void swap(cyclic_value& other); +void swap(cyclic_value& other) noexcept; ``` -Swaps with another cyclic value. +Swaps with another cyclic value. +`constexpr` from C++14. ---- - -```cpp -void swap(cyclic_value& lhs, cyclic_value& rhs); -``` -Swaps with another cyclic value. ## Operators ```cpp -operator T(); -operator const T() const; +operator T() noexcept; +operator const T() const noexcept; ``` -Conversion operators to `T`. +Conversion operators to `T`. +`constexpr` from C++11. --- ```cpp -cyclic_value& operator =(T t); +cyclic_value& operator =(T t) noexcept; ``` -Sets the current value to `t`. +Sets the current value to `t`. +`constexpr` from C++14. ## Non-member functions ```cpp template -void swap(cyclic_value& lhs, cyclic_value& rhs) +void swap(cyclic_value& lhs, cyclic_value& rhs) noexcept ``` Swaps two cyclic values. @@ -151,14 +200,52 @@ Swaps two cyclic values. ```cpp template -bool operator == (cyclic_value& lhs, cyclic_value& rhs) +bool operator == (cyclic_value& lhs, cyclic_value& rhs) noexcept ``` -Checks equality of two cyclic values. +Checks equality of two cyclic values. +`constexpr` from C++11. --- ```cpp template -bool operator != (cyclic_value& lhs, cyclic_value& rhs) +bool operator != (cyclic_value& lhs, cyclic_value& rhs) noexcept ``` -Checks inequality of two cyclic values. +Checks inequality of two cyclic values. +`constexpr` from C++11. + +--- + +```cpp +template +bool operator < (cyclic_value& lhs, cyclic_value& rhs) noexcept +``` +Checks if the current value of `lhs` is less than the current value of `rhs`. +`constexpr` from C++11. + +--- + +```cpp +template +bool operator <= (cyclic_value& lhs, cyclic_value& rhs) noexcept +``` +Checks if the current value of `lhs` is less than or equal the current value of `rhs`. +`constexpr` from C++11. + +--- + +```cpp +template +bool operator > (cyclic_value& lhs, cyclic_value& rhs) noexcept +``` +Checks if the current value of `lhs` is greater than the current value of `rhs`. +`constexpr` from C++11. + +--- + +```cpp +template +bool operator >= (cyclic_value& lhs, cyclic_value& rhs) noexcept +``` +Checks if the current value of `lhs` is greater than or equal the current value of `rhs`. +`constexpr` from C++11. diff --git a/include/etl/cyclic_value.h b/include/etl/cyclic_value.h index 6f20cfeb..0470284b 100644 --- a/include/etl/cyclic_value.h +++ b/include/etl/cyclic_value.h @@ -53,6 +53,34 @@ namespace etl typedef typename etl::make_unsigned::type unsigned_type; }; + //************************************************************************* + /// Increments a value and wraps it at the supplied limits. + ///\param value The current value. + ///\param min_value The minimum value. + ///\param max_value The maximum value. + ///\return The new value. + //************************************************************************* + template + ETL_NODISCARD + static ETL_CONSTEXPR14 T increment(T value, T min_value, T max_value) ETL_NOEXCEPT + { + return value == max_value ? min_value : static_cast(etl::to_unsigned(value) + 1U); + } + + //************************************************************************* + /// Decrements a value and wraps it at the supplied limits. + ///\param value The current value. + ///\param min_value The minimum value. + ///\param max_value The maximum value. + ///\return The new value. + //************************************************************************* + template + ETL_NODISCARD + static ETL_CONSTEXPR14 T decrement(T value, T min_value, T max_value) ETL_NOEXCEPT + { + return value == min_value ? max_value : static_cast(etl::to_unsigned(value) - 1U); + } + //************************************************************************* /// Advances a value and wraps it at the supplied limits. ///\param value The current value. @@ -63,23 +91,30 @@ namespace etl //************************************************************************* template ETL_NODISCARD - static ETL_CONSTEXPR14 T advance(T value, T min_value, T max_value, typename traits::unsigned_type unsigned_abs_value, - typename traits::unsigned_type unsigned_value, bool is_negative) ETL_NOEXCEPT + static ETL_CONSTEXPR14 T advance(T value, T min_value, T max_value, typename traits::unsigned_type unsigned_abs_step, + typename traits::unsigned_type unsigned_step, bool is_negative) ETL_NOEXCEPT { typedef typename traits::unsigned_type unsigned_type; - if (unsigned_abs_value == 0) + // No change if the step is zero. + if (unsigned_abs_step == 0) { return value; } + // Use the increment/decrement functions for a single step. + if (unsigned_abs_step == 1) + { + return is_negative ? decrement(value, min_value, max_value) : increment(value, min_value, max_value); + } + // Check for full range limits. const bool is_full_range = (min_value == etl::integral_limits::min) && (max_value == etl::integral_limits::max); if (is_full_range) { // This is safe as the type's own overflow behaviour is modulo wrap-around. - return static_cast(etl::to_unsigned(value) + unsigned_value); + return static_cast(etl::to_unsigned(value) + unsigned_step); } else { @@ -90,7 +125,7 @@ namespace etl const unsigned_type current = etl::to_unsigned(value) - etl::to_unsigned(min_value); // Reduce the step to something within a single lap of the range. - const unsigned_type step = unsigned_abs_value % range; + const unsigned_type step = unsigned_abs_step % range; // Direction-corrected offset to add, always in [0, range). const unsigned_type offset = is_negative ? (range - step) % range : step; @@ -182,11 +217,12 @@ namespace etl template ETL_CONSTEXPR14 cyclic_value& operator-=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - const unsigned_type unsigned_abs_value = etl::absolute_unsigned(n); - const unsigned_type unsigned_value = static_cast(n); - const bool is_negative = etl::is_negative(-n); + // Prepare the parameters for the advance function. + const unsigned_type unsigned_abs_step = etl::absolute_unsigned(n); + const unsigned_type unsigned_step = etl::to_unsigned(n); + const bool is_negative = etl::is_negative(-n); - value = private_cyclic_value::advance(value, First, Last, unsigned_abs_value, unsigned_value, is_negative); + value = private_cyclic_value::advance(value, First, Last, unsigned_abs_step, unsigned_step, is_negative); return *this; } @@ -223,11 +259,12 @@ namespace etl template ETL_CONSTEXPR14 void advance(TStep n) ETL_NOEXCEPT { - const unsigned_type unsigned_abs_value = etl::absolute_unsigned(n); - const unsigned_type unsigned_value = static_cast(n); - const bool is_negative = etl::is_negative(n); + // Prepare the parameters for the advance function. + const unsigned_type unsigned_abs_step = etl::absolute_unsigned(n); + const unsigned_type unsigned_step = etl::to_unsigned(n); + const bool is_negative = etl::is_negative(n); - value = private_cyclic_value::advance(value, First, Last, unsigned_abs_value, unsigned_value, is_negative); + value = private_cyclic_value::advance(value, First, Last, unsigned_abs_step, unsigned_step, is_negative); } //************************************************************************* @@ -244,7 +281,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 cyclic_value& operator++() ETL_NOEXCEPT { - value = private_cyclic_value::advance(value, First, Last, static_cast(1), static_cast(1), false); + value = private_cyclic_value::increment(value, First, Last); return *this; } @@ -266,7 +303,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 cyclic_value& operator--() ETL_NOEXCEPT { - value = private_cyclic_value::advance(value, First, Last, static_cast(1), static_cast(1), true); + value = private_cyclic_value::decrement(value, First, Last); return *this; } @@ -476,11 +513,12 @@ namespace etl template ETL_CONSTEXPR14 void advance(TStep n) ETL_NOEXCEPT { - const unsigned_type unsigned_abs_value = etl::absolute_unsigned(n); - const unsigned_type unsigned_value = static_cast(n); - const bool is_negative = etl::is_negative(n); + // Prepare the parameters for the advance function. + const unsigned_type unsigned_abs_step = etl::absolute_unsigned(n); + const unsigned_type unsigned_step = etl::to_unsigned(n); + const bool is_negative = etl::is_negative(n); - value = private_cyclic_value::advance(value, first_value, last_value, unsigned_abs_value, unsigned_value, is_negative); + value = private_cyclic_value::advance(value, first_value, last_value, unsigned_abs_step, unsigned_step, is_negative); } //************************************************************************* @@ -497,7 +535,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 cyclic_value& operator++() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - value = private_cyclic_value::advance(value, first_value, last_value, static_cast(1), static_cast(1), false); + value = private_cyclic_value::increment(value, first_value, last_value); return *this; } @@ -519,7 +557,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 cyclic_value& operator--() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - value = private_cyclic_value::advance(value, first_value, last_value, static_cast(1), static_cast(1), true); + value = private_cyclic_value::decrement(value, first_value, last_value); return *this; } @@ -578,11 +616,12 @@ namespace etl template ETL_CONSTEXPR14 cyclic_value& operator-=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT { - const unsigned_type unsigned_abs_value = etl::absolute_unsigned(n); - const unsigned_type unsigned_value = static_cast(n); - const bool is_negative = etl::is_negative(-n); + // Prepare the parameters for the advance function. + const unsigned_type unsigned_abs_step = etl::absolute_unsigned(n); + const unsigned_type unsigned_step = etl::to_unsigned(n); + const bool is_negative = etl::is_negative(-n); - value = private_cyclic_value::advance(value, first_value, last_value, unsigned_abs_value, unsigned_value, is_negative); + value = private_cyclic_value::advance(value, first_value, last_value, unsigned_abs_step, unsigned_step, is_negative); return *this; } diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index fcac0287..6a7de145 100755 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -11,14 +11,14 @@ TitleColour=$'\033[38;2;107;210;255m' HelpColour=$'\033[38;2;250;180;250m' NoColour=$'\033[0m' -ParseGitBranch() +ParseGitBranch() { git rev-parse --abbrev-ref HEAD } SetConfigurationName() { - configuration_name=$1 + configuration_name=$1 } PrintHeader() @@ -147,10 +147,9 @@ RunCheck() local cc_name=$1 local msg=$2 local no_stl=$3 - local builtins=$4 - local user_defined=$5 - local force_03=$6 - local build_dir=$7 + local user_defined=$4 + local force_03=$5 + local build_dir=$6 if [ "$compiler_enabled" != "$cc_name" ] && [ "$compiler_enabled" != "All compilers" ]; then return @@ -171,7 +170,7 @@ RunCheck() rm -rdf bgcc rm -rdf bclang cmake -E make_directory bgcc bclang - CC=$cc CXX=$cxx cmake -E chdir $build_dir cmake -DNO_STL=$no_stl -DETL_USE_TYPE_TRAITS_BUILTINS=$builtins -DETL_USER_DEFINED_TYPE_TRAITS=$user_defined -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=$force_03 -DETL_CXX_STANDARD=$cxx_standard .. + CC=$cc CXX=$cxx cmake -E chdir $build_dir cmake -DNO_STL=$no_stl -DETL_USER_DEFINED_TYPE_TRAITS=$user_defined -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=$force_03 -DETL_CXX_STANDARD=$cxx_standard .. cmake --build $build_dir if [ $? -eq 0 ]; then PassedCompilation @@ -193,25 +192,25 @@ RunStandard() cxx_standard=$std # GCC configurations - RunCheck gcc "STL" OFF OFF OFF OFF bgcc - RunCheck gcc "No STL" ON OFF OFF OFF bgcc - RunCheck gcc "STL - Built-in traits" OFF ON OFF OFF bgcc - RunCheck gcc "No STL - Built-in traits" ON ON OFF OFF bgcc + RunCheck gcc "STL" OFF OFF OFF bgcc + RunCheck gcc "No STL" ON OFF OFF bgcc + RunCheck gcc "STL - Built-in traits" OFF OFF OFF bgcc + RunCheck gcc "No STL - Built-in traits" ON OFF OFF bgcc if [ "$has_force_03" = "1" ]; then - RunCheck gcc "STL - Force C++03" OFF OFF OFF ON bgcc - RunCheck gcc "No STL - Force C++03" ON OFF OFF ON bgcc + RunCheck gcc "STL - Force C++03" OFF OFF ON bgcc + RunCheck gcc "No STL - Force C++03" ON OFF ON bgcc fi # Clang configurations - RunCheck clang "STL" OFF OFF OFF OFF bclang - RunCheck clang "No STL" ON OFF OFF OFF bclang - RunCheck clang "STL - Built-in traits" OFF ON OFF OFF bgcc - RunCheck clang "No STL - Built-in traits" ON ON OFF OFF bgcc + RunCheck clang "STL" OFF OFF OFF bclang + RunCheck clang "No STL" ON OFF OFF bclang + RunCheck clang "STL - Built-in traits" OFF OFF OFF bclang + RunCheck clang "No STL - Built-in traits" ON OFF OFF bclang if [ "$has_force_03" = "1" ]; then - RunCheck clang "STL - Force C++03" OFF OFF OFF ON bclang - RunCheck clang "No STL - Force C++03" ON OFF OFF ON bclang + RunCheck clang "STL - Force C++03" OFF OFF ON bclang + RunCheck clang "No STL - Force C++03" ON OFF ON bclang fi } diff --git a/test/test_cyclic_value.cpp b/test/test_cyclic_value.cpp index 7077628a..045d5be6 100644 --- a/test/test_cyclic_value.cpp +++ b/test/test_cyclic_value.cpp @@ -336,7 +336,7 @@ namespace { etl::cyclic_value value; - value.advance(14); + value.advance(20); CHECK_EQUAL(4, value); } @@ -347,7 +347,7 @@ namespace etl::cyclic_value value; value.set(2, 7); - value.advance(14); + value.advance(20); CHECK_EQUAL(4, value); } @@ -358,7 +358,7 @@ namespace etl::cyclic_value value; value.to_last(); - value.advance(-14); + value.advance(-20); CHECK_EQUAL(5, value); } @@ -370,7 +370,7 @@ namespace value.set(2, 7); value.to_last(); - value.advance(-14); + value.advance(-20); CHECK_EQUAL(5, value); } @@ -408,6 +408,180 @@ namespace CHECK_EQUAL(1U, value); } + //************************************************************************* + TEST(test_add_positive_n_compile_time) + { + etl::cyclic_value value; + + value += 2; + + CHECK_EQUAL(4, value); + } + + //************************************************************************* + TEST(test_add_positive_n_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value += 2; + + CHECK_EQUAL(4, value); + } + + //************************************************************************* + TEST(test_add_positive_n_large_compile_time) + { + etl::cyclic_value value; + + value += 20; + + CHECK_EQUAL(4, value); + } + + //************************************************************************* + TEST(test_add_positive_n_large_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value += 20; + + CHECK_EQUAL(4, value); + } + + //************************************************************************* + TEST(test_add_negative_n_large_compile_time) + { + etl::cyclic_value value; + + value.to_last(); + value += -20; + + CHECK_EQUAL(5, value); + } + + //************************************************************************* + TEST(test_add_negative_n_large_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value.to_last(); + value += -20; + + CHECK_EQUAL(5, value); + } + + //************************************************************************* + TEST(test_add_negative_n_unsigned_compile_time) + { + etl::cyclic_value value; + + value += -2; + + CHECK_EQUAL(1U, value); + } + + //************************************************************************* + TEST(test_add_negative_n_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value.to_last(); + value += -20; + + CHECK_EQUAL(5, value); + } + + //************************************************************************* + TEST(test_decrease_positive_compile_time) + { + etl::cyclic_value value; + + value -= 2; + + CHECK_EQUAL(6, value); + } + + //************************************************************************* + TEST(test_subtract_positive_n_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value -= 2; + + CHECK_EQUAL(6, value); + } + + //************************************************************************* + TEST(test_subtract_positive_n_large_compile_time) + { + etl::cyclic_value value; + + value -= 20; + + CHECK_EQUAL(6, value); + } + + //************************************************************************* + TEST(test_subtract_positive_n_large_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value -= 20; + + CHECK_EQUAL(6, value); + } + + //************************************************************************* + TEST(test_subtract_negative_n_large_compile_time) + { + etl::cyclic_value value; + + value.to_last(); + value -= -20; + + CHECK_EQUAL(3, value); + } + + //************************************************************************* + TEST(test_subtract_negative_n_large_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value.to_last(); + value -= -20; + + CHECK_EQUAL(3, value); + } + + //************************************************************************* + TEST(test_subtract_negative_n_unsigned_compile_time) + { + etl::cyclic_value value; + + value -= -2; + + CHECK_EQUAL(2U, value); + } + + //************************************************************************* + TEST(test_subtract_negative_n_run_time) + { + etl::cyclic_value value; + + value.set(2, 7); + value.to_last(); + value -= -20; + + CHECK_EQUAL(3, value); + } + //************************************************************************* TEST(test_assignment_compile_time) { @@ -493,7 +667,50 @@ namespace CHECK(data2 == compare1); } -#if ETL_USING_CPP14 + //************************************************************************* + TEST(test_comparison_operators) + { + etl::cyclic_value cv1(3); + etl::cyclic_value cv2(3); + etl::cyclic_value cv3(5); + etl::cyclic_value cv4(3); + + CHECK_TRUE(cv1 == cv2); + CHECK_FALSE(cv1 == cv3); + + CHECK_FALSE(cv1 != cv2); + CHECK_TRUE(cv1 != cv3); + + CHECK_FALSE(cv1 < cv2); + CHECK_FALSE(cv2 < cv1); + CHECK_TRUE(cv1 < cv3); + CHECK_FALSE(cv3 < cv1); + CHECK_FALSE(cv1 < cv4); + CHECK_FALSE(cv4 < cv1); + + CHECK_FALSE(cv1 > cv2); + CHECK_FALSE(cv2 > cv1); + CHECK_FALSE(cv1 > cv3); + CHECK_TRUE(cv3 > cv1); + CHECK_FALSE(cv1 > cv4); + CHECK_FALSE(cv4 > cv1); + + CHECK_TRUE(cv1 <= cv2); + CHECK_TRUE(cv2 <= cv1); + CHECK_TRUE(cv1 <= cv3); + CHECK_FALSE(cv3 <= cv1); + CHECK_TRUE(cv1 <= cv4); + CHECK_TRUE(cv4 <= cv1); + + CHECK_TRUE(cv1 >= cv2); + CHECK_TRUE(cv2 >= cv1); + CHECK_FALSE(cv1 >= cv3); + CHECK_TRUE(cv3 >= cv1); + CHECK_TRUE(cv1 >= cv4); + CHECK_TRUE(cv4 >= cv1); + } + +#if ETL_USING_CPP11 //************************************************************************* TEST(test_cyclic_value_constexpr_ctor) { @@ -519,6 +736,91 @@ namespace static_assert(cv2.get() == 0, "constexpr copy ctor"); CHECK(true); } + + //************************************************************************* + TEST(test_constexpr_comparison_operators) + { + constexpr etl::cyclic_value cv1(3); + constexpr etl::cyclic_value cv2(3); + constexpr etl::cyclic_value cv3(5); + constexpr etl::cyclic_value cv4(3); + + static_assert((cv1 == cv2), "(cv1 == cv2) failed"); + static_assert(!(cv1 == cv3), "!(cv1 == cv3) failed"); + + static_assert(!(cv1 != cv2), "!(cv1 != cv2) failed"); + static_assert((cv1 != cv3), "(cv1 != cv3) failed"); + + static_assert(!(cv1 < cv2), "!(cv1 < cv2) failed"); + static_assert(!(cv2 < cv1), "!(cv2 < cv1) failed"); + static_assert((cv1 < cv3), "(cv1 < cv3) failed"); + static_assert(!(cv3 < cv1), "!(cv3 < cv1) failed"); + static_assert(!(cv1 < cv4), "!(cv1 < cv4) failed"); + static_assert(!(cv4 < cv1), "!(cv4 < cv1) failed"); + + static_assert(!(cv1 > cv2), "!(cv1 > cv2) failed"); + static_assert(!(cv2 > cv1), "!(cv2 > cv1) failed"); + static_assert(!(cv1 > cv3), "!(cv1 > cv3) failed"); + static_assert((cv3 > cv1), "(cv3 > cv1) failed"); + static_assert(!(cv1 > cv4), "!(cv1 > cv4) failed"); + static_assert(!(cv4 > cv1), "!(cv4 > cv1) failed"); + + static_assert((cv1 <= cv2), "(cv1 <= cv2) failed"); + static_assert((cv2 <= cv1), "(cv2 <= cv1) failed"); + static_assert((cv1 <= cv3), "(cv1 <= cv3) failed"); + static_assert(!(cv3 <= cv1), "!(cv3 <= cv1) failed"); + static_assert((cv1 <= cv4), "(cv1 <= cv4) failed"); + static_assert((cv4 <= cv1), "(cv4 <= cv1) failed"); + + static_assert((cv1 >= cv2), "(cv1 >= cv2) failed"); + static_assert((cv2 >= cv1), "(cv2 >= cv1) failed"); + static_assert(!(cv1 >= cv3), "!(cv1 >= cv3) failed"); + static_assert((cv3 >= cv1), "(cv3 >= cv1) failed"); + static_assert((cv1 >= cv4), "(cv1 >= cv4) failed"); + static_assert((cv4 >= cv1), "(cv4 >= cv1) failed"); + } #endif + + //************************************************************************* + TEST(test_maximum_unsigned_range_wrap_with_large_step_type) + { + etl::cyclic_value value(0); + + value.advance(static_cast(255)); + CHECK_EQUAL(255, value); + + value.advance(static_cast(1)); + CHECK_EQUAL(0, value); + + value.advance(static_cast(256)); + CHECK_EQUAL(0, value); + + value.advance(static_cast(-256)); + CHECK_EQUAL(0, value); + + value.advance(static_cast(-1)); + CHECK_EQUAL(255, value); + } + + //************************************************************************* + TEST(test_maximum_signed_range_wrap_with_large_step_type) + { + etl::cyclic_value value(0); + + value.advance(static_cast(127)); + CHECK_EQUAL(127, int(value)); + + value.advance(static_cast(1)); + CHECK_EQUAL(-128, int(value)); + + value.advance(static_cast(256)); + CHECK_EQUAL(-128, int(value)); + + value.advance(static_cast(-256)); + CHECK_EQUAL(-128, int(value)); + + value.advance(static_cast(-1)); + CHECK_EQUAL(127, int(value)); + } } } // namespace