certi-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[certi-cvs] certi libCERTI/FedTime.cc include/fedtime.hh RT...


From: certi-cvs
Subject: [certi-cvs] certi libCERTI/FedTime.cc include/fedtime.hh RT...
Date: Tue, 06 May 2008 13:36:19 +0000

CVSROOT:        /sources/certi
Module name:    certi
Changes by:     Eric NOULARD <erk>      08/05/06 13:36:19

Modified files:
        libCERTI       : FedTime.cc 
        include        : fedtime.hh 
        RTIA           : TimeManagement.cc 

Log message:
        Fix bug #23090 : UpdateAttributeValues throws InvalidFederationTime
        We should use consistent epsilon value and carefully compare floating
        point numbers (for time)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/certi/libCERTI/FedTime.cc?cvsroot=certi&r1=3.12&r2=3.13
http://cvs.savannah.gnu.org/viewcvs/certi/include/fedtime.hh?cvsroot=certi&r1=3.8&r2=3.9
http://cvs.savannah.gnu.org/viewcvs/certi/RTIA/TimeManagement.cc?cvsroot=certi&r1=3.35&r2=3.36

Patches:
Index: libCERTI/FedTime.cc
===================================================================
RCS file: /sources/certi/certi/libCERTI/FedTime.cc,v
retrieving revision 3.12
retrieving revision 3.13
diff -u -b -r3.12 -r3.13
--- libCERTI/FedTime.cc 7 Apr 2008 15:08:27 -0000       3.12
+++ libCERTI/FedTime.cc 6 May 2008 13:36:18 -0000       3.13
@@ -19,7 +19,7 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 // ----------------------------------------------------------------------------
 
-
+#include <math.h>
 
 #include "certi.hh"
 #include "fedtime.hh"
@@ -63,6 +63,87 @@
     return const_cast<FedTime &>(time).isPositiveInfinity() == RTI::RTI_TRUE ;
 }
 
+/*
+ fcmp
+ Copyright (c) 1998-2000 Theodore C. Belding
+ University of Michigan Center for the Study of Complex Systems
+ <mailto:address@hidden>
+ <http://fcmp.sourceforge.net>    
+  
+ This file is part of the fcmp distribution. fcmp is free software;
+ you can redistribute and modify it under the terms of the GNU Library
+ General Public License (LGPL), version 2 or later.  This software
+ comes with absolutely no warranty. See the file COPYING for details
+ and terms of copying.
+
+ Description:
+ 
+ Knuth's floating point comparison operators, from:
+ Knuth, D. E. (1998). The Art of Computer Programming.
+ Volume 2: Seminumerical Algorithms. 3rd ed. Addison-Wesley.
+ Section 4.2.2, p. 233. ISBN 0-201-89684-2.
+
+ Input parameters:
+ x1, x2: numbers to be compared
+ epsilon: determines tolerance
+
+ epsilon should be carefully chosen based on the machine's precision,
+ the observed magnitude of error, the desired precision, and the
+ magnitude of the numbers to be compared. See the fcmp README file for
+ more information.
+
+ This routine may be used for both single-precision (float) and
+ double-precision (double) floating-point numbers.
+ 
+ Returns:
+ -1 if x1 < x2
+  0 if x1 == x2
+  1 if x1 > x2
+*/
+
+inline int
+fcmp(double x1,double x2, double epsilon)
+{
+    int exponent;
+    double delta;
+    double difference;
+    
+    /* Get exponent(max(fabs(x1), fabs(x2))) and store it in exponent. */
+
+    /* If neither x1 nor x2 is 0, */
+    /* this is equivalent to max(exponent(x1), exponent(x2)). */
+
+    /* If either x1 or x2 is 0, its exponent returned by frexp would be 0, */
+    /* which is much larger than the exponents of numbers close to 0 in */
+    /* magnitude. But the exponent of 0 should be less than any number */
+    /* whose magnitude is greater than 0. */
+    
+    /* So we only want to set exponent to 0 if both x1 and */
+    /* x2 are 0. Hence, the following works for all x1 and x2. */
+
+    frexp(fabs(x1) > fabs(x2) ? x1 : x2, &exponent);
+
+    /* Do the comparison. */
+
+    /* delta = epsilon * pow(2, exponent) */
+
+    /* Form a neighborhood around x2 of size delta in either direction. */
+    /* If x1 is within this delta neighborhood of x2, x1 == x2. */
+    /* Otherwise x1 > x2 or x1 < x2, depending on which side of */
+    /* the neighborhood x1 is on. */
+    
+    delta = ldexp(epsilon, exponent); 
+    
+    difference = x1 - x2;
+
+    if (difference > delta)
+        return 1; /* x1 > x2 */
+    else if (difference < -delta) 
+        return -1;  /* x1 < x2 */
+    else /* -delta <= difference <= delta */
+        return 0;  /* x1 == x2 */
+}
+
 const char *infinity_str = "+inf" ;
 
 } // anonymous namespace
