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 |