diff options
author | Sven Gothel <[email protected]> | 2022-05-18 13:58:02 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-05-18 13:58:02 +0200 |
commit | b9793167c6f4d577255122b962e32aa151b998e2 (patch) | |
tree | adcf64f23563e2a13b7ee67e47704cb6e0bab418 | |
parent | 9c600b83aa75d8ed90e5280540f278103aa09cfa (diff) |
fraction_timespec::normalize(): Fix underflow case, allow multiple of ns_per_sec
-rw-r--r-- | include/jau/fraction_type.hpp | 9 | ||||
-rw-r--r-- | test/test_fractions_01.cpp | 32 |
2 files changed, 37 insertions, 4 deletions
diff --git a/include/jau/fraction_type.hpp b/include/jau/fraction_type.hpp index d3c43bb..bbc32f8 100644 --- a/include/jau/fraction_type.hpp +++ b/include/jau/fraction_type.hpp @@ -931,8 +931,9 @@ namespace jau { using namespace jau::int_literals; const int64_t ns_per_sec = 1'000'000'000_i64; if( tv_nsec < 0 ) { - tv_nsec += ns_per_sec; - tv_sec -= 1; + const int64_t c = 1 + abs( tv_nsec ) / ns_per_sec; + tv_nsec += c * ns_per_sec; + tv_sec -= c; } else if( tv_nsec >= ns_per_sec ) { const int64_t c = tv_nsec / ns_per_sec; tv_nsec -= c * ns_per_sec; @@ -948,8 +949,8 @@ namespace jau { * @return reference to this instance, normalized */ constexpr fraction_timespec& operator+=(const fraction_timespec& rhs ) noexcept { + tv_nsec += rhs.tv_nsec; // we allow the 'overflow' over 1'000'000'000, fitting into type and normalize() later tv_sec += rhs.tv_sec; - tv_nsec += rhs.tv_nsec; return normalize(); } @@ -960,8 +961,8 @@ namespace jau { * @return reference to this instance, normalized */ constexpr fraction_timespec& operator-=(const fraction_timespec& rhs ) noexcept { + tv_nsec -= rhs.tv_nsec; // we allow the 'overflow' over 1'000'000'000, fitting into type and normalize() later tv_sec -= rhs.tv_sec; - tv_nsec -= rhs.tv_nsec; return normalize(); } diff --git a/test/test_fractions_01.cpp b/test/test_fractions_01.cpp index bdb3f00..2545635 100644 --- a/test/test_fractions_01.cpp +++ b/test/test_fractions_01.cpp @@ -616,6 +616,38 @@ TEST_CASE( "struct timespec type validation Test 03.00", "[fraction][struct_time TEST_CASE( "Fraction Time Arithmetic Add Test 03.1", "[fraction][fraction_timespec][add]" ) { + const int64_t ns_per_sec = 1'000'000'000_i64; + + // 12.4 + 12.4 = 24.8 w/ double overflow in tv_nsec + { + fraction_timespec a ( 10_i64, 2 * ns_per_sec + 400000000_i64 ); + fraction_timespec b ( 10_i64, 2 * ns_per_sec + 400000000_i64 ); + fraction_timespec exp_sum ( 24_i64, 800000000_i64 ); + INFO_STR(" a " + a.to_string() ); + INFO_STR(" b " + b.to_string() ); + INFO_STR(" a+b " + (a+b).to_string() ); + REQUIRE( ( a + b ) == exp_sum ); + } + // 13.4 - 3.4 = 10.0 w/ double overflow in tv_nsec + { + fraction_timespec a ( 13_i64, 400000000_i64 ); + fraction_timespec b ( 1_i64, 2 * ns_per_sec + 400000000_i64 ); + fraction_timespec exp_sum ( 10_i64, 0_i64 ); + INFO_STR(" a " + a.to_string() ); + INFO_STR(" b " + b.to_string() ); + INFO_STR(" a-b " + (a-b).to_string() ); + REQUIRE( ( a - b ) == exp_sum ); + } + // 12.0 - 1.9 = 10.1 w/ double overflow in tv_nsec + { + fraction_timespec a ( 12_i64, 0_i64 ); + fraction_timespec b ( 3_i64, -2 * ns_per_sec + 900000000_i64 ); + fraction_timespec exp_sum ( 10_i64, 100000000_i64 ); + INFO_STR(" a " + a.to_string() ); + INFO_STR(" b " + b.to_string() ); + INFO_STR(" a-b " + (a-b).to_string() ); + REQUIRE( ( a - b ) == exp_sum ); + } // 10.4 + 0.4 = 10.8 { fraction_timespec a ( 10_i64, 400000000_i64 ); |