Further optimsed advance

Updated docs and tests
This commit is contained in:
John Wellbelove 2026-09-14 18:41:49 +01:00
parent 295439c2cd
commit d4ca11f966
5 changed files with 525 additions and 97 deletions

View File

@ -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.
---

View File

@ -16,6 +16,8 @@ template <typename T, const T First = 0, const T Last = 0>
class cyclic_value
```
**Example**
```cpp
etl::cyclic_value<int, 2, 7> value_ct; // Compile time. Fixed range of 2 to 7 inclusive.
@ -25,125 +27,172 @@ value_rt.set(3, 8);
## Constructor
```cpp
cyclic_value<int> value;
cyclic_value<T>() 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<int, N, M> value;
cyclic_value<T>(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<int> value(N, M);
cyclic_value<T, First, Last>(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, Last>(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<T, First, Last>() 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 <typename TStep>
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 <typename TStep>
cyclic_value& operator +=(TSTep n) noexcept;
```
Advances the value by the specified amount, wrapping if necessary.
`constexpr` from C++14.
---
```cpp
template <typename TStep>
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<T, FIRST, LAST>& other);
void swap(cyclic_value<T, FIRST, LAST>& other) noexcept;
```
Swaps with another cyclic value.
Swaps with another cyclic value.
`constexpr` from C++14.
---
```cpp
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& 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 <typename T, const T FIRST, const T LAST>
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Swaps two cyclic values.
@ -151,14 +200,52 @@ Swaps two cyclic values.
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator == (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
bool operator == (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks equality of two cyclic values.
Checks equality of two cyclic values.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator != (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
bool operator != (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks inequality of two cyclic values.
Checks inequality of two cyclic values.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator < (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is less than the current value of `rhs`.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator <= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& 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 <typename T, const T FIRST, const T LAST>
bool operator > (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is greater than the current value of `rhs`.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator >= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is greater than or equal the current value of `rhs`.
`constexpr` from C++11.

View File

@ -53,6 +53,34 @@ namespace etl
typedef typename etl::make_unsigned<T>::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 <typename T>
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<T>(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 <typename T>
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<T>(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 <typename T>
ETL_NODISCARD
static ETL_CONSTEXPR14 T advance(T value, T min_value, T max_value, typename traits<T>::unsigned_type unsigned_abs_value,
typename traits<T>::unsigned_type unsigned_value, bool is_negative) ETL_NOEXCEPT
static ETL_CONSTEXPR14 T advance(T value, T min_value, T max_value, typename traits<T>::unsigned_type unsigned_abs_step,
typename traits<T>::unsigned_type unsigned_step, bool is_negative) ETL_NOEXCEPT
{
typedef typename traits<T>::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<T>::min) && (max_value == etl::integral_limits<T>::max);
if (is_full_range)
{
// This is safe as the type's own overflow behaviour is modulo wrap-around.
return static_cast<T>(etl::to_unsigned(value) + unsigned_value);
return static_cast<T>(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 <typename TStep>
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<unsigned_type>(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 <typename TStep>
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<unsigned_type>(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<unsigned_type>(1), static_cast<unsigned_type>(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<unsigned_type>(1), static_cast<unsigned_type>(1), true);
value = private_cyclic_value::decrement(value, First, Last);
return *this;
}
@ -476,11 +513,12 @@ namespace etl
template <typename TStep>
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<unsigned_type>(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<unsigned_type>(1), static_cast<unsigned_type>(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<unsigned_type>(1), static_cast<unsigned_type>(1), true);
value = private_cyclic_value::decrement(value, first_value, last_value);
return *this;
}
@ -578,11 +616,12 @@ namespace etl
template <typename TStep>
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<unsigned_type>(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;
}

View File

@ -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
}

View File

@ -336,7 +336,7 @@ namespace
{
etl::cyclic_value<int, 2, 7> value;
value.advance(14);
value.advance(20);
CHECK_EQUAL(4, value);
}
@ -347,7 +347,7 @@ namespace
etl::cyclic_value<int> value;
value.set(2, 7);
value.advance(14);
value.advance(20);
CHECK_EQUAL(4, value);
}
@ -358,7 +358,7 @@ namespace
etl::cyclic_value<int, 2, 7> 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<int, 2, 7> value;
value += 2;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value += 2;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value += 20;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value += 20;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_negative_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value.to_last();
value += -20;
CHECK_EQUAL(5, value);
}
//*************************************************************************
TEST(test_add_negative_n_large_run_time)
{
etl::cyclic_value<int> 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<size_t, 0U, 2U> value;
value += -2;
CHECK_EQUAL(1U, value);
}
//*************************************************************************
TEST(test_add_negative_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value.to_last();
value += -20;
CHECK_EQUAL(5, value);
}
//*************************************************************************
TEST(test_decrease_positive_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value -= 2;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value -= 2;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value -= 20;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value -= 20;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value.to_last();
value -= -20;
CHECK_EQUAL(3, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_large_run_time)
{
etl::cyclic_value<int> 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<size_t, 0U, 2U> value;
value -= -2;
CHECK_EQUAL(2U, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_run_time)
{
etl::cyclic_value<int> 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<int, 0, 9> cv1(3);
etl::cyclic_value<int, 0, 9> cv2(3);
etl::cyclic_value<int, 0, 9> cv3(5);
etl::cyclic_value<int, -1, 8> 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<int, 0, 9> cv1(3);
constexpr etl::cyclic_value<int, 0, 9> cv2(3);
constexpr etl::cyclic_value<int, 0, 9> cv3(5);
constexpr etl::cyclic_value<int, -1, 8> 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<uint8_t, 0, 255> value(0);
value.advance(static_cast<int32_t>(255));
CHECK_EQUAL(255, value);
value.advance(static_cast<int32_t>(1));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(256));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(-256));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(-1));
CHECK_EQUAL(255, value);
}
//*************************************************************************
TEST(test_maximum_signed_range_wrap_with_large_step_type)
{
etl::cyclic_value<int8_t, -128, 127> value(0);
value.advance(static_cast<int32_t>(127));
CHECK_EQUAL(127, int(value));
value.advance(static_cast<int32_t>(1));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(256));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(-256));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(-1));
CHECK_EQUAL(127, int(value));
}
}
} // namespace