adevs
|
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