adevs
/home/rotten/adevs-2.6/include/adevs_time.h
00001 /***************
00002 Copyright (C) 2008 by James Nutaro
00003 
00004 This library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Lesser General Public
00006 License as published by the Free Software Foundation; either
00007 version 2 of the License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 Bugs, comments, and questions can be sent to nutaro@gmail.com
00019 ***************/
00020 
00021 #ifndef __adevs_time_h_
00022 #define __adevs_time_h_
00023 #include <cfloat>
00024 #include <iostream>
00025 #include <cmath>
00026 #include <limits>
00027 
00029 template <class T> inline T adevs_inf();
00031 template <class T> inline T adevs_zero(); 
00033 template <class T> inline T adevs_sentinel(); 
00034 
00035 namespace adevs
00036 {
00037 
00043 template<class T = double> struct Time
00044 {
00045         T t;
00046         unsigned int c;
00048         static adevs::Time<T> Inf() { return Time<T>(adevs_inf<T>(),0); }
00050         Time(T t = 0, unsigned int c = 0):t(t),c(c){}
00052         Time(const Time& t2):t(t2.t),c(t2.c){}
00054         const Time& operator=(const Time& t2)
00055         {
00056                 t = t2.t;
00057                 c = t2.c;
00058                 return *this;
00059         }
00061         bool operator<(T t2) const { return t < t2; }
00066         const Time& operator=(T t2)
00067         {
00068                 t = t2;
00069                 c = 0;
00070                 return *this;
00071         }
00073         Time operator+(const Time& t2) const
00074         {
00075            if (t2.t == 0) return Time(t,t2.c+c);
00076            else return Time(t+t2.t,0);
00077         }
00079         const Time& operator+=(const Time& t2)
00080         {
00081                 *this = *this+t2;
00082                 return *this;
00083         }
00085         T operator-(T t2) const
00086         {
00087                 return t-t2;
00088         }
00090         bool operator==(const Time& t2) const
00091         {
00092                 return (t == t2.t && c == t2.c);
00093         }
00095         bool operator!=(const Time& t2) const
00096         {
00097                 return !(*this == t2);
00098         }
00100         bool operator<(const Time& t2) const
00101         {
00102                 return (t < t2.t || (t == t2.t && c < t2.c));
00103         }
00104         bool operator<=(const Time& t2) const
00105         {
00106                 return (*this == t2 || *this < t2);
00107         }
00108         bool operator>(const Time& t2) const
00109         {
00110                 return !(*this <= t2);
00111         }
00112         bool operator>=(const Time& t2) const
00113         {
00114                 return !(*this < t2);
00115         }
00116 };
00117 
00131 inline int fcmp(double x1, double x2, double epsilon) 
00132 {
00133     int exponent;
00134     double delta;
00135     double difference;
00136 
00137     /* Get exponent(max(fabs(x1), fabs(x2))) and store it in exponent. */
00138 
00139     /* If neither x1 nor x2 is 0, */
00140     /* this is equivalent to max(exponent(x1), exponent(x2)). */
00141 
00142     /* If either x1 or x2 is 0, its exponent returned by frexp would be 0, */
00143     /* which is much larger than the exponents of numbers close to 0 in */
00144     /* magnitude. But the exponent of 0 should be less than any number */
00145     /* whose magnitude is greater than 0. */
00146 
00147     /* So we only want to set exponent to 0 if both x1 and */
00148     /* x2 are 0. Hence, the following works for all x1 and x2. */
00149 
00150     frexp(fabs(x1) > fabs(x2) ? x1 : x2, &exponent);
00151 
00152     /* Do the comparison. */
00153 
00154     /* delta = epsilon * pow(2, exponent) */
00155 
00156     /* Form a neighborhood around x2 of size delta in either direction. */
00157     /* If x1 is within this delta neighborhood of x2, x1 == x2. */
00158     /* Otherwise x1 > x2 or x1 < x2, depending on which side of */
00159     /* the neighborhood x1 is on. */
00160 
00161     delta = ldexp(epsilon, exponent); 
00162 
00163     difference = x1 - x2;
00164 
00165     if (difference > delta)
00166         return 1; /* x1 > x2 */
00167     else if (difference < -delta)
00168         return -1;  /* x1 < x2 */
00169     else /* -delta <= difference <= delta */
00170         return 0;  /* x1 == x2 */
00171 }
00172 
00180 class double_fcmp {
00181 
00182 private:
00183         double d;
00184 
00185 public:
00190     static double epsilon;
00191 
00192     double_fcmp(double rhs = 0) 
00193         : d(rhs) { }
00194 
00195     const double_fcmp& operator=(const double_fcmp& rhs)
00196     {
00197         d = rhs.d;
00198         return *this;
00199     }
00200     const double_fcmp& operator=(double rhs)
00201     {
00202         d = rhs;
00203         return *this;
00204     }
00205     operator double()
00206     {
00207         return d;
00208     }
00209     bool operator<(double rhs) const
00210     {
00211         return (fcmp(d, rhs, epsilon) < 0);
00212     }
00213     bool operator<(const double_fcmp& rhs) const
00214     {
00215         return (fcmp(d, rhs.d, epsilon) < 0);
00216     }
00217     bool operator<=(const double_fcmp& rhs) const
00218     {
00219         return (fcmp(d, rhs.d, epsilon) <= 0);
00220     }
00221     bool operator>(const double_fcmp& rhs) const
00222     {
00223         return (fcmp(d, rhs.d, epsilon) > 0);
00224     }
00225     bool operator>=(const double_fcmp& rhs) const
00226     {
00227         return (fcmp(d, rhs.d, epsilon) >= 0);
00228     }
00229     bool operator==(double rhs) const
00230     {
00231         return (fcmp(d, rhs, epsilon) == 0);
00232     }
00233     bool operator==(const double_fcmp& rhs) const
00234     {
00235         return (fcmp(d, rhs.d, epsilon) == 0);
00236     }
00237 };
00238 
00239 } // end namespace
00240 
00241 template <> inline double adevs_inf() {
00242         return std::numeric_limits<double>::max(); }
00243 template <> inline int adevs_inf() {
00244         return std::numeric_limits<int>::max(); }
00245 template <> inline adevs::double_fcmp adevs_inf() {
00246         return std::numeric_limits<double>::max(); }
00247 
00248 template <> inline double adevs_zero() { return 0.0; }
00249 template <> inline int adevs_zero() { return 0; }
00250 template <> inline adevs::double_fcmp adevs_zero() { return 0.0; }
00251 
00252 template <> inline double adevs_sentinel() { return -1.0; }
00253 template <> inline int adevs_sentinel() { return -1; }
00254 template <> inline adevs::double_fcmp adevs_sentinel() { return -1.0; }
00255 
00256 template<class T>
00257 std::ostream& operator<<(std::ostream& strm, const adevs::Time<T>& t);
00258 
00259 #endif