OMNeT++ Simulation Library  5.6.1
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  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 #ifndef USE_OMNETPP4x_FINGERPRINTS
99  i64 = floor(i64 + 0.5);
100 #endif
101  if (fabs(i64) > INT64_MAX_DBL)
102  rangeErrorInt64(i64);
103  return (int64_t)i64;
104  }
105 
106  void setSeconds(int64_t sec) {
107  if (sec > maxseconds)
108  rangeErrorSeconds(sec);
109  t = dscale * sec;
110  }
111 
112  void checkedAdd(const SimTime& x) {
113  // if operands are the same sign but result has different sign ==> overflow
114  bool sameSign = haveSameSign(t, x.t);
115  t += x.t;
116  if (sameSign && !haveSameSign(t, x.t))
117  overflowAdding(x);
118  }
119 
120  void checkedSub(const SimTime& x) {
121  // if operands are different signs and result has same sign as x ==> overflow
122  bool differentSign = !haveSameSign(t, x.t);
123  t -= x.t;
124  if (differentSign && haveSameSign(t, x.t))
125  overflowSubtracting(x);
126  }
127 
128  void checkedMul(int64_t x);
129  void rangeErrorInt64(double i64);
130  void rangeErrorSeconds(int64_t x);
131  void overflowAdding(const SimTime& x);
132  void overflowSubtracting(const SimTime& x);
133  void overflowNegating();
134 
135  public:
136  // internal: Formats a time string. Use SIMTIME_MS etc constants for prec. Note: it performs TRUNCATION towards zero, not rounding!
137  std::string format(int prec=getScaleExp(), const char *decimalSep=".", const char *digitSep="", bool addUnits=false, const char *beforeUnit=nullptr, const char *afterUnit=nullptr) const;
138 
139  public:
145  SimTime() {t=0;}
146 
155  SimTime(double d) {operator=(d);}
156 
163  SimTime(cPar& d) {operator=(d);}
164 
180  SimTime(int64_t value, SimTimeUnit unit);
181 
185  SimTime(const SimTime& x) {t=x.t;}
187 
190  const SimTime& operator=(const SimTime& x) {t=x.t; return *this;}
191  const SimTime& operator=(const cPar& d);
192  const SimTime& operator=(double d) {assertInited(d); t=toInt64(fscale*d); return *this;}
193  const SimTime& operator=(short d) {assertInited(d); setSeconds(d); return *this;} //TODO check overflow
194  const SimTime& operator=(int d) {assertInited(d); setSeconds(d); return *this;}
195  const SimTime& operator=(long d) {assertInited(d); setSeconds(d); return *this;}
196  const SimTime& operator=(long long d) {assertInited(d); setSeconds(d); return *this;}
197  const SimTime& operator=(unsigned short d) {assertInited(d); setSeconds(d); return *this;}
198  const SimTime& operator=(unsigned int d) {assertInited(d); setSeconds(d); return *this;}
199  const SimTime& operator=(unsigned long d) {assertInited(d); setSeconds(d); return *this;}
200  const SimTime& operator=(unsigned long long d) {assertInited(d); setSeconds(d); return *this;}
201 
202  bool operator==(const SimTime& x) const {return t==x.t;}
203  bool operator!=(const SimTime& x) const {return t!=x.t;}
204  bool operator< (const SimTime& x) const {return t<x.t;}
205  bool operator> (const SimTime& x) const {return t>x.t;}
206  bool operator<=(const SimTime& x) const {return t<=x.t;}
207  bool operator>=(const SimTime& x) const {return t>=x.t;}
208 
209  SimTime operator-() const {SimTime x; x.t = -t; if (x.t==INT64_MIN) x.overflowNegating(); return x;}
210 
211  const SimTime& operator+=(const SimTime& x) {checkedAdd(x); return *this;}
212  const SimTime& operator-=(const SimTime& x) {checkedSub(x); return *this;}
213  friend const SimTime operator+(const SimTime& x, const SimTime& y) { return SimTime(x)+=y; }
214  friend const SimTime operator-(const SimTime& x, const SimTime& y) { return SimTime(x)-=y; }
215 
216  const SimTime& operator*=(double d) {t=toInt64(t*d); return *this;}
217  const SimTime& operator*=(short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
218  const SimTime& operator*=(int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
219  const SimTime& operator*=(long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
220  const SimTime& operator*=(long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
221  const SimTime& operator*=(unsigned short d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
222  const SimTime& operator*=(unsigned int d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
223  const SimTime& operator*=(unsigned long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
224  const SimTime& operator*=(unsigned long long d) {if (checkmul) checkedMul(d); else t*=d; return *this;}
225  const SimTime& operator*=(const cPar& p);
226 
227  const SimTime& operator/=(double d) {t=toInt64(t/d); return *this;}
228  const SimTime& operator/=(short d) {t/=d; return *this;}
229  const SimTime& operator/=(int d) {t/=d; return *this;}
230  const SimTime& operator/=(long d) {t/=d; return *this;}
231  const SimTime& operator/=(long long d) {t/=d; return *this;}
232  const SimTime& operator/=(unsigned short d) {t/=d; return *this;}
233  const SimTime& operator/=(unsigned int d) {t/=d; return *this;}
234  const SimTime& operator/=(unsigned long d) {t/=d; return *this;}
235  const SimTime& operator/=(unsigned long long d) {t/=d; return *this;}
236  const SimTime& operator/=(const cPar& p);
237 
238  friend const SimTime operator*(const SimTime& x, double d) { return SimTime(x)*=d; }
239  friend const SimTime operator*(const SimTime& x, short d) { return SimTime(x)*=d; }
240  friend const SimTime operator*(const SimTime& x, int d) { return SimTime(x)*=d; }
241  friend const SimTime operator*(const SimTime& x, long d) { return SimTime(x)*=d; }
242  friend const SimTime operator*(const SimTime& x, long long d) { return SimTime(x)*=d; }
243  friend const SimTime operator*(const SimTime& x, unsigned short d) { return SimTime(x)*=d; }
244  friend const SimTime operator*(const SimTime& x, unsigned int d) { return SimTime(x)*=d; }
245  friend const SimTime operator*(const SimTime& x, unsigned long d) { return SimTime(x)*=d; }
246  friend const SimTime operator*(const SimTime& x, unsigned long long d) { return SimTime(x)*=d; }
247  friend const SimTime operator*(const SimTime& x, const cPar& p) { return SimTime(x)*=p; }
248 
249  friend const SimTime operator*(double d, const SimTime& x) { return SimTime(x)*=d; }
250  friend const SimTime operator*(short d, const SimTime& x) { return SimTime(x)*=d; }
251  friend const SimTime operator*(int d, const SimTime& x) { return SimTime(x)*=d; }
252  friend const SimTime operator*(long d, const SimTime& x) { return SimTime(x)*=d; }
253  friend const SimTime operator*(long long d, const SimTime& x) { return SimTime(x)*=d; }
254  friend const SimTime operator*(unsigned short d, const SimTime& x) { return SimTime(x)*=d; }
255  friend const SimTime operator*(unsigned int d, const SimTime& x) { return SimTime(x)*=d; }
256  friend const SimTime operator*(unsigned long d, const SimTime& x) { return SimTime(x)*=d; }
257  friend const SimTime operator*(unsigned long long d, const SimTime& x) { return SimTime(x)*=d; }
258  friend const SimTime operator*(const cPar& p, const SimTime& x) { return SimTime(x)*=p; }
259 
260  friend const SimTime operator/(const SimTime& x, double d) { return SimTime(x)/=d; }
261  friend const SimTime operator/(const SimTime& x, short d) { return SimTime(x)/=d; }
262  friend const SimTime operator/(const SimTime& x, int d) { return SimTime(x)/=d; }
263  friend const SimTime operator/(const SimTime& x, long d) { return SimTime(x)/=d; }
264  friend const SimTime operator/(const SimTime& x, long long d) { return SimTime(x)/=d; }
265  friend const SimTime operator/(const SimTime& x, unsigned short d) { return SimTime(x)/=d; }
266  friend const SimTime operator/(const SimTime& x, unsigned int d) { return SimTime(x)/=d; }
267  friend const SimTime operator/(const SimTime& x, unsigned long d) { return SimTime(x)/=d; }
268  friend const SimTime operator/(const SimTime& x, unsigned long long d) { return SimTime(x)/=d; }
269  friend const SimTime operator/(const SimTime& x, const cPar& p) { return SimTime(x)/=p; }
270 
271  friend double operator/(const SimTime& x, const SimTime& y) { return (double)x.raw() / (double)y.raw(); }
272 
273  friend double operator/(double x, const SimTime& y) { return x / y.dbl(); }
274  friend double operator/(short x, const SimTime& y) { return (long long)x / y; }
275  friend double operator/(int x, const SimTime& y) { return (long long)x / y; }
276  friend double operator/(long x, const SimTime& y) { return (long long)x / y; }
277  friend double operator/(long long x, const SimTime& y);
278  friend double operator/(unsigned short x, const SimTime& y) { return (unsigned long long)x / y; }
279  friend double operator/(unsigned int x, const SimTime& y) { return (unsigned long long)x / y; }
280  friend double operator/(unsigned long x, const SimTime& y) { return (unsigned long long)x / y; }
281  friend double operator/(unsigned long long x, const SimTime& y);
282  friend double operator/(const cPar& p, const SimTime& x);
284 
287 
293  bool isZero() const {return t==0;}
294 
301  double dbl() const {return t*invfscale;}
302 
314  int64_t inUnit(SimTimeUnit unit) const;
315 
324  SimTime trunc(SimTimeUnit unit) const {return SimTime(inUnit(unit), unit);}
325 
332  SimTime remainderForUnit(SimTimeUnit unit) const {return (*this) - trunc(unit);}
333 
344  void split(SimTimeUnit unit, int64_t& outValue, SimTime& outRemainder) const;
345 
351  std::string str() const {char buf[64]; return str(buf);}
352 
360  char *str(char *buf) const {char *endp; return SimTime::ttoa(buf, t, getScaleExp(), endp);}
361 
368  std::string ustr() const;
369 
376  std::string ustr(SimTimeUnit unit) const;
377 
381  int64_t raw() const {return t;}
382 
386  static SimTime fromRaw(int64_t l) {SimTime tmp; tmp.t = l; return tmp;}
387 
391  const SimTime& setRaw(int64_t l) {t = l; return *this;}
392 
397  static const SimTime getMaxTime() {return SimTime().setRaw(INT64_MAX);}
398 
403  static int64_t getScale() {return dscale;}
404 
409  static int getScaleExp() {return scaleexp;}
410 
423  static void setScaleExp(int e);
424 
430  static const SimTime parse(const char *s);
431 
441  static const SimTime parse(const char *s, const char *&endp);
442 
452  static char *ttoa(char *buf, int64_t t, int scaleexp, char *&endp);
454 };
455 
456 inline std::ostream& operator<<(std::ostream& os, const SimTime& x)
457 {
458  char buf[64]; char *endp;
459  return os << SimTime::ttoa(buf, x.raw(), SimTime::getScaleExp(), endp);
460 }
461 
462 } // namespace omnetpp
463 
464 #endif
465 
466 
char * str(char *buf) const
Definition: simtime.h:360
SimTime(cPar &d)
Definition: simtime.h:163
int64_t raw() const
Definition: simtime.h:381
int64_t-based, base-10 fixed-point simulation time.
Definition: simtime.h:66
Represents a module or channel parameter.
Definition: cpar.h:68
static SimTime fromRaw(int64_t l)
Definition: simtime.h:386
SimTime()
Definition: simtime.h:145
static const SimTime ZERO
Definition: simtime.h:86
double dbl() const
Definition: simtime.h:301
SimTime(const SimTime &x)
Definition: simtime.h:185
std::string str() const
Definition: simtime.h:351
static const SimTime getMaxTime()
Definition: simtime.h:397
static int getScaleExp()
Definition: simtime.h:409
const SimTime & setRaw(int64_t l)
Definition: simtime.h:391
static char * ttoa(char *buf, int64_t t, int scaleexp, char *&endp)
SimTime remainderForUnit(SimTimeUnit unit) const
Definition: simtime.h:332
SimTime trunc(SimTimeUnit unit) const
Definition: simtime.h:324
SimTimeUnit
Enum for simulation time base-10 exponents.
Definition: simtime.h:36
Definition: cabstracthistogram.h:21
static int64_t getScale()
Definition: simtime.h:403
bool isZero() const
Definition: simtime.h:293
SimTime(double d)
Definition: simtime.h:155