Merge branch 'development' into fix-tuple-review

This commit is contained in:
John Wellbelove 2026-03-25 19:00:28 +00:00 committed by GitHub
commit be47621909
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 583 additions and 134 deletions

View File

@ -2005,11 +2005,12 @@ namespace etl
for (TIterator1 i = begin1; i != end1; ++i)
{
if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i)))
const typename etl::binder1st<TBinaryPredicate> predicate_is_i = etl::bind1st(predicate, *i);
if (i == etl::find_if(begin1, i, predicate_is_i))
{
size_t n = etl::count_if(begin2, end2, etl::bind1st(predicate, *i));
size_t n = etl::count_if(begin2, end2, predicate_is_i);
if (n == 0 || size_t(etl::count_if(i, end1, etl::bind1st(predicate, *i))) != n)
if (n == 0 || size_t(etl::count_if(i, end1, predicate_is_i)) != n)
{
return false;
}
@ -2038,15 +2039,18 @@ namespace etl
return false;
}
for (TIterator1 i = begin1; i != end1; ++i)
if (begin1 != end1)
{
if (i == etl::find(begin1, i, *i))
for (TIterator1 i = begin1; i != end1; ++i)
{
size_t n = etl::count(begin2, end2, *i);
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
if (i == etl::find(begin1, i, *i))
{
return false;
size_t n = etl::count(begin2, end2, *i);
if (n == 0 || size_t(etl::count(i, end1, *i)) != n)
{
return false;
}
}
}
}
@ -2073,15 +2077,19 @@ namespace etl
return false;
}
for (TIterator1 i = begin1; i != end1; ++i)
if (begin1 != end1)
{
if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i)))
for (TIterator1 i = begin1; i != end1; ++i)
{
size_t n = etl::count_if(begin2, end2, etl::bind1st(predicate, *i));
if (n == 0 || size_t(etl::count_if(i, end1, etl::bind1st(predicate, *i))) != n)
const typename etl::binder1st<TBinaryPredicate> predicate_is_i = etl::bind1st(predicate, *i);
if (i == etl::find_if(begin1, i, predicate_is_i))
{
return false;
size_t n = etl::count_if(begin2, end2, predicate_is_i);
if (n == 0 || size_t(etl::count_if(i, end1, predicate_is_i)) != n)
{
return false;
}
}
}
}
@ -2089,6 +2097,132 @@ namespace etl
return true;
}
//***************************************************************************
/// next_permutation
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/next_permutation"></a>
//***************************************************************************
template <typename TIterator, typename TCompare>
ETL_CONSTEXPR14
bool next_permutation(TIterator first, TIterator last, TCompare compare)
{
if (first == last)
{
return false;
}
TIterator i = last;
--i;
if (first == i)
{
return false;
}
while (true)
{
TIterator i1 = i;
--i;
if (compare(*i, *i1))
{
TIterator j = last;
--j;
while (!compare(*i, *j))
{
--j;
}
etl::iter_swap(i, j);
etl::reverse(i1, last);
return true;
}
if (i == first)
{
etl::reverse(first, last);
return false;
}
}
}
//***************************************************************************
/// next_permutation
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/next_permutation"></a>
//***************************************************************************
template <typename TIterator>
ETL_CONSTEXPR14
bool next_permutation(TIterator first, TIterator last)
{
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
return etl::next_permutation(first, last, compare());
}
//***************************************************************************
/// prev_permutation
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/prev_permutation"></a>
//***************************************************************************
template <typename TIterator, typename TCompare>
ETL_CONSTEXPR14
bool prev_permutation(TIterator first, TIterator last, TCompare compare)
{
if (first == last)
{
return false;
}
TIterator i = last;
--i;
if (first == i)
{
return false;
}
while (true)
{
TIterator i1 = i;
--i;
if (compare(*i1, *i))
{
TIterator j = last;
--j;
while (!compare(*j, *i))
{
--j;
}
etl::iter_swap(i, j);
etl::reverse(i1, last);
return true;
}
if (i == first)
{
etl::reverse(first, last);
return false;
}
}
}
//***************************************************************************
/// prev_permutation
///\ingroup algorithm
///<a href="http://en.cppreference.com/w/cpp/algorithm/prev_permutation"></a>
//***************************************************************************
template <typename TIterator>
ETL_CONSTEXPR14
bool prev_permutation(TIterator first, TIterator last)
{
typedef etl::less<typename etl::iterator_traits<TIterator>::value_type> compare;
return etl::prev_permutation(first, last, compare());
}
//***************************************************************************
/// is_partitioned
///\ingroup algorithm

