Chromium Code Reviews| 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 // TODO(srdjan): fix limitations. | 5 // TODO(srdjan): fix limitations. |
| 6 // - shift amount must be a Smi. | 6 // - shift amount must be a Smi. |
| 7 class _IntegerImplementation { | 7 class _IntegerImplementation { |
| 8 factory _IntegerImplementation._uninstantiable() { | 8 factory _IntegerImplementation._uninstantiable() { |
| 9 throw new UnsupportedError( | 9 throw new UnsupportedError( |
| 10 "_IntegerImplementation can only be allocated by the VM"); | 10 "_IntegerImplementation can only be allocated by the VM"); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 } | 253 } |
| 254 int get _identityHashCode { | 254 int get _identityHashCode { |
| 255 return this; | 255 return this; |
| 256 } | 256 } |
| 257 int operator ~() native "Smi_bitNegate"; | 257 int operator ~() native "Smi_bitNegate"; |
| 258 int get bitLength native "Smi_bitLength"; | 258 int get bitLength native "Smi_bitLength"; |
| 259 | 259 |
| 260 int _shrFromInt(int other) native "Smi_shrFromInt"; | 260 int _shrFromInt(int other) native "Smi_shrFromInt"; |
| 261 int _shlFromInt(int other) native "Smi_shlFromInt"; | 261 int _shlFromInt(int other) native "Smi_shlFromInt"; |
| 262 | 262 |
| 263 static const digits = const [ | |
|
Anders Johnsen
2014/03/05 14:41:33
better name?
Also, all of this new stuff should b
Lasse Reichstein Nielsen
2014/03/06 12:25:37
-> digitTable.
No *need* for private, it's all st
srdjan
2014/03/06 17:57:14
All public members of a private class are accessib
Lasse Reichstein Nielsen
2014/03/07 09:29:20
Private members are also accessible with the same
| |
| 264 0x30,0x30,0x30,0x31,0x30,0x32,0x30,0x33, | |
| 265 0x30,0x34,0x30,0x35,0x30,0x36,0x30,0x37, | |
| 266 0x30,0x38,0x30,0x39,0x31,0x30,0x31,0x31, | |
| 267 0x31,0x32,0x31,0x33,0x31,0x34,0x31,0x35, | |
| 268 0x31,0x36,0x31,0x37,0x31,0x38,0x31,0x39, | |
| 269 0x32,0x30,0x32,0x31,0x32,0x32,0x32,0x33, | |
| 270 0x32,0x34,0x32,0x35,0x32,0x36,0x32,0x37, | |
| 271 0x32,0x38,0x32,0x39,0x33,0x30,0x33,0x31, | |
| 272 0x33,0x32,0x33,0x33,0x33,0x34,0x33,0x35, | |
| 273 0x33,0x36,0x33,0x37,0x33,0x38,0x33,0x39, | |
| 274 0x34,0x30,0x34,0x31,0x34,0x32,0x34,0x33, | |
| 275 0x34,0x34,0x34,0x35,0x34,0x36,0x34,0x37, | |
| 276 0x34,0x38,0x34,0x39,0x35,0x30,0x35,0x31, | |
| 277 0x35,0x32,0x35,0x33,0x35,0x34,0x35,0x35, | |
| 278 0x35,0x36,0x35,0x37,0x35,0x38,0x35,0x39, | |
| 279 0x36,0x30,0x36,0x31,0x36,0x32,0x36,0x33, | |
| 280 0x36,0x34,0x36,0x35,0x36,0x36,0x36,0x37, | |
| 281 0x36,0x38,0x36,0x39,0x37,0x30,0x37,0x31, | |
| 282 0x37,0x32,0x37,0x33,0x37,0x34,0x37,0x35, | |
| 283 0x37,0x36,0x37,0x37,0x37,0x38,0x37,0x39, | |
| 284 0x38,0x30,0x38,0x31,0x38,0x32,0x38,0x33, | |
| 285 0x38,0x34,0x38,0x35,0x38,0x36,0x38,0x37, | |
| 286 0x38,0x38,0x38,0x39,0x39,0x30,0x39,0x31, | |
| 287 0x39,0x32,0x39,0x33,0x39,0x34,0x39,0x35, | |
| 288 0x39,0x36,0x39,0x37,0x39,0x38,0x39,0x39 | |
| 289 ]; | |
| 290 | |
| 291 static const int P01 = 10; | |
| 292 static const int P02 = 100; | |
| 293 static const int P03 = 1000; | |
| 294 static const int P04 = 10000; | |
| 295 static const int P05 = 100000; | |
| 296 static const int P06 = 1000000; | |
| 297 static const int P07 = 10000000; | |
| 298 static const int P08 = 100000000; | |
| 299 static const int P09 = 1000000000; | |
| 300 static const int P10 = 10000000000; | |
| 301 | |
| 302 // Find the number of decimal digits in a positive smi. | |
| 303 static int positiveBase10Length(var smi) { | |
| 304 // A positive smi has length <= 19 if 63-bit, <=10 if 31-bit. | |
| 305 // Avoid comparing a 31-bit smi to a non-smi. | |
| 306 if (smi < P03) return 3; | |
| 307 if (smi < P04) return 4; | |
| 308 if (smi < P07) { | |
| 309 if (smi < P05) return 5; | |
| 310 if (smi < P06) return 6; | |
| 311 return 7; | |
| 312 } | |
| 313 if (smi < P10) { | |
| 314 if (smi < P08) return 8; | |
| 315 if (smi < P09) return 9; | |
| 316 return 10; | |
| 317 } | |
| 318 smi = smi ~/ P10; | |
| 319 if (smi < P01) return 11; | |
| 320 if (smi < P02) return 12; | |
| 321 return 10 + positiveBase10Length(smi); | |
| 322 } | |
| 323 | |
| 263 String toString() { | 324 String toString() { |
| 264 if (this == 0) return "0"; | 325 if (this == 0) return "0"; |
| 265 var reversed = _toStringBuffer; | 326 if (this < 0) return negativeToString(this); |
| 266 var negative = false; | 327 // Inspired by Andrei Alexandrescu: "Three Optimization Tips for C++" |
| 267 var val = this; | 328 // Avoid expensive remainder operation by doing it on more than |
| 268 int index = 0; | 329 // one digit at a time. |
| 330 int length = this < 10 ? 1 : this < 100 ? 2 : positiveBase10Length(this); | |
|
srdjan
2014/03/05 17:40:46
Please use parentheses.
Lasse Reichstein Nielsen
2014/03/06 12:25:37
Rewritten.
| |
| 331 _OneByteString result = _OneByteString._allocate(length); | |
| 332 int index = length - 1; | |
| 333 var smi = this; | |
| 334 while (smi >= 100) { | |
| 335 // Two digits at a time. | |
| 336 var twoDigits = smi.remainder(100); | |
| 337 smi = smi ~/ 100; | |
| 338 int digitIndex = twoDigits * 2; | |
| 339 result._setAt(index, digits[digitIndex + 1]); | |
| 340 result._setAt(index - 1, digits[digitIndex]); | |
| 341 index -= 2; | |
| 342 } | |
| 343 if (smi >= 10) { | |
| 344 // No remainder for this case. | |
| 345 int digitIndex = smi * 2; | |
| 346 result._setAt(index, digits[digitIndex + 1]); | |
| 347 result._setAt(index - 1, digits[digitIndex]); | |
| 348 } else { | |
| 349 result._setAt(index, 0x30 + smi); | |
| 350 } | |
| 351 return result; | |
| 352 } | |
| 269 | 353 |
| 270 if (this < 0) { | 354 // Find the number of decimal digits in a negative smi. |
| 271 negative = true; | 355 static int negativeBase10Length(var negSmi) { |
| 272 // Handle the first digit as negative to avoid negating the minimum | 356 // A negative smi has length <= 19 if 63-bit, <=10 if 31-bit. |
| 273 // smi, for which the negation is not a smi. | 357 // Avoid comparing a 31-bit smi to a non-smi. |
| 274 int digit = -(val.remainder(10)); | 358 if (negSmi > -P03) return 3; |
| 275 reversed[index++] = digit + 0x30; | 359 if (negSmi > -P04) return 4; |
| 276 val = -(val ~/ 10); | 360 if (negSmi > -P07) { |
| 361 if (negSmi > -P05) return 5; | |
| 362 if (negSmi > -P06) return 6; | |
| 363 return 7; | |
| 277 } | 364 } |
| 365 if (negSmi > -P10) { | |
| 366 if (negSmi > -P08) return 8; | |
| 367 if (negSmi > -P09) return 9; | |
| 368 return 10; | |
| 369 } | |
| 370 negSmi = negSmi ~/ P10; | |
| 371 if (negSmi > -P01) return 11; | |
| 372 if (negSmi > -P02) return 12; | |
| 373 return 10 + negativeBase10Length(negSmi); | |
| 374 } | |
| 278 | 375 |
| 279 while (val > 0) { | 376 // Convert a negative smi to a string. |
| 280 int digit = val % 10; | 377 // Doesn't negate the smi to avoid negating the most negative smi, which |
| 281 val = val ~/ 10; | 378 // would become a non-smi. |
| 282 reversed[index++] = (digit + 0x30); | 379 static String negativeToString(int negSmi) { |
| 380 // Number of digits, not including minus. | |
| 381 int digitCount = | |
| 382 (negSmi > -10) ? 1 : (negSmi > -100) ? 2 : negativeBase10Length(negSmi); | |
| 383 _OneByteString result = _OneByteString._allocate(digitCount + 1); | |
| 384 result._setAt(0, 0x2D); // '-'. | |
| 385 int index = digitCount; | |
| 386 while (negSmi <= -100) { | |
| 387 var twoDigits = negSmi.remainder(100); | |
| 388 negSmi = negSmi ~/ 100; | |
| 389 int digitIndex = -twoDigits * 2; | |
| 390 result._setAt(index, digits[digitIndex + 1]); | |
| 391 result._setAt(index - 1, digits[digitIndex]); | |
| 392 index -= 2; | |
| 283 } | 393 } |
| 284 if (negative) reversed[index++] = 0x2D; // '-'. | 394 if (negSmi <= -10) { |
| 285 | 395 // No remainder necessary for this case. |
| 286 _OneByteString string = _OneByteString._allocate(index); | 396 int digitIndex = -negSmi * 2; |
| 287 for (int i = 0, j = index; i < index; i++) { | 397 result._setAt(index, digits[digitIndex + 1]); |
| 288 string._setAt(i, reversed[--j]); | 398 result._setAt(index - 1, digits[digitIndex]); |
| 399 } else { | |
| 400 result._setAt(index, 0x30 - negSmi); | |
| 289 } | 401 } |
| 290 return string; | 402 return result; |
| 291 } | 403 } |
| 292 } | 404 } |
| 293 | 405 |
| 294 // Reusable buffer used by smi.toString. | |
| 295 final List _toStringBuffer = new Uint8List(20); | |
| 296 | |
| 297 // Represents integers that cannot be represented by Smi but fit into 64bits. | 406 // Represents integers that cannot be represented by Smi but fit into 64bits. |
| 298 class _Mint extends _IntegerImplementation implements int { | 407 class _Mint extends _IntegerImplementation implements int { |
| 299 factory _Mint._uninstantiable() { | 408 factory _Mint._uninstantiable() { |
| 300 throw new UnsupportedError( | 409 throw new UnsupportedError( |
| 301 "_Mint can only be allocated by the VM"); | 410 "_Mint can only be allocated by the VM"); |
| 302 } | 411 } |
| 303 int get _identityHashCode { | 412 int get _identityHashCode { |
| 304 return this; | 413 return this; |
| 305 } | 414 } |
| 306 int operator ~() native "Mint_bitNegate"; | 415 int operator ~() native "Mint_bitNegate"; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 337 } else { | 446 } else { |
| 338 return 0; | 447 return 0; |
| 339 } | 448 } |
| 340 } | 449 } |
| 341 int _shlFromInt(int other) native "Bigint_shlFromInt"; | 450 int _shlFromInt(int other) native "Bigint_shlFromInt"; |
| 342 | 451 |
| 343 int pow(int exponent) { | 452 int pow(int exponent) { |
| 344 throw "Bigint.pow not implemented"; | 453 throw "Bigint.pow not implemented"; |
| 345 } | 454 } |
| 346 } | 455 } |
| OLD | NEW |