summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama-othman@users.noreply.github.com>2007-03-06 23:07:04 +0000
committerOssama Othman <ossama-othman@users.noreply.github.com>2007-03-06 23:07:04 +0000
commit8f64e37aaed7bce875157f711f71b6b28e3fbad4 (patch)
tree45547ab4d3daa28e629b94e9ca301ff72a816959
parenta66e2e62769504b69de2971866863c4071365a8b (diff)
downloadATCD-8f64e37aaed7bce875157f711f71b6b28e3fbad4.tar.gz
ChangeLogTag:Tue Mar 6 23:06:15 UTC 2007 Ossama Othman <ossama_othman at symantec dot com>
-rw-r--r--ACE/ChangeLog13
-rw-r--r--ACE/ace/Time_Value.cpp52
2 files changed, 50 insertions, 15 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog
index 7fe9f32d6d2..fa5ee5cefe2 100644
--- a/ACE/ChangeLog
+++ b/ACE/ChangeLog
@@ -1,3 +1,16 @@
+Tue Mar 6 23:06:15 UTC 2007 Ossama Othman <ossama_othman at symantec dot com>
+
+ * ace/Time_Value.cpp (operator*=):
+
+ Use long double for internal computations if double is not large
+ enough to retain precision of the time_t/suseconds_t values.
+ This will only provide improved behavior with compilers that
+ support double-extended precision floating numbers, i.e. >= 79
+ bits.
+
+ Added comments to explain what is being done in the
+ implementation.
+
Tue Mar 6 07:47:12 UTC 2007 Johnny Willemsen <jwillemsen@remedy.nl>
* ace/OS.inl:
diff --git a/ACE/ace/Time_Value.cpp b/ACE/ace/Time_Value.cpp
index bc8f6218159..97a6bd8c492 100644
--- a/ACE/ace/Time_Value.cpp
+++ b/ACE/ace/Time_Value.cpp
@@ -10,6 +10,7 @@ ACE_RCSID (ace,
#endif /* __ACE_INLINE__ */
#include "ace/Numeric_Limits.h"
+#include "ace/If_Then_Else.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
@@ -213,31 +214,52 @@ ACE_Time_Value::normalize (void)
ACE_Time_Value &
ACE_Time_Value::operator *= (double d)
{
- // double is long enough (16 digits) to not lose the accuracy.
- double time_total =
+ // The floating type to be used in the computations. It should be
+ // large enough to hold a time_t. We actually want a floating type
+ // with enough digits in its mantissa to hold a time_t without
+ // losing precision. For example, if FLT_RADIX is 2 and
+ // LDBL_MANT_DIG is 64, a long double has a 64 bit wide mantissa,
+ // which would be sufficient to hold a 64 bit time_t value without
+ // losing precision.
+ //
+ // For now we'll simply go with long double if it is larger than
+ // time_t. We're hosed if long double isn't large enough.
+ typedef ACE::If_Then_Else<(sizeof (double) > sizeof (time_t)),
+ double,
+ long double>::result_type float_type;
+
+ // long double is generally long enough to not lose precision.
+ float_type time_total =
(this->sec ()
- + static_cast<double> (this->usec ()) / ACE_ONE_SECOND_IN_USECS) * d;
+ + static_cast<float_type> (this->usec ()) / ACE_ONE_SECOND_IN_USECS) * d;
- // shall we saturate the result?
- static const double max_int = ACE_Numeric_Limits<time_t>::max () + 0.999999;
- static const double min_int = ACE_Numeric_Limits<time_t>::min () - 0.999999;
+ // Shall we saturate the result?
+ float_type const max_time =
+ ACE_Numeric_Limits<time_t>::max () + static_cast<float_type> (0.999999);
+ float_type const min_time =
+ ACE_Numeric_Limits<time_t>::min () - static_cast<float_type> (0.999999);
- if (time_total > max_int)
- time_total = max_int;
- if (time_total < min_int)
- time_total = min_int;
+ // Truncate if necessary.
+ if (time_total > max_time)
+ time_total = max_time;
+ else if (time_total < min_time)
+ time_total = min_time;
- const time_t time_sec = static_cast<time_t> (time_total);
+ // Retrieve non-fractional portion of seconds.
+ time_t const time_sec = static_cast<time_t> (time_total);
- time_total -= time_sec;
- time_total *= ACE_ONE_SECOND_IN_USECS;
+ time_total -= time_sec; // Retrieve the fraction of seconds.
+ time_total *= ACE_ONE_SECOND_IN_USECS; // Convert to microseconds.
suseconds_t time_usec = static_cast<suseconds_t> (time_total);
+ float_type const usec_diff = time_total - time_usec;
+ static float_type const roundup_threshold = 0.5; // Always 0.5.
+
// round up the result to save the last usec
- if (time_usec > 0 && (time_total - time_usec) >= 0.5)
+ if (time_usec > 0 && usec_diff >= roundup_threshold)
++time_usec;
- else if (time_usec < 0 && (time_total - time_usec) <= -0.5)
+ else if (time_usec < 0 && usec_diff <= -roundup_threshold)
--time_usec;
this->set (time_sec, time_usec);