View File

@ -169,21 +169,19 @@ namespace etl
}
//***************************************************************************
/// Constructor from value type.
/// Converting constructor from value type.
/// Constructs T in-place from U&&, without requiring T to be
/// copy/move constructible.
//***************************************************************************
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
!etl::is_same<typename etl::decay<U>::type, optional_impl>::value, int>::type = 0>
ETL_CONSTEXPR20_STL
optional_impl(const T& value_)
optional_impl(U&& value_)
{
storage.construct(value_);
}
//***************************************************************************
/// Constructor from value type.
//***************************************************************************
ETL_CONSTEXPR20_STL
optional_impl(T&& value_)
{
storage.construct(etl::move(value_));
storage.construct(etl::forward<U>(value_));
}
//***************************************************************************
@ -280,23 +278,24 @@ namespace etl
//***************************************************************************
/// Assignment operator from value type.
//***************************************************************************
#if ETL_USING_CPP11
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, optional_impl>::value, int>::type = 0>
ETL_CONSTEXPR20_STL
optional_impl& operator =(U&& value_)
{
storage.construct(etl::forward<U>(value_));
return *this;
}
#else
ETL_CONSTEXPR20_STL
optional_impl& operator =(const T& value_)
{
storage.construct(value_);
return *this;
}
#if ETL_USING_CPP11
//***************************************************************************
/// Assignment operator from value type.
//***************************************************************************
ETL_CONSTEXPR20_STL
optional_impl& operator =(T&& value_)
{
storage.construct(etl::move(value_));
return *this;
}
#endif
@ -1442,22 +1441,36 @@ namespace etl
#if ETL_USING_CPP11
//***************************************************************************
/// Construct from value type.
/// Converting constructor from value type.
/// Constructs T in-place from U&&, without requiring T to be
/// copy/move constructible.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
ETL_CONSTEXPR14
optional(const T& value_)
: impl_t(value_)
optional(U&& value_)
: impl_t(etl::forward<U>(value_))
{
}
//***************************************************************************
/// Construct from value type.
/// Converting constructor from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::in_place_t>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
!etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
ETL_CONSTEXPR20_STL
optional(const T& value_)
: impl_t(value_)
optional(U&& value_)
: impl_t(etl::forward<U>(value_))
{
}
#else
@ -1470,29 +1483,6 @@ namespace etl
}
#endif
#if ETL_USING_CPP11
//***************************************************************************
/// Move construct from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14
optional(T&& value_)
: impl_t(etl::move(value_))
{
}
//***************************************************************************
/// Move construct from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL
optional(T&& value_)
: impl_t(etl::move(value_))
{
}
#endif
#if ETL_USING_CPP11
//***************************************************************************
/// Emplace construct from arguments.
@ -1641,25 +1631,35 @@ namespace etl
#if ETL_USING_CPP11
//***************************************************************************
/// Assignment operator from value type.
/// Converting assignment operator from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
ETL_CONSTEXPR14
optional& operator =(const T& value_)
optional& operator =(U&& value_)
{
impl_t::operator=(value_);
impl_t::operator=(etl::forward<U>(value_));
return *this;
}
//***************************************************************************
/// Assignment operator from value type.
/// Converting assignment operator from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
template <typename U,
typename etl::enable_if<
etl::is_constructible<T, U&&>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::optional<T>>::value &&
!etl::is_same<typename etl::decay<U>::type, etl::nullopt_t>::value &&
!etl::is_pod<typename etl::remove_cv<T>::type>::value, int>::type = 0>
ETL_CONSTEXPR20_STL
optional& operator =(const T& value_)
optional& operator =(U&& value_)
{
impl_t::operator=(value_);
impl_t::operator=(etl::forward<U>(value_));
return *this;
}
@ -1675,32 +1675,6 @@ namespace etl
}
#endif
#if ETL_USING_CPP11
//***************************************************************************
/// Move assignment operator from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
ETL_CONSTEXPR14
optional& operator =(T&& value_)
{
impl_t::operator=(etl::move(value_));
return *this;
}
//***************************************************************************
/// Move assignment operator from value type.
//***************************************************************************
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
ETL_CONSTEXPR20_STL
optional& operator =(T&& value_)
{
impl_t::operator=(etl::move(value_));
return *this;
}
#endif
//***************************************************************************
/// Returns an iterator to the beginning of the optional.
//***************************************************************************

