OMNeT++ API 6.1
Discrete Event Simulation Library
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  void fromInt64WithUnit(int64_t d, SimTimeUnit unit);
98  void fromUint64WithUnit(uint64_t d, SimTimeUnit unit);
99 
100  int64_t toInt64(double d) {
101  d = floor(d + 0.5);
102  if (fabs(d) <= INT64_MAX_DBL)
103  return (int64_t)d;
104  else // out of range or NaN
105  rangeErrorInt64(d);
106  }
107 
108  int64_t fromUint64(uint64_t u) {
109  if (u > (uint64_t)INT64_MAX)
110  rangeErrorInt64(u); //TODO
111  return (int64_t)u;
112  }
113 
114  void setSeconds(int64_t sec) {
115  if (sec > maxseconds || sec < -maxseconds)
116  rangeErrorSeconds(sec);
117  t = dscale * sec;
118  }
119 
120  void setSecondsU(uint64_t sec) {
121  if (sec > (uint64_t)maxseconds)
122  rangeErrorSeconds(sec);
123  t = dscale * sec;
124  }
125 
126  void checkedAdd(const SimTime& x) {
127  // if operands are the same sign but result has different sign ==> overflow
128  bool sameSign = haveSameSign(t, x.t);
129  t += x.t;
130  if (sameSign && !haveSameSign(t, x.t))
131  overflowAdding(x);
132  }
133 
134  void checkedSub(const SimTime& x) {
135  // if operands are different signs and result has same sign as x ==> overflow
136  bool differentSign = !haveSameSign(t, x.t);
137  t -= x.t;
138  if (differentSign && haveSameSign(t, x.t))
139  overflowSubtracting(x);
140  }
141 
142  void checkedMul(int64_t x);
143 
144  [[noreturn]] void rangeErrorInt64(double i64);
145  [[noreturn]] void rangeErrorSeconds(int64_t x);
146  [[noreturn]] void overflowAdding(const SimTime& x);
147  [[noreturn]] void overflowSubtracting(const SimTime& x);
148  [[noreturn]] void overflowNegating();
149 
150  public:
151  // internal: Formats a time string. Use SIMTIME_MS etc constants for prec. Note: it performs TRUNCATION towards zero, not rounding!
152  std::string format(int prec=getScaleExp(), const char *decimalSep=".", const char *digitSep="", bool addUnits=false, const char *beforeUnit=nullptr, const char *afterUnit=nullptr) const;
153 
154  public:
160  SimTime(): t(0) {}
161 
168  SimTime(double d) {operator=(d);}
169 
174  SimTime(short d) {operator=(d);}
175  SimTime(int d) {operator=(d);}
176  SimTime(long d) {operator=(d);}
177  SimTime(long long d) {operator=(d);}
178  SimTime(unsigned short d) {operator=(d);}
179  SimTime(unsigned int d) {operator=(d);}
180  SimTime(unsigned long d) {operator=(d);}
181  SimTime(unsigned long long d) {operator=(d);}
182 
189  SimTime(const cPar& d) {operator=(d);}
190 
206  SimTime(double value, SimTimeUnit unit, bool allowRounding=false);
207 
218  SimTime(short d, SimTimeUnit unit) {fromInt64WithUnit(d, unit);}
219  SimTime(int d, SimTimeUnit unit) {fromInt64WithUnit(d, unit);}
220  SimTime(long d, SimTimeUnit unit) {fromInt64WithUnit(d, unit);}
221  SimTime(long long d, SimTimeUnit unit) {fromInt64WithUnit(d, unit);}
222  SimTime(unsigned short d, SimTimeUnit unit) {fromUint64WithUnit(d, unit);}
223  SimTime(unsigned int d, SimTimeUnit unit) {fromUint64WithUnit(d, unit);}
224  SimTime(unsigned long d, SimTimeUnit unit) {fromUint64WithUnit(d, unit);}
225  SimTime(unsigned long long d, SimTimeUnit unit) {fromUint64WithUnit(d, unit);}
226 
230  SimTime(const SimTime& x) {t=x.t;}
232 
235  SimTime& operator=(const SimTime& x) = default;
236  SimTime& operator=(const cPar& d);
237  SimTime& operator=(double d) {assertInited(d); t=toInt64(fscale*d); return *this;}
238  SimTime& operator=(short d) {assertInited(d); setSeconds(d); return *this;}
239  SimTime& operator=(int d) {assertInited(d); setSeconds(d); return *this;}
240  SimTime& operator=(long d) {assertInited(d); setSeconds(d); return *this;}
241  SimTime& operator=(long long d) {assertInited(d); setSeconds(d); return *this;}
242  SimTime& operator=(unsigned short d) {assertInited(d); setSecondsU(d); return *this;}
243  SimTime& operator=(unsigned int d) {assertInited(d); setSecondsU(d); return *this;}
244  SimTime& operator=(unsigned long d) {assertInited(d); setSecondsU(d); return *this;}
245  SimTime& operator=(unsigned long long d) {assertInited(d); setSecondsU(d); return *this;}
246 
247  bool operator==(const SimTime& x) const {return t==x.t;}
248  bool operator!=(const SimTime& x) const {return t!=x.t;}
249  bool operator< (const SimTime& x) const {return t<x.t;}
250  bool operator> (const SimTime& x) const {return t>x.t;}
251  bool operator<=(const SimTime& x) const {return t<=x.t;}
252  bool operator>=(const SimTime& x) const {return t>=x.t;}
253 
254  SimTime operator-() const {SimTime x; x.t = -t; if (x.t==INT64_MIN) x.overflowNegating(); return x;}
255 
256  const SimTime& operator+=(const SimTime& x) {checkedAdd(x); return *this;}
257  const SimTime& operator-=(const SimTime& x) {checkedSub(x); return *this;}
258  friend const SimTime operator+(const SimTime& x, const SimTime& y) { return SimTime(x)+=y; }
259  friend const SimTime operator-(const SimTime& x, const SimTime& y) { return SimTime(x)-=y; }
260 
261  const SimTime& operator*=(double d) {t=toInt64(t*d); return *this;}
262  const SimTime& operator*=(short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
263  const SimTime& operator*=(int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
264  const SimTime& operator*=(long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
265  const SimTime& operator*=(long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
266  const SimTime& operator*=(unsigned short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
267  const SimTime& operator*=(unsigned int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
268  const SimTime& operator*=(unsigned long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
269  const SimTime& operator*=(unsigned long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;} //TODO check overflow from unsigned->signed conversion
270  const SimTime& operator*=(const cPar& p);
271 
272  const SimTime& operator/=(double d) {t=toInt64(t/d); return *this;}
273  const SimTime& operator/=(short d) {t/=d; return *this;}
274  const SimTime& operator/=(int d) {t/=d; return *this;}
275  const SimTime& operator/=(long d) {t/=d; return *this;}
276  const SimTime& operator/=(long long d) {t/=d; return *this;}
277  const SimTime& operator/=(unsigned short d) {t/=d; return *this;}
278  const SimTime& operator/=(unsigned int d) {t/=d; return *this;}
279  const SimTime& operator/=(unsigned long d) {t/=d; return *this;}
280  const SimTime& operator/=(unsigned long long d) {t/=d; return *this;}
281  const SimTime& operator/=(const cPar& p);
282 
283  friend const SimTime operator*(const SimTime& x, double d) { return SimTime(x)*=d; }
284  friend const SimTime operator*(const SimTime& x, short d) { return SimTime(x)*=d; }
285  friend const SimTime operator*(const SimTime& x, int d) { return SimTime(x)*=d; }
286  friend const SimTime operator*(const SimTime& x, long d) { return SimTime(x)*=d; }
287  friend const SimTime operator*(const SimTime& x, long long d) { return SimTime(x)*=d; }
288  friend const SimTime operator*(const SimTime& x, unsigned short d) { return SimTime(x)*=d; }
289  friend const SimTime operator*(const SimTime& x, unsigned int d) { return SimTime(x)*=d; }
290  friend const SimTime operator*(const SimTime& x, unsigned long d) { return SimTime(x)*=d; }
291  friend const SimTime operator*(const SimTime& x, unsigned long long d) { return SimTime(x)*=d; }
292  friend const SimTime operator*(const SimTime& x, const cPar& p) { return SimTime(x)*=p; }
293 
294  friend const SimTime operator*(double d, const SimTime& x) { return SimTime(x)*=d; }
295  friend const SimTime operator*(short d, const SimTime& x) { return SimTime(x)*=d; }
296  friend const SimTime operator*(int d, const SimTime& x) { return SimTime(x)*=d; }
297  friend const SimTime operator*(long d, const SimTime& x) { return SimTime(x)*=d; }
298  friend const SimTime operator*(long long d, const SimTime& x) { return SimTime(x)*=d; }
299  friend const SimTime operator*(unsigned short d, const SimTime& x) { return SimTime(x)*=d; }
300  friend const SimTime operator*(unsigned int d, const SimTime& x) { return SimTime(x)*=d; }
301  friend const SimTime operator*(unsigned long d, const SimTime& x) { return SimTime(x)*=d; }
302  friend const SimTime operator*(unsigned long long d, const SimTime& x) { return SimTime(x)*=d; }
303  friend const SimTime operator*(const cPar& p, const SimTime& x) { return SimTime(x)*=p; }
304 
305  friend const SimTime operator/(const SimTime& x, double d) { return SimTime(x)/=d; }
306  friend const SimTime operator/(const SimTime& x, short d) { return SimTime(x)/=d; }
307  friend const SimTime operator/(const SimTime& x, int d) { return SimTime(x)/=d; }
308  friend const SimTime operator/(const SimTime& x, long d) { return SimTime(x)/=d; }
309  friend const SimTime operator/(const SimTime& x, long long d) { return SimTime(x)/=d; }
310  friend const SimTime operator/(const SimTime& x, unsigned short d) { return SimTime(x)/=d; }
311  friend const SimTime operator/(const SimTime& x, unsigned int d) { return SimTime(x)/=d; }
312  friend const SimTime operator/(const SimTime& x, unsigned long d) { return SimTime(x)/=d; }
313  friend const SimTime operator/(const SimTime& x, unsigned long long d) { return SimTime(x)/=d; }
314  friend const SimTime operator/(const SimTime& x, const cPar& p) { return SimTime(x)/=p; }
315 
316  friend double operator/(const SimTime& x, const SimTime& y) { return (double)x.raw() / (double)y.raw(); }
317 
318  friend double operator/(double x, const SimTime& y) { return x / y.dbl(); }
319  friend double operator/(short x, const SimTime& y) { return (long long)x / y; }
320  friend double operator/(int x, const SimTime& y) { return (long long)x / y; }
321  friend double operator/(long x, const SimTime& y) { return (long long)x / y; }
322  friend SIM_API double operator/(long long x, const SimTime& y);
323  friend double operator/(unsigned short x, const SimTime& y) { return (unsigned long long)x / y; }
324  friend double operator/(unsigned int x, const SimTime& y) { return (unsigned long long)x / y; }
325  friend double operator/(unsigned long x, const SimTime& y) { return (unsigned long long)x / y; }
326  friend SIM_API double operator/(unsigned long long x, const SimTime& y);
327  friend SIM_API double operator/(const cPar& p, const SimTime& x);
329 
332 
338  bool isZero() const {return t==0;}
339 
346  double dbl() const {return t*invfscale;}
347 
359  int64_t inUnit(SimTimeUnit unit) const;
360 
369  SimTime trunc(SimTimeUnit unit) const {return SimTime(inUnit(unit), unit);}
370 
377  SimTime remainderForUnit(SimTimeUnit unit) const {return (*this) - trunc(unit);}
378 
389  void split(SimTimeUnit unit, int64_t& outValue, SimTime& outRemainder) const;
390 
396  std::string str() const {char buf[64]; return str(buf);}
397 
405  char *str(char *buf) const {char *endp; return SimTime::ttoa(buf, t, getScaleExp(), endp);}
406 
413  std::string ustr() const;
414 
421  std::string ustr(SimTimeUnit unit) const;
422 
426  int64_t raw() const {return t;}
427 
431  static SimTime fromRaw(int64_t l) {SimTime tmp; tmp.t = l; return tmp;}
432 
436  const SimTime& setRaw(int64_t l) {t = l; return *this;}
437 
442  static const SimTime getMaxTime() {return SimTime().setRaw(INT64_MAX);}
443 
448  static int64_t getScale() {return dscale;}
449 
454  static int getScaleExp() {return scaleexp;}
455 
468  static void setScaleExp(int e);
469 
475  static const SimTime parse(const char *s);
476 
486  static const SimTime parse(const char *s, const char *&endp);
487 
497  static char *ttoa(char *buf, int64_t t, int scaleexp, char *&endp);
499 };
500 
501 inline std::ostream& operator<<(std::ostream& os, const SimTime& x)
502 {
503  char buf[64]; char *endp;
504  return os << SimTime::ttoa(buf, x.raw(), SimTime::getScaleExp(), endp);
505 }
506 
507 } // namespace omnetpp
508 
509 #endif
510 
511 
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:230
omnetpp::SimTime::getScaleExp
static int getScaleExp()
Definition: simtime.h:454
omnetpp::SimTime::setRaw
const SimTime & setRaw(int64_t l)
Definition: simtime.h:436
omnetpp::SimTime::fromRaw
static SimTime fromRaw(int64_t l)
Definition: simtime.h:431
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:396
omnetpp::SimTime::SimTime
SimTime(short d)
Definition: simtime.h:174
omnetpp::SimTime::isZero
bool isZero() const
Definition: simtime.h:338
omnetpp::SimTime::str
char * str(char *buf) const
Definition: simtime.h:405
omnetpp::cPar
Represents a module or channel parameter.
Definition: cpar.h:70
omnetpp::SimTime::dbl
double dbl() const
Definition: simtime.h:346
omnetpp::SimTime::getMaxTime
static const SimTime getMaxTime()
Definition: simtime.h:442
omnetpp::SimTime::getScale
static int64_t getScale()
Definition: simtime.h:448
omnetpp::SimTime::SimTime
SimTime(const cPar &d)
Definition: simtime.h:189
omnetpp::SimTime::remainderForUnit
SimTime remainderForUnit(SimTimeUnit unit) const
Definition: simtime.h:377
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:168
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:426
omnetpp::SimTime::SimTime
SimTime()
Definition: simtime.h:160
omnetpp::SimTime::SimTime
SimTime(short d, SimTimeUnit unit)
Definition: simtime.h:218
omnetpp::SimTime::trunc
SimTime trunc(SimTimeUnit unit) const
Definition: simtime.h:369