~ubuntu-branches/ubuntu/gutsy/icu/gutsy

« back to all changes in this revision

Viewing changes to source/i18n/llong.h

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2005-05-21 22:44:31 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: package-import@ubuntu.com-20050521224431-r7rktfhnu1n4tf1g
Tags: 2.1-2.1
Rename icu-doc to icu21-doc. icu-doc is built by the icu28 package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
******************************************************************************
3
 
*   Copyright (C) 1997-2001, International Business Machines
4
 
*   Corporation and others.  All Rights Reserved.
5
 
******************************************************************************
6
 
*   file name:  llong.h
7
 
*   encoding:   US-ASCII
8
 
*   tab size:   8 (not used)
9
 
*   indentation:4
10
 
*
11
 
* Modification history
12
 
* Date        Name      Comments
13
 
* 10/11/2001  Doug      Ported from ICU4J (thanks to Mike Cowlishaw)
14
 
*/
15
 
 
16
 
#ifndef LLONG_H
17
 
#define LLONG_H
18
 
 
19
 
#include "unicode/utypes.h"
20
 
 
21
 
U_NAMESPACE_BEGIN
22
 
 
23
 
// machine dependent value, need to move
24
 
//#define __u_IntBits 32
25
 
 
26
 
// export so that we can test this
27
 
class U_I18N_API llong {
28
 
#ifdef RBNF_DEBUG
29
 
public:
30
 
#else
31
 
private:
32
 
#endif
33
 
    uint32_t lo;
34
 
    int32_t hi;
35
 
private:
36
 
 
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
40
 
public:
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
44
 
 
45
 
    llong(int32_t h, uint32_t l) : lo(l), hi(h) {}
46
 
private:
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; }
54
 
 
55
 
public:
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) {}
62
 
//#endif
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) {}
67
 
//#endif
68
 
    llong(double d);
69
 
 
70
 
    llong(const llong& rhs) : lo(rhs.lo), hi(rhs.hi) {}
71
 
 
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;
78
 
 
79
 
    inline int32_t  asInt() const;
80
 
    inline uint32_t asUInt() const;
81
 
    inline double   asDouble() const;
82
 
 
83
 
    inline llong& operator=(const llong& rhs) { lo = rhs.lo; hi = rhs.hi; return *this; }
84
 
 
85
 
    // left shift
86
 
    inline llong& operator<<=(int32_t shift) {
87
 
        shift &= 63; // like java spec
88
 
        if (shift < 32) {
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!
91
 
                        if (shift > 0) {
92
 
                                hi = (int32_t)(hi << shift | lo >> (32 - shift)); // no sign extension on lo since unsigned
93
 
                                lo <<= shift;
94
 
                        }
95
 
        } else {
96
 
            hi = (int32_t)(lo << (shift - 32));
97
 
            lo = 0;
98
 
        }
99
 
        return *this;
100
 
    }
101
 
    inline llong operator<<(int32_t shift) const { llong r(*this); r <<= shift; return r; }
102
 
 
103
 
    // right shift with sign extension
104
 
    inline llong& operator>>=(int32_t shift) {
105
 
        shift &= 63; // like java spec
106
 
        if (shift < 32) {
107
 
                        if (shift > 0) {
108
 
                                lo >>= shift; 
109
 
                                lo |= (hi << (32 - shift)); 
110
 
                                hi = hi >> shift; // note sign extension
111
 
                        }
112
 
        } else {
113
 
            lo = (uint32_t)(hi >> (shift - 32)); // note sign extension
114
 
            hi = hi < 0 ? -1 : 0;
115
 
        }
116
 
        return *this; 
117
 
    }
118
 
    inline llong operator>>(int32_t shift) const { llong r(*this); r >>= shift; return r; }
119
 
 
120
 
     // right shift without sign extension, non-const 
121
 
    llong& ushr(int32_t shift) {
122
 
        shift &= 63;
123
 
        if (shift < 32) {
124
 
                        if (shift > 0) {
125
 
                                lo >>= shift;
126
 
                                lo |= (hi << (32 - shift));
127
 
                                hi = (int32_t)(((unsigned)hi) >> shift);
128
 
                        }
129
 
        } else {
130
 
            lo = (uint32_t)(((unsigned)hi) >> (shift - 32));
131
 
            hi = 0;
132
 
        }
133
 
        return *this;
134
 
    }
