root / src / common / bigdecimal.h @ e1750c09
History  View  Annotate  Download (8.94 KB)
1 
//==========================================================================


2 
// BIGDECIMAL.H  part of

3 
// OMNeT++/OMNEST

4 
// Discrete System Simulation in C++

5 
//

6 
// Author: Tamas Borbely

7 
//

8 
//==========================================================================

9  
10 
/**

11 
Copyright (C) 20062008 OpenSim Ltd.

12 

13 
This file is distributed WITHOUT ANY WARRANTY. See the file

14 
`license' for details on this and other legal matters.

15 
**/

16  
17 
#ifndef __BIGDECIMAL_H

18 
#define __BIGDECIMAL_H

19  
20 
#include <string> 
21 
#include <iostream> 
22 
#include <math.h> 
23 
#include <limits.h> 
24 
#include "commondefs.h" 
25 
#include "exception.h" 
26 
#include "intxtypes.h" 
27  
28 
NAMESPACE_BEGIN 
29  
30 
// maximum number of digits in an int64 number, i.e. number of digits in INT64_MAX.

31 
#define INT64_MAX_DIGITS 19 
32  
33 
/**

34 
* BigDecimal stores a decimal value as a 64bit integer and a scale.

35 
* Arithmetic operations are performed by converting the values

36 
* to double and converting the result to BigDecimal, so they

37 
* may lose precision.

38 
*/