View File

@ -33,7 +33,11 @@ SOFTWARE.
#endif
#if !defined(ETL_CHRONO_SYSTEM_CLOCK_DURATION)
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::nanoseconds
#if (INT_MAX >= INT32_MAX)
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::nanoseconds
#else
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::milliseconds
#endif
#endif
#if !defined(ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY)
@ -41,7 +45,11 @@ SOFTWARE.
#endif
#if !defined(ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION)
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::nanoseconds
#if (INT_MAX >= INT32_MAX)
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::nanoseconds
#else
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::milliseconds
#endif
#endif
#if !defined(ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY)
@ -49,7 +57,11 @@ SOFTWARE.
#endif
#if !defined(ETL_CHRONO_STEADY_CLOCK_DURATION)
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::nanoseconds
#if (INT_MAX >= INT32_MAX)
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::nanoseconds
#else
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::milliseconds
#endif
#endif
extern "C" ETL_CHRONO_SYSTEM_CLOCK_DURATION::rep etl_get_system_clock();

View File

@ -315,13 +315,17 @@ namespace etl
/// Duration types
//***********************************************************************
#if (ETL_USING_64BIT_TYPES)
#if (INT_MAX >= INT32_MAX)
using nanoseconds = etl::chrono::duration<int64_t, etl::nano>;
using microseconds = etl::chrono::duration<int64_t, etl::micro>;
#endif
using milliseconds = etl::chrono::duration<int64_t, etl::milli>;
using seconds = etl::chrono::duration<int64_t, etl::ratio<1U>>;
#else
#if (INT_MAX >= INT32_MAX)
using nanoseconds = etl::chrono::duration<int32_t, etl::nano>;
using microseconds = etl::chrono::duration<int32_t, etl::micro>;
#endif
using milliseconds = etl::chrono::duration<int32_t, etl::milli>;
using seconds = etl::chrono::duration<int32_t, etl::ratio<1U>>;
#endif
@ -811,6 +815,7 @@ namespace etl
return etl::chrono::duration<double, milli>(s);
}
#if (INT_MAX >= INT32_MAX)
//***********************************************************************
/// Literal for microseconds duration
//***********************************************************************
@ -848,7 +853,7 @@ namespace etl
}
//***********************************************************************
/// Literal for floating point microseconds duration
/// Literal for floating point nanoseconds duration
//***********************************************************************
#if ETL_USING_VERBOSE_CHRONO_LITERALS
inline ETL_CONSTEXPR14 etl::chrono::duration<double, nano> operator ""_nanoseconds(long double s) ETL_NOEXCEPT
@ -858,6 +863,7 @@ namespace etl
{
return etl::chrono::duration<double, nano>(s);
}
#endif
}
}
}

View File

@ -1068,7 +1068,7 @@ namespace etl
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT
{
return (pend - pbegin);
return static_cast<size_t>(pend - pbegin);
}
//*************************************************************************
@ -1076,7 +1076,7 @@ namespace etl
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR size_t size_bytes() const ETL_NOEXCEPT
{
return sizeof(element_type) * (pend - pbegin);
return sizeof(element_type) * static_cast<size_t>(pend - pbegin);
}
//*************************************************************************
@ -1262,7 +1262,7 @@ namespace etl
ETL_ASSERT(etl::is_aligned<etl::alignment_of<TNew>::value>(pbegin), ETL_ERROR(span_alignment_exception));
return etl::span<TNew, etl::dynamic_extent>(reinterpret_cast<TNew*>(pbegin),
(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
static_cast<size_t>(pend - pbegin) * sizeof(element_type) / sizeof(TNew));
}
//*************************************************************************

