| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of fixnum; | 5 part of fixnum; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * An immutable 32-bit signed integer, in the range [-2^31, 2^31 - 1]. | 8 * An immutable 32-bit signed integer, in the range [-2^31, 2^31 - 1]. |
| 9 * Arithmetic operations may overflow in order to maintain this range. | 9 * Arithmetic operations may overflow in order to maintain this range. |
| 10 */ | 10 */ |
| 11 class int32 implements intx { | 11 class Int32 implements Intx { |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * The maximum positive value attainable by an [int32], namely | 14 * The maximum positive value attainable by an [Int32], namely |
| 15 * 2147483647. | 15 * 2147483647. |
| 16 */ | 16 */ |
| 17 static const int32 MAX_VALUE = const int32._internal(0x7FFFFFFF); | 17 static const Int32 MAX_VALUE = const Int32._internal(0x7FFFFFFF); |
| 18 | 18 |
| 19 /** | 19 /** |
| 20 * The minimum positive value attainable by an [int32], namely | 20 * The minimum positive value attainable by an [Int32], namely |
| 21 * -2147483648. | 21 * -2147483648. |
| 22 */ | 22 */ |
| 23 static int32 MIN_VALUE = const int32._internal(-0x80000000); | 23 static Int32 MIN_VALUE = const Int32._internal(-0x80000000); |
| 24 | 24 |
| 25 /** | 25 /** |
| 26 * An [int32] constant equal to 0. | 26 * An [Int32] constant equal to 0. |
| 27 */ | 27 */ |
| 28 static int32 ZERO = const int32._internal(0); | 28 static Int32 ZERO = const Int32._internal(0); |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * An [int32] constant equal to 1. | 31 * An [Int32] constant equal to 1. |
| 32 */ | 32 */ |
| 33 static int32 ONE = const int32._internal(1); | 33 static Int32 ONE = const Int32._internal(1); |
| 34 | 34 |
| 35 /** | 35 /** |
| 36 * An [int32] constant equal to 2. | 36 * An [Int32] constant equal to 2. |
| 37 */ | 37 */ |
| 38 static int32 TWO = const int32._internal(2); | 38 static Int32 TWO = const Int32._internal(2); |
| 39 | 39 |
| 40 // Hex digit char codes | 40 // Hex digit char codes |
| 41 static const int _CC_0 = 48; // '0'.codeUnitAt(0) | 41 static const int _CC_0 = 48; // '0'.codeUnitAt(0) |
| 42 static const int _CC_9 = 57; // '9'.codeUnitAt(0) | 42 static const int _CC_9 = 57; // '9'.codeUnitAt(0) |
| 43 static const int _CC_a = 97; // 'a'.codeUnitAt(0) | 43 static const int _CC_a = 97; // 'a'.codeUnitAt(0) |
| 44 static const int _CC_z = 122; // 'z'.codeUnitAt(0) | 44 static const int _CC_z = 122; // 'z'.codeUnitAt(0) |
| 45 static const int _CC_A = 65; // 'A'.codeUnitAt(0) | 45 static const int _CC_A = 65; // 'A'.codeUnitAt(0) |
| 46 static const int _CC_Z = 90; // 'Z'.codeUnitAt(0) | 46 static const int _CC_Z = 90; // 'Z'.codeUnitAt(0) |
| 47 | 47 |
| 48 static int _decodeHex(int c) { | 48 static int _decodeHex(int c) { |
| 49 if (c >= _CC_0 && c <= _CC_9) { | 49 if (c >= _CC_0 && c <= _CC_9) { |
| 50 return c - _CC_0; | 50 return c - _CC_0; |
| 51 } else if (c >= _CC_a && c <= _CC_z) { | 51 } else if (c >= _CC_a && c <= _CC_z) { |
| 52 return c - _CC_a + 10; | 52 return c - _CC_a + 10; |
| 53 } else if (c >= _CC_A && c <= _CC_Z) { | 53 } else if (c >= _CC_A && c <= _CC_Z) { |
| 54 return c - _CC_A + 10; | 54 return c - _CC_A + 10; |
| 55 } else { | 55 } else { |
| 56 return -1; // bad char code | 56 return -1; // bad char code |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | 59 |
| 60 /** | 60 /** |
| 61 * Parses a [String] in a given [radix] between 2 and 16 and returns an | 61 * Parses a [String] in a given [radix] between 2 and 16 and returns an |
| 62 * [int32]. | 62 * [Int32]. |
| 63 */ | 63 */ |
| 64 // TODO(rice) - Make this faster by converting several digits at once. | 64 // TODO(rice) - Make this faster by converting several digits at once. |
| 65 static int32 parseRadix(String s, int radix) { | 65 static Int32 parseRadix(String s, int radix) { |
| 66 if ((radix <= 1) || (radix > 16)) { | 66 if ((radix <= 1) || (radix > 16)) { |
| 67 throw "Bad radix: $radix"; | 67 throw "Bad radix: $radix"; |
| 68 } | 68 } |
| 69 int32 x = ZERO; | 69 Int32 x = ZERO; |
| 70 for (int i = 0; i < s.length; i++) { | 70 for (int i = 0; i < s.length; i++) { |
| 71 int c = s.codeUnitAt(i); | 71 int c = s.codeUnitAt(i); |
| 72 int digit = _decodeHex(c); | 72 int digit = _decodeHex(c); |
| 73 if (digit < 0 || digit >= radix) { | 73 if (digit < 0 || digit >= radix) { |
| 74 throw new Exception("Non-radix code unit: $c"); | 74 throw new Exception("Non-radix code unit: $c"); |
| 75 } | 75 } |
| 76 x = (x * radix) + digit; | 76 x = (x * radix) + digit; |
| 77 } | 77 } |
| 78 return x; | 78 return x; |
| 79 } | 79 } |
| 80 | 80 |
| 81 /** | 81 /** |
| 82 * Parses a decimal [String] and returns an [int32]. | 82 * Parses a decimal [String] and returns an [Int32]. |
| 83 */ | 83 */ |
| 84 static int32 parseInt(String s) => new int32.fromInt(int.parse(s)); | 84 static Int32 parseInt(String s) => new Int32.fromInt(int.parse(s)); |
| 85 | 85 |
| 86 /** | 86 /** |
| 87 * Parses a hexadecimal [String] and returns an [int32]. | 87 * Parses a hexadecimal [String] and returns an [Int32]. |
| 88 */ | 88 */ |
| 89 static int32 parseHex(String s) => parseRadix(s, 16); | 89 static Int32 parseHex(String s) => parseRadix(s, 16); |
| 90 | 90 |
| 91 // Assumes i is <= 32-bit. | 91 // Assumes i is <= 32-bit. |
| 92 static int _bitCount(int i) { | 92 static int _bitCount(int i) { |
| 93 // See "Hacker's Delight", section 5-1, "Counting 1-Bits". | 93 // See "Hacker's Delight", section 5-1, "Counting 1-Bits". |
| 94 | 94 |
| 95 // The basic strategy is to use "divide and conquer" to | 95 // The basic strategy is to use "divide and conquer" to |
| 96 // add pairs (then quads, etc.) of bits together to obtain | 96 // add pairs (then quads, etc.) of bits together to obtain |
| 97 // sub-counts. | 97 // sub-counts. |
| 98 // | 98 // |
| 99 // A straightforward approach would look like: | 99 // A straightforward approach would look like: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 123 i |= i >> 8; | 123 i |= i >> 8; |
| 124 i |= i >> 16; | 124 i |= i >> 16; |
| 125 return _bitCount(~i); | 125 return _bitCount(~i); |
| 126 } | 126 } |
| 127 | 127 |
| 128 static int _numberOfTrailingZeros(int i) => _bitCount((i & -i) - 1); | 128 static int _numberOfTrailingZeros(int i) => _bitCount((i & -i) - 1); |
| 129 | 129 |
| 130 // The internal value, kept in the range [MIN_VALUE, MAX_VALUE]. | 130 // The internal value, kept in the range [MIN_VALUE, MAX_VALUE]. |
| 131 final int _i; | 131 final int _i; |
| 132 | 132 |
| 133 const int32._internal(int i) : _i = i; | 133 const Int32._internal(int i) : _i = i; |
| 134 | 134 |
| 135 /** | 135 /** |
| 136 * Constructs an [int32] from an [int]. Only the low 32 bits of the input | 136 * Constructs an [Int32] from an [int]. Only the low 32 bits of the input |
| 137 * are used. | 137 * are used. |
| 138 */ | 138 */ |
| 139 int32.fromInt(int i) : _i = (i & 0x7fffffff) - (i & 0x80000000); | 139 Int32.fromInt(int i) : _i = (i & 0x7fffffff) - (i & 0x80000000); |
| 140 | 140 |
| 141 // Returns the [int] representation of the specified value. Throws | 141 // Returns the [int] representation of the specified value. Throws |
| 142 // [ArgumentError] for non-integer arguments. | 142 // [ArgumentError] for non-integer arguments. |
| 143 int _toInt(val) { | 143 int _toInt(val) { |
| 144 if (val is int32) { | 144 if (val is Int32) { |
| 145 return val._i; | 145 return val._i; |
| 146 } else if (val is int) { | 146 } else if (val is int) { |
| 147 return val; | 147 return val; |
| 148 } | 148 } |
| 149 throw new ArgumentError(val); | 149 throw new ArgumentError(val); |
| 150 } | 150 } |
| 151 | 151 |
| 152 // The +, -, * , &, |, and ^ operaters deal with types as follows: | 152 // The +, -, * , &, |, and ^ operaters deal with types as follows: |
| 153 // | 153 // |
| 154 // int32 + int => int32 | 154 // Int32 + int => Int32 |
| 155 // int32 + int32 => int32 | 155 // Int32 + Int32 => Int32 |
| 156 // int32 + int64 => int64 | 156 // Int32 + Int64 => Int64 |
| 157 // | 157 // |
| 158 // The %, ~/ and remainder operators return an int32 even with an int64 | 158 // The %, ~/ and remainder operators return an Int32 even with an Int64 |
| 159 // argument, since the result cannot be greater than the value on the | 159 // argument, since the result cannot be greater than the value on the |
| 160 // left-hand side: | 160 // left-hand side: |
| 161 // | 161 // |
| 162 // int32 % int => int32 | 162 // Int32 % int => Int32 |
| 163 // int32 % int32 => int32 | 163 // Int32 % Int32 => Int32 |
| 164 // int32 % int64 => int32 | 164 // Int32 % Int64 => Int32 |
| 165 | 165 |
| 166 intx operator +(other) { | 166 Intx operator +(other) { |
| 167 if (other is int64) { | 167 if (other is Int64) { |
| 168 return this.toInt64() + other; | 168 return this.toInt64() + other; |
| 169 } | 169 } |
| 170 return new int32.fromInt(_i + _toInt(other)); | 170 return new Int32.fromInt(_i + _toInt(other)); |
| 171 } | 171 } |
| 172 | 172 |
| 173 intx operator -(other) { | 173 Intx operator -(other) { |
| 174 if (other is int64) { | 174 if (other is Int64) { |
| 175 return this.toInt64() - other; | 175 return this.toInt64() - other; |
| 176 } | 176 } |
| 177 return new int32.fromInt(_i - _toInt(other)); | 177 return new Int32.fromInt(_i - _toInt(other)); |
| 178 } | 178 } |
| 179 | 179 |
| 180 int32 operator -() => new int32.fromInt(-_i); | 180 Int32 operator -() => new Int32.fromInt(-_i); |
| 181 | 181 |
| 182 intx operator *(other) { | 182 Intx operator *(other) { |
| 183 if (other is int64) { | 183 if (other is Int64) { |
| 184 return this.toInt64() * other; | 184 return this.toInt64() * other; |
| 185 } | 185 } |
| 186 // TODO(rice) - optimize | 186 // TODO(rice) - optimize |
| 187 return (this.toInt64() * other).toInt32(); | 187 return (this.toInt64() * other).toInt32(); |
| 188 } | 188 } |
| 189 | 189 |
| 190 int32 operator %(other) { | 190 Int32 operator %(other) { |
| 191 if (other is int64) { | 191 if (other is Int64) { |
| 192 // Result will be int32 | 192 // Result will be Int32 |
| 193 return (this.toInt64() % other).toInt32(); | 193 return (this.toInt64() % other).toInt32(); |
| 194 } | 194 } |
| 195 return new int32.fromInt(_i % _toInt(other)); | 195 return new Int32.fromInt(_i % _toInt(other)); |
| 196 } | 196 } |
| 197 | 197 |
| 198 int32 operator ~/(other) { | 198 Int32 operator ~/(other) { |
| 199 if (other is int64) { | 199 if (other is Int64) { |
| 200 return (this.toInt64() ~/ other).toInt32(); | 200 return (this.toInt64() ~/ other).toInt32(); |
| 201 } | 201 } |
| 202 return new int32.fromInt(_i ~/ _toInt(other)); | 202 return new Int32.fromInt(_i ~/ _toInt(other)); |
| 203 } | 203 } |
| 204 | 204 |
| 205 int32 remainder(other) { | 205 Int32 remainder(other) { |
| 206 if (other is int64) { | 206 if (other is Int64) { |
| 207 int64 t = this.toInt64(); | 207 Int64 t = this.toInt64(); |
| 208 return (t - (t ~/ other) * other).toInt32(); | 208 return (t - (t ~/ other) * other).toInt32(); |
| 209 } | 209 } |
| 210 return this - (this ~/ other) * other; | 210 return this - (this ~/ other) * other; |
| 211 } | 211 } |
| 212 | 212 |
| 213 int32 operator &(other) { | 213 Int32 operator &(other) { |
| 214 if (other is int64) { | 214 if (other is Int64) { |
| 215 return (this.toInt64() & other).toInt32(); | 215 return (this.toInt64() & other).toInt32(); |
| 216 } | 216 } |
| 217 return new int32.fromInt(_i & _toInt(other)); | 217 return new Int32.fromInt(_i & _toInt(other)); |
| 218 } | 218 } |
| 219 | 219 |
| 220 int32 operator |(other) { | 220 Int32 operator |(other) { |
| 221 if (other is int64) { | 221 if (other is Int64) { |
| 222 return (this.toInt64() | other).toInt32(); | 222 return (this.toInt64() | other).toInt32(); |
| 223 } | 223 } |
| 224 return new int32.fromInt(_i | _toInt(other)); | 224 return new Int32.fromInt(_i | _toInt(other)); |
| 225 } | 225 } |
| 226 | 226 |
| 227 int32 operator ^(other) { | 227 Int32 operator ^(other) { |
| 228 if (other is int64) { | 228 if (other is Int64) { |
| 229 return (this.toInt64() ^ other).toInt32(); | 229 return (this.toInt64() ^ other).toInt32(); |
| 230 } | 230 } |
| 231 return new int32.fromInt(_i ^ _toInt(other)); | 231 return new Int32.fromInt(_i ^ _toInt(other)); |
| 232 } | 232 } |
| 233 | 233 |
| 234 int32 operator ~() => new int32.fromInt(~_i); | 234 Int32 operator ~() => new Int32.fromInt(~_i); |
| 235 | 235 |
| 236 int32 operator <<(int n) { | 236 Int32 operator <<(int n) { |
| 237 if (n < 0) { | 237 if (n < 0) { |
| 238 throw new ArgumentError("$n"); | 238 throw new ArgumentError("$n"); |
| 239 } | 239 } |
| 240 n &= 31; | 240 n &= 31; |
| 241 return new int32.fromInt(_i << n); | 241 return new Int32.fromInt(_i << n); |
| 242 } | 242 } |
| 243 | 243 |
| 244 int32 operator >>(int n) { | 244 Int32 operator >>(int n) { |
| 245 if (n < 0) { | 245 if (n < 0) { |
| 246 throw new ArgumentError("$n"); | 246 throw new ArgumentError("$n"); |
| 247 } | 247 } |
| 248 n &= 31; | 248 n &= 31; |
| 249 int value; | 249 int value; |
| 250 if (_i >= 0) { | 250 if (_i >= 0) { |
| 251 value = _i >> n; | 251 value = _i >> n; |
| 252 } else { | 252 } else { |
| 253 value = (_i >> n) | (0xffffffff << (32 - n)); | 253 value = (_i >> n) | (0xffffffff << (32 - n)); |
| 254 } | 254 } |
| 255 return new int32.fromInt(value); | 255 return new Int32.fromInt(value); |
| 256 } | 256 } |
| 257 | 257 |
| 258 int32 shiftRightUnsigned(int n) { | 258 Int32 shiftRightUnsigned(int n) { |
| 259 if (n < 0) { | 259 if (n < 0) { |
| 260 throw new ArgumentError("$n"); | 260 throw new ArgumentError("$n"); |
| 261 } | 261 } |
| 262 n &= 31; | 262 n &= 31; |
| 263 int value; | 263 int value; |
| 264 if (_i >= 0) { | 264 if (_i >= 0) { |
| 265 value = _i >> n; | 265 value = _i >> n; |
| 266 } else { | 266 } else { |
| 267 value = (_i >> n) & ((1 << (32 - n)) - 1); | 267 value = (_i >> n) & ((1 << (32 - n)) - 1); |
| 268 } | 268 } |
| 269 return new int32.fromInt(value); | 269 return new Int32.fromInt(value); |
| 270 } | 270 } |
| 271 | 271 |
| 272 /** | 272 /** |
| 273 * Returns [true] if this [int32] has the same numeric value as the | 273 * Returns [true] if this [Int32] has the same numeric value as the |
| 274 * given object. The argument may be an [int] or an [intx]. | 274 * given object. The argument may be an [int] or an [Intx]. |
| 275 */ | 275 */ |
| 276 bool operator ==(other) { | 276 bool operator ==(other) { |
| 277 if (other is int32) { | 277 if (other is Int32) { |
| 278 return _i == other._i; | 278 return _i == other._i; |
| 279 } else if (other is int64) { | 279 } else if (other is Int64) { |
| 280 return this.toInt64() == other; | 280 return this.toInt64() == other; |
| 281 } else if (other is int) { | 281 } else if (other is int) { |
| 282 return _i == other; | 282 return _i == other; |
| 283 } | 283 } |
| 284 return false; | 284 return false; |
| 285 } | 285 } |
| 286 | 286 |
| 287 int compareTo(Comparable other) { | 287 int compareTo(Comparable other) { |
| 288 if (other is int64) { | 288 if (other is Int64) { |
| 289 return this.toInt64().compareTo(other); | 289 return this.toInt64().compareTo(other); |
| 290 } | 290 } |
| 291 return _i.compareTo(_toInt(other)); | 291 return _i.compareTo(_toInt(other)); |
| 292 } | 292 } |
| 293 | 293 |
| 294 bool operator <(other) { | 294 bool operator <(other) { |
| 295 if (other is int64) { | 295 if (other is Int64) { |
| 296 return this.toInt64() < other; | 296 return this.toInt64() < other; |
| 297 } | 297 } |
| 298 return _i < _toInt(other); | 298 return _i < _toInt(other); |
| 299 } | 299 } |
| 300 | 300 |
| 301 bool operator <=(other) { | 301 bool operator <=(other) { |
| 302 if (other is int64) { | 302 if (other is Int64) { |
| 303 return this.toInt64() <= other; | 303 return this.toInt64() <= other; |
| 304 } | 304 } |
| 305 return _i <= _toInt(other); | 305 return _i <= _toInt(other); |
| 306 } | 306 } |
| 307 | 307 |
| 308 bool operator >(other) { | 308 bool operator >(other) { |
| 309 if (other is int64) { | 309 if (other is Int64) { |
| 310 return this.toInt64() > other; | 310 return this.toInt64() > other; |
| 311 } | 311 } |
| 312 return _i > _toInt(other); | 312 return _i > _toInt(other); |
| 313 } | 313 } |
| 314 | 314 |
| 315 bool operator >=(other) { | 315 bool operator >=(other) { |
| 316 if (other is int64) { | 316 if (other is Int64) { |
| 317 return this.toInt64() >= other; | 317 return this.toInt64() >= other; |
| 318 } | 318 } |
| 319 return _i >= _toInt(other); | 319 return _i >= _toInt(other); |
| 320 } | 320 } |
| 321 | 321 |
| 322 bool get isEven => (_i & 0x1) == 0; | 322 bool get isEven => (_i & 0x1) == 0; |
| 323 bool get isMaxValue => _i == 2147483647; | 323 bool get isMaxValue => _i == 2147483647; |
| 324 bool get isMinValue => _i == -2147483648; | 324 bool get isMinValue => _i == -2147483648; |
| 325 bool get isNegative => _i < 0; | 325 bool get isNegative => _i < 0; |
| 326 bool get isOdd => (_i & 0x1) == 1; | 326 bool get isOdd => (_i & 0x1) == 1; |
| 327 bool get isZero => _i == 0; | 327 bool get isZero => _i == 0; |
| 328 | 328 |
| 329 int get hashCode => _i; | 329 int get hashCode => _i; |
| 330 | 330 |
| 331 int32 abs() => _i < 0 ? new int32.fromInt(-_i) : this; | 331 Int32 abs() => _i < 0 ? new Int32.fromInt(-_i) : this; |
| 332 | 332 |
| 333 int numberOfLeadingZeros() => _numberOfLeadingZeros(_i); | 333 int numberOfLeadingZeros() => _numberOfLeadingZeros(_i); |
| 334 int numberOfTrailingZeros() => _numberOfTrailingZeros(_i); | 334 int numberOfTrailingZeros() => _numberOfTrailingZeros(_i); |
| 335 | 335 |
| 336 List<int> toBytes() { | 336 List<int> toBytes() { |
| 337 List<int> result = new List<int>(4); | 337 List<int> result = new List<int>(4); |
| 338 result[0] = _i & 0xff; | 338 result[0] = _i & 0xff; |
| 339 result[1] = (_i >> 8) & 0xff; | 339 result[1] = (_i >> 8) & 0xff; |
| 340 result[2] = (_i >> 16) & 0xff; | 340 result[2] = (_i >> 16) & 0xff; |
| 341 result[3] = (_i >> 24) & 0xff; | 341 result[3] = (_i >> 24) & 0xff; |
| 342 return result; | 342 return result; |
| 343 } | 343 } |
| 344 | 344 |
| 345 int toInt() => _i; | 345 int toInt() => _i; |
| 346 int32 toInt32() => this; | 346 Int32 toInt32() => this; |
| 347 int64 toInt64() => new int64.fromInt(_i); | 347 Int64 toInt64() => new Int64.fromInt(_i); |
| 348 | 348 |
| 349 String toString() => _i.toString(); | 349 String toString() => _i.toString(); |
| 350 String toHexString() => _i.toRadixString(16); | 350 String toHexString() => _i.toRadixString(16); |
| 351 String toRadixString(int radix) => _i.toRadixString(radix); | 351 String toRadixString(int radix) => _i.toRadixString(radix); |
| 352 } | 352 } |
| OLD | NEW |