OMNeT++ Simulation Library  6.0.3
simtime.h
1 //==========================================================================
2 // SIMTIME.H - part of
3 // OMNeT++/OMNEST
4 // Discrete System Simulation in C++
5 //
6 //==========================================================================
7 
8 /*--------------------------------------------------------------*
9  Copyright (C) 1992-2017 Andras Varga
10  Copyright (C) 2006-2017 OpenSim Ltd.
11 
12  This file is distributed WITHOUT ANY WARRANTY. See the file
13  `license' for details on this and other legal matters.
14 *--------------------------------------------------------------*/
15 
16 #ifndef __OMNETPP_SIMTIME_H
17 #define __OMNETPP_SIMTIME_H
18 
19 #include <string>
20 #include <iostream>
21 #include <cstdint>
22 #include "platdep/intlimits.h"
23 #include "simkerneldefs.h"
24 
25 namespace omnetpp {
26 
27 class cPar;
28 
29 // the most positive int64_t value, represented as double
30 #define INT64_MAX_DBL 9.22337203685e18
31 
37 {
38  SIMTIME_S = 0,
39  SIMTIME_MS = -3,
40  SIMTIME_US = -6,
41  SIMTIME_NS = -9,
42  SIMTIME_PS = -12,
43  SIMTIME_FS = -15,
44  SIMTIME_AS = -18
45 };
46 
66 class SIM_API SimTime
67 {
68  private:
69  int64_t t;
70 
71  static int scaleexp; // scale exponent in the range -18..0
72  static int64_t dscale; // 10^-scaleexp, that is 1 or 1000 or 1000000...
73  static double fscale; // 10^-scaleexp, that is 1 or 1000 or 1000000...
74  static double invfscale; // 1/fscale; we store it because floating-point multiplication is faster than division
75  static int64_t maxseconds; // the largest number in seconds that can be represented with this scaleexp
76  static bool checkmul; // when true, multiplications are checked for integer overflow
77 
78  static const int SCALEEXP_UNINITIALIZED = 0xffff;
79 
80  public:
86  static const SimTime ZERO;
87 
88  protected:
89  static void resetScale() {scaleexp = SCALEEXP_UNINITIALIZED;} // for unit tests only
90 
91  private:
92  template<typename T> void assertInited(T d) {if (scaleexp==SCALEEXP_UNINITIALIZED) initError(d);}
93  [[noreturn]] void initError(double d);
94 
95  bool haveSameSign(int64_t a, int64_t b) { return (a^b) >= 0; }
96 
97  int64_t toInt64(double i64) {
98  i64 = floor(i64 + 0.5);
99  if (fabs(i64) <= INT64_MAX_DBL)
100  return (int64_t)i64;
101  else // out of range or NaN
102  rangeErrorInt64(i64);
103  }
104 
105  void setSeconds(int64_t sec) {
106  if (sec > maxseconds || sec < -maxseconds)
107  rangeErrorSeconds(sec);
108  t = dscale * sec;
109  }
110 
111  void setSecondsU(uint64_t sec) {
112  if (sec > maxseconds)
113  rangeErrorSeconds(sec);
114  t = dscale * sec;
115  }
116 
117  void checkedAdd(const SimTime& x) {
118  // if operands are the same sign but result has different sign ==> overflow
119  bool sameSign = haveSameSign(t, x.t);
120  t += x.t;
121  if (sameSign && !haveSameSign(t, x.t))
122  overflowAdding(x);
123  }
124 
125  void checkedSub(const SimTime& x) {
126  // if operands are different signs and result has same sign as x ==> overflow
127  bool differentSign = !haveSameSign(t, x.t);
128  t -= x.t;
129  if (differentSign && haveSameSign(t, x.t))
130  overflowSubtracting(x);
131  }
132 
133  void checkedMul(int64_t x);
134 
135  [[noreturn]] void rangeErrorInt64(double i64);
136  [[noreturn]] void rangeErrorSeconds(int64_t x);
137  [[noreturn]] void overflowAdding(const SimTime& x);
138  [[noreturn]] void overflowSubtracting(const SimTime& x);
139  [[noreturn]] void overflowNegating();
140 
141  public:
142  // internal: Formats a time string. Use SIMTIME_MS etc constants for prec. Note: it performs TRUNCATION towards zero, not rounding!
143  std::string format(int prec=getScaleExp(), const char *decimalSep=".", const char *digitSep="", bool addUnits=false, const char *beforeUnit=nullptr, const char *afterUnit=nullptr) const;
144 
145  public:
151  SimTime(): t(0) {}
152 
161  SimTime(double d) {operator=(d);}
162 
169  SimTime(cPar& d) {operator=(d);}
170 
186  SimTime(int64_t value, SimTimeUnit unit);
187 
191  SimTime(const SimTime& x) {t=x.t;}
193 
196  SimTime& operator=(const SimTime& x) = default;
197  SimTime& operator=(const cPar& d);
198  SimTime& operator=(double d) {assertInited(d); t=toInt64(fscale*d); return *this;}
199  SimTime& operator=(short d) {assertInited(d); setSeconds(d); return *this;}
200  SimTime& operator=(int d) {assertInited(d); setSeconds(d); return *this;}
201  SimTime& operator=(long d) {assertInited(d); setSeconds(d); return *this;}
202  SimTime& operator=(long long d) {assertInited(d); setSeconds(d); return *this;}
203  SimTime& operator=(unsigned short d) {assertInited(d); setSecondsU(d); return *this;}
204  SimTime& operator=(unsigned int d) {assertInited(d); setSecondsU(d); return *this;}
205  SimTime& operator=(unsigned long d) {assertInited(d); setSecondsU(d); return *this;}
206  SimTime& operator=(unsigned long long d) {assertInited(d); setSecondsU(d); return *this;}
207 
208  bool operator==(const SimTime& x) const {return t==x.t;}
209  bool operator!=(const SimTime& x) const {return t!=x.t;}
210  bool operator< (const SimTime& x) const {return t<x.t;}
211  bool operator> (const SimTime& x) const {return t>x.t;}
212  bool operator<=(const SimTime& x) const {return t<=x.t;}
213  bool operator>=(const SimTime& x) const {return t>=x.t;}
214 
215  SimTime operator-() const {SimTime x; x.t = -t; if (x.t==INT64_MIN) x.overflowNegating(); return x;}
216 
217  const SimTime& operator+=(const SimTime& x) {checkedAdd(x); return *this;}
218  const SimTime& operator-=(const SimTime& x) {checkedSub(x); return *this;}
219  friend const SimTime operator+(const SimTime& x, const SimTime& y) { return SimTime(x)+=y; }
220  friend const SimTime operator-(const SimTime& x, const SimTime& y) { return SimTime(x)-=y; }
221 
222  const SimTime& operator*=(double d) {t=toInt64(t*d); return *this;}
223  const SimTime& operator*=(short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
224  const SimTime& operator*=(int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
225  const SimTime& operator*=(long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
226  const SimTime& operator*=(long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
227  const SimTime& operator*=(unsigned short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
228  const SimTime& operator*=(unsigned int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
229  const SimTime& operator*=(unsigned long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
230  const SimTime& operator*=(unsigned long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;} //TODO check overflow from unsigned->signed conversion
231  const SimTime& operator*=(const cPar& p);
232 
233  const SimTime& operator/=(double d) {t=toInt64(t/d); return *this;}
234  const SimTime& operator/=(short d) {t/=d; return *this;}
235  const SimTime& operator/=(int d) {t/=d; return *this;}
236  const SimTime& operator/=(long d) {t/=d; return *this;}
237  const SimTime& operator/=(long long d) {t/=d; return *this;}
238  const SimTime& operator/=(unsigned short d) {t/=d; return *this;}
239  const SimTime& operator/=(unsigned int d) {t/=d; return *this;}
240  const SimTime& operator/=(unsigned long d) {t/=d; return *this;}
241  const SimTime& operator/=(unsigned long long d) {t/=d; return *this;}
242  const SimTime& operator/=(const cPar& p);
243 
244  friend const SimTime operator*(const SimTime& x, double d) { return SimTime(x)*=d; }
245  friend const SimTime operator*(const SimTime& x, short d) { return SimTime(x)*=d; }
246  friend const SimTime operator*(const SimTime& x, int d) { return SimTime(x)*=d; }
247  friend const SimTime operator*(const SimTime& x, long d) { return SimTime(x)*=d; }
248  friend const SimTime operator*(const SimTime& x, long long d) { return SimTime(x)*=d; }
249  friend const SimTime operator*(const SimTime& x, unsigned short d) { return SimTime(x)*=d; }
250  friend const SimTime operator*(const SimTime& x, unsigned int d) { return SimTime(x)*=d; }
251  friend const SimTime operator*(const SimTime& x, unsigned long d) { return SimTime(x)*=d; }
252  friend const SimTime operator*(const SimTime& x, unsigned long long d) { return SimTime(x)*=d; }
253  friend const SimTime operator*(const SimTime& x, const cPar& p) { return SimTime(x)*=p; }
254 
255  friend const SimTime operator*(double d, const SimTime& x) { return SimTime(x)*=d; }
256  friend const SimTime operator*(short d, const SimTime& x) { return SimTime(x)*=d; }
257  friend const SimTime operator*(int d, const SimTime& x) { return SimTime(x)*=d; }
258  friend const SimTime operator*(long d, const SimTime& x) { return SimTime(x)*=d; }
259  friend const SimTime operator*(long long d, const SimTime& x) { return SimTime(x)*=d; }
260  friend const SimTime operator*(unsigned short d, const SimTime& x) { return SimTime(x)*=d; }
261  friend const SimTime operator*(unsigned int d, const SimTime& x) { return SimTime(x)*=d; }
262  friend const SimTime operator*(unsigned long d, const SimTime& x) { return SimTime(x)*=d; }
263  friend const SimTime operator*(unsigned long long d, const SimTime& x) { return SimTime(x)*=d; }
264  friend const SimTime operator*(const cPar& p, const SimTime& x) { return SimTime(x)*=p; }
265 
266  friend const SimTime operator/(const SimTime& x, double d) { return SimTime(x)/=d; }
267  friend const SimTime operator/(const SimTime& x, short d) { return SimTime(x)/=d; }
268  friend const SimTime operator/(const SimTime& x, int d) { return SimTime(x)/=d; }
269  friend const SimTime operator/(const SimTime& x, long d) { return SimTime(x)/=d; }
270  friend const SimTime operator/(const SimTime& x, long long d) { return SimTime(x)/=d; }
271  friend const SimTime operator/(const SimTime& x, unsigned short d) { return SimTime(x)/=d; }
272  friend const SimTime operator/(const SimTime& x, unsigned int d) { return SimTime(x)/=d; }
273  friend const SimTime operator/(const SimTime& x, unsigned long d) { return SimTime(x)/=d; }
274  friend const SimTime operator/(const SimTime& x, unsigned long long d) { return SimTime(x)/=d; }
275  friend const SimTime operator/(const SimTime& x, const cPar& p) { return SimTime(x)/=p; }
276 
277  friend double operator/(const SimTime& x, const SimTime& y) { return (double)x.raw() / (double)y.raw(); }
278 
279  friend double operator/(double x, const SimTime& y) { return x / y.dbl(); }
280  friend double operator/(short x, const SimTime& y) { return (long long)x / y; }
281  friend double operator/(int x, const SimTime& y) { return (long long)x / y; }
282  friend double operator/(long x, const SimTime& y) { return (long long)x / y; }
283  friend SIM_API double operator/(long long x, const SimTime& y);
284  friend double operator/(unsigned short x, const SimTime& y) { return (unsigned long long)x / y; }
285  friend double operator/(unsigned int x, const SimTime& y) { return (unsigned long long)x / y; }
286  friend double operator/(unsigned long x, const SimTime& y) { return (unsigned long long)x / y; }
287  friend SIM_API double operator/(unsigned long long x, const SimTime& y);
288  friend SIM_API double operator/(const cPar& p, const SimTime& x);
290 
293 
299  bool isZero() const {return t==0;}
300 
307  double dbl() const {return t*invfscale;}
308 
320  int64_t inUnit(SimTimeUnit unit) const;
321 
330  SimTime trunc(SimTimeUnit unit) const {return SimTime(inUnit(unit), unit);}
331 
338  SimTime remainderForUnit(SimTimeUnit unit) const {return (*this) - trunc(unit);}
339 
350  void split(SimTimeUnit unit, int64_t& outValue, SimTime& outRemainder) const;
351 
357  std::string str() const {char buf[64]; return str(buf);}
358 
366  char *str(char *buf) const {char *endp; return SimTime::ttoa(buf, t, getScaleExp(), endp);}
367 
374  std::string ustr() const;
375 
382  std::string ustr(SimTimeUnit unit) const;
383 
387  int64_t raw() const {return t;}
388 
392  static SimTime fromRaw(int64_t l) {SimTime tmp; tmp.t = l; return tmp;}
393 
397  const SimTime& setRaw(int64_t l) {t = l; return *this;}
398 
403  static const SimTime getMaxTime() {return SimTime().setRaw(INT64_MAX);}
404 
409  static int64_t getScale() {return dscale;}
410 
415  static int getScaleExp() {return scaleexp;}
416 
429  static void setScaleExp(int e);
430 
436  static const SimTime parse(const char *s);
437 
447  static const SimTime parse(const char *s, const char *&endp);
448 
458  static char *ttoa(char *buf, int64_t t, int scaleexp, char *&endp);
460 };
461 
462 inline std::ostream& operator<<(std::ostream& os, const SimTime& x)
463 {
464  char buf[64]; char *endp;
465  return os << SimTime::ttoa(buf, x.raw(), SimTime::getScaleExp(), endp);
466 }
467 
468 } // namespace omnetpp
469 
470 #endif
471 
472 
omnetpp::SimTime::ttoa
static char * ttoa(char *buf, int64_t t, int scaleexp, char *&endp)
omnetpp::SimTimeUnit
SimTimeUnit
Enum for simulation time base-10 exponents.
Definition: simtime.h:36
omnetpp::SimTime::ZERO
static const SimTime ZERO
Definition: simtime.h:86
omnetpp::SimTime::SimTime
SimTime(const SimTime &x)
Definition: simtime.h:191
omnetpp::SimTime::getScaleExp
static int getScaleExp()
Definition: simtime.h:415
omnetpp::SimTime::setRaw
const SimTime & setRaw(int64_t l)
Definition: simtime.h:397
omnetpp::SimTime::fromRaw
static SimTime fromRaw(int64_t l)
Definition: simtime.h:392
omnetpp::SimTime
int64_t-based, base-10 fixed-point simulation time.
Definition: simtime.h:66
omnetpp::SimTime::str
std::string str() const
Definition: simtime.h:357
omnetpp::SimTime::isZero
bool isZero() const
Definition: simtime.h:299
omnetpp::SimTime::str
char * str(char *buf) const
Definition: simtime.h:366
omnetpp::cPar
Represents a module or channel parameter.
Definition: cpar.h:70
omnetpp::SimTime::SimTime
SimTime(cPar &d)
Definition: simtime.h:169
omnetpp::SimTime::dbl
double dbl() const
Definition: simtime.h:307
omnetpp::SimTime::getMaxTime
static const SimTime getMaxTime()
Definition: simtime.h:403
omnetpp::SimTime::getScale
static int64_t getScale()
Definition: simtime.h:409
omnetpp::SimTime::remainderForUnit
SimTime remainderForUnit(SimTimeUnit unit) const
Definition: simtime.h:338
omnetpp::floor
const SimTime floor(const SimTime &x)
simtime_t version of floor(double) from math.h.
Definition: simtimemath.h:38
omnetpp::SimTime::SimTime
SimTime(double d)
Definition: simtime.h:161
omnetpp::fabs
const SimTime fabs(const SimTime &x)
Returns the absolute value of the simulation time x.
Definition: simtimemath.h:85
omnetpp::SimTime::raw
int64_t raw() const
Definition: simtime.h:387
omnetpp::SimTime::SimTime
SimTime()
Definition: simtime.h:151
omnetpp::SimTime::trunc
SimTime trunc(SimTimeUnit unit) const
Definition: simtime.h:330