View File

@ -345,8 +345,8 @@ namespace etl
{
memcpy(store, &value, Size_);
#if ETL_HAS_CONSTEXPR_ENDIANESS
if ETL_IF_CONSTEXPR(Endian_ == etl::endianness::value())
#if ETL_HAS_CONSTEXPR_ENDIANNESS
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
#else
if (Endian_ != etl::endianness::value())
#endif
@ -361,8 +361,8 @@ namespace etl
{
memcpy(&value, store, Size_);
#if ETL_HAS_CONSTEXPR_ENDIANESS
if ETL_IF_CONSTEXPR(Endian == etl::endianness::value())
#if ETL_HAS_CONSTEXPR_ENDIANNESS
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
#else
if (Endian_ != etl::endianness::value())
#endif
@ -402,8 +402,8 @@ namespace etl
{
memcpy(store, &value, Size_);
#if ETL_HAS_CONSTEXPR_ENDIANESS
if ETL_IF_CONSTEXPR(Endian_ == etl::endianness::value())
#if ETL_HAS_CONSTEXPR_ENDIANNESS
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
#else
if (Endian_ != etl::endianness::value())
#endif
@ -418,14 +418,14 @@ namespace etl
{
memcpy(&value, store, Size_);
#if ETL_HAS_CONSTEXPR_ENDIANESS
if ETL_IF_CONSTEXPR(Endian == etl::endianness::value())
#if ETL_HAS_CONSTEXPR_ENDIANNESS
if ETL_IF_CONSTEXPR(Endian_ != etl::endianness::value())
#else
if (Endian_ != etl::endianness::value())
if (Endian_ != etl::endianness::value())
#endif
{
etl::reverse(reinterpret_cast<pointer>(&value), reinterpret_cast<pointer>(&value) + Size_);
}
{
etl::reverse(reinterpret_cast<pointer>(&value), reinterpret_cast<pointer>(&value) + Size_);
}
}
//*******************************

View File

@ -116,6 +116,14 @@ namespace
}
};
struct DataEquivalenceByA : public etl::binary_function<Data, Data, bool>
{
bool operator ()(const Data& lhs, const Data& rhs) const
{
return lhs.a == rhs.a;
}
};
Data dataD[10] = { Data(1, 2), Data(2, 1), Data(3, 4), Data(4, 3), Data(5, 6), Data(6, 5), Data(7, 8), Data(8, 7), Data(9, 10), Data(10, 9) };
struct Greater : public etl::binary_function<int, int, bool>
@ -3449,18 +3457,174 @@ namespace
}
//*************************************************************************
TEST(stable_sort_greater)
TEST(next_permutation)
{
std::vector<NDC> initial_data = { NDC(1, 1), NDC(2, 1), NDC(3, 1), NDC(2, 2), NDC(3, 2), NDC(4, 1), NDC(2, 3), NDC(3, 3), NDC(5, 1) };
std::array<int, 4U> expected = { 1, 1, 2, 2 };
std::array<int, 4U> result = expected;
std::vector<NDC> data1(initial_data);
std::vector<NDC> data2(initial_data);
for (size_t i = 0U; i < 8U; ++i)
{
bool expected_has_next = std::next_permutation(expected.begin(), expected.end());
bool result_has_next = etl::next_permutation(result.begin(), result.end());
std::stable_sort(data1.begin(), data1.end(), std::greater<NDC>());
etl::stable_sort(data2.begin(), data2.end(), std::greater<NDC>());
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
}
bool is_same = std::equal(data1.begin(), data1.end(), data2.begin(), NDC::are_identical);
CHECK(is_same);
// Check one past the end.
bool expected_has_next = std::next_permutation(expected.begin(), expected.end());
bool result_has_next = etl::next_permutation(result.begin(), result.end());
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
int single_expected[] = { 1 };
int single_result[] = { 1 };
expected_has_next = std::next_permutation(std::begin(single_expected), std::end(single_expected));
result_has_next = etl::next_permutation(std::begin(single_result), std::end(single_result));
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(single_expected, single_result, 1U);
// Check for what happens if the beginning and end are the same.
expected_has_next = std::next_permutation(std::begin(single_expected), std::begin(single_expected));
result_has_next = etl::next_permutation(std::begin(single_result), std::begin(single_result));
CHECK_EQUAL(expected_has_next, result_has_next);
}
//*************************************************************************
TEST(next_permutation_compare)
{
std::array<int, 4U> expected = { 3, 2, 2, 1 };
std::array<int, 4U> result = expected;
for (size_t i = 0U; i < 8U; ++i)
{
bool expected_has_next = std::next_permutation(expected.begin(), expected.end(), std::greater<int>());
bool result_has_next = etl::next_permutation(result.begin(), result.end(), std::greater<int>());
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
}
// Check one past the end.
bool expected_has_next = std::next_permutation(expected.begin(), expected.end(), std::greater<int>());
bool result_has_next = etl::next_permutation(result.begin(), result.end(), std::greater<int>());
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
int single_expected[] = { 1 };
int single_result[] = { 1 };
// Check for what happens if the beginning and end are the same.
expected_has_next = std::next_permutation(std::begin(single_expected), std::begin(single_expected), std::greater<int>());
result_has_next = etl::next_permutation(std::begin(single_result), std::begin(single_result), std::greater<int>());
CHECK_EQUAL(expected_has_next, result_has_next);
CHECK_ARRAY_EQUAL(single_expected, single_result, 1U);
}
//*************************************************************************
TEST(prev_permutation)
{
std::array<int, 4U> expected = { 2, 2, 1, 1 };
std::array<int, 4U> result = expected;
for (size_t i = 0U; i < 8U; ++i)
{
bool expected_has_prev = std::prev_permutation(expected.begin(), expected.end());
bool result_has_prev = etl::prev_permutation(result.begin(), result.end());
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
}
// Check one past the end.
bool expected_has_prev = std::prev_permutation(expected.begin(), expected.end());
bool result_has_prev = etl::prev_permutation(result.begin(), result.end());
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
int single_expected[] = { 1 };
int single_result[] = { 1 };
expected_has_prev = std::prev_permutation(std::begin(single_expected), std::end(single_expected));
result_has_prev = etl::prev_permutation(std::begin(single_result), std::end(single_result));
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(single_expected, single_result, 1U);
// Check for what happens if the beginning and end are the same.
expected_has_prev = std::prev_permutation(std::begin(single_expected), std::begin(single_expected));
result_has_prev = etl::prev_permutation(std::begin(single_result), std::begin(single_result));
CHECK_EQUAL(expected_has_prev, result_has_prev);
}
//*************************************************************************
TEST(prev_permutation_compare)
{
std::array<int, 4U> expected = { 1, 1, 2, 3 };
std::array<int, 4U> result = expected;
for (size_t i = 0U; i < 8U; ++i)
{
bool expected_has_prev = std::prev_permutation(expected.begin(), expected.end(), std::greater<int>());
bool result_has_prev = etl::prev_permutation(result.begin(), result.end(), std::greater<int>());
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
}
// Check one past the end.
bool expected_has_prev = std::prev_permutation(expected.begin(), expected.end(), std::greater<int>());
bool result_has_prev = etl::prev_permutation(result.begin(), result.end(), std::greater<int>());
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(expected.data(), result.data(), result.size());
int single_expected[] = { 1 };
int single_result[] = { 1 };
// Check for what happens if the beginning and end are the same.
expected_has_prev = std::prev_permutation(std::begin(single_expected), std::begin(single_expected), std::greater<int>());
result_has_prev = etl::prev_permutation(std::begin(single_result), std::begin(single_result), std::greater<int>());
CHECK_EQUAL(expected_has_prev, result_has_prev);
CHECK_ARRAY_EQUAL(single_expected, single_result, 1U);
}
//*************************************************************************
TEST(is_permutation_length_mismatch)
{
int data1[] = { 1, 2, 3 };
int data2[] = { 1, 2, 3, 4 };
bool is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(data2), std::end(data2));
CHECK_FALSE(is_permutation);
is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(data2), std::end(data2), etl::equal_to<int>());
CHECK_FALSE(is_permutation);
}
//*************************************************************************
TEST(is_permutation_predicate)
{
Data data1[] = { Data(1, 10), Data(2, 20), Data(2, 30), Data(3, 40) };
Data permutation[] = { Data(2, 200), Data(1, 100), Data(3, 300), Data(2, 400) };
Data not_permutation[] = { Data(2, 200), Data(1, 100), Data(4, 300), Data(2, 400) };
bool is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(permutation), DataEquivalenceByA());
CHECK_TRUE(is_permutation);
is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(not_permutation), DataEquivalenceByA());
CHECK_FALSE(is_permutation);
is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(permutation), std::end(permutation), DataEquivalenceByA());
CHECK_TRUE(is_permutation);
is_permutation = etl::is_permutation(std::begin(data1), std::end(data1), std::begin(not_permutation), std::end(not_permutation), DataEquivalenceByA());
CHECK_FALSE(is_permutation);
}
//*************************************************************************