135
 
 
136
 
   // right shift without sign extension, const
137
 
    inline llong ushr(int32_t shift) const;
138
 
 
139
 
    // bit operations
140
 
    inline llong operator&(const llong& rhs) const;
141
 
    inline llong operator|(const llong& rhs) const;
142
 
    inline llong operator^(const llong& rhs) const;
143
 
 
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;
147
 
 
148
 
    llong operator~() const { return llong(~hi, ~lo); }
149
 
    // is this useful?
150
 
    // UBool operator!() const { return !(hi | lo); }
151
 
 
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; }
155
 
 
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; }
159
 
 
160
 
    // no logical ops since we can't enforce order of evaluation, not much use anyway?
161
 
 
162
 
    // comparison
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;
169
 
 
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;
177
 
 
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;
183
 
 
184
 
    // prefix inc/dec
185
 
    llong& operator++() { if (!++lo) ++hi; return *this; }
186
 
    llong& operator--() { if (!lo--) --hi; return *this; }
187
 
 
188
 
    // postfix inc/dec
189
 
    llong operator++(int) { llong r(*this); if (!++lo) ++hi; return r; }
190
 
    llong operator--(int) { llong r(*this); if (!lo--) --hi; return r; }
191
 
    
192
 
    // unary minus
193
 
    llong operator-() const { uint32_t l = ~lo + 1; return llong(l ? ~hi : ~hi + 1, l); }
194
 
 
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); }
198
 
 
199
 
    inline llong& operator+=(const llong& rhs) { return *this -= -rhs; }
200
 
    inline llong operator+(const llong& rhs) const { return *this - -rhs; }
201
 
 
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; }
205
 
 
206
 
    llong& operator/=(const llong& rhs);
207
 
    inline llong operator/(const llong& rhs) const { llong r(*this); r /= rhs; return r; }
208
 
 
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; }
211
 
 
212
 
    // power function, positive integral powers only
213
 
    inline llong pow(uint32_t n) const;
214
 
 
215
 
    // absolute value
216
 
    inline llong abs() const;
217
 
 
218
 
    // simple construction from ASCII and Unicode strings
219
 
#ifdef RBNF_DEBUG
220
 
    static llong atoll(const char* str, uint32_t radix = 10);
221
 
#endif
222
 
    static llong utoll(const UChar* str, uint32_t radix = 10);
223
 
 
224
 
    // output as ASCII or Unicode strings or as raw values, preceeding '-' if signed
225
 
#ifdef RBNF_DEBUG
226
 
    uint32_t lltoa(char* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE) const;
227
 
#endif
228
 
    uint32_t lltou(UChar* buffer, uint32_t buflen, uint32_t radix = 10, UBool raw = FALSE) const;
229
 
 
230
 
private:
231
 
    static const llong getMaxDouble();
232
 
    static const llong getMinDouble();
233
 
 
234
 
    // back door for test
235
 
    friend void llong_test();
236
 
};
237
 
 
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); }
241
 
 
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); }
245
 
 
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; }
252
 
 
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); }
263
 
 
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; }
268
 
 
269
 
inline llong llong::ushr(int32_t shift) const { llong r(*this); r.ushr(shift); return r; }
270
 
 
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; }
274
 
 
275
 
inline llong llong::pow(uint32_t n) const { 
276
 
    if (isZero()) {
277
 
        return llong(0, 0); /* zero */
278
 
    } else if (n == 0) {
279
 
        return llong(0, 1); /* one */
280
 
    } else {
281
 
        llong r(*this);
282
 
        while (--n > 0) {
283
 
            r *= *this;
284
 
        }
285
 
        return r;
286
 
    }
287
 
}
288
 
 
289
 
inline llong llong::abs() const { return isNegative() ? -(*this) : *this; }
290
 
 
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.
296
 
 
297
 
#if 0
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; }
304
 
#endif
305
 
 
306
 
U_NAMESPACE_END
307
 
 
308
 
// LLONG_H
309
 
#endif