| 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 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 } | 714 } |
| 715 | 715 |
| 716 // Comba multiplication: compute each column separately. | 716 // Comba multiplication: compute each column separately. |
| 717 // Example: r = a2a1a0 * b2b1b0. | 717 // Example: r = a2a1a0 * b2b1b0. |
| 718 // r = 1 * a0b0 + | 718 // r = 1 * a0b0 + |
| 719 // 10 * (a1b0 + a0b1) + | 719 // 10 * (a1b0 + a0b1) + |
| 720 // 100 * (a2b0 + a1b1 + a0b2) + | 720 // 100 * (a2b0 + a1b1 + a0b2) + |
| 721 // 1000 * (a2b1 + a1b2) + | 721 // 1000 * (a2b1 + a1b2) + |
| 722 // 10000 * a2b2 | 722 // 10000 * a2b2 |
| 723 // | 723 // |
| 724 // Each column will be accumulated in an integer of type DoubleChunk. We | 724 // Each column will be accumulated in an integer of type DoubleChunk. We must |
| 725 // must guarantee that the column-sum will not overflow. | 725 // guarantee that the column-sum will not overflow. We achieve this by |
| 726 // 'blocking' the sum into overflow-free sums followed by propagating the |
| 727 // overflow. |
| 726 // | 728 // |
| 727 // In the worst case we have to accumulate k = Min(a.length, b.length) | 729 // Each bigint digit fits in kDigitBitSize bits. |
| 728 // products plus the carry from the previous round. | 730 // Each product fits in 2*kDigitBitSize bits. |
| 729 // Each bigint-digit is smaller than beta = 2^kDigitBitSize. | 731 // The accumulator is 8 * sizeof(DoubleChunk) == 2*kDigitBitSize + kCarryBits. |
| 730 // Each product is at most (beta - 1)^2. | 732 // |
| 731 // If we want to use Comba multiplication the following condition must hold: | 733 // Each time we add a product to the accumulator it could carry one bit into |
| 732 // k * (beta - 1)^2 + (2^(kDoubleChunkBitSize - kDigitBitSize) - 1) < | 734 // the carry bits, supporting kBlockSize = 2^kCarryBits - 1 addition |
| 733 // 2^kDoubleChunkBitSize. | 735 // operations before the DoubleChunk overflows. |
| 734 const DoubleChunk square = | 736 // |
| 735 static_cast<DoubleChunk>(kDigitMaxValue) * kDigitMaxValue; | 737 // At the end of the column sum and after each batch of kBlockSize additions |
| 736 const DoubleChunk kDoubleChunkMaxValue = static_cast<DoubleChunk>(-1); | 738 // the high kCarryBits+kDigitBitSize of accumulator are flushed to |
| 737 const DoubleChunk left_over_carry = kDoubleChunkMaxValue >> kDigitBitSize; | 739 // accumulator_overflow. |
| 738 const intptr_t kMaxDigits = (kDoubleChunkMaxValue - left_over_carry) / square; | 740 // |
| 739 if (Utils::Minimum(a_length, b_length) > kMaxDigits) { | 741 // Diagramatically, using one char per 4 bits: |
| 740 // Use the preallocated out of memory exception to avoid calling | 742 // |
| 741 // into dart code or allocating any code. | 743 // 0aaaaaaa * 0bbbbbbb -> 00pppppppppppppp product of 2 digits |
| 742 Isolate* isolate = Isolate::Current(); | 744 // | |
| 743 const Instance& exception = | 745 // + ...added to |
| 744 Instance::Handle(isolate->object_store()->out_of_memory()); | 746 // v |
| 745 Exceptions::Throw(exception); | 747 // ccSSSSSSSsssssss accumulator |
| 746 UNREACHABLE(); | 748 // ...flushed to |
| 747 } | 749 // 000000000sssssss accumulator |
| 750 // vvvvvvvvvVVVVVVV accumulator_overflow |
| 751 // |
| 752 // 'sssssss' becomes the column sum an overflow is carried to next column: |
| 753 // |
| 754 // 000000000VVVVVVV accumulator |
| 755 // 0000000vvvvvvvvv accumulator_overflow |
| 756 // |
| 757 // accumulator_overflow supports 2^(kDigitBitSize + kCarryBits) additions of |
| 758 // products. |
| 759 // |
| 760 // Since the bottom (kDigitBitSize + kCarryBits) bits of accumulator_overflow |
| 761 // are initialized from the previous column, that uses up the capacity to |
| 762 // absorb 2^kCarryBits additions. The accumulator_overflow can overflow if |
| 763 // the column has more than 2^(kDigitBitSize + kCarryBits) - 2^kCarryBits |
| 764 // elements With current configuration that is 2^36-2^8 elements. That is too |
| 765 // high to happen in practice. Comba multiplication is O(N^2) so overflow |
| 766 // won't happen during a human lifespan. |
| 767 |
| 768 const intptr_t kCarryBits = 8 * sizeof(DoubleChunk) - 2 * kDigitBitSize; |
| 769 const intptr_t kBlockSize = (1 << kCarryBits) - 1; |
| 748 | 770 |
| 749 DoubleChunk accumulator = 0; // Accumulates the result of one column. | 771 DoubleChunk accumulator = 0; // Accumulates the result of one column. |
| 772 DoubleChunk accumulator_overflow = 0; |
| 750 for (intptr_t i = 0; i < result_length; i++) { | 773 for (intptr_t i = 0; i < result_length; i++) { |
| 751 // Example: r = a2a1a0 * b2b1b0. | 774 // Example: r = a2a1a0 * b2b1b0. |
| 752 // For i == 0, compute a0b0. | 775 // For i == 0, compute a0b0. |
| 753 // i == 1, a1b0 + a0b1 + overflow from i == 0. | 776 // i == 1, a1b0 + a0b1 + overflow from i == 0. |
| 754 // i == 2, a2b0 + a1b1 + a0b2 + overflow from i == 1. | 777 // i == 2, a2b0 + a1b1 + a0b2 + overflow from i == 1. |
| 755 // ... | 778 // ... |
| 756 // The indices into a and b are such that their sum equals i. | 779 // The indices into a and b are such that their sum equals i. |
| 757 intptr_t a_index = Utils::Minimum(a_length - 1, i); | 780 intptr_t a_index = Utils::Minimum(a_length - 1, i); |
| 758 intptr_t b_index = i - a_index; | 781 intptr_t b_index = i - a_index; |
| 759 ASSERT(a_index + b_index == i); | 782 ASSERT(a_index + b_index == i); |
| 760 | 783 |
| 761 // Instead of testing for a_index >= 0 && b_index < b_length we compute the | 784 // Instead of testing for a_index >= 0 && b_index < b_length we compute the |
| 762 // number of iterations first. | 785 // number of iterations first. |
| 763 intptr_t iterations = Utils::Minimum(b_length - b_index, a_index + 1); | 786 intptr_t iterations = Utils::Minimum(b_length - b_index, a_index + 1); |
| 764 for (intptr_t j = 0; j < iterations; j++) { | 787 |
| 765 DoubleChunk chunk_a = a.GetChunkAt(a_index); | 788 // For large products we need extra bit for the overflow. The sum is broken |
| 766 DoubleChunk chunk_b = b.GetChunkAt(b_index); | 789 // into blocks to avoid dealing with the overflow on each iteration. |
| 767 accumulator += chunk_a * chunk_b; | 790 for (intptr_t j_block = 0; j_block < iterations; j_block += kBlockSize) { |
| 768 a_index--; | 791 intptr_t j_end = Utils::Minimum(j_block + kBlockSize, iterations); |
| 769 b_index++; | 792 for (intptr_t j = j_block; j < j_end; j++) { |
| 793 DoubleChunk chunk_a = a.GetChunkAt(a_index); |
| 794 DoubleChunk chunk_b = b.GetChunkAt(b_index); |
| 795 accumulator += chunk_a * chunk_b; |
| 796 a_index--; |
| 797 b_index++; |
| 798 } |
| 799 accumulator_overflow += (accumulator >> kDigitBitSize); |
| 800 accumulator &= kDigitMask; |
| 770 } | 801 } |
| 771 result.SetChunkAt(i, static_cast<Chunk>(accumulator & kDigitMask)); | 802 result.SetChunkAt(i, static_cast<Chunk>(accumulator)); |
| 772 accumulator >>= kDigitBitSize; | 803 // Overflow becomes the initial accumulator for the next column. |
| 804 accumulator = accumulator_overflow & kDigitMask; |
| 805 // And the overflow from the overflow becomes the new overflow. |
| 806 accumulator_overflow = (accumulator_overflow >> kDigitBitSize); |
| 773 } | 807 } |
| 774 ASSERT(accumulator == 0); | 808 ASSERT(accumulator == 0); |
| 809 ASSERT(accumulator_overflow == 0); |
| 775 | 810 |
| 776 Clamp(result); | 811 Clamp(result); |
| 777 return result.raw(); | 812 return result.raw(); |
| 778 } | 813 } |
| 779 | 814 |
| 780 | 815 |
| 781 RawBigint* BigintOperations::Divide(const Bigint& a, const Bigint& b) { | 816 RawBigint* BigintOperations::Divide(const Bigint& a, const Bigint& b) { |
| 782 Bigint& quotient = Bigint::Handle(); | 817 Bigint& quotient = Bigint::Handle(); |
| 783 Bigint& remainder = Bigint::Handle(); | 818 Bigint& remainder = Bigint::Handle(); |
| 784 DivideRemainder(a, b, "ient, &remainder); | 819 DivideRemainder(a, b, "ient, &remainder); |
| (...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1672 int BigintOperations::CountBits(Chunk digit) { | 1707 int BigintOperations::CountBits(Chunk digit) { |
| 1673 int result = 0; | 1708 int result = 0; |
| 1674 while (digit != 0) { | 1709 while (digit != 0) { |
| 1675 digit >>= 1; | 1710 digit >>= 1; |
| 1676 result++; | 1711 result++; |
| 1677 } | 1712 } |
| 1678 return result; | 1713 return result; |
| 1679 } | 1714 } |
| 1680 | 1715 |
| 1681 } // namespace dart | 1716 } // namespace dart |
| OLD | NEW |