summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-05-18 13:58:02 +0200
committerSven Gothel <[email protected]>2022-05-18 13:58:02 +0200
commitb9793167c6f4d577255122b962e32aa151b998e2 (patch)
treeadcf64f23563e2a13b7ee67e47704cb6e0bab418
parent9c600b83aa75d8ed90e5280540f278103aa09cfa (diff)
fraction_timespec::normalize(): Fix underflow case, allow multiple of ns_per_sec
-rw-r--r--include/jau/fraction_type.hpp9
-rw-r--r--test/test_fractions_01.cpp32
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 );