simtime.h Source File¶

API: simtime.h Source File
API
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
25namespace omnetpp {
26
27class 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
66class 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:
157
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
501inline 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
int64_t-based, base-10 fixed-point simulation time.
Definition simtime.h:67
static const SimTime parse(const char *s, const char *&endp)
bool isZero() const
Definition simtime.h:338
int64_t raw() const
Definition simtime.h:426
SimTime(const cPar &d)
Definition simtime.h:189
static int64_t getScale()
Definition simtime.h:448
char * str(char *buf) const
Definition simtime.h:405
std::string ustr(SimTimeUnit unit) const
SimTime(double d)
Definition simtime.h:168
static void setScaleExp(int e)
static const SimTime parse(const char *s)
SimTime remainderForUnit(SimTimeUnit unit) const
Definition simtime.h:377
SimTime(short d)
Definition simtime.h:174
static SimTime fromRaw(int64_t l)
Definition simtime.h:431
const SimTime & setRaw(int64_t l)
Definition simtime.h:436
static const SimTime getMaxTime()
Definition simtime.h:442
int64_t inUnit(SimTimeUnit unit) const
static char * ttoa(char *buf, int64_t t, int scaleexp, char *&endp)
SimTime(double value, SimTimeUnit unit, bool allowRounding=false)
SimTime()
Definition simtime.h:160
SimTime(short d, SimTimeUnit unit)
Definition simtime.h:218
SimTime(const SimTime &x)
Definition simtime.h:230
static int getScaleExp()
Definition simtime.h:454
SimTime trunc(SimTimeUnit unit) const
Definition simtime.h:369
void split(SimTimeUnit unit, int64_t &outValue, SimTime &outRemainder) const
static const SimTime ZERO
Definition simtime.h:86
std::string ustr() const
double dbl() const
Definition simtime.h:346
std::string str() const
Definition simtime.h:396
Represents a module or channel parameter.
Definition cpar.h:71
const SimTime floor(const SimTime &x)
simtime_t version of floor(double) from math.h.
Definition simtimemath.h:38
const SimTime fabs(const SimTime &x)
Returns the absolute value of the simulation time x.
Definition simtimemath.h:85
SimTimeUnit
Enum for simulation time base-10 exponents.
Definition simtime.h:37