39 
class COMMON_API BigDecimal 
40 
{ 
41 
private:

42 
/*

43 
* The value of the number is intVal * 10^scale.

44 
* If two decimal is equal then they have the same intVal and scale (see normalize()).

45 
* Special values (NaN, +infinity, Nil) use the scale INT_MAX.

46 
*/

47 
int64 intVal; // stores digits of the decimal number (up to 18 digits can be stored)

48 
int scale; // stores the position of the decimal point, must be in the [0,18] range 
49  
50 
static const int minScale = 18; // XXX the range length must be <= 18, see buffer allocation in ttoa() 
51 
static const int maxScale = 0; 
52  
53 
void checkScale(int scale) const 
54 
{ 
55 
if (scale < minScale  scale > maxScale)

56 
throw opp_runtime_error("Scale must be between %d and %d.", minScale, maxScale);

57 
} 
58  
59 
/*

60 
* Sets scale between minScale and maxScale and strips trailing zeros when scale<maxScale.

61 
* 0.0 always has scale=0.

62 
* If x and y equal decimals, then x.intVal==y.intVal and x.scale==y.scale after normalization.

63 
*/

64 
void normalize();

65  
66 
/*

67 
* Returns digits of the decimal number from placevalues in [scale,scale+numDigits) as an int64.

68 
*/

69 
int64 getDigits(int scale, int numDigits) const; 
70  
71 
public:

72 
/** @name Constants */

73 
//@{

74 
static BigDecimal Zero;

75 
static BigDecimal One;

76 
static BigDecimal MinusOne;

77 
static BigDecimal NaN;

78 
static BigDecimal PositiveInfinity;

79 
static BigDecimal NegativeInfinity;

80 
static BigDecimal Nil;

81 
//@}

82  
83 
/** @name Constructors. */

84 
//@{

85 
BigDecimal() {intVal=INT64_MAX; scale=INT_MAX;} // == Nil

86 
explicit BigDecimal(int64 intVal, int scale=0) : intVal(intVal), scale(scale) { normalize(); } 
87 
BigDecimal(const BigDecimal &x) {operator=(x);}

88 
BigDecimal(double d) {operator=(d);}

89 
//@}

90  
91 
/** @name Testing for special values */

92 
//@{

93 
bool isNaN() const { return scale == INT_MAX && intVal == 0; } 
94 
bool isNil() const { return *this == Nil; } 
95 
bool isPositiveInfinity() const {return *this==PositiveInfinity;} 
96 
bool isNegativeInfinity() const {return *this==NegativeInfinity;} 
97 
bool isInfinity() const {return isPositiveInfinity()  isNegativeInfinity();} 
98 
bool isSpecial() const { return scale == INT_MAX; } 
99 
//@}

100  
101 
/** @name Assignments */

102 
//@{

103 
const BigDecimal& operator=(double d); 
104 
const BigDecimal& operator=(const BigDecimal& x) {intVal=x.intVal; scale=x.scale; return *this;} 
105 
//@}

106  
107 
/** @name Arithmetic operations */

108 
//@{

109 
const BigDecimal& operator+=(const BigDecimal& x) {*this=*this+x; return *this;} 
110 
const BigDecimal& operator=(const BigDecimal& x) {*this=*thisx; return *this;} 
111 
const BigDecimal& operator*=(double d) {*this=BigDecimal(dbl()*d); return *this;} 
112 
const BigDecimal& operator/=(double d) {*this=BigDecimal(dbl()/d); return *this;} 
113  
114 
#define CHK(a,b) { if ((a).isNaN()  (b).isNaN()) return false; } 
115  
116 
bool operator==(const BigDecimal& x) const {CHK(*this,x); return intVal == x.intVal && scale == x.scale;} 
117 
bool operator!=(const BigDecimal& x) const {CHK(*this, x); return intVal != x.intVal  scale != x.scale;} 
118 
bool operator< (const BigDecimal& x) const; 
119 
bool operator> (const BigDecimal& x) const {CHK(*this, x); return x < *this;} 
120 
bool operator<=(const BigDecimal& x) const {CHK(*this, x); return *this == x  *this < x;} 
121 
bool operator>=(const BigDecimal& x) const {CHK(*this, x); return *this == x  *this > x;} 
122  
123 
COMMON_API friend const BigDecimal operator+(const BigDecimal& x, const BigDecimal& y); 
124 
COMMON_API friend const BigDecimal operator(const BigDecimal& x, const BigDecimal& y); 
125  
126 
friend const BigDecimal operator*(const BigDecimal& x, double d); 
127 
friend const BigDecimal operator*(double d, const BigDecimal& x); 
128 
friend const BigDecimal operator/(const BigDecimal& x, double d); 
129 
friend const BigDecimal operator/(const BigDecimal& x, const BigDecimal& y); 
130 
//@}

131  
132 
/** @name Conversions */

133 
//@{

134 
/**

135 
* Converts big decimal to double. Note that conversion to and from

136 
* double may lose precision.

137 
*/

138 
double dbl() const; 
139  
140 
/**

141 
* Converts to string.

142 
*/

143 
std::string str() const;

144  
145 
/**

146 
* Converts to a string. Use this variant over str() where performance is

147 
* critical. The result is placed somewhere in the given buffer (pointer

148 
* is returned), but for performance reasons, not necessarily at the buffer's

149 
* beginning. Please read the documentation of ttoa() for the minimum

150 
* required buffer size.

151 
*/

152 
char *str(char *buf) const {char *endp; return BigDecimal::ttoa(buf, *this, endp);} 
153  
154 
/**

155 
* Returns the underlying 64bit integer.

156 
*/

157 
int64 getIntValue() const {return intVal;} 
158  
159 
/**

160 
* Directly sets the underlying 64bit integer.

161 
*/

162 
const BigDecimal& setIntValue(int64 l) {intVal = l; return *this;} 
163  
164 
/**

165 
* Returns the scale exponent.

166 
*/

167 
int getScale() const {return scale;} 
168  
169 
/**

170 
* Sets the scale exponent.

171 
*/

172 
void setScale(int s) { checkScale(s); scale = s; normalize(); }; 
173  
174 
/**

175 
* Returns the mantissa as if scale was the given value;

176 
*/

177 
int64 getMantissaForScale(int scale) const; 
178  
179 
/**

180 
* Converts the given string to big decimal. Throws an error if

181 
* there is an error during conversion.

182 
*/

183 
static const BigDecimal parse(const char *s); 
184  
185 
/**

186 
* Converts a prefix of the given string to big decimal, up to the

187 
* first character that cannot occur in big decimal strings:

188 
* not (digit or letter or "." or "+" or "" or whitespace).

189 
*/

190 
static const BigDecimal parse(const char *s, const char *&endp); 
191  
192 
/**

193 
* Utility function to convert a big decimal into a string

194 
* buffer. scaleexp must be in the 18..0 range, and the buffer must be

195 
* at least 64 bytes long. A pointer to the result string will be

196 
* returned. A pointer to the terminating '\0' will be returned in endp.

197 
*

198 
* ATTENTION: For performance reasons, the returned pointer will point

199 
* *somewhere* into the buffer, but NOT necessarily at the beginning.

200 
*/

201 
static char *ttoa(char *buf, const BigDecimal &x, char *&endp); 
202 
//@}

203 
}; 
204  
205 
inline bool haveSameSign(int64 a, int64 b) { return (a^b) >= 0; } 
206  
207 
inline const BigDecimal operator*(const BigDecimal& x, double d) 
208 
{ 
209 
return BigDecimal(x.dbl()*d);

210 
} 
211  
212 
inline const BigDecimal operator*(double d, const BigDecimal& x) 
213 
{ 
214 
return BigDecimal(d*x.dbl());

215 
} 
216  
217 
inline const BigDecimal operator/(const BigDecimal& x, double d) 
218 
{ 
219 
return BigDecimal(x.dbl()/d);

220 
} 
221  
222 
inline const BigDecimal operator/(const BigDecimal& x, const BigDecimal& y) 
223 
{ 
224 
return BigDecimal(x.dbl()/y.dbl());

225 
} 
226  
227 
inline std::ostream& operator<<(std::ostream& os, const BigDecimal& x) 
228 
{ 
229 
char buf[64]; char *endp; 
230 
return os << BigDecimal::ttoa(buf, x, endp);

231 
} 
232  
233 
NAMESPACE_END 
234  
235 
/**

236 
* BigDecimal version of floor(double) from math.h.

237 
*/

