Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 | 2 |
| 3 #include "vm/bigint_operations.h" | 3 #include "vm/bigint_operations.h" |
| 4 | 4 |
| 5 #include "platform/utils.h" | 5 #include "platform/utils.h" |
| 6 | 6 |
| 7 #include "vm/double_internals.h" | 7 #include "vm/double_internals.h" |
| 8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
| 9 #include "vm/zone.h" | 9 #include "vm/zone.h" |
| 10 | 10 |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 NoGCScope no_gc; | 329 NoGCScope no_gc; |
| 330 | 330 |
| 331 intptr_t length = bigint.Length(); | 331 intptr_t length = bigint.Length(); |
| 332 return ToHexCString(length, | 332 return ToHexCString(length, |
| 333 bigint.IsNegative(), | 333 bigint.IsNegative(), |
| 334 length ? bigint.ChunkAddr(0) : NULL, | 334 length ? bigint.ChunkAddr(0) : NULL, |
| 335 allocator); | 335 allocator); |
| 336 } | 336 } |
| 337 | 337 |
| 338 | 338 |
| 339 const char* BigintOperations::ToDecimalCString( | |
| 340 const Bigint& bigint, uword (*allocator)(intptr_t size)) { | |
| 341 intptr_t length = bigint.Length(); | |
| 342 // We guard against overflows by using 64 bit computations. | |
|
siva
2012/03/02 19:31:45
On 64 bit machines the signed_length is actually a
floitsch
2012/03/05 14:28:17
Refactored.
| |
| 343 int64_t bit_length = length * kDigitBitSize; | |
| 344 // Approximate the size of the resulting string. We prefer overestimating | |
| 345 // to not allocating enough. | |
| 346 // log10(2) ~= 0.30102999566398114. | |
| 347 int64_t decimal_length = (bit_length * 30103 / 100000) + 1; | |
| 348 // Add one byte for the trailing \0 character. | |
| 349 int64_t required_size = decimal_length + 1; | |
| 350 if (bigint.IsNegative()) { | |
| 351 required_size++; | |
| 352 } | |
| 353 // TODO(floitsch): what to do if we had an overflow? | |
| 354 if (required_size != static_cast<intptr_t>(required_size)) { | |
|
siva
2012/03/02 19:31:45
I think we should assert here instead of silently
floitsch
2012/03/05 14:28:17
That's why there was a TODO. Now throwing an OOM-e
| |
| 355 return ""; | |
| 356 } | |
| 357 // We will fill the result in the inverse order and then exchange at the end. | |
| 358 char* result = | |
| 359 reinterpret_cast<char*>(allocator(static_cast<intptr_t>(required_size))); | |
|
siva
2012/03/02 19:31:45
ASSERT(result != NULL);
floitsch
2012/03/05 14:28:17
Done.
| |
| 360 int result_pos = 0; | |
| 361 | |
| 362 // We divide the input into pieces of ~27 bits which can be efficiently | |
| 363 // handled. | |
| 364 const intptr_t kDivisorValue = 100000000; | |
| 365 const int kPowerOfTen = 8; | |
| 366 ASSERT(pow(10, kPowerOfTen) == kDivisorValue); | |
| 367 ASSERT(static_cast<Chunk>(kDivisorValue) < kDigitMaxValue); | |
| 368 ASSERT(Smi::IsValid(kDivisorValue)); | |
| 369 const Smi& divisor_smi = Smi::Handle(Smi::New(kDivisorValue)); | |
| 370 const Bigint& divisor = Bigint::Handle(NewFromSmi(divisor_smi)); | |
| 371 | |
| 372 // Rest contains the remaining bigint that needs to be printed. | |
| 373 Bigint& rest = Bigint::Handle(bigint.raw()); | |
| 374 Bigint& quotient = Bigint::Handle(); | |
| 375 Bigint& remainder = Bigint::Handle(); | |
| 376 while (!rest.IsZero()) { | |
| 377 DivideRemainder(rest, divisor, "ient, &remainder); | |
| 378 ASSERT(remainder.Length() == 1); | |
| 379 intptr_t part = static_cast<intptr_t>(remainder.GetChunkAt(0)); | |
| 380 for (int i = 0; i < kPowerOfTen; i++) { | |
| 381 result[result_pos++] = '0' + part % 10; | |
|
siva
2012/03/02 19:31:45
'0' + (part % 10);
to make it clear for operator p
floitsch
2012/03/05 14:28:17
Done.
| |
| 382 part /= 10; | |
| 383 } | |
| 384 ASSERT(part == 0); | |
| 385 rest = quotient.raw(); | |
| 386 } | |
| 387 // Move the resulting position back until we don't have any zeroes anymore. | |
|
siva
2012/03/02 19:31:45
// This is done so that we can remove all leading
floitsch
2012/03/05 14:28:17
Done.
| |
| 388 while (result_pos > 1 && result[result_pos - 1] == '0') { | |
| 389 result_pos--; | |
| 390 } | |
| 391 if (bigint.IsNegative()) { | |
| 392 result[result_pos++] = '-'; | |
| 393 } | |
| 394 // Reverse the string. | |
| 395 int i = 0; | |
| 396 int j = result_pos - 1; | |
| 397 while (i < j) { | |
| 398 char tmp = result[i]; | |
| 399 result[i] = result[j]; | |
| 400 result[j] = tmp; | |
| 401 i++; | |
| 402 j--; | |
| 403 } | |
|
siva
2012/03/02 19:31:45
ASSERt(result_pos >= 0);
floitsch
2012/03/05 14:28:17
Done.
| |
| 404 result[result_pos] = '\0'; | |
| 405 return result; | |
| 406 } | |
| 407 | |
| 408 | |
| 339 bool BigintOperations::FitsIntoSmi(const Bigint& bigint) { | 409 bool BigintOperations::FitsIntoSmi(const Bigint& bigint) { |
| 340 intptr_t bigint_length = bigint.Length(); | 410 intptr_t bigint_length = bigint.Length(); |
| 341 if (bigint_length == 0) { | 411 if (bigint_length == 0) { |
| 342 return true; | 412 return true; |
| 343 } | 413 } |
| 344 if ((bigint_length == 1) && | 414 if ((bigint_length == 1) && |
| 345 (static_cast<size_t>(kDigitBitSize) < | 415 (static_cast<size_t>(kDigitBitSize) < |
| 346 (sizeof(intptr_t) * kBitsPerByte))) { | 416 (sizeof(intptr_t) * kBitsPerByte))) { |
| 347 return true; | 417 return true; |
| 348 } | 418 } |
| (...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1415 int BigintOperations::CountBits(Chunk digit) { | 1485 int BigintOperations::CountBits(Chunk digit) { |
| 1416 int result = 0; | 1486 int result = 0; |
| 1417 while (digit != 0) { | 1487 while (digit != 0) { |
| 1418 digit >>= 1; | 1488 digit >>= 1; |
| 1419 result++; | 1489 result++; |
| 1420 } | 1490 } |
| 1421 return result; | 1491 return result; |
| 1422 } | 1492 } |
| 1423 | 1493 |
| 1424 } // namespace dart | 1494 } // namespace dart |
| OLD | NEW |