View File

@ -35,6 +35,8 @@ SOFTWARE.
#include "etl/crc8_nrsc5.h"
#include <etl/endianness.h>
//*****************************************************************************
// The results for these tests were created from https://crccalc.com/
//*****************************************************************************
@ -115,7 +117,15 @@ namespace
TEST(test_crc8_nrsc5_4_add_range_endian)
{
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
std::vector<uint32_t> data2;
if (etl::endianness::value() == etl::endian::little)
{
data2 = { 0x04030201UL, 0x08070605UL };
}
else
{
data2 = { 0x01020304UL, 0x05060708UL };
}
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
uint8_t crc1 = etl::crc8_nrsc5_t4(data1.begin(), data1.end());
@ -198,7 +208,15 @@ namespace
TEST(test_crc8_nrsc5_16_add_range_endian)
{
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
std::vector<uint32_t> data2;
if (etl::endianness::value() == etl::endian::little)
{
data2 = { 0x04030201UL, 0x08070605UL };
}
else
{
data2 = { 0x01020304UL, 0x05060708UL };
}
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
uint8_t crc1 = etl::crc8_nrsc5_t16(data1.begin(), data1.end());
@ -281,7 +299,15 @@ namespace
TEST(test_crc8_nrsc5_256_add_range_endian)
{
std::vector<uint8_t> data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U };
std::vector<uint32_t> data2 = { 0x04030201UL, 0x08070605UL };
std::vector<uint32_t> data2;
if (etl::endianness::value() == etl::endian::little)
{
data2 = { 0x04030201UL, 0x08070605UL };
}
else
{
data2 = { 0x01020304UL, 0x05060708UL };
}
std::vector<uint8_t> data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U };
uint8_t crc1 = etl::crc8_nrsc5(data1.begin(), data1.end());

View File

@ -1118,5 +1118,46 @@ namespace
CHECK_EQUAL(42, *opt);
}
//*************************************************************************
// GitHub issue #146: etl::optional doesn't compile with deleted copy constructor
//*************************************************************************
#if ETL_USING_CPP11
struct Issue146_NonCopyable
{
Issue146_NonCopyable(int some) : _some(some) {}
Issue146_NonCopyable(const Issue146_NonCopyable&) = delete;
Issue146_NonCopyable(Issue146_NonCopyable&&) = delete;
Issue146_NonCopyable& operator=(const Issue146_NonCopyable&) = delete;
int _some;
};
struct Issue146_Container
{
Issue146_Container(int a_val) : a(a_val) {}
Issue146_Container() : a(etl::nullopt) {}
etl::optional<Issue146_NonCopyable> a;
};
TEST(test_optional_issue_146_deleted_copy_ctor)
{
// etl::optional<T> should compile when T has deleted copy/move constructors,
// as long as T is constructible from the given arguments.
Issue146_Container with_value(42);
Issue146_Container without_value;
CHECK_TRUE(with_value.a.has_value());
CHECK_EQUAL(42, with_value.a->_some);
CHECK_FALSE(without_value.a.has_value());
// in_place construction should also work
etl::optional<Issue146_NonCopyable> opt(etl::in_place_t{}, 99);
CHECK_TRUE(opt.has_value());
CHECK_EQUAL(99, opt->_some);
}
#endif
}
}