238 
inline const OPP::BigDecimal floor(const OPP::BigDecimal& x) 
239 
{ 
240 
return OPP::BigDecimal(floor(x.dbl()));

241 
} 
242  
243 
/**

244 
* BigDecimal version of ceil(double) from math.h.

245 
*/

246 
inline const OPP::BigDecimal ceil(const OPP::BigDecimal& x) 
247 
{ 
248 
return OPP::BigDecimal(ceil(x.dbl()));

249 
} 
250  
251 
/**

252 
* BigDecimal version of fabs(double) from math.h.

253 
*/

254 
inline const OPP::BigDecimal fabs(const OPP::BigDecimal& x) 
255 
{ 
256 
return x.getIntValue()<0 ? OPP::BigDecimal(x).setIntValue(x.getIntValue()) : x; 
257 
} 
258  
259 
/**

260 
* BigDecimal version of fmod(double,double) from math.h.

261 
*/

262 
inline const OPP::BigDecimal fmod(const OPP::BigDecimal& x, const OPP::BigDecimal& y) 
263 
{ 
264 
return OPP::BigDecimal(fmod(x.dbl(), y.dbl()));

265 
} 
266  
267 
/**

268 
* Returns the greater of the two arguments.

269 
*/

270 
inline const OPP::BigDecimal max(const OPP::BigDecimal& x, const OPP::BigDecimal& y) 
271 
{ 
272 
return x > y ? x : y;

273 
} 
274  
275 
/**

276 
* Returns the smaller of the two arguments.

277 
*/

278 
inline const OPP::BigDecimal min(const OPP::BigDecimal& x, const OPP::BigDecimal& y) 
279 
{ 
280 
return x < y ? x : y;

281 
} 
282  
283 
#endif

284  
285 