etl::duration work in progress

This commit is contained in:
John Wellbelove 2024-09-13 19:55:18 +01:00
parent 4942ff840e
commit 0d0b9be310
2 changed files with 204 additions and 16 deletions

View File

@ -35,6 +35,7 @@ SOFTWARE.
#include "../../ratio.h"
#include "../../static_assert.h"
#include "../../limits.h"
#include "../../type_traits.h"
namespace etl
{
@ -88,6 +89,12 @@ namespace etl
}
};
template <typename TRep, typename TPeriod>
class duration;
template <typename TToDuration, typename TRep, typename TPeriod>
ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT;
//***********************************************************************
/// duration
//***********************************************************************
@ -96,8 +103,8 @@ namespace etl
{
public:
typedef TRep rep;
typedef TPeriod period;
typedef TRep rep;
typedef typename TPeriod::type period;
//***********************************************************************
ETL_CONSTEXPR duration() ETL_NOEXCEPT
@ -119,19 +126,47 @@ namespace etl
}
//***********************************************************************
template <typename TRep2, typename TPeriod2>
template <typename TRep2, typename TPeriod2, typename etl::enable_if<etl::ratio_divide<TPeriod2, TPeriod>::type::den == 1, int>::type = 0>
ETL_CONSTEXPR duration(const etl::chrono::duration<TRep2, TPeriod2>& other) ETL_NOEXCEPT
: value(static_cast<TRep>(other.count()))
: value(etl::chrono::duration_cast<etl::chrono::duration<TRep, TPeriod> >(other).count())
{
bool b = etl::ratio_divide<TPeriod2, TPeriod>::type::den == 1;
ETL_STATIC_ASSERT(!(etl::is_integral<TRep>::value && etl::is_floating_point<TRep2>::value), "Cannot convert duration from floating point to integral");
}
//***********************************************************************
template <typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14
typename etl::enable_if<etl::ratio_divide<TPeriod2, TPeriod>::type::den == 1, etl::chrono::duration<TRep, TPeriod>&>::type
operator =(const etl::chrono::duration<TRep2, TPeriod2>& other) ETL_NOEXCEPT
{
bool b = etl::ratio_divide<TPeriod2, TPeriod>::type::den == 1;
value = etl::chrono::duration_cast<etl::chrono::duration<TRep, TPeriod> >(other).count();
return *this;
}
//***********************************************************************
ETL_CONSTEXPR TRep count() const ETL_NOEXCEPT
{
return value;
}
//***********************************************************************
ETL_CONSTEXPR etl::common_type_t<duration> operator +() const
{
return etl::common_type_t<duration>(*this);
}
//***********************************************************************
ETL_CONSTEXPR etl::common_type_t<duration> operator -() const
{
return etl::common_type_t<duration>(-value);
}
//***********************************************************************
static ETL_CONSTEXPR etl::chrono::duration<TRep, TPeriod> zero() ETL_NOEXCEPT
{
@ -152,7 +187,7 @@ namespace etl
private:
TRep value;
TRep value;
};
//***********************************************************************
@ -180,7 +215,7 @@ namespace etl
/// duration_cast
//***********************************************************************
template <typename TToDuration, typename TRep, typename TPeriod>
ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration<TRep, TPeriod>& d) ETL_NOEXCEPT
{
typedef TRep from_rep;
typedef TPeriod from_period;
@ -221,7 +256,7 @@ namespace etl
template <typename TRep, typename TPeriod>
struct hash<etl::chrono::duration<TRep, TPeriod> >
{
size_t operator()(const etl::chrono::duration<TRep, TPeriod>& d) const
ETL_CONSTEXPR14 size_t operator()(const etl::chrono::duration<TRep, TPeriod>& d) const
{
TRep value = d.count();
size_t num = TPeriod::num;
@ -248,6 +283,70 @@ namespace etl
using type = etl::chrono::duration<value_type, period_type>;
};
//***********************************************************************
/// Check equality.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator ==(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
typedef typename etl::common_type<etl::chrono::duration<TRep1, TPeriod1>, etl::chrono::duration<TRep2, TPeriod2> >::type common_t;
common_t l = etl::chrono::duration_cast<common_t>(lhs);
common_t r = etl::chrono::duration_cast<common_t>(rhs);
return l.count() == r.count();
}
//***********************************************************************
/// Check inequality.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator !=(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
return !(lhs == rhs);
}
//***********************************************************************
/// Less-than.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator <(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
typedef typename etl::common_type<etl::chrono::duration<TRep1, TPeriod1>, etl::chrono::duration<TRep2, TPeriod2> >::type common_t;
common_t l = etl::chrono::duration_cast<common_t>(lhs);
common_t r = etl::chrono::duration_cast<common_t>(rhs);
return l.count() < r.count();
}
//***********************************************************************
/// Less-than-or-equal.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator <=(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
return !(rhs < lhs);
}
//***********************************************************************
/// Greater-than.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator >(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
return rhs < lhs;
}
//***********************************************************************
/// Greater-than-or-equal.
//***********************************************************************
template <typename TRep1, typename TPeriod1, typename TRep2, typename TPeriod2>
ETL_CONSTEXPR14 bool operator >=(const etl::chrono::duration<TRep1, TPeriod1>& lhs, const etl::chrono::duration<TRep2, TPeriod2>& rhs)
{
return !(lhs < rhs);
}
}
#if ETL_HAS_CHRONO_LITERALS_DAY
@ -269,7 +368,7 @@ namespace etl
//***********************************************************************
/// Literal for minutes duration
//***********************************************************************
ETL_IF_CONSTEXPR etl::chrono::hours operator ""_minutes(unsigned long long m) noexcept
ETL_IF_CONSTEXPR etl::chrono::minutes operator ""_minutes(unsigned long long m) noexcept
{
return etl::chrono::minutes(static_cast<etl::chrono::minutes::rep>(m));
}

