From 196e3bfd229ecdb75ff5e6656f93212429234fc1 Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Mon, 15 Apr 2024 23:26:45 -0400 Subject: [PATCH 1/6] Creating more accuracy in NS_TO_S Signed-off-by: CursedRock17 --- include/rcutils/time.h | 5 ++++- test/test_time.cpp | 5 ----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/rcutils/time.h b/include/rcutils/time.h index 0fb765e7..7c73c0ba 100644 --- a/include/rcutils/time.h +++ b/include/rcutils/time.h @@ -36,7 +36,10 @@ extern "C" #define RCUTILS_US_TO_NS(microseconds) ((microseconds) * 1000LL) /// Convenience macro to convert nanoseconds to seconds. -#define RCUTILS_NS_TO_S(nanoseconds) ((nanoseconds) / (1000LL * 1000LL * 1000LL)) +#define RCUTILS_NS_TO_S(nanoseconds) \ +((1e-9 * (double)((int32_t)(nanoseconds % 1000000000l))) + \ +((double)((int32_t)((nanoseconds - ((int32_t)(nanoseconds % 1000000000l))) / 1000000000l)))) + /// Convenience macro to convert nanoseconds to milliseconds. #define RCUTILS_NS_TO_MS(nanoseconds) ((nanoseconds) / (1000LL * 1000LL)) /// Convenience macro to convert nanoseconds to microseconds. diff --git a/test/test_time.cpp b/test/test_time.cpp index 5976cabf..6cf3ddf1 100644 --- a/test/test_time.cpp +++ b/test/test_time.cpp @@ -94,11 +94,6 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_macros) { EXPECT_EQ(RCUTILS_NS_TO_S(1000000000ll), 1ll); // int64_t EXPECT_EQ(RCUTILS_NS_TO_S(1000000042ll), 1ll); // int64_t (truncated) EXPECT_EQ(RCUTILS_NS_TO_S(-1999999999ll), -1ll); // int64_t (truncated) - EXPECT_EQ(RCUTILS_NS_TO_S(200000000.), 0.2); // double - EXPECT_EQ(RCUTILS_NS_TO_S(1.0 + 1.0), 0.000000002); // sum of doubles - EXPECT_EQ( - RCUTILS_NS_TO_S(9007199254740992.), - 9007199.254740992); // maximum precision double (53 bits) // nanoseconds to milliseconds EXPECT_EQ(RCUTILS_NS_TO_MS(1000000ll), 1ll); // int64_t From 375e2f225a1d3ddb51f652db7ee7fa6fba36beb2 Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Tue, 16 Apr 2024 23:38:06 -0400 Subject: [PATCH 2/6] More precise testing Signed-off-by: CursedRock17 --- test/test_time.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/test_time.cpp b/test/test_time.cpp index 6cf3ddf1..8ead1fcb 100644 --- a/test/test_time.cpp +++ b/test/test_time.cpp @@ -91,9 +91,12 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_macros) { 9007199254740992.); // value is truncated! // nanoseconds to seconds - EXPECT_EQ(RCUTILS_NS_TO_S(1000000000ll), 1ll); // int64_t - EXPECT_EQ(RCUTILS_NS_TO_S(1000000042ll), 1ll); // int64_t (truncated) - EXPECT_EQ(RCUTILS_NS_TO_S(-1999999999ll), -1ll); // int64_t (truncated) + EXPECT_EQ(RCUTILS_NS_TO_S(1000000000ll), 1.0); // int64_t + EXPECT_EQ(RCUTILS_NS_TO_S(1000000042ll), 1.000000042); // int64_t + EXPECT_EQ(RCUTILS_NS_TO_S(-1999999999ll), -1.999999999); // int64_t + EXPECT_EQ(RCUTILS_NS_TO_S(1 + 1), 0.000000002); // sum of two int64_ts + EXPECT_EQ(RCUTILS_NS_TO_S(9007199254740992ll), + 9007199.254740992); // maximum precision int64_t // nanoseconds to milliseconds EXPECT_EQ(RCUTILS_NS_TO_MS(1000000ll), 1ll); // int64_t From 431e7f6cd19fe207247b1619ff12c17401339cfa Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Wed, 17 Apr 2024 20:37:24 -0400 Subject: [PATCH 3/6] Fixing uncrustify Signed-off-by: CursedRock17 --- include/rcutils/time.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rcutils/time.h b/include/rcutils/time.h index 7c73c0ba..c7158e8a 100644 --- a/include/rcutils/time.h +++ b/include/rcutils/time.h @@ -37,8 +37,8 @@ extern "C" /// Convenience macro to convert nanoseconds to seconds. #define RCUTILS_NS_TO_S(nanoseconds) \ -((1e-9 * (double)((int32_t)(nanoseconds % 1000000000l))) + \ -((double)((int32_t)((nanoseconds - ((int32_t)(nanoseconds % 1000000000l))) / 1000000000l)))) + ((1e-9 * (double)((int32_t)(nanoseconds % 1000000000l))) + \ + ((double)((int32_t)((nanoseconds - ((int32_t)(nanoseconds % 1000000000l))) / 1000000000l)))) /// Convenience macro to convert nanoseconds to milliseconds. #define RCUTILS_NS_TO_MS(nanoseconds) ((nanoseconds) / (1000LL * 1000LL)) From 627a2ea76368a374320c163615c2a0414cf87309 Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Fri, 12 Jul 2024 03:04:53 -0400 Subject: [PATCH 4/6] Adding custom functions Signed-off-by: CursedRock17 --- include/rcutils/time.h | 68 +++++++++++++++++++++++++++++++++++++++--- src/time.c | 42 ++++++++++++++++++++++++++ test/test_time.cpp | 45 ++++++++++++++++++++++++---- 3 files changed, 145 insertions(+), 10 deletions(-) diff --git a/include/rcutils/time.h b/include/rcutils/time.h index c7158e8a..2ef6ee25 100644 --- a/include/rcutils/time.h +++ b/include/rcutils/time.h @@ -36,10 +36,7 @@ extern "C" #define RCUTILS_US_TO_NS(microseconds) ((microseconds) * 1000LL) /// Convenience macro to convert nanoseconds to seconds. -#define RCUTILS_NS_TO_S(nanoseconds) \ - ((1e-9 * (double)((int32_t)(nanoseconds % 1000000000l))) + \ - ((double)((int32_t)((nanoseconds - ((int32_t)(nanoseconds % 1000000000l))) / 1000000000l)))) - +#define RCUTILS_NS_TO_S(nanoseconds) ((nanoseconds) / (1000LL * 1000LL * 1000LL)) /// Convenience macro to convert nanoseconds to milliseconds. #define RCUTILS_NS_TO_MS(nanoseconds) ((nanoseconds) / (1000LL * 1000LL)) /// Convenience macro to convert nanoseconds to microseconds. @@ -52,6 +49,69 @@ typedef int64_t rcutils_time_point_value_t; /// A duration of time, measured in nanoseconds. typedef int64_t rcutils_duration_value_t; +/** + * This function returns an accurate conversion from nanoseconds to seconds. + * + * The nanoseconds argument has to be an int64_t to ensure exact division + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] nanoseconds The int64_t needed for conversion + * \return double That nanoseconds number as seconds. + */ +RCUTILS_PUBLIC +RCUTILS_WARN_UNUSED +double +rcutils_nanoseconds_to_seconds(const int64_t nanoseconds); + +/** + * This function returns an accurate conversion from nanoseconds to milliseconds. + * + * The nanoseconds argument has to be an int64_t to ensure exact division + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] nanoseconds The int64_t needed for conversion + * \return double That nanoseconds number as milliseconds. + */ +RCUTILS_PUBLIC +RCUTILS_WARN_UNUSED +double +rcutils_nanoseconds_to_milliseconds(const int64_t nanoseconds); + +/** + * This function returns an accurate conversion from nanoseconds to microseconds. + * + * The nanoseconds argument has to be an int64_t to ensure exact division + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] nanoseconds The int64_t needed for conversion + * \return double That nanoseconds number as microseconds. + */ +RCUTILS_PUBLIC +RCUTILS_WARN_UNUSED +double +rcutils_nanoseconds_to_microseconds(const int64_t nanoseconds); + /** * This function returns the time from a system clock. * The closest equivalent would be to std::chrono::system_clock::now(); diff --git a/src/time.c b/src/time.c index 882c9d98..d2a13b6b 100644 --- a/src/time.c +++ b/src/time.c @@ -28,6 +28,48 @@ extern "C" #include "rcutils/error_handling.h" #include "rcutils/snprintf.h" +double +rcutils_nanoseconds_to_seconds(const int64_t nanoseconds) +{ + // scale the nanoseconds separately for improved accuracy + int64_t sec, nsec; + nsec = (nanoseconds % 1000000000l); + sec = ((nanoseconds - nsec) / 1000000000l); + + double sec_double, nsec_double; + nsec_double = 1e-9 * (double)(nsec); + sec_double = (double)(sec); + return sec_double + nsec_double; +} + +double +rcutils_nanoseconds_to_milliseconds(const int64_t nanoseconds) +{ + // scale the nanoseconds separately for improved accuracy + int64_t sec, nsec; + nsec = (nanoseconds % 1000000l); + sec = ((nanoseconds - nsec) / 1000000l); + + double sec_double, nsec_double; + nsec_double = 1e-6 * (double)(nsec); + sec_double = (double)(sec); + return sec_double + nsec_double; +} + +double +rcutils_nanoseconds_to_microseconds(const int64_t nanoseconds) +{ + // scale the nanoseconds separately for improved accuracy + int64_t sec, nsec; + nsec = (nanoseconds % 1000l); + sec = ((nanoseconds - nsec) / 1000l); + + double sec_double, nsec_double; + nsec_double = 1e-3 * (double)(nsec); + sec_double = (double)(sec); + return sec_double + nsec_double; +} + rcutils_ret_t rcutils_time_point_value_as_nanoseconds_string( const rcutils_time_point_value_t * time_point, diff --git a/test/test_time.cpp b/test/test_time.cpp index 8ead1fcb..93b5a8ca 100644 --- a/test/test_time.cpp +++ b/test/test_time.cpp @@ -91,12 +91,15 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_macros) { 9007199254740992.); // value is truncated! // nanoseconds to seconds - EXPECT_EQ(RCUTILS_NS_TO_S(1000000000ll), 1.0); // int64_t - EXPECT_EQ(RCUTILS_NS_TO_S(1000000042ll), 1.000000042); // int64_t - EXPECT_EQ(RCUTILS_NS_TO_S(-1999999999ll), -1.999999999); // int64_t - EXPECT_EQ(RCUTILS_NS_TO_S(1 + 1), 0.000000002); // sum of two int64_ts - EXPECT_EQ(RCUTILS_NS_TO_S(9007199254740992ll), - 9007199.254740992); // maximum precision int64_t + EXPECT_EQ(RCUTILS_NS_TO_S(1000000000ll), 1ll); // int64_t + EXPECT_EQ(RCUTILS_NS_TO_S(1000000042ll), 1ll); // int64_t (truncated) + EXPECT_EQ(RCUTILS_NS_TO_S(-1999999999ll), -1ll); // int64_t (truncated) + EXPECT_EQ(RCUTILS_NS_TO_S(200000000.), 0.2); // double + EXPECT_EQ(RCUTILS_NS_TO_S(1.0 + 1.0), 0.000000002); // sum of doubles + EXPECT_EQ( + RCUTILS_NS_TO_S(9007199254740992.), + 9007199.254740992); // maximum precision double (53 bits) + // nanoseconds to milliseconds EXPECT_EQ(RCUTILS_NS_TO_MS(1000000ll), 1ll); // int64_t @@ -119,6 +122,36 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_macros) { 9007199254740.992); // maximum precision double (53 bits) } +// Tests the rcutils time unit conversion functions. +TEST_F(TestTimeFixture, test_rcutils_time_conversion_functions) { + // nanoseconds to seconds + EXPECT_EQ(rcutils_nanoseconds_to_seconds(1000000000ll), 1.0); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_seconds(1000000042ll), 1.000000042); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_seconds(-2999999999ll), -2.999999999); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_seconds(1 + 1), 0.000000002); // sum of two int64_ts + EXPECT_EQ( + rcutils_nanoseconds_to_seconds(9007199254740992), + 9007199.254740992); // maximum precision double as a int64_t + + // nanoseconds to milliseconds + EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(1000000ll), 1.0); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(1000042ll), 1.000042); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(-2999999ll), -2.999999); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(1 + 1), 0.000002); // sum of int64_ts + EXPECT_EQ( + rcutils_nanoseconds_to_milliseconds(9007199254740992), + 9007199254.740992); // maximum precision double as a int64_t + + // nanoseconds to microseconds + EXPECT_EQ(rcutils_nanoseconds_to_microseconds(1000ll), 1.0); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_microseconds(1042ll), 1.042); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_microseconds(-2999ll), -2.999); // int64_t + EXPECT_EQ(rcutils_nanoseconds_to_microseconds(1 + 1), 0.002); // sum of int64_ts + EXPECT_EQ( + rcutils_nanoseconds_to_microseconds(9007199254740992), + 9007199254740.992); // maximum precision double as a int64_t +} + // Tests the rcutils_system_time_now() function. TEST_F(TestTimeFixture, test_rcutils_system_time_now) { rcutils_ret_t ret; From 006e4140d2ad7a442fec348f5f8d03c821b67447 Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Fri, 12 Jul 2024 09:59:24 -0400 Subject: [PATCH 5/6] Nitpiking Signed-off-by: CursedRock17 --- test/test_time.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/test_time.cpp b/test/test_time.cpp index 93b5a8ca..a76be533 100644 --- a/test/test_time.cpp +++ b/test/test_time.cpp @@ -100,7 +100,6 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_macros) { RCUTILS_NS_TO_S(9007199254740992.), 9007199.254740992); // maximum precision double (53 bits) - // nanoseconds to milliseconds EXPECT_EQ(RCUTILS_NS_TO_MS(1000000ll), 1ll); // int64_t EXPECT_EQ(RCUTILS_NS_TO_MS(1000042ll), 1ll); // int64_t (truncated) @@ -131,7 +130,7 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_functions) { EXPECT_EQ(rcutils_nanoseconds_to_seconds(1 + 1), 0.000000002); // sum of two int64_ts EXPECT_EQ( rcutils_nanoseconds_to_seconds(9007199254740992), - 9007199.254740992); // maximum precision double as a int64_t + 9007199.254740992); // maximum precision double as an int64_t // nanoseconds to milliseconds EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(1000000ll), 1.0); // int64_t @@ -140,7 +139,7 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_functions) { EXPECT_EQ(rcutils_nanoseconds_to_milliseconds(1 + 1), 0.000002); // sum of int64_ts EXPECT_EQ( rcutils_nanoseconds_to_milliseconds(9007199254740992), - 9007199254.740992); // maximum precision double as a int64_t + 9007199254.740992); // maximum precision double as an int64_t // nanoseconds to microseconds EXPECT_EQ(rcutils_nanoseconds_to_microseconds(1000ll), 1.0); // int64_t @@ -149,7 +148,7 @@ TEST_F(TestTimeFixture, test_rcutils_time_conversion_functions) { EXPECT_EQ(rcutils_nanoseconds_to_microseconds(1 + 1), 0.002); // sum of int64_ts EXPECT_EQ( rcutils_nanoseconds_to_microseconds(9007199254740992), - 9007199254740.992); // maximum precision double as a int64_t + 9007199254740.992); // maximum precision double as an int64_t } // Tests the rcutils_system_time_now() function. From 4f51c49244c1d821b2ec4655e32277df73c49a88 Mon Sep 17 00:00:00 2001 From: CursedRock17 Date: Tue, 23 Jul 2024 02:28:17 -0400 Subject: [PATCH 6/6] Adding better definitions Signed-off-by: CursedRock17 --- include/rcutils/time.h | 17 +++++++++++------ src/time.c | 12 ++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include/rcutils/time.h b/include/rcutils/time.h index 2ef6ee25..8ae8e6d3 100644 --- a/include/rcutils/time.h +++ b/include/rcutils/time.h @@ -28,19 +28,24 @@ extern "C" #include "rcutils/types.h" #include "rcutils/visibility_control.h" +/// Convenience defintitions to commonly used numbers. +#define RCUTILS_NANOSECONDS_PER_SEC 1000000000l +#define RCUTILS_NANOSECONDS_PER_MILLISEC 1000000l +#define RCUTILS_NANOSECONDS_PER_MICROSEC 1000l + /// Convenience macro to convert seconds to nanoseconds. -#define RCUTILS_S_TO_NS(seconds) ((seconds) * (1000LL * 1000LL * 1000LL)) +#define RCUTILS_S_TO_NS(seconds) ((seconds) * RCUTILS_NANOSECONDS_PER_SEC) /// Convenience macro to convert milliseconds to nanoseconds. -#define RCUTILS_MS_TO_NS(milliseconds) ((milliseconds) * (1000LL * 1000LL)) +#define RCUTILS_MS_TO_NS(milliseconds) ((milliseconds) * RCUTILS_NANOSECONDS_PER_MILLISEC) /// Convenience macro to convert microseconds to nanoseconds. -#define RCUTILS_US_TO_NS(microseconds) ((microseconds) * 1000LL) +#define RCUTILS_US_TO_NS(microseconds) ((microseconds) * RCUTILS_NANOSECONDS_PER_MICROSEC) /// Convenience macro to convert nanoseconds to seconds. -#define RCUTILS_NS_TO_S(nanoseconds) ((nanoseconds) / (1000LL * 1000LL * 1000LL)) +#define RCUTILS_NS_TO_S(nanoseconds) ((nanoseconds) / RCUTILS_NANOSECONDS_PER_SEC) /// Convenience macro to convert nanoseconds to milliseconds. -#define RCUTILS_NS_TO_MS(nanoseconds) ((nanoseconds) / (1000LL * 1000LL)) +#define RCUTILS_NS_TO_MS(nanoseconds) ((nanoseconds) / RCUTILS_NANOSECONDS_PER_MILLISEC) /// Convenience macro to convert nanoseconds to microseconds. -#define RCUTILS_NS_TO_US(nanoseconds) ((nanoseconds) / 1000LL) +#define RCUTILS_NS_TO_US(nanoseconds) ((nanoseconds) / RCUTILS_NANOSECONDS_PER_MICROSEC) /// Convenience macro for rcutils_steady_time_now(rcutils_time_point_value_t *). #define RCUTILS_STEADY_TIME rcutils_steady_time_now diff --git a/src/time.c b/src/time.c index d2a13b6b..a2a88b3d 100644 --- a/src/time.c +++ b/src/time.c @@ -33,8 +33,8 @@ rcutils_nanoseconds_to_seconds(const int64_t nanoseconds) { // scale the nanoseconds separately for improved accuracy int64_t sec, nsec; - nsec = (nanoseconds % 1000000000l); - sec = ((nanoseconds - nsec) / 1000000000l); + nsec = (nanoseconds % RCUTILS_NANOSECONDS_PER_SEC); + sec = ((nanoseconds - nsec) / RCUTILS_NANOSECONDS_PER_SEC); double sec_double, nsec_double; nsec_double = 1e-9 * (double)(nsec); @@ -47,8 +47,8 @@ rcutils_nanoseconds_to_milliseconds(const int64_t nanoseconds) { // scale the nanoseconds separately for improved accuracy int64_t sec, nsec; - nsec = (nanoseconds % 1000000l); - sec = ((nanoseconds - nsec) / 1000000l); + nsec = (nanoseconds % RCUTILS_NANOSECONDS_PER_MILLISEC); + sec = ((nanoseconds - nsec) / RCUTILS_NANOSECONDS_PER_MILLISEC); double sec_double, nsec_double; nsec_double = 1e-6 * (double)(nsec); @@ -61,8 +61,8 @@ rcutils_nanoseconds_to_microseconds(const int64_t nanoseconds) { // scale the nanoseconds separately for improved accuracy int64_t sec, nsec; - nsec = (nanoseconds % 1000l); - sec = ((nanoseconds - nsec) / 1000l); + nsec = (nanoseconds % RCUTILS_NANOSECONDS_PER_MICROSEC); + sec = ((nanoseconds - nsec) / RCUTILS_NANOSECONDS_PER_MICROSEC); double sec_double, nsec_double; nsec_double = 1e-3 * (double)(nsec);