Project

General

Profile

Statistics
| Branch: | Revision:

root / src / sim / simtime.cc @ a3be1d55

History | View | Annotate | Download (5.45 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
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, endp-s).c_str());
196
}