Project

General

Profile

Statistics
| Branch: | Revision:

root / src / sim / simtime.cc @ fbe00e73

History | View | Annotate | Download (5.63 KB)

1
//==========================================================================
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
//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
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
}
202