simtime.h

00001 //==========================================================================
00002 //   SIMTIME.H  - part of
00003 //                     OMNeT++/OMNEST
00004 //            Discrete System Simulation in C++
00005 //
00006 //==========================================================================
00007 
00008 /*--------------------------------------------------------------*
00009   Copyright (C) 1992-2008 Andras Varga
00010   Copyright (C) 2006-2008 OpenSim Ltd.
00011 
00012   This file is distributed WITHOUT ANY WARRANTY. See the file
00013   `license' for details on this and other legal matters.
00014 *--------------------------------------------------------------*/
00015 
00016 #ifndef __SIMTIME_H
00017 #define __SIMTIME_H
00018 
00019 #include <string>
00020 #include <iostream>
00021 #include "simkerneldefs.h"
00022 #include "platdep/intxtypes.h"
00023 
00024 NAMESPACE_BEGIN
00025 
00026 class cPar;
00027 
00028 // the most positive int64 value, represented as double
00029 #define INT64_MAX_DBL  9.22337203685e18
00030 
00034 enum SimTimeUnit
00035 {
00036     SIMTIME_S  =  0,
00037     SIMTIME_MS = -3,
00038     SIMTIME_US = -6,
00039     SIMTIME_NS = -9,
00040     SIMTIME_PS = -12,
00041     SIMTIME_FS = -15
00042 };
00043 
00060 class SIM_API SimTime
00061 {
00062   private:
00063     int64 t;
00064 
00065     static int scaleexp;     // scale exponent in the range -18..0
00066     static int64 dscale;     // 10^-scaleexp, that is 1 or 1000 or 1000000...
00067     static double fscale;    // 10^-scaleexp, that is 1 or 1000 or 1000000...
00068     static double invfscale; // 1/fscale; we store it because floating-point multiplication is faster than division
00069 
00070   protected:
00071     static void resetScale() {scaleexp = SCALEEXP_UNINITIALIZED;} // for unit tests only
00072 
00073   private:
00074     template<typename T> void check(T d) {if (scaleexp==SCALEEXP_UNINITIALIZED) initError(d);}
00075     void initError(double d);
00076 
00077     bool haveSameSign(int64 a, int64 b) { return (a^b) >= 0; }
00078 
00079     int64 toInt64(double i64) {
00080          if (fabs(i64) > INT64_MAX_DBL)
00081              rangeError(i64);
00082          return (int64)i64;
00083     }
00084 
00085     void checkedAdd(const SimTime& x) {
00086         // if operands are the same sign but result has different sign ==> overflow
00087         bool sameSign = haveSameSign(t, x.t);
00088         t += x.t;
00089         if (sameSign && !haveSameSign(t, x.t))
00090             overflowAdding(x);
00091     }
00092 
00093     void checkedSub(const SimTime& x) {
00094         // if operands are different signs and result has same sign as x ==> overflow
00095         bool differentSign = !haveSameSign(t, x.t);
00096         t -= x.t;
00097         if (differentSign && haveSameSign(t, x.t))
00098             overflowSubtracting(x);
00099     }
00100 
00101     void rangeError(double i64);
00102     void overflowAdding(const SimTime& x);
00103     void overflowSubtracting(const SimTime& x);
00104 
00105   public:
00106     // renamed constants (use SIMTIME_x instead)
00107     _OPPDEPRECATED static const int SCALEEXP_S;
00108     _OPPDEPRECATED static const int SCALEEXP_MS;
00109     _OPPDEPRECATED static const int SCALEEXP_US;
00110     _OPPDEPRECATED static const int SCALEEXP_NS;
00111     _OPPDEPRECATED static const int SCALEEXP_PS;
00112     _OPPDEPRECATED static const int SCALEEXP_FS;
00113 
00114     static const int SCALEEXP_UNINITIALIZED = 0xffff;
00115 
00121     SimTime() {t=0;}
00122 
00131     SimTime(double d) {operator=(d);}
00132 
00139     SimTime(cPar& d) {operator=(d);}
00140 
00141     // Note: a generic template constructor (commented out below) is not a good idea -- often causes surprises
00142     // template<typename T> SimTime(T d) {operator=(d);}
00143 
00159     SimTime(int64 significand, int exponent);
00160 
00164     SimTime(const SimTime& x) {operator=(x);}
00166 
00169     const SimTime& operator=(double d) {check(d); t=toInt64(fscale*d); return *this;}
00170     const SimTime& operator=(const cPar& d);
00171     const SimTime& operator=(const SimTime& x) {t=x.t; return *this;}
00172     template<typename T> const SimTime& operator=(T d) {check(d); t=toInt64(dscale*d); return *this;}
00173 
00174     const SimTime& operator+=(const SimTime& x) {checkedAdd(x); return *this;}
00175     const SimTime& operator-=(const SimTime& x) {checkedSub(x); return *this;}
00176 
00177     const SimTime& operator*=(double d) {t=toInt64(t*d); return *this;}
00178     const SimTime& operator/=(double d) {t=toInt64(t/d); return *this;}
00179     const SimTime& operator*=(const cPar& p);
00180     const SimTime& operator/=(const cPar& p);
00181     template<typename T> const SimTime& operator*=(T d) {t*=d; return *this;}
00182     template<typename T> const SimTime& operator/=(T d) {t/=d; return *this;}
00183 
00184     bool operator==(const SimTime& x) const  {return t==x.t;}
00185     bool operator!=(const SimTime& x) const  {return t!=x.t;}
00186     bool operator< (const SimTime& x) const  {return t<x.t;}
00187     bool operator> (const SimTime& x) const  {return t>x.t;}
00188     bool operator<=(const SimTime& x) const  {return t<=x.t;}
00189     bool operator>=(const SimTime& x) const  {return t>=x.t;}
00190 
00191     SimTime operator-() const {SimTime x; x.t = -t; return x;}
00192 
00193     friend const SimTime operator+(const SimTime& x, const SimTime& y);
00194     friend const SimTime operator-(const SimTime& x, const SimTime& y);
00195 
00196     friend const SimTime operator*(const SimTime& x, double d);
00197     friend const SimTime operator*(double d, const SimTime& x);
00198     friend const SimTime operator/(const SimTime& x, double d);
00199     friend double operator/(double d, const SimTime& x);
00200     friend double operator/(const SimTime& x, const SimTime& y);
00201 
00202     friend const SimTime operator*(const SimTime& x, const cPar& p);
00203     friend const SimTime operator*(const cPar& p, const SimTime& x);
00204     friend const SimTime operator/(const SimTime& x, const cPar& p);
00206 
00213     double dbl() const  {return t*invfscale;}
00214 
00230     int64 inUnit(int exponent) const;
00231 
00242     SimTime trunc(int exponent) const  {return SimTime(inUnit(exponent), exponent);}
00243 
00250     SimTime remainderForUnit(int exponent) const  {return (*this) - trunc(exponent);}
00251 
00263     void split(int exponent, int64& outValue, SimTime& outRemainder) const;
00264 
00268     std::string str() const;
00269 
00277     char *str(char *buf) const {char *endp; return SimTime::ttoa(buf, t, getScaleExp(), endp);}
00278 
00282     int64 raw() const  {return t;}
00283 
00287     const SimTime& setRaw(int64 l) {t = l; return *this;}
00288 
00293     static const SimTime getMaxTime() {return SimTime().setRaw(INT64_MAX);}
00294 
00299     static int64 getScale()  {return dscale;}
00300 
00305     static int getScaleExp() {return scaleexp;}
00306 
00319     static void setScaleExp(int e);
00320 
00326     static const SimTime parse(const char *s);
00327 
00337     static const SimTime parse(const char *s, const char *&endp);
00338 
00348     static char *ttoa(char *buf, int64 t, int scaleexp, char *&endp);
00349 };
00350 
00351 /*
00352  for *= and /=, we might need the following code:
00353     // linux bug workaround; don't change next two lines
00354     volatile double tmp = uint64_to_double( m_value ) * d;
00355     m_value = static_cast<int64>( tmp );
00356     return *this;
00357 */
00358 
00359 inline const SimTime operator+(const SimTime& x, const SimTime& y)
00360 {
00361     return SimTime(x)+=y;
00362 }
00363 
00364 inline const SimTime operator-(const SimTime& x, const SimTime& y)
00365 {
00366     return SimTime(x)-=y;
00367 }
00368 
00369 inline const SimTime operator*(const SimTime& x, double d)
00370 {
00371     return SimTime(x)*=d;
00372 }
00373 
00374 inline const SimTime operator*(double d, const SimTime& x)
00375 {
00376     return SimTime(x)*=d;
00377 }
00378 
00379 inline const SimTime operator/(const SimTime& x, double d)
00380 {
00381     return SimTime(x)/=d;
00382 }
00383 
00384 inline double operator/(double d, const SimTime& x)
00385 {
00386     return d / x.dbl();
00387 }
00388 
00389 inline double operator/(const SimTime& x, const SimTime& y)
00390 {
00391     return (double)x.raw() / (double)y.raw();
00392 }
00393 
00394 inline std::ostream& operator<<(std::ostream& os, const SimTime& x)
00395 {
00396     char buf[64]; char *endp;
00397     return os << SimTime::ttoa(buf, x.raw(), SimTime::getScaleExp(), endp);
00398 }
00399 
00400 NAMESPACE_END
00401 
00402 // used locally; needed because sign of a%b is implementation dependent if a<0
00403 inline int64 _i64mod(const int64& any_t, const int64& positive_u)
00404 {
00405     int64 m = any_t % positive_u;
00406     return m>=0 ? m : m+positive_u;
00407 }
00408 
00412 inline const OPP::SimTime floor(const OPP::SimTime& x)
00413 {
00414     int64 u = OPP::SimTime::getScale();
00415     int64 t = x.raw();
00416     return OPP::SimTime().setRaw(t - _i64mod(t,u));
00417 }
00418 
00426 inline const OPP::SimTime floor(const OPP::SimTime& x, const OPP::SimTime& unit, const OPP::SimTime& offset = OPP::SimTime())
00427 {
00428     int64 off = offset.raw();
00429     int64 u = unit.raw();
00430     int64 t = x.raw() - off;
00431     return OPP::SimTime().setRaw(t - _i64mod(t,u) + off);
00432 }
00433 
00437 inline const OPP::SimTime ceil(const OPP::SimTime& x)
00438 {
00439     int64 u = OPP::SimTime::getScale();
00440     int64 t = x.raw() + u-1;
00441     return OPP::SimTime().setRaw(t - _i64mod(t,u));
00442 }
00443 
00448 inline const OPP::SimTime ceil(const OPP::SimTime& x, const OPP::SimTime& unit, const OPP::SimTime& offset = OPP::SimTime())
00449 {
00450     int64 off = offset.raw();
00451     int64 u = unit.raw();
00452     int64 t = x.raw() - off + u-1;
00453     return OPP::SimTime().setRaw(t - _i64mod(t,u) + off);
00454 }
00455 
00459 inline const OPP::SimTime fabs(const OPP::SimTime& x)
00460 {
00461     return x.raw()<0 ? OPP::SimTime().setRaw(-x.raw()) : x;
00462 }
00463 
00467 inline const OPP::SimTime fmod(const OPP::SimTime& x, const OPP::SimTime& y)
00468 {
00469     return OPP::SimTime().setRaw(x.raw() % y.raw());
00470 }
00471 
00472 #endif
00473 
00474 
Generated on Tue Dec 2 11:16:27 2014 for OMNeT++ Simulation Library by  doxygen 1.6.3