View File

@ -1030,6 +1030,98 @@ namespace
CHECK_EQUAL(0x12, bev0);
CHECK_EQUAL(0x34, bev1);
}
#if ETL_HAS_CONSTEXPR_ENDIANNESS
//*************************************************************************
TEST(test_constexpr_endianness_integral_round_trip)
{
// Store a known value in LE, BE, and host-order unaligned types.
const uint32_t value = 0x12345678U;
etl::le_uint32_t le_v(value);
etl::be_uint32_t be_v(value);
etl::host_uint32_t host_v(value);
// All must read back the original value.
CHECK_EQUAL(value, uint32_t(le_v));
CHECK_EQUAL(value, uint32_t(be_v));
CHECK_EQUAL(value, uint32_t(host_v));
// Verify the storage byte order is correct.
// LE stores LSB first: 0x78, 0x56, 0x34, 0x12
CHECK_EQUAL(0x78, int(le_v[0]));
CHECK_EQUAL(0x56, int(le_v[1]));
CHECK_EQUAL(0x34, int(le_v[2]));
CHECK_EQUAL(0x12, int(le_v[3]));
// BE stores MSB first: 0x12, 0x34, 0x56, 0x78
CHECK_EQUAL(0x12, int(be_v[0]));
CHECK_EQUAL(0x34, int(be_v[1]));
CHECK_EQUAL(0x56, int(be_v[2]));
CHECK_EQUAL(0x78, int(be_v[3]));
// Host-order must match one of the above depending on the platform.
if (etl::endianness::value() == etl::endian::little)
{
CHECK_EQUAL(0x78, int(host_v[0]));
CHECK_EQUAL(0x56, int(host_v[1]));
CHECK_EQUAL(0x34, int(host_v[2]));
CHECK_EQUAL(0x12, int(host_v[3]));
}
else
{
CHECK_EQUAL(0x12, int(host_v[0]));
CHECK_EQUAL(0x34, int(host_v[1]));
CHECK_EQUAL(0x56, int(host_v[2]));
CHECK_EQUAL(0x78, int(host_v[3]));
}
}
//*************************************************************************
TEST(test_constexpr_endianness_float_round_trip)
{
// Store a known float value in LE, BE, and host-order unaligned types.
const float value = 3.1415927f;
etl::le_float_t le_v(value);
etl::be_float_t be_v(value);
etl::host_float_t host_v(value);
// All must read back the original value.
CHECK_CLOSE(value, float(le_v), 0.0001f);
CHECK_CLOSE(value, float(be_v), 0.0001f);
CHECK_CLOSE(value, float(host_v), 0.0001f);
// LE and BE storage bytes must be the reverse of each other.
CHECK_EQUAL(int(le_v[0]), int(be_v[3]));
CHECK_EQUAL(int(le_v[1]), int(be_v[2]));
CHECK_EQUAL(int(le_v[2]), int(be_v[1]));
CHECK_EQUAL(int(le_v[3]), int(be_v[0]));
}
//*************************************************************************
TEST(test_constexpr_endianness_cross_endian_copy)
{
// Verify that converting between LE <-> BE via host works correctly.
const uint16_t value = 0xABCDU;
etl::le_uint16_t le_v(value);
etl::be_uint16_t be_v(value);
etl::host_uint16_t host_from_le(le_v);
etl::host_uint16_t host_from_be(be_v);
CHECK_EQUAL(value, uint16_t(host_from_le));
CHECK_EQUAL(value, uint16_t(host_from_be));
// Round-trip: host -> le -> read back
etl::le_uint16_t le_from_host(host_from_le);
CHECK_EQUAL(value, uint16_t(le_from_host));
// Round-trip: host -> be -> read back
etl::be_uint16_t be_from_host(host_from_be);
CHECK_EQUAL(value, uint16_t(be_from_host));
}
#endif
}
}