Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: vm/bigint_operations.cc

Issue 12052033: Added macros OBJECT_IMPLEMENTATION and FINAL_OBJECT_IMPLEMENTATION (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/ast.cc ('k') | vm/cha.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 // Then multiply the temporary result by 10^kDigitsPerIteration and add 177 // Then multiply the temporary result by 10^kDigitsPerIteration and add
178 // 'increment' to the new result. 178 // 'increment' to the new result.
179 const Bigint& increment = Bigint::Handle(Bigint::Allocate(1)); 179 const Bigint& increment = Bigint::Handle(Bigint::Allocate(1));
180 while (str_pos < str_length - 1) { 180 while (str_pos < str_length - 1) {
181 Chunk digit = 0; 181 Chunk digit = 0;
182 for (intptr_t i = 0; i < kDigitsPerIteration; i++) { 182 for (intptr_t i = 0; i < kDigitsPerIteration; i++) {
183 char c = str[str_pos++]; 183 char c = str[str_pos++];
184 ASSERT(('0' <= c) && (c <= '9')); 184 ASSERT(('0' <= c) && (c <= '9'));
185 digit = digit * 10 + c - '0'; 185 digit = digit * 10 + c - '0';
186 } 186 }
187 result |= MultiplyWithDigit(result, kTenMultiplier); 187 result = MultiplyWithDigit(result, kTenMultiplier);
188 if (digit != 0) { 188 if (digit != 0) {
189 increment.SetChunkAt(0, digit); 189 increment.SetChunkAt(0, digit);
190 result |= Add(result, increment); 190 result = Add(result, increment);
191 } 191 }
192 } 192 }
193 Clamp(result); 193 Clamp(result);
194 if ((space == Heap::kOld) && !result.IsOld()) { 194 if ((space == Heap::kOld) && !result.IsOld()) {
195 result |= Object::Clone(result, Heap::kOld); 195 result ^= Object::Clone(result, Heap::kOld);
196 } 196 }
197 return result.raw(); 197 return result.raw();
198 } 198 }
199 199
200 200
201 RawBigint* BigintOperations::NewFromDouble(double d, Heap::Space space) { 201 RawBigint* BigintOperations::NewFromDouble(double d, Heap::Space space) {
202 if ((-1.0 < d) && (d < 1.0)) { 202 if ((-1.0 < d) && (d < 1.0)) {
203 // Shortcut for small numbers. Also makes the right-shift below 203 // Shortcut for small numbers. Also makes the right-shift below
204 // well specified. 204 // well specified.
205 Smi& zero = Smi::Handle(Smi::New(0)); 205 Smi& zero = Smi::Handle(Smi::New(0));
(...skipping 1267 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 const Bigint& a, const Bigint& b, Bigint* quotient, Bigint* remainder) { 1473 const Bigint& a, const Bigint& b, Bigint* quotient, Bigint* remainder) {
1474 // TODO(floitsch): This function is very memory-intensive since all 1474 // TODO(floitsch): This function is very memory-intensive since all
1475 // intermediate bigint results are allocated in new memory. It would be 1475 // intermediate bigint results are allocated in new memory. It would be
1476 // much more efficient to reuse the space of temporary intermediate variables. 1476 // much more efficient to reuse the space of temporary intermediate variables.
1477 ASSERT(IsClamped(a)); 1477 ASSERT(IsClamped(a));
1478 ASSERT(IsClamped(b)); 1478 ASSERT(IsClamped(b));
1479 ASSERT(!b.IsZero()); 1479 ASSERT(!b.IsZero());
1480 1480
1481 int comp = UnsignedCompare(a, b); 1481 int comp = UnsignedCompare(a, b);
1482 if (comp < 0) { 1482 if (comp < 0) {
1483 (*quotient) |= Zero(); 1483 (*quotient) = Zero();
1484 (*remainder) |= Copy(a); // TODO(floitsch): can we reuse the input? 1484 (*remainder) = Copy(a); // TODO(floitsch): can we reuse the input?
1485 return; 1485 return;
1486 } else if (comp == 0) { 1486 } else if (comp == 0) {
1487 (*quotient) |= One(); 1487 (*quotient) = One();
1488 quotient->SetSign(a.IsNegative() != b.IsNegative()); 1488 quotient->SetSign(a.IsNegative() != b.IsNegative());
1489 (*remainder) |= Zero(); 1489 (*remainder) = Zero();
1490 return; 1490 return;
1491 } 1491 }
1492 1492
1493 // High level description: 1493 // High level description:
1494 // The algorithm is basically the algorithm that is taught in school: 1494 // The algorithm is basically the algorithm that is taught in school:
1495 // Let a the dividend and b the divisor. We are looking for 1495 // Let a the dividend and b the divisor. We are looking for
1496 // the quotient q = truncate(a / b), and 1496 // the quotient q = truncate(a / b), and
1497 // the remainder r = a - q * b. 1497 // the remainder r = a - q * b.
1498 // School algorithm: 1498 // School algorithm:
1499 // q = 0 1499 // q = 0
(...skipping 14 matching lines...) Expand all
1514 Bigint& dividend = Bigint::Handle(ShiftLeft(a, normalization_shift)); 1514 Bigint& dividend = Bigint::Handle(ShiftLeft(a, normalization_shift));
1515 const Bigint& divisor = Bigint::Handle(ShiftLeft(b, normalization_shift)); 1515 const Bigint& divisor = Bigint::Handle(ShiftLeft(b, normalization_shift));
1516 dividend.SetSign(false); 1516 dividend.SetSign(false);
1517 divisor.SetSign(false); 1517 divisor.SetSign(false);
1518 1518
1519 intptr_t dividend_length = dividend.Length(); 1519 intptr_t dividend_length = dividend.Length();
1520 intptr_t divisor_length = b_length; 1520 intptr_t divisor_length = b_length;
1521 ASSERT(divisor_length == divisor.Length()); 1521 ASSERT(divisor_length == divisor.Length());
1522 1522
1523 intptr_t quotient_length = dividend_length - divisor_length + 1; 1523 intptr_t quotient_length = dividend_length - divisor_length + 1;
1524 *quotient |= Bigint::Allocate(quotient_length); 1524 *quotient = Bigint::Allocate(quotient_length);
1525 quotient->SetSign(a.IsNegative() != b.IsNegative()); 1525 quotient->SetSign(a.IsNegative() != b.IsNegative());
1526 1526
1527 intptr_t quotient_pos = dividend_length - divisor_length; 1527 intptr_t quotient_pos = dividend_length - divisor_length;
1528 // Find the first quotient-digit. 1528 // Find the first quotient-digit.
1529 // The first digit must be computed separately from the other digits because 1529 // The first digit must be computed separately from the other digits because
1530 // the preconditions for the loop are not yet satisfied. 1530 // the preconditions for the loop are not yet satisfied.
1531 // For simplicity use a shifted divisor, so that the comparison and 1531 // For simplicity use a shifted divisor, so that the comparison and
1532 // subtraction are easier. 1532 // subtraction are easier.
1533 int divisor_shift_amount = dividend_length - divisor_length; 1533 int divisor_shift_amount = dividend_length - divisor_length;
1534 Bigint& shifted_divisor = 1534 Bigint& shifted_divisor =
1535 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount)); 1535 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount));
1536 Chunk first_quotient_digit = 0; 1536 Chunk first_quotient_digit = 0;
1537 while (UnsignedCompare(dividend, shifted_divisor) >= 0) { 1537 while (UnsignedCompare(dividend, shifted_divisor) >= 0) {
1538 first_quotient_digit++; 1538 first_quotient_digit++;
1539 dividend |= Subtract(dividend, shifted_divisor); 1539 dividend = Subtract(dividend, shifted_divisor);
1540 } 1540 }
1541 quotient->SetChunkAt(quotient_pos--, first_quotient_digit); 1541 quotient->SetChunkAt(quotient_pos--, first_quotient_digit);
1542 1542
1543 // Find the remainder of the digits. 1543 // Find the remainder of the digits.
1544 1544
1545 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1); 1545 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1);
1546 // The short divisor only represents the first two digits of the divisor. 1546 // The short divisor only represents the first two digits of the divisor.
1547 // If the divisor has only one digit, then the second part is zeroed out. 1547 // If the divisor has only one digit, then the second part is zeroed out.
1548 Bigint& short_divisor = Bigint::Handle(Bigint::Allocate(2)); 1548 Bigint& short_divisor = Bigint::Handle(Bigint::Allocate(2));
1549 if (divisor_length > 1) { 1549 if (divisor_length > 1) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 } 1602 }
1603 1603
1604 // Refine estimation. 1604 // Refine estimation.
1605 quotient_digit++; // The following loop will start by decrementing. 1605 quotient_digit++; // The following loop will start by decrementing.
1606 Bigint& estimation_product = Bigint::Handle(); 1606 Bigint& estimation_product = Bigint::Handle();
1607 target.SetChunkAt(0, ((i - 2) < 0) ? 0 : dividend.GetChunkAt(i - 2)); 1607 target.SetChunkAt(0, ((i - 2) < 0) ? 0 : dividend.GetChunkAt(i - 2));
1608 target.SetChunkAt(1, ((i - 1) < 0) ? 0 : dividend.GetChunkAt(i - 1)); 1608 target.SetChunkAt(1, ((i - 1) < 0) ? 0 : dividend.GetChunkAt(i - 1));
1609 target.SetChunkAt(2, dividend_digit); 1609 target.SetChunkAt(2, dividend_digit);
1610 do { 1610 do {
1611 quotient_digit = (quotient_digit - 1) & kDigitMask; 1611 quotient_digit = (quotient_digit - 1) & kDigitMask;
1612 estimation_product |= MultiplyWithDigit(short_divisor, quotient_digit); 1612 estimation_product = MultiplyWithDigit(short_divisor, quotient_digit);
1613 } while (UnsignedCompareNonClamped(estimation_product, target) > 0); 1613 } while (UnsignedCompareNonClamped(estimation_product, target) > 0);
1614 // At this point the quotient_digit is fairly accurate. 1614 // At this point the quotient_digit is fairly accurate.
1615 // At the worst it is off by one. 1615 // At the worst it is off by one.
1616 // Remove a multiple of the divisor. If the estimate is incorrect we will 1616 // Remove a multiple of the divisor. If the estimate is incorrect we will
1617 // subtract the divisor another time. 1617 // subtract the divisor another time.
1618 // Let t = i - divisor_length. 1618 // Let t = i - divisor_length.
1619 // dividend -= (quotient_digit * divisor) << (t * kDigitBitSize); 1619 // dividend -= (quotient_digit * divisor) << (t * kDigitBitSize);
1620 shifted_divisor |= MultiplyWithDigit(divisor, quotient_digit); 1620 shifted_divisor = MultiplyWithDigit(divisor, quotient_digit);
1621 shifted_divisor |= DigitsShiftLeft(shifted_divisor, i - divisor_length); 1621 shifted_divisor = DigitsShiftLeft(shifted_divisor, i - divisor_length);
1622 dividend = Subtract(dividend, shifted_divisor); 1622 dividend = Subtract(dividend, shifted_divisor);
1623 if (dividend.IsNegative()) { 1623 if (dividend.IsNegative()) {
1624 // The estimation was still too big. 1624 // The estimation was still too big.
1625 quotient_digit--; 1625 quotient_digit--;
1626 // TODO(floitsch): allocate space for the shifted_divisor once and reuse 1626 // TODO(floitsch): allocate space for the shifted_divisor once and reuse
1627 // it at every iteration. 1627 // it at every iteration.
1628 shifted_divisor |= DigitsShiftLeft(divisor, i - divisor_length); 1628 shifted_divisor = DigitsShiftLeft(divisor, i - divisor_length);
1629 // TODO(floitsch): reuse the space of the previous dividend. 1629 // TODO(floitsch): reuse the space of the previous dividend.
1630 dividend = Add(dividend, shifted_divisor); 1630 dividend = Add(dividend, shifted_divisor);
1631 } 1631 }
1632 quotient->SetChunkAt(quotient_pos--, quotient_digit); 1632 quotient->SetChunkAt(quotient_pos--, quotient_digit);
1633 } 1633 }
1634 ASSERT(quotient_pos == -1); 1634 ASSERT(quotient_pos == -1);
1635 Clamp(*quotient); 1635 Clamp(*quotient);
1636 *remainder |= ShiftRight(dividend, normalization_shift); 1636 *remainder = ShiftRight(dividend, normalization_shift);
1637 remainder->SetSign(a.IsNegative()); 1637 remainder->SetSign(a.IsNegative());
1638 } 1638 }
1639 1639
1640 1640
1641 void BigintOperations::Clamp(const Bigint& bigint) { 1641 void BigintOperations::Clamp(const Bigint& bigint) {
1642 intptr_t length = bigint.Length(); 1642 intptr_t length = bigint.Length();
1643 while (length > 0 && (bigint.GetChunkAt(length - 1) == 0)) { 1643 while (length > 0 && (bigint.GetChunkAt(length - 1) == 0)) {
1644 length--; 1644 length--;
1645 } 1645 }
1646 // TODO(floitsch): We change the size of bigint-objects here. 1646 // TODO(floitsch): We change the size of bigint-objects here.
(...skipping 15 matching lines...) Expand all
1662 int BigintOperations::CountBits(Chunk digit) { 1662 int BigintOperations::CountBits(Chunk digit) {
1663 int result = 0; 1663 int result = 0;
1664 while (digit != 0) { 1664 while (digit != 0) {
1665 digit >>= 1; 1665 digit >>= 1;
1666 result++; 1666 result++;
1667 } 1667 }
1668 return result; 1668 return result;
1669 } 1669 }
1670 1670
1671 } // namespace dart 1671 } // namespace dart
OLDNEW
« no previous file with comments | « vm/ast.cc ('k') | vm/cha.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698