diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 2163b925..9cc58ea9 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -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 + class duration; + + template + ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration& 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 + template ::type::den == 1, int>::type = 0> ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT - : value(static_cast(other.count())) + : value(etl::chrono::duration_cast >(other).count()) { + + bool b = etl::ratio_divide::type::den == 1; + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); } + //*********************************************************************** + template + ETL_CONSTEXPR14 + typename etl::enable_if::type::den == 1, etl::chrono::duration&>::type + operator =(const etl::chrono::duration& other) ETL_NOEXCEPT + { + bool b = etl::ratio_divide::type::den == 1; + + value = etl::chrono::duration_cast >(other).count(); + + return *this; + } + //*********************************************************************** ETL_CONSTEXPR TRep count() const ETL_NOEXCEPT { return value; } + //*********************************************************************** + ETL_CONSTEXPR etl::common_type_t operator +() const + { + return etl::common_type_t(*this); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::common_type_t operator -() const + { + return etl::common_type_t(-value); + } + //*********************************************************************** static ETL_CONSTEXPR etl::chrono::duration zero() ETL_NOEXCEPT { @@ -152,7 +187,7 @@ namespace etl private: - TRep value; + TRep value; }; //*********************************************************************** @@ -180,7 +215,7 @@ namespace etl /// duration_cast //*********************************************************************** template - ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT + ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT { typedef TRep from_rep; typedef TPeriod from_period; @@ -221,7 +256,7 @@ namespace etl template struct hash > { - size_t operator()(const etl::chrono::duration& d) const + ETL_CONSTEXPR14 size_t operator()(const etl::chrono::duration& d) const { TRep value = d.count(); size_t num = TPeriod::num; @@ -248,6 +283,70 @@ namespace etl using type = etl::chrono::duration; }; + + //*********************************************************************** + /// Check equality. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator ==(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + typedef typename etl::common_type, etl::chrono::duration >::type common_t; + + common_t l = etl::chrono::duration_cast(lhs); + common_t r = etl::chrono::duration_cast(rhs); + + return l.count() == r.count(); + } + + //*********************************************************************** + /// Check inequality. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator !=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Less-than. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator <(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + typedef typename etl::common_type, etl::chrono::duration >::type common_t; + + common_t l = etl::chrono::duration_cast(lhs); + common_t r = etl::chrono::duration_cast(rhs); + + return l.count() < r.count(); + } + + //*********************************************************************** + /// Less-than-or-equal. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator <=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return !(rhs < lhs); + } + + //*********************************************************************** + /// Greater-than. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator >(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return rhs < lhs; + } + + //*********************************************************************** + /// Greater-than-or-equal. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator >=(const etl::chrono::duration& lhs, const etl::chrono::duration& 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(m)); } diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index e8eddac8..f20ed3fc 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -38,6 +38,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -70,13 +71,13 @@ namespace { using duration_type = etl::chrono::duration; - //CHECK_EQUAL(duration_type(0), duration_type::zero()); - //CHECK_EQUAL(duration_type(std::numeric_limits::min()), duration_type::min()); - //CHECK_EQUAL(duration_type(std::numeric_limits::max()), duration_type::max()); + CHECK_EQUAL(duration_type(0).count(), duration_type::zero().count()); + CHECK_EQUAL(duration_type(std::numeric_limits::min()).count(), duration_type::min().count()); + CHECK_EQUAL(duration_type(std::numeric_limits::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::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::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; + using duration_type2 = etl::chrono::duration; + + 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; + + 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) {