2
******************************************************************************
3
* Copyright (C) 1997-2001, International Business Machines
4
* Corporation and others. All Rights Reserved.
5
******************************************************************************
8
* tab size: 8 (not used)
11
* Modification history
13
* 10/11/2001 Doug Ported from ICU4J (thanks to Mike Cowlishaw)
19
#include "unicode/utypes.h"
23
// machine dependent value, need to move
24
//#define __u_IntBits 32
26
// export so that we can test this
27
class U_I18N_API llong {
37
// private constructor
38
// should be private, but we can't construct the way we want using SOLARISCC
39
// so make public in order that file statics can access this constructor
41
static const double kD32; // 2^^32 as a double
42
// static const double kDMin; // -(2^^54), minimum double with full integer precision
43
// static const double kDMax; // 2^^54, maximum double with full integer precision
45
llong(int32_t h, uint32_t l) : lo(l), hi(h) {}
47
// convenience, size reduction in inline code
48
llong& nnot() { hi = ~hi; lo = ~lo; return *this; }
49
llong& negate() { hi = ~hi; lo = ~lo; if (!++lo) ++hi; return *this; }
50
llong& abs() { if (hi < 0) negate(); return *this; }
51
UBool notZero() const { return (hi | lo) != 0; }
52
UBool isZero() const { return (hi | lo) == 0; }
53
UBool isNegative() const { return hi < 0; }
56
llong() : lo(0), hi(0) {}
57
llong(const int32_t l) : lo((unsigned)l), hi(l < 0 ? -1 : 0) {}
58
llong(const int16_t l) : lo((unsigned)l), hi(l < 0 ? -1 : 0) {}
59
llong(const int8_t l) : lo((unsigned)l), hi(l < 0 ? -1 : 0) {}
60
//#if __u_IntBits == 64
61
// llong(const int i) : lo(i & MASK32), hi(i >> 32) {}
63
llong(uint16_t s) : lo(s), hi(0) {}
64
llong(uint32_t l) : lo(l), hi(0) {}
65
//#if __u_IntBits == 64
66
// llong(unsigned int i) : lo(i & MASK32), hi(i >> 32) {}
70
llong(const llong& rhs) : lo(rhs.lo), hi(rhs.hi) {}
72
// the following cause ambiguities in binary expressions,
73
// even if we overload all methods on all args!
74
// so you have to use global functions
75
// operator const int32_t() const;
76
// operator const uint32_t() const;
77
// operator const double() const;
79
inline int32_t asInt() const;
80
inline uint32_t asUInt() const;
81
inline double asDouble() const;
83
inline llong& operator=(const llong& rhs) { lo = rhs.lo; hi = rhs.hi; return *this; }
86
inline llong& operator<<=(int32_t shift) {
87
shift &= 63; // like java spec
89
// akkk! msvc 6 compiler bug generates shr/shl which only uses low 5 bits of shift
90
// so e.g. lo >> 32 -> lo is unchanged!
92
hi = (int32_t)(hi << shift | lo >> (32 - shift)); // no sign extension on lo since unsigned
96
hi = (int32_t)(lo << (shift - 32));
101
inline llong operator<<(int32_t shift) const { llong r(*this); r <<= shift; return r; }
103
// right shift with sign extension
104
inline llong& operator>>=(int32_t shift) {
105
shift &= 63; // like java spec
109
lo |= (hi << (32 - shift));
110
hi = hi >> shift; // note sign extension
113
lo = (uint32_t)(hi >> (shift - 32)); // note sign extension
114
hi = hi < 0 ? -1 : 0;
118
inline llong operator>>(int32_t shift) const { llong r(*this); r >>= shift; return r; }
120
// right shift without sign extension, non-const
121
llong& ushr(int32_t shift) {
126
lo |= (hi << (32 - shift));
127
hi = (int32_t)(((unsigned)hi) >> shift);
130
lo = (uint32_t)(((unsigned)hi) >> (shift - 32));
136
// right shift without sign extension, const
137
inline llong ushr(int32_t shift) const;
140
inline llong operator&(const llong& rhs) const;
141
inline llong operator|(const llong& rhs) const;
142
inline llong operator^(const llong& rhs) const;
144
inline llong operator&(const uint32_t rhs) const;
145
inline llong operator|(const uint32_t rhs) const;
146
inline llong operator^(const uint32_t rhs) const;
148
llong operator~() const { return llong(~hi, ~lo); }
150
// UBool operator!() const { return !(hi | lo); }
152
inline llong& operator&=(const llong& rhs) { hi &= rhs.hi; lo &= rhs.lo; return *this; }
153
inline llong& operator|=(const llong& rhs) { hi |= rhs.hi; lo |= rhs.lo; return *this; }
154
inline llong& operator^=(const llong& rhs) { hi ^= rhs.hi; lo ^= rhs.lo; return *this; }
156
inline llong& operator&=(const uint32_t rhs) { hi = 0; lo &= rhs; return *this; }
157
inline llong& operator|=(const uint32_t rhs) { lo |= rhs; return *this; }
158
inline llong& operator^=(const uint32_t rhs) { lo ^= rhs; return *this; }
160
// no logical ops since we can't enforce order of evaluation, not much use anyway?
163
inline UBool operator==(const llong& rhs) const;
164
inline UBool operator!=(const llong& rhs) const;
165
inline UBool operator> (const llong& rhs) const;
166
inline UBool operator< (const llong& rhs) const;
167
inline UBool operator>=(const llong& rhs) const;
168
inline UBool operator<=(const llong& rhs) const;
170
// overload comparison to native int to avoid conversion to llong for common comparisons
171
inline UBool operator==(const int32_t rhs) const;
172
inline UBool operator!=(const int32_t rhs) const;
173
inline UBool operator> (const int32_t rhs) const;
174
inline UBool operator< (const int32_t rhs) const;
175
inline UBool operator>=(const int32_t rhs) const;
176
inline UBool operator<=(const int32_t rhs) const;
178
// unsigned comparison
179
inline UBool ugt(const llong& rhs) const;
180
inline UBool ult(const llong& rhs) const;
181
inline UBool uge(const llong& rhs) const;
182
inline UBool ule(const llong& rhs) const;
185
llong& operator++() { if (!++lo) ++hi; return *this; }
186
llong& operator--() { if (!lo--) --hi; return *this; }
189
llong operator++(int) { llong r(*this); if (!++lo) ++hi; return r; }
190
llong operator--(int) { llong r(*this); if (!lo--) --hi; return r; }
193
llong operator-() const { uint32_t l = ~lo + 1; return llong(l ? ~hi : ~hi + 1, l); }
195
// addition and subtraction
196
llong& operator-=(const llong& rhs) { hi -= rhs.hi; if (lo < rhs.lo) --hi; lo -= rhs.lo; return *this; }
197
inline llong operator-(const llong& rhs) const { return llong(lo < rhs.lo ? hi - rhs.hi - 1 : hi - rhs.hi, lo - rhs.lo); }
199
inline llong& operator+=(const llong& rhs) { return *this -= -rhs; }
200
inline llong operator+(const llong& rhs) const { return *this - -rhs; }
202
// pluttification and fizzen'
203
llong& operator*=(const llong& rhs);
204
inline llong operator*(const llong& rhs) const { llong r(*this); r *= rhs; return r; }
206
llong& operator/=(const llong& rhs);
207
inline llong operator/(const llong& rhs) const { llong r(*this); r /= rhs; return r; }
209
llong& operator%=(const llong& rhs) { return operator-=((*this / rhs) * rhs); }
210
inline llong operator%(const llong& rhs) const { llong r(*this); r %= rhs; return r; }
212
// power function, positive integral powers only
213
inline llong pow(uint32_t n) const;
216
inline llong abs() const;
218
// simple construction from ASCII and Unicode strings
220
static llong atoll(const char* str, uint32_t radix = 10);
222
static llong utoll(const UChar* str, uint32_t radix = 10);
224
// output as ASCII or Unicode strings or as raw values, preceeding '-' if signed
226
uint32_t lltoa(char* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE) const;
228
uint32_t lltou(UChar* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE) const;
231
static const llong getMaxDouble();
232
static const llong getMinDouble();
234
// back door for test
235
friend void llong_test();
238
inline llong llong::operator& (const llong& rhs) const { return llong(hi & rhs.hi, lo & rhs.lo); }
239
inline llong llong::operator| (const llong& rhs) const { return llong(hi | rhs.hi, lo | rhs.lo); }
240
inline llong llong::operator^ (const llong& rhs) const { return llong(hi ^ rhs.hi, lo ^ rhs.lo); }
242
inline llong llong::operator& (const uint32_t rhs) const { return llong(0, lo & rhs); }
243
inline llong llong::operator| (const uint32_t rhs) const { return llong(hi, lo | rhs); }
244
inline llong llong::operator^ (const uint32_t rhs) const { return llong(hi, lo ^ rhs); }
246
inline UBool llong::operator==(const llong& rhs) const { return lo == rhs.lo && hi == rhs.hi; }
247
inline UBool llong::operator!=(const llong& rhs) const { return lo != rhs.lo || hi != rhs.hi; }
248
inline UBool llong::operator> (const llong& rhs) const { return hi == rhs.hi ? lo > rhs.lo : hi > rhs.hi; }
249
inline UBool llong::operator< (const llong& rhs) const { return hi == rhs.hi ? lo < rhs.lo : hi < rhs.hi; }
250
inline UBool llong::operator>=(const llong& rhs) const { return hi == rhs.hi ? lo >= rhs.lo : hi >= rhs.hi; }
251
inline UBool llong::operator<=(const llong& rhs) const { return hi == rhs.hi ? lo <= rhs.lo : hi <= rhs.hi; }
253
inline UBool llong::operator==(const int32_t rhs) const { return lo == (unsigned)rhs && hi == (rhs < 0 ? -1 : 0); }
254
inline UBool llong::operator!=(const int32_t rhs) const { return lo != (unsigned)rhs || hi != (rhs < 0 ? -1 : 0); }
255
inline UBool llong::operator> (const int32_t rhs) const { return rhs < 0 ? (hi == -1 ? lo > (unsigned)rhs : hi > -1)
256
: (hi == 0 ? lo > (unsigned)rhs : hi > 0); }
257
inline UBool llong::operator< (const int32_t rhs) const { return rhs < 0 ? (hi == -1 ? lo < (unsigned)rhs : hi < -1)
258
: (hi == 0 ? lo < (unsigned)rhs : hi < 0); }
259
inline UBool llong::operator>=(const int32_t rhs) const { return rhs < 0 ? (hi == -1 ? lo >= (unsigned)rhs : hi > -1)
260
: (hi == 0 ? lo >= (unsigned)rhs : hi > 0); }
261
inline UBool llong::operator<=(const int32_t rhs) const { return rhs < 0 ? (hi == -1 ? lo <= (unsigned)rhs : hi < -1)
262
: (hi == 0 ? lo <= (unsigned)rhs : hi < 0); }
264
inline UBool llong::ugt(const llong& rhs) const { return hi == rhs.hi ? lo > rhs.lo : (unsigned)hi > (unsigned)rhs.hi; }
265
inline UBool llong::ult(const llong& rhs) const { return hi == rhs.hi ? lo < rhs.lo : (unsigned)hi < (unsigned)rhs.hi; }
266
inline UBool llong::uge(const llong& rhs) const { return hi == rhs.hi ? lo >= rhs.lo : (unsigned)hi >= (unsigned)rhs.hi; }
267
inline UBool llong::ule(const llong& rhs) const { return hi == rhs.hi ? lo <= rhs.lo : (unsigned)hi <= (unsigned)rhs.hi; }
269
inline llong llong::ushr(int32_t shift) const { llong r(*this); r.ushr(shift); return r; }
271
inline int32_t llong::asInt() const { return (int32_t)((lo & 0x7fffffff) | (hi < 0 ? 0x80000000 : 0)); }
272
inline uint32_t llong::asUInt() const { return lo; }
273
inline double llong::asDouble() const { return llong::kD32 * hi + lo; }
275
inline llong llong::pow(uint32_t n) const {
277
return llong(0, 0); /* zero */
279
return llong(0, 1); /* one */
289
inline llong llong::abs() const { return isNegative() ? -(*this) : *this; }
291
// Originally, I thought that overloading on int32 was too complex or to large to get inlined, and
292
// since I mainly wanted to optimize comparisons to zero, I overloaded on uint32_t instead
293
// since it has a simpler implementation.
294
// But this means that llong(-1) != -1 (since the comparison treats the rhs as unsigned, but
295
// the constructor does not). So I am using the signed versions after all.
298
inline UBool operator==(const llong& lhs, const uint32_t rhs) { return lhs.lo == rhs && lhs.hi == 0; }
299
inline UBool operator!=(const llong& lhs, const uint32_t rhs) { return lhs.lo != rhs || lhs.hi != 0; }
300
inline UBool operator> (const llong& lhs, const uint32_t rhs) { return lhs.hi == 0 ? lhs.lo > rhs : lhs.hi > 0; }
301
inline UBool operator< (const llong& lhs, const uint32_t rhs) { return lhs.hi == 0 ? lhs.lo < rhs : lhs.hi < 0; }
302
inline UBool operator>=(const llong& lhs, const uint32_t rhs) { return lhs.hi == 0 ? lhs.lo >= rhs : lhs.hi >= 0; }
303
inline UBool operator<=(const llong& lhs, const uint32_t rhs) { return lhs.hi == 0 ? lhs.lo <= rhs : lhs.hi <= 0; }