## root / src / sim / simtime.cc @ 3e29b8a0

History | View | Annotate | Download (5.63 KB)

1 | 01873262 | Georg Kunz | ```
//==========================================================================
``` |
---|---|---|---|

2 | ```
// SIMTIME.CC - part of
``` |
||

3 | ```
// OMNeT++/OMNEST
``` |
||

4 | ```
// Discrete System Simulation in C++
``` |
||

5 | ```
//
``` |
||

6 | ```
//==========================================================================
``` |
||

7 | |||

8 | ```
/*--------------------------------------------------------------*
``` |
||

9 | ```
Copyright (C) 1992-2008 Andras Varga
``` |
||

10 | ```
Copyright (C) 2006-2008 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 | #include <sstream> |
||

17 | #include "opp_ctype.h" |
||

18 | #include "simtime.h" |
||

19 | #include "cexception.h" |
||

20 | #include "unitconversion.h" |
||

21 | #include "cpar.h" |
||

22 | |||

23 | USING_NAMESPACE |
||

24 | |||

25 | |||

26 | ```
int SimTime::scaleexp = SimTime::SCALEEXP_UNINITIALIZED;
``` |
||

27 | int64 SimTime::dscale; |
||

28 | ```
double SimTime::fscale;
``` |
||

29 | ```
double SimTime::invfscale;
``` |
||

30 | ```
const SimTime SimTime::simTimeZero = SimTime();
``` |
||

31 | |||

32 | 0e7ff5c8 | Simon Tenbusch | ```
//Used as return value for getProcessingDelay
``` |

33 | const double SimTime::simTimeSequentialExecution = -2; |
||

34 | ```
//Used in cMessage::getEventDuration
``` |
||

35 | const double SimTime::simTimeUninitialized = -1; |
||

36 | |||

37 | 01873262 | Georg Kunz | void SimTime::setScaleExp(int e) |

38 | { |
||

39 | ```
if (e == scaleexp)
``` |
||

40 | ```
return;
``` |
||

41 | ```
if (scaleexp != SCALEEXP_UNINITIALIZED)
``` |
||

42 | throw cRuntimeError("SimTime::setScaleExp(): Attempt to change the scale exponent after initialization"); |
||

43 | |||

44 | if (e < -18 || e > 0) |
||

45 | throw cRuntimeError("simtime_t scale exponent %d is out of accepted range -18..0; " |
||

46 | ```
"recommended value is -12 (picosecond resolution with range +-106 days)", e);
``` |
||

47 | |||

48 | ```
// calculate 10^-e
``` |
||

49 | scaleexp = e; |
||

50 | ```
int64 scale = 1;
``` |
||

51 | while(e++ < 0) |
||

52 | ```
scale *= 10;
``` |
||

53 | |||

54 | ```
// store it in double too
``` |
||

55 | dscale = scale; |
||

56 | ```
fscale = (double) scale;
``` |
||

57 | invfscale = 1.0 / fscale; |
||

58 | } |
||

59 | |||

60 | static std::string range() |
||

61 | { |
||

62 | return std::string("(-") + SimTime::getMaxTime().str() + "," + SimTime::getMaxTime().str() + ")"; |
||

63 | } |
||

64 | |||

65 | void SimTime::initError(double d) |
||

66 | { |
||

67 | throw cRuntimeError("Global simtime_t variable found, with value %g. Global simtime_t variables are " |
||

68 | ```
"forbidden, because scale exponent is not yet known at the time they get initialized. "
``` |
||

69 | ```
"Please use double or const_simtime_t instead", d);
``` |
||

70 | } |
||

71 | |||

72 | void SimTime::rangeError(double i64) |
||

73 | { |
||

74 | throw cRuntimeError("Cannot convert %g to simtime_t: out of range %s, allowed by scale exponent %d", |
||

75 | i64*invfscale, range().c_str(), scaleexp); |
||

76 | } |
||

77 | |||

78 | void SimTime::overflowAdding(const SimTime& x) |
||

79 | { |
||

80 | ```
t -= x.t; // restore original value
``` |
||

81 | throw cRuntimeError("simtime_t overflow adding %s to %s: result is out of range %s, allowed by scale exponent %d", |
||

82 | x.str().c_str(), str().c_str(), range().c_str(), scaleexp); |
||

83 | } |
||

84 | |||

85 | void SimTime::overflowSubstracting(const SimTime& x) |
||

86 | { |
||

87 | ```
t += x.t; // restore original value
``` |
||

88 | throw cRuntimeError("simtime_t overflow substracting %s from %s: result is out of range %s, allowed by scale exponent %d", |
||

89 | x.str().c_str(), str().c_str(), range().c_str(), scaleexp); |
||

90 | } |
||

91 | |||

92 | ```
//XXX inline, at the end of simtime.h, just after #include "cpar.h" ?
``` |
||

93 | const SimTime& SimTime::operator=(const cPar& p) |
||

94 | { |
||

95 | return operator=((double)p); |
||

96 | } |
||

97 | |||

98 | const SimTime& SimTime::operator*=(const cPar& p) |
||

99 | { |
||

100 | return operator*=((double)p); |
||

101 | } |
||

102 | |||

103 | const SimTime& SimTime::operator/=(const cPar& p) |
||

104 | { |
||

105 | return operator/=((double)p); |
||

106 | } |
||

107 | |||

108 | const SimTime operator*(const SimTime& x, const cPar& p) |
||

109 | { |
||

110 | return operator*(x, (double)p); |
||

111 | } |
||

112 | |||

113 | const SimTime operator*(const cPar& p, const SimTime& x) |
||

114 | { |
||

115 | return operator*((double)p, x); |
||

116 | } |
||

117 | |||

118 | const SimTime operator/(const SimTime& x, const cPar& p) |
||

119 | { |
||

120 | return operator/(x, (double)p); |
||

121 | } |
||

122 | |||

123 | std::string SimTime::str() const |
||

124 | { |
||

125 | ```
// delegate to operator<<
``` |
||

126 | std::stringstream out; |
||

127 | ```
out << *this;
``` |
||

128 | ```
return out.str();
``` |
||

129 | } |
||

130 | |||

131 | char *SimTime::ttoa(char *buf, int64 t, int scaleexp, char *&endp) |
||

132 | { |
||

133 | ASSERT(scaleexp<=0 && scaleexp>=-18); |
||

134 | |||

135 | ```
// prepare for conversion
``` |
||

136 | endp = buf+63; //19+19+5 should be enough, but play it safe |
||

137 | ```
*endp = '\0';
``` |
||

138 | ```
char *s = endp;
``` |
||

139 | if (t==0) |
||

140 | {*--s = '0'; return s;} |
||

141 | |||

142 | ```
// convert digits
``` |
||

143 | bool negative = t<0; |
||

144 | ```
if (negative) t = -t;
``` |
||

145 | |||

146 | bool skipzeros = true; |
||

147 | ```
int decimalplace = scaleexp;
``` |
||

148 | ```
do {
``` |
||

149 | ```
int64 res = t / 10;
``` |
||

150 | int digit = t - (10*res); |
||

151 | |||

152 | if (skipzeros && (digit!=0 || decimalplace>=0)) |
||

153 | ```
skipzeros = false;
``` |
||

154 | if (decimalplace++==0 && s!=endp) |
||

155 | ```
*--s = '.';
``` |
||

156 | ```
if (!skipzeros)
``` |
||

157 | ```
*--s = '0'+digit;
``` |
||

158 | t = res; |
||

159 | ```
} while (t);
``` |
||

160 | |||

161 | ```
// add leading zeros, decimal point, etc if needed
``` |
||

162 | if (decimalplace<=0) |
||

163 | { |
||

164 | while (decimalplace++ < 0) |
||

165 | ```
*--s = '0';
``` |
||

166 | ```
*--s = '.';
``` |
||

167 | ```
*--s = '0';
``` |
||

168 | } |
||

169 | |||

170 | if (negative) *--s = '-'; |
||

171 | ```
return s;
``` |
||

172 | } |
||

173 | |||

174 | const SimTime SimTime::parse(const char *s) |
||

175 | { |
||

176 | ```
try {
``` |
||

177 | ```
// Note: UnitConversion calculates in double, so we may lose precision during conversion
``` |
||

178 | ```
std::string unit;
``` |
||

179 | double d = UnitConversion::parseQuantity(s, unit); // "unit" is OUT parameter |
||

180 | return unit.empty() ? d : UnitConversion::convertUnit(d, unit.c_str(), "s"); |
||

181 | } |
||

182 | ```
catch (std::exception& e) {
``` |
||

183 | throw cRuntimeError("Error converting string \"%s\" to SimTime: %s", s, e.what()); |
||

184 | } |
||

185 | } |
||

186 | |||

187 | const SimTime SimTime::parse(const char *s, const char *&endp) |
||

188 | { |
||

189 | ```
// find end of the simtime literal in the string
``` |
||

190 | endp = s; |
||

191 | ```
while (opp_isspace(*endp))
``` |
||

192 | endp++; |
||

193 | ```
if (!*endp)
``` |
||

194 | {endp = s; return 0;} // it was just space |
||

195 | |||

196 | while (opp_isalnum(*endp) || opp_isspace(*endp) || *endp=='+' || *endp=='-' || *endp=='.') |
||

197 | endp++; |
||

198 | |||

199 | ```
// delegate to the other parse() method
``` |
||

200 | return parse(std::string(s, endp-s).c_str()); |
||

201 | } |