@@ -89,24 +170,31 @@
 //{
 //}
 
+const double RTIfedTime::epsilon = std::numeric_limits<double>::epsilon();
+
+int
+RTIfedTime::fcmp(const double x1, const double x2) {
+       return ::fcmp(x1,x2,RTIfedTime::epsilon); 
+}
+
 // ----------------------------------------------------------------------------
 // RTIfedTime
 RTIfedTime::RTIfedTime()
     : _fedTime(0),
       _zero(0),
-      _epsilon(std::numeric_limits<double>::epsilon()),
+      _epsilon(RTIfedTime::epsilon),
       _positiveInfinity(std::numeric_limits<double>::infinity()) { }
 
 RTIfedTime::RTIfedTime(const RTI::Double &time)
     : _fedTime(time),
       _zero(0),
-      _epsilon(std::numeric_limits<double>::epsilon()),
+      _epsilon(RTIfedTime::epsilon),
       _positiveInfinity(std::numeric_limits<double>::infinity()) { }
 
 RTIfedTime::RTIfedTime(const FedTime &time)
     : _fedTime(rft(time).getTime()),
       _zero(0),
-      _epsilon(std::numeric_limits<double>::epsilon()),
+      _epsilon(RTIfedTime::epsilon),
       _positiveInfinity(std::numeric_limits<double>::infinity()) { }
 
 // ----------------------------------------------------------------------------
@@ -228,7 +316,7 @@
     else if (is_infinity(*this))
        return RTI::RTI_FALSE ;
     else
-       return RTI::Boolean(_fedTime <= rft(time)._fedTime);
+       return RTI::Boolean(::fcmp(_fedTime, rft(time)._fedTime, _epsilon) <= 
0);
 }
 
 // ----------------------------------------------------------------------------
@@ -239,7 +327,7 @@
     if (is_infinity(*this))
        return RTI::RTI_FALSE ;
     else 
-       return RTI::Boolean(is_infinity(time) || _fedTime < rft(time)._fedTime);
+       return RTI::Boolean(is_infinity(time) || ::fcmp(_fedTime, 
rft(time)._fedTime, _epsilon) < 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -252,7 +340,7 @@
     else if (is_infinity(time))
        return RTI::RTI_FALSE ;
     else
-       return RTI::Boolean(_fedTime >= rft(time)._fedTime);
+       return RTI::Boolean(::fcmp(_fedTime, rft(time)._fedTime, _epsilon) >= 
0);
 }
 
 // ----------------------------------------------------------------------------
@@ -263,7 +351,7 @@
     if (is_infinity(time))
        return RTI::RTI_FALSE ;
     else
