| 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 abstract class _IntegerImplementation { | 5 abstract class _IntegerImplementation { |
| 6 // The Dart class _Bigint extending _IntegerImplementation requires a | 6 // The Dart class _Bigint extending _IntegerImplementation requires a |
| 7 // default constructor. | 7 // default constructor. |
| 8 | 8 |
| 9 num operator +(num other) { | 9 num operator +(num other) { |
| 10 var result = other._addFromInteger(this); | 10 var result = other._addFromInteger(this); |
| 11 if (result != null) return result; | 11 if (result != null) return result; |
| 12 return other._toBigint()._addFromInteger(this); | 12 return other._toBigint()._addFromInteger(this); |
| 13 } | 13 } |
| 14 |
| 14 num operator -(num other) { | 15 num operator -(num other) { |
| 15 var result = other._subFromInteger(this); | 16 var result = other._subFromInteger(this); |
| 16 if (result != null) return result; | 17 if (result != null) return result; |
| 17 return other._toBigint()._subFromInteger(this); | 18 return other._toBigint()._subFromInteger(this); |
| 18 } | 19 } |
| 20 |
| 19 num operator *(num other) { | 21 num operator *(num other) { |
| 20 var result = other._mulFromInteger(this); | 22 var result = other._mulFromInteger(this); |
| 21 if (result != null) return result; | 23 if (result != null) return result; |
| 22 return other._toBigint()._mulFromInteger(this); | 24 return other._toBigint()._mulFromInteger(this); |
| 23 } | 25 } |
| 26 |
| 24 num operator ~/(num other) { | 27 num operator ~/(num other) { |
| 25 if ((other is int) && (other == 0)) { | 28 if ((other is int) && (other == 0)) { |
| 26 throw const IntegerDivisionByZeroException(); | 29 throw const IntegerDivisionByZeroException(); |
| 27 } | 30 } |
| 28 var result = other._truncDivFromInteger(this); | 31 var result = other._truncDivFromInteger(this); |
| 29 if (result != null) return result; | 32 if (result != null) return result; |
| 30 return other._toBigint()._truncDivFromInteger(this); | 33 return other._toBigint()._truncDivFromInteger(this); |
| 31 } | 34 } |
| 35 |
| 32 num operator /(num other) { | 36 num operator /(num other) { |
| 33 return this.toDouble() / other.toDouble(); | 37 return this.toDouble() / other.toDouble(); |
| 34 } | 38 } |
| 39 |
| 35 num operator %(num other) { | 40 num operator %(num other) { |
| 36 if ((other is int) && (other == 0)) { | 41 if ((other is int) && (other == 0)) { |
| 37 throw const IntegerDivisionByZeroException(); | 42 throw const IntegerDivisionByZeroException(); |
| 38 } | 43 } |
| 39 var result = other._moduloFromInteger(this); | 44 var result = other._moduloFromInteger(this); |
| 40 if (result != null) return result; | 45 if (result != null) return result; |
| 41 return other._toBigint()._moduloFromInteger(this); | 46 return other._toBigint()._moduloFromInteger(this); |
| 42 } | 47 } |
| 48 |
| 43 int operator -() { | 49 int operator -() { |
| 44 return 0 - this; | 50 return 0 - this; |
| 45 } | 51 } |
| 52 |
| 46 int operator &(int other) { | 53 int operator &(int other) { |
| 47 var result = other._bitAndFromInteger(this); | 54 var result = other._bitAndFromInteger(this); |
| 48 if (result != null) return result; | 55 if (result != null) return result; |
| 49 return other._toBigint()._bitAndFromInteger(this); | 56 return other._toBigint()._bitAndFromInteger(this); |
| 50 } | 57 } |
| 58 |
| 51 int operator |(int other) { | 59 int operator |(int other) { |
| 52 var result = other._bitOrFromInteger(this); | 60 var result = other._bitOrFromInteger(this); |
| 53 if (result != null) return result; | 61 if (result != null) return result; |
| 54 return other._toBigint()._bitOrFromInteger(this); | 62 return other._toBigint()._bitOrFromInteger(this); |
| 55 } | 63 } |
| 64 |
| 56 int operator ^(int other) { | 65 int operator ^(int other) { |
| 57 var result = other._bitXorFromInteger(this); | 66 var result = other._bitXorFromInteger(this); |
| 58 if (result != null) return result; | 67 if (result != null) return result; |
| 59 return other._toBigint()._bitXorFromInteger(this); | 68 return other._toBigint()._bitXorFromInteger(this); |
| 60 } | 69 } |
| 70 |
| 61 num remainder(num other) { | 71 num remainder(num other) { |
| 62 return other._remainderFromInteger(this); | 72 return other._remainderFromInteger(this); |
| 63 } | 73 } |
| 74 |
| 64 int _bitAndFromSmi(int other) native "Integer_bitAndFromInteger"; | 75 int _bitAndFromSmi(int other) native "Integer_bitAndFromInteger"; |
| 65 int _bitAndFromInteger(int other) native "Integer_bitAndFromInteger"; | 76 int _bitAndFromInteger(int other) native "Integer_bitAndFromInteger"; |
| 66 int _bitOrFromInteger(int other) native "Integer_bitOrFromInteger"; | 77 int _bitOrFromInteger(int other) native "Integer_bitOrFromInteger"; |
| 67 int _bitXorFromInteger(int other) native "Integer_bitXorFromInteger"; | 78 int _bitXorFromInteger(int other) native "Integer_bitXorFromInteger"; |
| 68 int _addFromInteger(int other) native "Integer_addFromInteger"; | 79 int _addFromInteger(int other) native "Integer_addFromInteger"; |
| 69 int _subFromInteger(int other) native "Integer_subFromInteger"; | 80 int _subFromInteger(int other) native "Integer_subFromInteger"; |
| 70 int _mulFromInteger(int other) native "Integer_mulFromInteger"; | 81 int _mulFromInteger(int other) native "Integer_mulFromInteger"; |
| 71 int _truncDivFromInteger(int other) native "Integer_truncDivFromInteger"; | 82 int _truncDivFromInteger(int other) native "Integer_truncDivFromInteger"; |
| 72 int _moduloFromInteger(int other) native "Integer_moduloFromInteger"; | 83 int _moduloFromInteger(int other) native "Integer_moduloFromInteger"; |
| 73 int _remainderFromInteger(int other) { | 84 int _remainderFromInteger(int other) { |
| 74 return other - (other ~/ this) * this; | 85 return other - (other ~/ this) * this; |
| 75 } | 86 } |
| 87 |
| 76 int operator >>(int other) { | 88 int operator >>(int other) { |
| 77 var result = other._shrFromInt(this); | 89 var result = other._shrFromInt(this); |
| 78 if (result != null) return result; | 90 if (result != null) return result; |
| 79 return other._toBigint()._shrFromInt(this); | 91 return other._toBigint()._shrFromInt(this); |
| 80 } | 92 } |
| 93 |
| 81 int operator <<(int other) { | 94 int operator <<(int other) { |
| 82 var result = other._shlFromInt(this); | 95 var result = other._shlFromInt(this); |
| 83 if (result != null) return result; | 96 if (result != null) return result; |
| 84 return other._toBigint()._shlFromInt(this); | 97 return other._toBigint()._shlFromInt(this); |
| 85 } | 98 } |
| 99 |
| 86 bool operator <(num other) { | 100 bool operator <(num other) { |
| 87 return other > this; | 101 return other > this; |
| 88 } | 102 } |
| 103 |
| 89 bool operator >(num other) { | 104 bool operator >(num other) { |
| 90 return other._greaterThanFromInteger(this); | 105 return other._greaterThanFromInteger(this); |
| 91 } | 106 } |
| 107 |
| 92 bool operator >=(num other) { | 108 bool operator >=(num other) { |
| 93 return (this == other) || (this > other); | 109 return (this == other) || (this > other); |
| 94 } | 110 } |
| 111 |
| 95 bool operator <=(num other) { | 112 bool operator <=(num other) { |
| 96 return (this == other) || (this < other); | 113 return (this == other) || (this < other); |
| 97 } | 114 } |
| 115 |
| 98 bool _greaterThanFromInteger(int other) | 116 bool _greaterThanFromInteger(int other) |
| 99 native "Integer_greaterThanFromInteger"; | 117 native "Integer_greaterThanFromInteger"; |
| 100 bool operator ==(other) { | 118 bool operator ==(other) { |
| 101 if (other is num) { | 119 if (other is num) { |
| 102 return other._equalToInteger(this); | 120 return other._equalToInteger(this); |
| 103 } | 121 } |
| 104 return false; | 122 return false; |
| 105 } | 123 } |
| 124 |
| 106 bool _equalToInteger(int other) native "Integer_equalToInteger"; | 125 bool _equalToInteger(int other) native "Integer_equalToInteger"; |
| 107 int abs() { | 126 int abs() { |
| 108 return this < 0 ? -this : this; | 127 return this < 0 ? -this : this; |
| 109 } | 128 } |
| 129 |
| 110 int get sign { | 130 int get sign { |
| 111 return (this > 0) ? 1 : (this < 0) ? -1 : 0; | 131 return (this > 0) ? 1 : (this < 0) ? -1 : 0; |
| 112 } | 132 } |
| 133 |
| 113 bool get isEven => ((this & 1) == 0); | 134 bool get isEven => ((this & 1) == 0); |
| 114 bool get isOdd => !isEven; | 135 bool get isOdd => !isEven; |
| 115 bool get isNaN => false; | 136 bool get isNaN => false; |
| 116 bool get isNegative => this < 0; | 137 bool get isNegative => this < 0; |
| 117 bool get isInfinite => false; | 138 bool get isInfinite => false; |
| 118 bool get isFinite => true; | 139 bool get isFinite => true; |
| 119 | 140 |
| 120 int toUnsigned(int width) { | 141 int toUnsigned(int width) { |
| 121 return this & ((1 << width) - 1); | 142 return this & ((1 << width) - 1); |
| 122 } | 143 } |
| 123 | 144 |
| 124 int toSigned(int width) { | 145 int toSigned(int width) { |
| 125 // The value of binary number weights each bit by a power of two. The | 146 // The value of binary number weights each bit by a power of two. The |
| 126 // twos-complement value weights the sign bit negatively. We compute the | 147 // twos-complement value weights the sign bit negatively. We compute the |
| 127 // value of the negative weighting by isolating the sign bit with the | 148 // value of the negative weighting by isolating the sign bit with the |
| 128 // correct power of two weighting and subtracting it from the value of the | 149 // correct power of two weighting and subtracting it from the value of the |
| 129 // lower bits. | 150 // lower bits. |
| 130 int signMask = 1 << (width - 1); | 151 int signMask = 1 << (width - 1); |
| 131 return (this & (signMask - 1)) - (this & signMask); | 152 return (this & (signMask - 1)) - (this & signMask); |
| 132 } | 153 } |
| 133 | 154 |
| 134 int compareTo(num other) { | 155 int compareTo(num other) { |
| 135 const int EQUAL = 0, LESS = -1, GREATER = 1; | 156 const int EQUAL = 0, LESS = -1, GREATER = 1; |
| 136 if (other is double) { | 157 if (other is double) { |
| 137 const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53. | 158 const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53. |
| 138 const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE; | 159 const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE; |
| 139 double d = other; | 160 double d = other; |
| 140 if (d.isInfinite) { | 161 if (d.isInfinite) { |
| 141 return d == double.NEGATIVE_INFINITY ? GREATER : LESS; | 162 return d == double.NEGATIVE_INFINITY ? GREATER : LESS; |
| 142 } | 163 } |
| 143 if (d.isNaN) { | 164 if (d.isNaN) { |
| 144 return LESS; | 165 return LESS; |
| 145 } | 166 } |
| 146 if (MIN_EXACT_INT_TO_DOUBLE <= this && this <= MAX_EXACT_INT_TO_DOUBLE) { | 167 if (MIN_EXACT_INT_TO_DOUBLE <= this && this <= MAX_EXACT_INT_TO_DOUBLE) { |
| 147 // Let the double implementation deal with -0.0. | 168 // Let the double implementation deal with -0.0. |
| 148 return -(d.compareTo(this.toDouble())); | 169 return -(d.compareTo(this.toDouble())); |
| 149 } else { | 170 } else { |
| 150 // If abs(other) > MAX_EXACT_INT_TO_DOUBLE, then other has an integer | 171 // If abs(other) > MAX_EXACT_INT_TO_DOUBLE, then other has an integer |
| 151 // value (no bits below the decimal point). | 172 // value (no bits below the decimal point). |
| 152 other = d.toInt(); | 173 other = d.toInt(); |
| 153 } | 174 } |
| 154 } | 175 } |
| 155 if (this < other) { | 176 if (this < other) { |
| 156 return LESS; | 177 return LESS; |
| 157 } else if (this > other) { | 178 } else if (this > other) { |
| 158 return GREATER; | 179 return GREATER; |
| 159 } else { | 180 } else { |
| 160 return EQUAL; | 181 return EQUAL; |
| 161 } | 182 } |
| 162 } | 183 } |
| 163 | 184 |
| 164 int round() { return this; } | 185 int round() { |
| 165 int floor() { return this; } | 186 return this; |
| 166 int ceil() { return this; } | 187 } |
| 167 int truncate() { return this; } | |
| 168 | 188 |
| 169 double roundToDouble() { return this.toDouble(); } | 189 int floor() { |
| 170 double floorToDouble() { return this.toDouble(); } | 190 return this; |
| 171 double ceilToDouble() { return this.toDouble(); } | 191 } |
| 172 double truncateToDouble() { return this.toDouble(); } | 192 |
| 193 int ceil() { |
| 194 return this; |
| 195 } |
| 196 |
| 197 int truncate() { |
| 198 return this; |
| 199 } |
| 200 |
| 201 double roundToDouble() { |
| 202 return this.toDouble(); |
| 203 } |
| 204 |
| 205 double floorToDouble() { |
| 206 return this.toDouble(); |
| 207 } |
| 208 |
| 209 double ceilToDouble() { |
| 210 return this.toDouble(); |
| 211 } |
| 212 |
| 213 double truncateToDouble() { |
| 214 return this.toDouble(); |
| 215 } |
| 173 | 216 |
| 174 num clamp(num lowerLimit, num upperLimit) { | 217 num clamp(num lowerLimit, num upperLimit) { |
| 175 if (lowerLimit is! num) { | 218 if (lowerLimit is! num) { |
| 176 throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number"); | 219 throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number"); |
| 177 } | 220 } |
| 178 if (upperLimit is! num) { | 221 if (upperLimit is! num) { |
| 179 throw new ArgumentError.value(upperLimit, "upperLimit", "not a number"); | 222 throw new ArgumentError.value(upperLimit, "upperLimit", "not a number"); |
| 180 } | 223 } |
| 181 | 224 |
| 182 // Special case for integers. | 225 // Special case for integers. |
| 183 if (lowerLimit is int && upperLimit is int && lowerLimit <= upperLimit) { | 226 if (lowerLimit is int && upperLimit is int && lowerLimit <= upperLimit) { |
| 184 if (this < lowerLimit) return lowerLimit; | 227 if (this < lowerLimit) return lowerLimit; |
| 185 if (this > upperLimit) return upperLimit; | 228 if (this > upperLimit) return upperLimit; |
| 186 return this; | 229 return this; |
| 187 } | 230 } |
| 188 // Generic case involving doubles, and invalid integer ranges. | 231 // Generic case involving doubles, and invalid integer ranges. |
| 189 if (lowerLimit.compareTo(upperLimit) > 0) { | 232 if (lowerLimit.compareTo(upperLimit) > 0) { |
| 190 throw new ArgumentError(lowerLimit); | 233 throw new ArgumentError(lowerLimit); |
| 191 } | 234 } |
| 192 if (lowerLimit.isNaN) return lowerLimit; | 235 if (lowerLimit.isNaN) return lowerLimit; |
| 193 // Note that we don't need to care for -0.0 for the lower limit. | 236 // Note that we don't need to care for -0.0 for the lower limit. |
| 194 if (this < lowerLimit) return lowerLimit; | 237 if (this < lowerLimit) return lowerLimit; |
| 195 if (this.compareTo(upperLimit) > 0) return upperLimit; | 238 if (this.compareTo(upperLimit) > 0) return upperLimit; |
| 196 return this; | 239 return this; |
| 197 } | 240 } |
| 198 | 241 |
| 199 int toInt() { return this; } | 242 int toInt() { |
| 200 double toDouble() { return new _Double.fromInteger(this); } | 243 return this; |
| 201 _Bigint _toBigint() { return new _Bigint._fromInt(this); } | 244 } |
| 202 num _toBigintOrDouble() { return _toBigint(); } | 245 |
| 246 double toDouble() { |
| 247 return new _Double.fromInteger(this); |
| 248 } |
| 249 |
| 250 _Bigint _toBigint() { |
| 251 return new _Bigint._fromInt(this); |
| 252 } |
| 253 |
| 254 num _toBigintOrDouble() { |
| 255 return _toBigint(); |
| 256 } |
| 203 | 257 |
| 204 String toStringAsFixed(int fractionDigits) { | 258 String toStringAsFixed(int fractionDigits) { |
| 205 return this.toDouble().toStringAsFixed(fractionDigits); | 259 return this.toDouble().toStringAsFixed(fractionDigits); |
| 206 } | 260 } |
| 261 |
| 207 String toStringAsExponential([int fractionDigits]) { | 262 String toStringAsExponential([int fractionDigits]) { |
| 208 return this.toDouble().toStringAsExponential(fractionDigits); | 263 return this.toDouble().toStringAsExponential(fractionDigits); |
| 209 } | 264 } |
| 265 |
| 210 String toStringAsPrecision(int precision) { | 266 String toStringAsPrecision(int precision) { |
| 211 return this.toDouble().toStringAsPrecision(precision); | 267 return this.toDouble().toStringAsPrecision(precision); |
| 212 } | 268 } |
| 213 | 269 |
| 214 static const _digits = "0123456789abcdefghijklmnopqrstuvwxyz"; | 270 static const _digits = "0123456789abcdefghijklmnopqrstuvwxyz"; |
| 215 | 271 |
| 216 String toRadixString(int radix) { | 272 String toRadixString(int radix) { |
| 217 if (radix < 2 || 36 < radix) { | 273 if (radix < 2 || 36 < radix) { |
| 218 throw new RangeError.range(radix, 2, 36, "radix"); | 274 throw new RangeError.range(radix, 2, 36, "radix"); |
| 219 } | 275 } |
| 220 if (radix & (radix - 1) == 0) { | 276 if (radix & (radix - 1) == 0) { |
| 221 return _toPow2String(radix); | 277 return _toPow2String(radix); |
| 222 } | 278 } |
| 223 if (radix == 10) return this.toString(); | 279 if (radix == 10) return this.toString(); |
| 224 final bool isNegative = this < 0; | 280 final bool isNegative = this < 0; |
| 225 int value = isNegative ? -this : this; | 281 int value = isNegative ? -this : this; |
| 226 List temp = new List(); | 282 List temp = new List(); |
| 227 do { | 283 do { |
| 228 int digit = value % radix; | 284 int digit = value % radix; |
| 229 value ~/= radix; | 285 value ~/= radix; |
| 230 temp.add(_digits.codeUnitAt(digit)); | 286 temp.add(_digits.codeUnitAt(digit)); |
| 231 } while (value > 0); | 287 } while (value > 0); |
| 232 if (isNegative) temp.add(0x2d); // '-'. | 288 if (isNegative) temp.add(0x2d); // '-'. |
| 233 | 289 |
| 234 _OneByteString string = _OneByteString._allocate(temp.length); | 290 _OneByteString string = _OneByteString._allocate(temp.length); |
| 235 for (int i = 0, j = temp.length; j > 0; i++) { | 291 for (int i = 0, j = temp.length; j > 0; i++) { |
| 236 string._setAt(i, temp[--j]); | 292 string._setAt(i, temp[--j]); |
| 237 } | 293 } |
| 238 return string; | 294 return string; |
| 239 } | 295 } |
| 240 | 296 |
| 241 String _toPow2String(int radix) { | 297 String _toPow2String(int radix) { |
| 242 int value = this; | 298 int value = this; |
| 243 if (value == 0) return "0"; | 299 if (value == 0) return "0"; |
| 244 assert(radix & (radix - 1) == 0); | 300 assert(radix & (radix - 1) == 0); |
| 245 var negative = value < 0; | 301 var negative = value < 0; |
| 246 var bitsPerDigit = radix.bitLength - 1; | 302 var bitsPerDigit = radix.bitLength - 1; |
| 247 var length = 0; | 303 var length = 0; |
| 248 if (negative) { | 304 if (negative) { |
| 249 value = -value; | 305 value = -value; |
| 250 length = 1; | 306 length = 1; |
| 251 } | 307 } |
| 252 // Integer division, rounding up, to find number of _digits. | 308 // Integer division, rounding up, to find number of _digits. |
| 253 length += (value.bitLength + bitsPerDigit - 1) ~/ bitsPerDigit; | 309 length += (value.bitLength + bitsPerDigit - 1) ~/ bitsPerDigit; |
| 254 _OneByteString string = _OneByteString._allocate(length); | 310 _OneByteString string = _OneByteString._allocate(length); |
| 255 string._setAt(0, 0x2d); // '-'. Is overwritten if not negative. | 311 string._setAt(0, 0x2d); // '-'. Is overwritten if not negative. |
| 256 var mask = radix - 1; | 312 var mask = radix - 1; |
| 257 do { | 313 do { |
| 258 string._setAt(--length, _digits.codeUnitAt(value & mask)); | 314 string._setAt(--length, _digits.codeUnitAt(value & mask)); |
| 259 value >>= bitsPerDigit; | 315 value >>= bitsPerDigit; |
| 260 } while (value > 0); | 316 } while (value > 0); |
| 261 return string; | 317 return string; |
| 262 } | 318 } |
| 263 | 319 |
| 264 // Returns pow(this, e) % m. | 320 // Returns pow(this, e) % m. |
| 265 int modPow(int e, int m) { | 321 int modPow(int e, int m) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 } | 359 } |
| 304 if (y.isOdd) { | 360 if (y.isOdd) { |
| 305 var t = x; | 361 var t = x; |
| 306 x = y; | 362 x = y; |
| 307 y = t; | 363 y = t; |
| 308 } | 364 } |
| 309 } | 365 } |
| 310 final bool ac = x.isEven; | 366 final bool ac = x.isEven; |
| 311 int u = x; | 367 int u = x; |
| 312 int v = y; | 368 int v = y; |
| 313 int a = 1, | 369 int a = 1, b = 0, c = 0, d = 1; |
| 314 b = 0, | |
| 315 c = 0, | |
| 316 d = 1; | |
| 317 do { | 370 do { |
| 318 while (u.isEven) { | 371 while (u.isEven) { |
| 319 u >>= 1; | 372 u >>= 1; |
| 320 if (ac) { | 373 if (ac) { |
| 321 if (!a.isEven || !b.isEven) { | 374 if (!a.isEven || !b.isEven) { |
| 322 a += y; | 375 a += y; |
| 323 b -= x; | 376 b -= x; |
| 324 } | 377 } |
| 325 a >>= 1; | 378 a >>= 1; |
| 326 } else if (!b.isEven) { | 379 } else if (!b.isEven) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 if ((x == 1) || (y == 1)) return 1; | 449 if ((x == 1) || (y == 1)) return 1; |
| 397 if (y is _Bigint) { | 450 if (y is _Bigint) { |
| 398 return x._toBigint().gcd(y); | 451 return x._toBigint().gcd(y); |
| 399 } | 452 } |
| 400 return _binaryGcd(x, y, false); | 453 return _binaryGcd(x, y, false); |
| 401 } | 454 } |
| 402 } | 455 } |
| 403 | 456 |
| 404 class _Smi extends _IntegerImplementation implements int { | 457 class _Smi extends _IntegerImplementation implements int { |
| 405 factory _Smi._uninstantiable() { | 458 factory _Smi._uninstantiable() { |
| 406 throw new UnsupportedError( | 459 throw new UnsupportedError("_Smi can only be allocated by the VM"); |
| 407 "_Smi can only be allocated by the VM"); | |
| 408 } | 460 } |
| 409 int get hashCode => this; | 461 int get hashCode => this; |
| 410 int get _identityHashCode => this; | 462 int get _identityHashCode => this; |
| 411 int operator ~() native "Smi_bitNegate"; | 463 int operator ~() native "Smi_bitNegate"; |
| 412 int get bitLength native "Smi_bitLength"; | 464 int get bitLength native "Smi_bitLength"; |
| 413 | 465 |
| 414 int operator &(int other) => other._bitAndFromSmi(this); | 466 int operator &(int other) => other._bitAndFromSmi(this); |
| 415 | 467 |
| 416 int _bitAndFromSmi(int other) native "Smi_bitAndFromSmi"; | 468 int _bitAndFromSmi(int other) native "Smi_bitAndFromSmi"; |
| 417 int _shrFromInt(int other) native "Smi_shrFromInt"; | 469 int _shrFromInt(int other) native "Smi_shrFromInt"; |
| 418 int _shlFromInt(int other) native "Smi_shlFromInt"; | 470 int _shlFromInt(int other) native "Smi_shlFromInt"; |
| 419 | 471 |
| 420 /** | 472 /** |
| 421 * The digits of '00', '01', ... '99' as a single array. | 473 * The digits of '00', '01', ... '99' as a single array. |
| 422 * | 474 * |
| 423 * Get the digits of `n`, with `0 <= n < 100`, as | 475 * Get the digits of `n`, with `0 <= n < 100`, as |
| 424 * `_digitTable[n * 2]` and `_digitTable[n * 2 + 1]`. | 476 * `_digitTable[n * 2]` and `_digitTable[n * 2 + 1]`. |
| 425 */ | 477 */ |
| 426 static const _digitTable = const [ | 478 static const _digitTable = const [ |
| 427 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, | 479 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, // |
| 428 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, | 480 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, // |
| 429 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31, | 481 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31, // |
| 430 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35, | 482 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35, // |
| 431 0x31, 0x36, 0x31, 0x37, 0x31, 0x38, 0x31, 0x39, | 483 0x31, 0x36, 0x31, 0x37, 0x31, 0x38, 0x31, 0x39, // |
| 432 0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33, | 484 0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33, // |
| 433 0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37, | 485 0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37, // |
| 434 0x32, 0x38, 0x32, 0x39, 0x33, 0x30, 0x33, 0x31, | 486 0x32, 0x38, 0x32, 0x39, 0x33, 0x30, 0x33, 0x31, // |
| 435 0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35, | 487 0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35, // |
| 436 0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39, | 488 0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39, // |
| 437 0x34, 0x30, 0x34, 0x31, 0x34, 0x32, 0x34, 0x33, | 489 0x34, 0x30, 0x34, 0x31, 0x34, 0x32, 0x34, 0x33, // |
| 438 0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37, | 490 0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37, // |
| 439 0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31, | 491 0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31, // |
| 440 0x35, 0x32, 0x35, 0x33, 0x35, 0x34, 0x35, 0x35, | 492 0x35, 0x32, 0x35, 0x33, 0x35, 0x34, 0x35, 0x35, // |
| 441 0x35, 0x36, 0x35, 0x37, 0x35, 0x38, 0x35, 0x39, | 493 0x35, 0x36, 0x35, 0x37, 0x35, 0x38, 0x35, 0x39, // |
| 442 0x36, 0x30, 0x36, 0x31, 0x36, 0x32, 0x36, 0x33, | 494 0x36, 0x30, 0x36, 0x31, 0x36, 0x32, 0x36, 0x33, // |
| 443 0x36, 0x34, 0x36, 0x35, 0x36, 0x36, 0x36, 0x37, | 495 0x36, 0x34, 0x36, 0x35, 0x36, 0x36, 0x36, 0x37, // |
| 444 0x36, 0x38, 0x36, 0x39, 0x37, 0x30, 0x37, 0x31, | 496 0x36, 0x38, 0x36, 0x39, 0x37, 0x30, 0x37, 0x31, // |
| 445 0x37, 0x32, 0x37, 0x33, 0x37, 0x34, 0x37, 0x35, | 497 0x37, 0x32, 0x37, 0x33, 0x37, 0x34, 0x37, 0x35, // |
| 446 0x37, 0x36, 0x37, 0x37, 0x37, 0x38, 0x37, 0x39, | 498 0x37, 0x36, 0x37, 0x37, 0x37, 0x38, 0x37, 0x39, // |
| 447 0x38, 0x30, 0x38, 0x31, 0x38, 0x32, 0x38, 0x33, | 499 0x38, 0x30, 0x38, 0x31, 0x38, 0x32, 0x38, 0x33, // |
| 448 0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37, | 500 0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37, // |
| 449 0x38, 0x38, 0x38, 0x39, 0x39, 0x30, 0x39, 0x31, | 501 0x38, 0x38, 0x38, 0x39, 0x39, 0x30, 0x39, 0x31, // |
| 450 0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35, | 502 0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35, // |
| 451 0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39 | 503 0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39, // |
| 452 ]; | 504 ]; |
| 453 | 505 |
| 454 /** | 506 /** |
| 455 * Result of int.toString for -99, -98, ..., 98, 99. | 507 * Result of int.toString for -99, -98, ..., 98, 99. |
| 456 */ | 508 */ |
| 457 static const _smallLookupTable = const [ | 509 static const _smallLookupTable = const [ |
| 458 "-99", "-98", "-97", "-96", "-95", "-94", "-93", "-92", "-91", "-90", | 510 "-99", "-98", "-97", "-96", "-95", "-94", "-93", "-92", "-91", "-90", // |
| 459 "-89", "-88", "-87", "-86", "-85", "-84", "-83", "-82", "-81", "-80", | 511 "-89", "-88", "-87", "-86", "-85", "-84", "-83", "-82", "-81", "-80", // |
| 460 "-79", "-78", "-77", "-76", "-75", "-74", "-73", "-72", "-71", "-70", | 512 "-79", "-78", "-77", "-76", "-75", "-74", "-73", "-72", "-71", "-70", // |
| 461 "-69", "-68", "-67", "-66", "-65", "-64", "-63", "-62", "-61", "-60", | 513 "-69", "-68", "-67", "-66", "-65", "-64", "-63", "-62", "-61", "-60", // |
| 462 "-59", "-58", "-57", "-56", "-55", "-54", "-53", "-52", "-51", "-50", | 514 "-59", "-58", "-57", "-56", "-55", "-54", "-53", "-52", "-51", "-50", // |
| 463 "-49", "-48", "-47", "-46", "-45", "-44", "-43", "-42", "-41", "-40", | 515 "-49", "-48", "-47", "-46", "-45", "-44", "-43", "-42", "-41", "-40", // |
| 464 "-39", "-38", "-37", "-36", "-35", "-34", "-33", "-32", "-31", "-30", | 516 "-39", "-38", "-37", "-36", "-35", "-34", "-33", "-32", "-31", "-30", // |
| 465 "-29", "-28", "-27", "-26", "-25", "-24", "-23", "-22", "-21", "-20", | 517 "-29", "-28", "-27", "-26", "-25", "-24", "-23", "-22", "-21", "-20", // |
| 466 "-19", "-18", "-17", "-16", "-15", "-14", "-13", "-12", "-11", "-10", | 518 "-19", "-18", "-17", "-16", "-15", "-14", "-13", "-12", "-11", "-10", // |
| 467 "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", | 519 "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", // |
| 468 "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", | 520 "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", // |
| 469 "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", | 521 "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", // |
| 470 "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", | 522 "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", // |
| 471 "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", | 523 "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", // |
| 472 "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", | 524 "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", // |
| 473 "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", | 525 "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", // |
| 474 "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", | 526 "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", // |
| 475 "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", | 527 "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", // |
| 476 "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", | 528 "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", // |
| 477 "91", "92", "93", "94", "95", "96", "97", "98", "99" | 529 "91", "92", "93", "94", "95", "96", "97", "98", "99" // |
| 478 ]; | 530 ]; |
| 479 | 531 |
| 480 // Powers of 10 above 1000000 are indistinguishable by eye. | 532 // Powers of 10 above 1000000 are indistinguishable by eye. |
| 481 static const int _POW_10_7 = 10000000; | 533 static const int _POW_10_7 = 10000000; |
| 482 static const int _POW_10_8 = 100000000; | 534 static const int _POW_10_8 = 100000000; |
| 483 static const int _POW_10_9 = 1000000000; | 535 static const int _POW_10_9 = 1000000000; |
| 484 | 536 |
| 485 // Find the number of decimal digits in a positive smi. | 537 // Find the number of decimal digits in a positive smi. |
| 486 // Never called with numbers < 100. These are handled before calling. | 538 // Never called with numbers < 100. These are handled before calling. |
| 487 static int _positiveBase10Length(var smi) { | 539 static int _positiveBase10Length(var smi) { |
| 488 // A positive smi has length <= 19 if 63-bit, <=10 if 31-bit. | 540 // A positive smi has length <= 19 if 63-bit, <=10 if 31-bit. |
| 489 // Avoid comparing a 31-bit smi to a non-smi. | 541 // Avoid comparing a 31-bit smi to a non-smi. |
| 490 if (smi < 1000) return 3; | 542 if (smi < 1000) return 3; |
| 491 if (smi < 10000) return 4; | 543 if (smi < 10000) return 4; |
| 492 if (smi < _POW_10_7) { | 544 if (smi < _POW_10_7) { |
| 493 if (smi < 100000) return 5; | 545 if (smi < 100000) return 5; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 | 610 |
| 559 // Convert a negative smi to a string. | 611 // Convert a negative smi to a string. |
| 560 // Doesn't negate the smi to avoid negating the most negative smi, which | 612 // Doesn't negate the smi to avoid negating the most negative smi, which |
| 561 // would become a non-smi. | 613 // would become a non-smi. |
| 562 static String _negativeToString(int negSmi) { | 614 static String _negativeToString(int negSmi) { |
| 563 // Character code for '-' | 615 // Character code for '-' |
| 564 const int MINUS_SIGN = 0x2d; | 616 const int MINUS_SIGN = 0x2d; |
| 565 // Character code for '0'. | 617 // Character code for '0'. |
| 566 const int DIGIT_ZERO = 0x30; | 618 const int DIGIT_ZERO = 0x30; |
| 567 if (negSmi > -10) { | 619 if (negSmi > -10) { |
| 568 return _OneByteString._allocate(2).._setAt(0, MINUS_SIGN) | 620 return _OneByteString._allocate(2) |
| 569 .._setAt(1, DIGIT_ZERO - negSmi); | 621 .._setAt(0, MINUS_SIGN) |
| 622 .._setAt(1, DIGIT_ZERO - negSmi); |
| 570 } | 623 } |
| 571 if (negSmi > -100) { | 624 if (negSmi > -100) { |
| 572 int digitIndex = 2 * -negSmi; | 625 int digitIndex = 2 * -negSmi; |
| 573 return _OneByteString._allocate(3) | 626 return _OneByteString._allocate(3) |
| 574 .._setAt(0, MINUS_SIGN) | 627 .._setAt(0, MINUS_SIGN) |
| 575 .._setAt(1, _digitTable[digitIndex]) | 628 .._setAt(1, _digitTable[digitIndex]) |
| 576 .._setAt(2, _digitTable[digitIndex + 1]); | 629 .._setAt(2, _digitTable[digitIndex + 1]); |
| 577 } | 630 } |
| 578 // Number of digits, not including minus. | 631 // Number of digits, not including minus. |
| 579 int digitCount = _negativeBase10Length(negSmi); | 632 int digitCount = _negativeBase10Length(negSmi); |
| 580 _OneByteString result = _OneByteString._allocate(digitCount + 1); | 633 _OneByteString result = _OneByteString._allocate(digitCount + 1); |
| 581 result._setAt(0, MINUS_SIGN); // '-'. | 634 result._setAt(0, MINUS_SIGN); // '-'. |
| 582 int index = digitCount; | 635 int index = digitCount; |
| 583 do { | 636 do { |
| 584 var twoDigits = negSmi.remainder(100); | 637 var twoDigits = negSmi.remainder(100); |
| 585 negSmi = negSmi ~/ 100; | 638 negSmi = negSmi ~/ 100; |
| 586 int digitIndex = -twoDigits * 2; | 639 int digitIndex = -twoDigits * 2; |
| 587 result._setAt(index, _digitTable[digitIndex + 1]); | 640 result._setAt(index, _digitTable[digitIndex + 1]); |
| 588 result._setAt(index - 1, _digitTable[digitIndex]); | 641 result._setAt(index - 1, _digitTable[digitIndex]); |
| 589 index -= 2; | 642 index -= 2; |
| 590 } while (negSmi <= -100); | 643 } while (negSmi <= -100); |
| 591 if (negSmi > -10) { | 644 if (negSmi > -10) { |
| 592 result._setAt(index, DIGIT_ZERO - negSmi); | 645 result._setAt(index, DIGIT_ZERO - negSmi); |
| 593 } else { | 646 } else { |
| 594 // No remainder necessary for this case. | 647 // No remainder necessary for this case. |
| 595 int digitIndex = -negSmi * 2; | 648 int digitIndex = -negSmi * 2; |
| 596 result._setAt(index, _digitTable[digitIndex + 1]); | 649 result._setAt(index, _digitTable[digitIndex + 1]); |
| 597 result._setAt(index - 1, _digitTable[digitIndex]); | 650 result._setAt(index - 1, _digitTable[digitIndex]); |
| 598 } | 651 } |
| 599 return result; | 652 return result; |
| 600 } | 653 } |
| 601 } | 654 } |
| 602 | 655 |
| 603 // Represents integers that cannot be represented by Smi but fit into 64bits. | 656 // Represents integers that cannot be represented by Smi but fit into 64bits. |
| 604 class _Mint extends _IntegerImplementation implements int { | 657 class _Mint extends _IntegerImplementation implements int { |
| 605 factory _Mint._uninstantiable() { | 658 factory _Mint._uninstantiable() { |
| 606 throw new UnsupportedError( | 659 throw new UnsupportedError("_Mint can only be allocated by the VM"); |
| 607 "_Mint can only be allocated by the VM"); | |
| 608 } | 660 } |
| 609 int get hashCode => this; | 661 int get hashCode => this; |
| 610 int get _identityHashCode => this; | 662 int get _identityHashCode => this; |
| 611 int operator ~() native "Mint_bitNegate"; | 663 int operator ~() native "Mint_bitNegate"; |
| 612 int get bitLength native "Mint_bitLength"; | 664 int get bitLength native "Mint_bitLength"; |
| 613 | 665 |
| 614 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); | 666 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); |
| 615 | 667 |
| 616 // Shift by mint exceeds range that can be handled by the VM. | 668 // Shift by mint exceeds range that can be handled by the VM. |
| 617 int _shrFromInt(int other) { | 669 int _shrFromInt(int other) { |
| 618 if (other < 0) { | 670 if (other < 0) { |
| 619 return -1; | 671 return -1; |
| 620 } else { | 672 } else { |
| 621 return 0; | 673 return 0; |
| 622 } | 674 } |
| 623 } | 675 } |
| 676 |
| 624 int _shlFromInt(int other) native "Mint_shlFromInt"; | 677 int _shlFromInt(int other) native "Mint_shlFromInt"; |
| 625 } | 678 } |
| OLD | NEW |