View File

@ -38,6 +38,7 @@ SOFTWARE.
#include <algorithm>
#include <limits>
#include <vector>
#include <chrono>
namespace
{
@ -70,13 +71,13 @@ namespace
{
using duration_type = etl::chrono::duration<size_t, etl::milli>;
//CHECK_EQUAL(duration_type(0), duration_type::zero());
//CHECK_EQUAL(duration_type(std::numeric_limits<size_t>::min()), duration_type::min());
//CHECK_EQUAL(duration_type(std::numeric_limits<size_t>::max()), duration_type::max());
CHECK_EQUAL(duration_type(0).count(), duration_type::zero().count());
CHECK_EQUAL(duration_type(std::numeric_limits<size_t>::min()).count(), duration_type::min().count());
CHECK_EQUAL(duration_type(std::numeric_limits<size_t>::max()).count(), duration_type::max().count());
}
//*************************************************************************
TEST(test_predefined_duration_types)
TEST(test_predefined_duration_periods)
{
CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::num), etl::chrono::nanoseconds::period::num);
CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::den), etl::chrono::nanoseconds::period::den);
@ -149,10 +150,10 @@ namespace
typedef typename etl::ratio_divide<duration_type1::period, duration_type2::period>::type ratio_divide_t;
int multiplier = duration_type1::period::den / duration_type2::period::den;
int microseonds_per_millisecond = duration_type1::period::den / duration_type2::period::den;
CHECK_EQUAL(1, ratio_divide_t::num);
CHECK_EQUAL(dur1.count(), dur2.count() * multiplier);
CHECK_EQUAL(dur1.count(), dur2.count() * microseonds_per_millisecond);
}
//*************************************************************************
@ -166,10 +167,10 @@ namespace
typedef typename etl::ratio_divide<duration_type1::period, duration_type2::period>::type ratio_divide_t;
int multiplier = duration_type2::period::den / duration_type1::period::den;
int microseonds_per_millisecond = duration_type2::period::den / duration_type1::period::den;
CHECK_EQUAL(1, ratio_divide_t::den);
CHECK_EQUAL(dur1.count() * multiplier, dur2.count());
CHECK_EQUAL(dur1.count() * microseonds_per_millisecond, dur2.count());
}
//*************************************************************************
@ -189,6 +190,94 @@ namespace
CHECK_EQUAL(dur1.count(), (dur2.count() * duration_type2::period::num) / duration_type1::period::num);
}
//*************************************************************************
TEST(test_duration_assignment)
{
int Two_Hours = 2;
int Four_Hours = 4;
etl::chrono::hours hours1(Two_Hours);
etl::chrono::hours hours2(Four_Hours);
etl::chrono::seconds seconds(0);
seconds = hours1;
int seconds_per_hour = etl::chrono::hours::period::num / etl::chrono::seconds::period::num;
CHECK_EQUAL(seconds.count(), hours1.count() * seconds_per_hour);
CHECK_EQUAL(Two_Hours, hours1.count());
hours1 = hours2;
CHECK_EQUAL(Four_Hours, hours1.count());
CHECK_EQUAL(Four_Hours, hours2.count());
}
//*************************************************************************
TEST(test_duration_comparison_operators)
{
using duration_type1 = etl::chrono::duration<size_t, etl::milli>;
using duration_type2 = etl::chrono::duration<int, etl::micro>;
duration_type1 dur1a(245);
duration_type1 dur1b(245);
duration_type1 dur1c(246);
duration_type2 dur2b(245000);
duration_type2 dur2c(245001);
// Same duration types
CHECK_TRUE(dur1a == dur1b);
CHECK_TRUE(dur1a != dur1c);
CHECK_FALSE(dur1a < dur1b);
CHECK_TRUE(dur1a <= dur1b);
CHECK_FALSE(dur1a > dur1b);
CHECK_TRUE(dur1a >= dur1b);
CHECK_TRUE(dur1a < dur1c);
CHECK_FALSE(dur1c < dur1a);
CHECK_TRUE(dur1a <= dur1c);
CHECK_FALSE(dur1c <= dur1a);
CHECK_FALSE(dur1a > dur1c);
CHECK_TRUE(dur1c > dur1a);
CHECK_FALSE(dur1a >= dur1c);
CHECK_TRUE(dur1c >= dur1a);
// Different duration types
CHECK_TRUE(dur1a == dur2b);
CHECK_TRUE(dur2b == dur1a);
CHECK_TRUE(dur2c != dur1a);
CHECK_TRUE(dur1a != dur2c);
CHECK_FALSE(dur1a < dur2b);
CHECK_FALSE(dur2b < dur1a);
CHECK_TRUE(dur1a <= dur2b);
CHECK_TRUE(dur2b <= dur1a);
CHECK_FALSE(dur1a > dur2b);
CHECK_FALSE(dur2b > dur1a);
CHECK_TRUE(dur1a >= dur2b);
CHECK_TRUE(dur2b >= dur1a);
CHECK_TRUE(dur1a < dur2c);
CHECK_FALSE(dur2c < dur1a);
CHECK_TRUE(dur1a <= dur2c);
CHECK_FALSE(dur2c <= dur1a);
CHECK_FALSE(dur1a > dur2c);
CHECK_TRUE(dur2c > dur1a);
CHECK_FALSE(dur1a >= dur2c);
CHECK_TRUE(dur2c >= dur1a);
}
//*************************************************************************
TEST(test_duration_unary_operators)
{
using duration_type = etl::chrono::duration<int, etl::milli>;
duration_type dur(245);
duration_type positive = +dur;
duration_type negative = -dur;
CHECK_EQUAL(245, positive.count());
CHECK_EQUAL(-245, negative.count());
}
//*************************************************************************
TEST(test_duration_hashes_are_unique)
{