-       return RTI::Boolean(is_infinity(*this) || _fedTime > 
rft(time)._fedTime);
+       return RTI::Boolean(is_infinity(*this) || ::fcmp(_fedTime, 
rft(time)._fedTime, _epsilon) > 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -276,7 +364,7 @@
     else if (is_infinity(*this) || is_infinity(time))
        return RTI::RTI_FALSE ;
     else
-       return RTI::Boolean(_fedTime == rft(time)._fedTime);
+       return RTI::Boolean(::fcmp(_fedTime, rft(time)._fedTime, _epsilon) == 
0);
 }
 
 // ----------------------------------------------------------------------------
@@ -300,7 +388,7 @@
 RTIfedTime::operator==(const Double &time) const
     throw (RTI::InvalidFederationTime)
 {
-    return RTI::Boolean(!is_infinity(*this) && _fedTime == time);
+    return RTI::Boolean(!is_infinity(*this) && ::fcmp(_fedTime, time, 
_epsilon) == 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -308,7 +396,7 @@
 RTIfedTime::operator!=(const FedTime &time) const
     throw (RTI::InvalidFederationTime)
 {
-    return RTI::Boolean(!(*this == time));
+    return RTI::Boolean(::fcmp(_fedTime, rft(time)._fedTime, _epsilon) != 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -316,7 +404,7 @@
 RTIfedTime::operator!=(const Double &time) const
     throw (RTI::InvalidFederationTime)
 {
-    return RTI::Boolean(is_infinity(*this) || _fedTime != time);
+    return RTI::Boolean(is_infinity(*this) || ::fcmp(_fedTime, time, _epsilon) 
!= 0);
 }
 
 // ----------------------------------------------------------------------------

Index: include/fedtime.hh
===================================================================
RCS file: /sources/certi/certi/include/fedtime.hh,v
retrieving revision 3.8
retrieving revision 3.9
diff -u -b -r3.8 -r3.9
--- include/fedtime.hh  26 Sep 2007 14:14:46 -0000      3.8
+++ include/fedtime.hh  6 May 2008 13:36:19 -0000       3.9
@@ -1,5 +1,5 @@
 // HLA 1.3 Header "fedtime.hh"
-// $Id: fedtime.hh,v 3.8 2007/09/26 14:14:46 erk Exp $
+// $Id: fedtime.hh,v 3.9 2008/05/06 13:36:19 erk Exp $
 
 #ifndef HLA_FEDTIME_HH
 #define HLA_FEDTIME_HH
@@ -15,6 +15,10 @@
 class CERTI_EXPORT RTIfedTime : public RTI::FedTime
 {
 public:
+       
+       static const double epsilon; 
+       static int fcmp(const double x1, const double x2);
+       
     RTIfedTime();
     RTIfedTime(const RTI::Double &);
     RTIfedTime(const RTI::FedTime &);
@@ -131,4 +135,4 @@
 
 #endif // HLA_FEDTIME_HH
 
-// $Id: fedtime.hh,v 3.8 2007/09/26 14:14:46 erk Exp $
+// $Id: fedtime.hh,v 3.9 2008/05/06 13:36:19 erk Exp $

Index: RTIA/TimeManagement.cc
===================================================================
RCS file: /sources/certi/certi/RTIA/TimeManagement.cc,v
retrieving revision 3.35
retrieving revision 3.36
diff -u -b -r3.35 -r3.36
--- RTIA/TimeManagement.cc      5 May 2008 09:47:20 -0000       3.35
+++ RTIA/TimeManagement.cc      6 May 2008 13:36:19 -0000       3.36
@@ -18,7 +18,7 @@
 // along with this program ; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 //
-// $Id: TimeManagement.cc,v 3.35 2008/05/05 09:47:20 erk Exp $
+// $Id: TimeManagement.cc,v 3.36 2008/05/06 13:36:19 erk Exp $
 // ----------------------------------------------------------------------------
 
 #include <config.h>
@@ -33,7 +33,6 @@
 
 PrettyDebug D("RTIA_TM", __FILE__);
 static PrettyDebug G("GENDOC",__FILE__) ;
-const double epsilon = 1.0e-6 ;
 
 }
 
@@ -480,8 +479,11 @@
 
         _type_granted_state = AFTER_TAR_OR_NER ;  // will be
 
-        if (_lookahead_courant == 0.0) {
-           _lookahead_courant = epsilon ;
+        // FIXME Erk-->Pierre 
+        // We were changing lookahead value to epsilon
+        // when doing zero lookahead I'd rather handle
+        // _any_ near-to-zero lookahead as ZERO_LK
+        if (0==RTIfedTime::fcmp(_lookahead_courant,0.0)) {           
            _type_granted_state = AFTER_TAR_OR_NER_WITH_ZERO_LK ;
         }
 
@@ -668,26 +670,35 @@
 bool
 TimeManagement::testValidTime(FederationTime theTime)
 {
-       RTIfedTime epsilon;
-       
-   epsilon.setEpsilon();
+   int compareResult;
+   // FIXME Erk-->Pierre
+   // We should use RTIfedTime object and not _plain_ double
+   // value
    if (_avancee_en_cours == PAS_D_AVANCEE) {
       if (_type_granted_state == AFTER_TAR_OR_NER_WITH_ZERO_LK) {
-         if (theTime <= _heure_courante)
+        compareResult = RTIfedTime::fcmp(theTime,_heure_courante);
+        // if theTime <= _heure_courante
+         if (compareResult==-1 || compareResult==0)
             return false;
       }
       else {  // AFTER_TAR_OR_NER or AFTER_TARA_OR_NARA
-         if (theTime + epsilon.getTime() < _heure_courante + 
_lookahead_courant)
+        compareResult = RTIfedTime::fcmp(theTime,_heure_courante + 
_lookahead_courant);
+        // if theTime  < _heure_courante + _lookahead_courant
+         if (compareResult == -1)
             return false;
       }
    }
    else {
       if (_type_granted_state == AFTER_TAR_OR_NER_WITH_ZERO_LK) {
-         if (theTime <= date_avancee)
+        compareResult = RTIfedTime::fcmp(theTime,date_avancee);
+        // if theTime <= date_avancee
+         if (compareResult==-1 || compareResult==0)
             return false;
       }
       else {  // AFTER_TAR_OR_NER or AFTER_TARA_OR_NARA
-         if (theTime + epsilon.getTime() < date_avancee + _lookahead_courant)
+        compareResult = RTIfedTime::fcmp(theTime,date_avancee + 
_lookahead_courant);
+        // if (theTime  < date_avancee + _lookahead_courant)
+         if (compareResult == -1)
             return false;
       }
    }
@@ -827,9 +838,6 @@
     D.Out(pdRegister, "timeAdvanceGrant sent to federate (time = %f).",
           req.getFederationTime());
 
-    if (_lookahead_courant == epsilon)
-       _lookahead_courant = 0.0 ;
-
     _tick_state = TICK_NEXT;  // indicate the callback was processed
 
     comm->requestFederateService(&req);
@@ -863,8 +871,11 @@
 
         _type_granted_state = AFTER_TAR_OR_NER ;  // will be
 
-        if (_lookahead_courant == 0.0) {
-           _lookahead_courant = epsilon ;
+        // FIXME Erk-->Pierre 
+        // We were changing lookahead value to epsilon
+        // when doing zero lookahead I'd rather handle
+        // _any_ near-to-zero lookahead as ZERO_LK
+        if (0==RTIfedTime::fcmp(_lookahead_courant,0.0)) {         
            _type_granted_state = AFTER_TAR_OR_NER_WITH_ZERO_LK ;
         }
 
@@ -921,4 +932,4 @@
 
 }} // namespaces
 
-// $Id: TimeManagement.cc,v 3.35 2008/05/05 09:47:20 erk Exp $
+// $Id: TimeManagement.cc,v 3.36 2008/05/06 13:36:19 erk Exp $




reply via email to

[Prev in Thread] Current Thread [Next in Thread]