root / src / sim / simtime.cc @ a3be1d55
History  View  Annotate  Download (5.45 KB)
1 
//==========================================================================


2 
// SIMTIME.CC  part of

3 
// OMNeT++/OMNEST

4 
// Discrete System Simulation in C++

5 
//

6 
//==========================================================================

7  
8 
/**

9 
Copyright (C) 19922008 Andras Varga

10 
Copyright (C) 20062008 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 
void SimTime::setScaleExp(int e) 
33 
{ 
34 
if (e == scaleexp)

35 
return;

36 
if (scaleexp != SCALEEXP_UNINITIALIZED)

37 
throw cRuntimeError("SimTime::setScaleExp(): Attempt to change the scale exponent after initialization"); 
38  
39 
if (e < 18  e > 0) 
40 
throw cRuntimeError("simtime_t scale exponent %d is out of accepted range 18..0; " 
41 
"recommended value is 12 (picosecond resolution with range +106 days)", e);

42  
43 
// calculate 10^e

44 
scaleexp = e; 
45 
int64 scale = 1;

46 
while(e++ < 0) 
47 
scale *= 10;

48  
49 
// store it in double too

50 
dscale = scale; 
51 
fscale = (double) scale;

52 
invfscale = 1.0 / fscale; 
53 
} 
54  
55 
static std::string range() 
56 
{ 
57 
return std::string("(") + SimTime::getMaxTime().str() + "," + SimTime::getMaxTime().str() + ")"; 
58 
} 
59  
60 
void SimTime::initError(double d) 
61 
{ 
62 
throw cRuntimeError("Global simtime_t variable found, with value %g. Global simtime_t variables are " 
63 
"forbidden, because scale exponent is not yet known at the time they get initialized. "

64 
"Please use double or const_simtime_t instead", d);

65 
} 
66  
67 
void SimTime::rangeError(double i64) 
68 
{ 
69 
throw cRuntimeError("Cannot convert %g to simtime_t: out of range %s, allowed by scale exponent %d", 
70 
i64*invfscale, range().c_str(), scaleexp); 
71 
} 
72  
73 
void SimTime::overflowAdding(const SimTime& x) 
74 
{ 
75 
t = x.t; // restore original value

76 
throw cRuntimeError("simtime_t overflow adding %s to %s: result is out of range %s, allowed by scale exponent %d", 
77 
x.str().c_str(), str().c_str(), range().c_str(), scaleexp); 
78 
} 
79  
80 
void SimTime::overflowSubstracting(const SimTime& x) 
81 
{ 
82 
t += x.t; // restore original value

83 
throw cRuntimeError("simtime_t overflow substracting %s from %s: result is out of range %s, allowed by scale exponent %d", 
84 
x.str().c_str(), str().c_str(), range().c_str(), scaleexp); 
85 
} 
86  
87 
//XXX inline, at the end of simtime.h, just after #include "cpar.h" ?

88 
const SimTime& SimTime::operator=(const cPar& p) 
89 
{ 
90 
return operator=((double)p); 
91 
} 
92  
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 operator*(const SimTime& x, const cPar& p) 
104 
{ 
105 
return operator*(x, (double)p); 
106 
} 
107  
108 
const SimTime operator*(const cPar& p, const SimTime& x) 
109 
{ 
110 
return operator*((double)p, x); 
111 
} 
112  
113 
const SimTime operator/(const SimTime& x, const cPar& p) 
114 
{ 
115 
return operator/(x, (double)p); 
116 
} 
117  
118 
std::string SimTime::str() const 
119 
{ 
120 
// delegate to operator<<

121 
std::stringstream out; 
122 
out << *this;

123 
return out.str();

124 
} 
125  
126 
char *SimTime::ttoa(char *buf, int64 t, int scaleexp, char *&endp) 
127 
{ 
128 
ASSERT(scaleexp<=0 && scaleexp>=18); 
129  
130 
// prepare for conversion

131 
endp = buf+63; //19+19+5 should be enough, but play it safe 
132 
*endp = '\0';

133 
char *s = endp;

134 
if (t==0) 
135 
{*s = '0'; return s;} 
136  
137 
// convert digits

138 
bool negative = t<0; 
139 
if (negative) t = t;

140  
141 
bool skipzeros = true; 
142 
int decimalplace = scaleexp;

143 
do {

144 
int64 res = t / 10;

145 
int digit = t  (10*res); 
146  
147 
if (skipzeros && (digit!=0  decimalplace>=0)) 
148 
skipzeros = false;

149 
if (decimalplace++==0 && s!=endp) 
150 
*s = '.';

151 
if (!skipzeros)

152 
*s = '0'+digit;

153 
t = res; 
154 
} while (t);

155  
156 
// add leading zeros, decimal point, etc if needed

157 
if (decimalplace<=0) 
158 
{ 
159 
while (decimalplace++ < 0) 
160 
*s = '0';

161 
*s = '.';

162 
*s = '0';

163 
} 
164  
165 
if (negative) *s = ''; 
166 
return s;

167 
} 
168  
169 
const SimTime SimTime::parse(const char *s) 
170 
{ 
171 
try {

172 
// Note: UnitConversion calculates in double, so we may lose precision during conversion

173 
std::string unit;

174 
double d = UnitConversion::parseQuantity(s, unit); // "unit" is OUT parameter 
175 
return unit.empty() ? d : UnitConversion::convertUnit(d, unit.c_str(), "s"); 
176 
} 
177 
catch (std::exception& e) {

178 
throw cRuntimeError("Error converting string \"%s\" to SimTime: %s", s, e.what()); 
179 
} 
180 
} 
181  
182 
const SimTime SimTime::parse(const char *s, const char *&endp) 
183 
{ 
184 
// find end of the simtime literal in the string

185 
endp = s; 
186 
while (opp_isspace(*endp))

187 
endp++; 
188 
if (!*endp)

189 
{endp = s; return 0;} // it was just space 
190  
191 
while (opp_isalnum(*endp)  opp_isspace(*endp)  *endp=='+'  *endp==''  *endp=='.') 
192 
endp++; 
193  
194 
// delegate to the other parse() method

195 
return parse(std::string(s, endps).c_str()); 
196 
} 
197 