| 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/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/zone.h" | 10 #include "vm/zone.h" |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 const Bigint& bigint, uword (*allocator)(intptr_t size)) { | 322 const Bigint& bigint, uword (*allocator)(intptr_t size)) { |
| 323 // log10(2) ~= 0.30102999566398114. | 323 // log10(2) ~= 0.30102999566398114. |
| 324 const intptr_t kLog2Dividend = 30103; | 324 const intptr_t kLog2Dividend = 30103; |
| 325 const intptr_t kLog2Divisor = 100000; | 325 const intptr_t kLog2Divisor = 100000; |
| 326 // We remove a small constant for rounding imprecision, the \0 character and | 326 // We remove a small constant for rounding imprecision, the \0 character and |
| 327 // the negative sign. | 327 // the negative sign. |
| 328 const intptr_t kMaxAllowedDigitLength = | 328 const intptr_t kMaxAllowedDigitLength = |
| 329 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; | 329 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; |
| 330 | 330 |
| 331 intptr_t length = bigint.Length(); | 331 intptr_t length = bigint.Length(); |
| 332 Isolate* isolate = Isolate::Current(); |
| 332 if (length >= kMaxAllowedDigitLength) { | 333 if (length >= kMaxAllowedDigitLength) { |
| 333 // Use the preallocated out of memory exception to avoid calling | 334 // Use the preallocated out of memory exception to avoid calling |
| 334 // into dart code or allocating any code. | 335 // into dart code or allocating any code. |
| 335 Isolate* isolate = Isolate::Current(); | |
| 336 const Instance& exception = | 336 const Instance& exception = |
| 337 Instance::Handle(isolate->object_store()->out_of_memory()); | 337 Instance::Handle(isolate->object_store()->out_of_memory()); |
| 338 Exceptions::Throw(exception); | 338 Exceptions::Throw(exception); |
| 339 UNREACHABLE(); | 339 UNREACHABLE(); |
| 340 } | 340 } |
| 341 | 341 |
| 342 // Approximate the size of the resulting string. We prefer overestimating | 342 // Approximate the size of the resulting string. We prefer overestimating |
| 343 // to not allocating enough. | 343 // to not allocating enough. |
| 344 int64_t bit_length = length * kDigitBitSize; | 344 int64_t bit_length = length * kDigitBitSize; |
| 345 ASSERT(bit_length > length); | 345 ASSERT(bit_length > length); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 363 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor); | 363 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor); |
| 364 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue); | 364 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue); |
| 365 ASSERT(Smi::IsValid(kChunkDivisor)); | 365 ASSERT(Smi::IsValid(kChunkDivisor)); |
| 366 const Bigint& divisor = Bigint::Handle(NewFromInt64(kChunkDivisor)); | 366 const Bigint& divisor = Bigint::Handle(NewFromInt64(kChunkDivisor)); |
| 367 | 367 |
| 368 // Rest contains the remaining bigint that needs to be printed. | 368 // Rest contains the remaining bigint that needs to be printed. |
| 369 Bigint& rest = Bigint::Handle(bigint.raw()); | 369 Bigint& rest = Bigint::Handle(bigint.raw()); |
| 370 Bigint& quotient = Bigint::Handle(); | 370 Bigint& quotient = Bigint::Handle(); |
| 371 Bigint& remainder = Bigint::Handle(); | 371 Bigint& remainder = Bigint::Handle(); |
| 372 while (!rest.IsZero()) { | 372 while (!rest.IsZero()) { |
| 373 HANDLESCOPE(isolate); |
| 373 DivideRemainder(rest, divisor, "ient, &remainder); | 374 DivideRemainder(rest, divisor, "ient, &remainder); |
| 374 ASSERT(remainder.Length() <= 1); | 375 ASSERT(remainder.Length() <= 1); |
| 375 intptr_t part = (remainder.Length() == 1) | 376 intptr_t part = (remainder.Length() == 1) |
| 376 ? static_cast<intptr_t>(remainder.GetChunkAt(0)) | 377 ? static_cast<intptr_t>(remainder.GetChunkAt(0)) |
| 377 : 0; | 378 : 0; |
| 378 for (int i = 0; i < kChunkDigits; i++) { | 379 for (int i = 0; i < kChunkDigits; i++) { |
| 379 result[result_pos++] = '0' + (part % 10); | 380 result[result_pos++] = '0' + (part % 10); |
| 380 part /= 10; | 381 part /= 10; |
| 381 } | 382 } |
| 382 ASSERT(part == 0); | 383 ASSERT(part == 0); |
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 intptr_t quotient_pos = dividend_length - divisor_length; | 1531 intptr_t quotient_pos = dividend_length - divisor_length; |
| 1531 // Find the first quotient-digit. | 1532 // Find the first quotient-digit. |
| 1532 // The first digit must be computed separately from the other digits because | 1533 // The first digit must be computed separately from the other digits because |
| 1533 // the preconditions for the loop are not yet satisfied. | 1534 // the preconditions for the loop are not yet satisfied. |
| 1534 // For simplicity use a shifted divisor, so that the comparison and | 1535 // For simplicity use a shifted divisor, so that the comparison and |
| 1535 // subtraction are easier. | 1536 // subtraction are easier. |
| 1536 int divisor_shift_amount = dividend_length - divisor_length; | 1537 int divisor_shift_amount = dividend_length - divisor_length; |
| 1537 Bigint& shifted_divisor = | 1538 Bigint& shifted_divisor = |
| 1538 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount)); | 1539 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount)); |
| 1539 Chunk first_quotient_digit = 0; | 1540 Chunk first_quotient_digit = 0; |
| 1541 Isolate* isolate = Isolate::Current(); |
| 1540 while (UnsignedCompare(dividend, shifted_divisor) >= 0) { | 1542 while (UnsignedCompare(dividend, shifted_divisor) >= 0) { |
| 1543 HANDLESCOPE(isolate); |
| 1541 first_quotient_digit++; | 1544 first_quotient_digit++; |
| 1542 dividend = Subtract(dividend, shifted_divisor); | 1545 dividend = Subtract(dividend, shifted_divisor); |
| 1543 } | 1546 } |
| 1544 quotient->SetChunkAt(quotient_pos--, first_quotient_digit); | 1547 quotient->SetChunkAt(quotient_pos--, first_quotient_digit); |
| 1545 | 1548 |
| 1546 // Find the remainder of the digits. | 1549 // Find the remainder of the digits. |
| 1547 | 1550 |
| 1548 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1); | 1551 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1); |
| 1549 // The short divisor only represents the first two digits of the divisor. | 1552 // The short divisor only represents the first two digits of the divisor. |
| 1550 // If the divisor has only one digit, then the second part is zeroed out. | 1553 // If the divisor has only one digit, then the second part is zeroed out. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 int BigintOperations::CountBits(Chunk digit) { | 1668 int BigintOperations::CountBits(Chunk digit) { |
| 1666 int result = 0; | 1669 int result = 0; |
| 1667 while (digit != 0) { | 1670 while (digit != 0) { |
| 1668 digit >>= 1; | 1671 digit >>= 1; |
| 1669 result++; | 1672 result++; |
| 1670 } | 1673 } |
| 1671 return result; | 1674 return result; |
| 1672 } | 1675 } |
| 1673 | 1676 |
| 1674 } // namespace dart | 1677 } // namespace dart |
| OLD | NEW |