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

Side by Side Diff: runtime/vm/bigint_operations.cc

Issue 26294002: Cleanups: int -> intptr_t for "array" lengths, memory sizes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 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 | « runtime/vm/bigint_operations.h ('k') | runtime/vm/bit_vector.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/assert.h" 5 #include "platform/assert.h"
6 #include "platform/utils.h" 6 #include "platform/utils.h"
7 7
8 #include "vm/double_internals.h" 8 #include "vm/double_internals.h"
9 #include "vm/exceptions.h" 9 #include "vm/exceptions.h"
10 #include "vm/object_store.h" 10 #include "vm/object_store.h"
(...skipping 19 matching lines...) Expand all
30 // Count number of needed Digits. 30 // Count number of needed Digits.
31 intptr_t digit_count = 0; 31 intptr_t digit_count = 0;
32 intptr_t count_value = value; 32 intptr_t count_value = value;
33 while (count_value > 0) { 33 while (count_value > 0) {
34 digit_count++; 34 digit_count++;
35 count_value >>= kDigitBitSize; 35 count_value >>= kDigitBitSize;
36 } 36 }
37 37
38 // Allocate a bigint of the correct size and copy the bits. 38 // Allocate a bigint of the correct size and copy the bits.
39 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space)); 39 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space));
40 for (int i = 0; i < digit_count; i++) { 40 for (intptr_t i = 0; i < digit_count; i++) {
41 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask)); 41 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask));
42 value >>= kDigitBitSize; 42 value >>= kDigitBitSize;
43 } 43 }
44 result.SetSign(is_negative); 44 result.SetSign(is_negative);
45 ASSERT(IsClamped(result)); 45 ASSERT(IsClamped(result));
46 return result.raw(); 46 return result.raw();
47 } 47 }
48 48
49 49
50 RawBigint* BigintOperations::NewFromInt64(int64_t value, Heap::Space space) { 50 RawBigint* BigintOperations::NewFromInt64(int64_t value, Heap::Space space) {
(...skipping 18 matching lines...) Expand all
69 // Count number of needed Digits. 69 // Count number of needed Digits.
70 intptr_t digit_count = 0; 70 intptr_t digit_count = 0;
71 uint64_t count_value = value; 71 uint64_t count_value = value;
72 while (count_value > 0) { 72 while (count_value > 0) {
73 digit_count++; 73 digit_count++;
74 count_value >>= kDigitBitSize; 74 count_value >>= kDigitBitSize;
75 } 75 }
76 76
77 // Allocate a bigint of the correct size and copy the bits. 77 // Allocate a bigint of the correct size and copy the bits.
78 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space)); 78 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space));
79 for (int i = 0; i < digit_count; i++) { 79 for (intptr_t i = 0; i < digit_count; i++) {
80 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask)); 80 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask));
81 value >>= kDigitBitSize; 81 value >>= kDigitBitSize;
82 } 82 }
83 result.SetSign(false); 83 result.SetSign(false);
84 ASSERT(IsClamped(result)); 84 ASSERT(IsClamped(result));
85 return result.raw(); 85 return result.raw();
86 } 86 }
87 87
88 88
89 RawBigint* BigintOperations::NewFromCString(const char* str, 89 RawBigint* BigintOperations::NewFromCString(const char* str,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 167
168 const intptr_t str_length = strlen(str); 168 const intptr_t str_length = strlen(str);
169 if (str_length < 0) { 169 if (str_length < 0) {
170 FATAL("Fatal error in BigintOperations::FromDecimalCString: " 170 FATAL("Fatal error in BigintOperations::FromDecimalCString: "
171 "string too long"); 171 "string too long");
172 } 172 }
173 intptr_t str_pos = 0; 173 intptr_t str_pos = 0;
174 174
175 // Read first digit separately. This avoids a multiplication and addition. 175 // Read first digit separately. This avoids a multiplication and addition.
176 // The first digit might also not have kDigitsPerIteration decimal digits. 176 // The first digit might also not have kDigitsPerIteration decimal digits.
177 int first_digit_decimal_digits = str_length % kDigitsPerIteration; 177 intptr_t first_digit_decimal_digits = str_length % kDigitsPerIteration;
178 Chunk digit = 0; 178 Chunk digit = 0;
179 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { 179 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) {
180 char c = str[str_pos++]; 180 char c = str[str_pos++];
181 ASSERT(('0' <= c) && (c <= '9')); 181 ASSERT(('0' <= c) && (c <= '9'));
182 digit = digit * 10 + c - '0'; 182 digit = digit * 10 + c - '0';
183 } 183 }
184 Bigint& result = Bigint::Handle(Bigint::Allocate(1)); 184 Bigint& result = Bigint::Handle(Bigint::Allocate(1));
185 result.SetChunkAt(0, digit); 185 result.SetChunkAt(0, digit);
186 Clamp(result); // Multiplication requires the inputs to be clamped. 186 Clamp(result); // Multiplication requires the inputs to be clamped.
187 187
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 return NewFromSmi(zero, space); 219 return NewFromSmi(zero, space);
220 } 220 }
221 DoubleInternals internals = DoubleInternals(d); 221 DoubleInternals internals = DoubleInternals(d);
222 if (internals.IsSpecial()) { 222 if (internals.IsSpecial()) {
223 const Array& exception_arguments = Array::Handle(Array::New(1)); 223 const Array& exception_arguments = Array::Handle(Array::New(1));
224 exception_arguments.SetAt( 224 exception_arguments.SetAt(
225 0, Object::Handle(String::New("BigintOperations::NewFromDouble"))); 225 0, Object::Handle(String::New("BigintOperations::NewFromDouble")));
226 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); 226 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments);
227 } 227 }
228 uint64_t significand = internals.Significand(); 228 uint64_t significand = internals.Significand();
229 int exponent = internals.Exponent(); 229 intptr_t exponent = internals.Exponent();
230 int sign = internals.Sign(); 230 intptr_t sign = internals.Sign();
231 if (exponent <= 0) { 231 if (exponent <= 0) {
232 significand >>= -exponent; 232 significand >>= -exponent;
233 exponent = 0; 233 exponent = 0;
234 } else if (exponent <= 10) { 234 } else if (exponent <= 10) {
235 // A double significand has at most 53 bits. The following shift will 235 // A double significand has at most 53 bits. The following shift will
236 // hence not overflow, and yield an integer of at most 63 bits. 236 // hence not overflow, and yield an integer of at most 63 bits.
237 significand <<= exponent; 237 significand <<= exponent;
238 exponent = 0; 238 exponent = 0;
239 } 239 }
240 // A significand has at most 63 bits (after the shift above). 240 // A significand has at most 63 bits (after the shift above).
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 ASSERT(result != NULL); 277 ASSERT(result != NULL);
278 memmove(result, zero, kLength); 278 memmove(result, zero, kLength);
279 result[kLength] = '\0'; 279 result[kLength] = '\0';
280 return result; 280 return result;
281 } 281 }
282 ASSERT(chunk_data != NULL); 282 ASSERT(chunk_data != NULL);
283 283
284 // Compute the number of hex-digits that are needed to represent the 284 // Compute the number of hex-digits that are needed to represent the
285 // leading bigint-digit. All other digits need exactly kHexCharsPerDigit 285 // leading bigint-digit. All other digits need exactly kHexCharsPerDigit
286 // characters. 286 // characters.
287 int leading_hex_digits = 0; 287 intptr_t leading_hex_digits = 0;
288 Chunk leading_digit = chunk_data[chunk_length - 1]; 288 Chunk leading_digit = chunk_data[chunk_length - 1];
289 while (leading_digit != 0) { 289 while (leading_digit != 0) {
290 leading_hex_digits++; 290 leading_hex_digits++;
291 leading_digit >>= 4; 291 leading_digit >>= 4;
292 } 292 }
293 // Sum up the space that is needed for the string-representation. 293 // Sum up the space that is needed for the string-representation.
294 intptr_t required_size = 0; 294 intptr_t required_size = 0;
295 if (is_negative) { 295 if (is_negative) {
296 required_size++; // For the leading "-". 296 required_size++; // For the leading "-".
297 } 297 }
298 required_size += 2; // For the "0x". 298 required_size += 2; // For the "0x".
299 required_size += leading_hex_digits; 299 required_size += leading_hex_digits;
300 required_size += (chunk_length - 1) * kHexCharsPerDigit; 300 required_size += (chunk_length - 1) * kHexCharsPerDigit;
301 required_size++; // For the trailing '\0'. 301 required_size++; // For the trailing '\0'.
302 char* result = reinterpret_cast<char*>(allocator(required_size)); 302 char* result = reinterpret_cast<char*>(allocator(required_size));
303 // Print the number into the string. 303 // Print the number into the string.
304 // Start from the last position. 304 // Start from the last position.
305 intptr_t pos = required_size - 1; 305 intptr_t pos = required_size - 1;
306 result[pos--] = '\0'; 306 result[pos--] = '\0';
307 for (intptr_t i = 0; i < (chunk_length - 1); i++) { 307 for (intptr_t i = 0; i < (chunk_length - 1); i++) {
308 // Print all non-leading characters (which are printed with 308 // Print all non-leading characters (which are printed with
309 // kHexCharsPerDigit characters. 309 // kHexCharsPerDigit characters.
310 Chunk digit = chunk_data[i]; 310 Chunk digit = chunk_data[i];
311 for (int j = 0; j < kHexCharsPerDigit; j++) { 311 for (intptr_t j = 0; j < kHexCharsPerDigit; j++) {
312 result[pos--] = Utils::IntToHexDigit(static_cast<int>(digit & 0xF)); 312 result[pos--] = Utils::IntToHexDigit(static_cast<int>(digit & 0xF));
313 digit >>= 4; 313 digit >>= 4;
314 } 314 }
315 } 315 }
316 // Print the leading digit. 316 // Print the leading digit.
317 leading_digit = chunk_data[chunk_length - 1]; 317 leading_digit = chunk_data[chunk_length - 1];
318 while (leading_digit != 0) { 318 while (leading_digit != 0) {
319 result[pos--] = Utils::IntToHexDigit(static_cast<int>(leading_digit & 0xF)); 319 result[pos--] = Utils::IntToHexDigit(static_cast<int>(leading_digit & 0xF));
320 leading_digit >>= 4; 320 leading_digit >>= 4;
321 } 321 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 // Add one byte for the trailing \0 character. 370 // Add one byte for the trailing \0 character.
371 int64_t required_size = decimal_length + 1; 371 int64_t required_size = decimal_length + 1;
372 if (bigint.IsNegative()) { 372 if (bigint.IsNegative()) {
373 required_size++; 373 required_size++;
374 } 374 }
375 ASSERT(required_size == static_cast<intptr_t>(required_size)); 375 ASSERT(required_size == static_cast<intptr_t>(required_size));
376 // We will fill the result in the inverse order and then exchange at the end. 376 // We will fill the result in the inverse order and then exchange at the end.
377 char* result = 377 char* result =
378 reinterpret_cast<char*>(allocator(static_cast<intptr_t>(required_size))); 378 reinterpret_cast<char*>(allocator(static_cast<intptr_t>(required_size)));
379 ASSERT(result != NULL); 379 ASSERT(result != NULL);
380 int result_pos = 0; 380 intptr_t result_pos = 0;
381 381
382 // We divide the input into pieces of ~27 bits which can be efficiently 382 // We divide the input into pieces of ~27 bits which can be efficiently
383 // handled. 383 // handled.
384 const intptr_t kChunkDivisor = 100000000; 384 const intptr_t kChunkDivisor = 100000000;
385 const int kChunkDigits = 8; 385 const int kChunkDigits = 8;
386 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor); 386 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor);
387 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue); 387 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue);
388 ASSERT(Smi::IsValid(kChunkDivisor)); 388 ASSERT(Smi::IsValid(kChunkDivisor));
389 const Chunk divisor = static_cast<Chunk>(kChunkDivisor); 389 const Chunk divisor = static_cast<Chunk>(kChunkDivisor);
390 390
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 uintptr_t limit; 437 uintptr_t limit;
438 if (bigint.IsNegative()) { 438 if (bigint.IsNegative()) {
439 limit = static_cast<uintptr_t>(-Smi::kMinValue); 439 limit = static_cast<uintptr_t>(-Smi::kMinValue);
440 } else { 440 } else {
441 limit = static_cast<uintptr_t>(Smi::kMaxValue); 441 limit = static_cast<uintptr_t>(Smi::kMaxValue);
442 } 442 }
443 bool bigint_is_greater = false; 443 bool bigint_is_greater = false;
444 // Consume the least-significant digits of the bigint. 444 // Consume the least-significant digits of the bigint.
445 // If bigint_is_greater is set, then the processed sub-part of the bigint is 445 // If bigint_is_greater is set, then the processed sub-part of the bigint is
446 // greater than the corresponding part of the limit. 446 // greater than the corresponding part of the limit.
447 for (int i = 0; i < bigint_length - 1; i++) { 447 for (intptr_t i = 0; i < bigint_length - 1; i++) {
448 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask); 448 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask);
449 Chunk bigint_digit = bigint.GetChunkAt(i); 449 Chunk bigint_digit = bigint.GetChunkAt(i);
450 if (limit_digit < bigint_digit) { 450 if (limit_digit < bigint_digit) {
451 bigint_is_greater = true; 451 bigint_is_greater = true;
452 } else if (limit_digit > bigint_digit) { 452 } else if (limit_digit > bigint_digit) {
453 bigint_is_greater = false; 453 bigint_is_greater = false;
454 } // else don't change the boolean. 454 } // else don't change the boolean.
455 limit >>= kDigitBitSize; 455 limit >>= kDigitBitSize;
456 456
457 // Bail out if the bigint is definitely too big. 457 // Bail out if the bigint is definitely too big.
458 if (limit == 0) { 458 if (limit == 0) {
459 return false; 459 return false;
460 } 460 }
461 } 461 }
462 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1); 462 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1);
463 if (limit > most_significant_digit) { 463 if (limit > most_significant_digit) {
464 return true; 464 return true;
465 } 465 }
466 if (limit < most_significant_digit) { 466 if (limit < most_significant_digit) {
467 return false; 467 return false;
468 } 468 }
469 return !bigint_is_greater; 469 return !bigint_is_greater;
470 } 470 }
471 471
472 472
473 RawSmi* BigintOperations::ToSmi(const Bigint& bigint) { 473 RawSmi* BigintOperations::ToSmi(const Bigint& bigint) {
474 ASSERT(FitsIntoSmi(bigint)); 474 ASSERT(FitsIntoSmi(bigint));
475 intptr_t value = 0; 475 intptr_t value = 0;
476 for (int i = bigint.Length() - 1; i >= 0; i--) { 476 for (intptr_t i = bigint.Length() - 1; i >= 0; i--) {
477 value <<= kDigitBitSize; 477 value <<= kDigitBitSize;
478 value += static_cast<intptr_t>(bigint.GetChunkAt(i)); 478 value += static_cast<intptr_t>(bigint.GetChunkAt(i));
479 } 479 }
480 if (bigint.IsNegative()) { 480 if (bigint.IsNegative()) {
481 value = -value; 481 value = -value;
482 } 482 }
483 return Smi::New(value); 483 return Smi::New(value);
484 } 484 }
485 485
486 486
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 uint64_t limit; 636 uint64_t limit;
637 if (bigint.IsNegative()) { 637 if (bigint.IsNegative()) {
638 limit = static_cast<uint64_t>(Mint::kMinValue); 638 limit = static_cast<uint64_t>(Mint::kMinValue);
639 } else { 639 } else {
640 limit = static_cast<uint64_t>(Mint::kMaxValue); 640 limit = static_cast<uint64_t>(Mint::kMaxValue);
641 } 641 }
642 bool bigint_is_greater = false; 642 bool bigint_is_greater = false;
643 // Consume the least-significant digits of the bigint. 643 // Consume the least-significant digits of the bigint.
644 // If bigint_is_greater is set, then the processed sub-part of the bigint is 644 // If bigint_is_greater is set, then the processed sub-part of the bigint is
645 // greater than the corresponding part of the limit. 645 // greater than the corresponding part of the limit.
646 for (int i = 0; i < bigint_length - 1; i++) { 646 for (intptr_t i = 0; i < bigint_length - 1; i++) {
647 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask); 647 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask);
648 Chunk bigint_digit = bigint.GetChunkAt(i); 648 Chunk bigint_digit = bigint.GetChunkAt(i);
649 if (limit_digit < bigint_digit) { 649 if (limit_digit < bigint_digit) {
650 bigint_is_greater = true; 650 bigint_is_greater = true;
651 } else if (limit_digit > bigint_digit) { 651 } else if (limit_digit > bigint_digit) {
652 bigint_is_greater = false; 652 bigint_is_greater = false;
653 } // else don't change the boolean. 653 } // else don't change the boolean.
654 limit >>= kDigitBitSize; 654 limit >>= kDigitBitSize;
655 655
656 // Bail out if the bigint is definitely too big. 656 // Bail out if the bigint is definitely too big.
657 if (limit == 0) { 657 if (limit == 0) {
658 return false; 658 return false;
659 } 659 }
660 } 660 }
661 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1); 661 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1);
662 if (limit > most_significant_digit) { 662 if (limit > most_significant_digit) {
663 return true; 663 return true;
664 } 664 }
665 if (limit < most_significant_digit) { 665 if (limit < most_significant_digit) {
666 return false; 666 return false;
667 } 667 }
668 return !bigint_is_greater; 668 return !bigint_is_greater;
669 } 669 }
670 670
671 671
672 uint64_t BigintOperations::AbsToUint64(const Bigint& bigint) { 672 uint64_t BigintOperations::AbsToUint64(const Bigint& bigint) {
673 ASSERT(AbsFitsIntoUint64(bigint)); 673 ASSERT(AbsFitsIntoUint64(bigint));
674 uint64_t value = 0; 674 uint64_t value = 0;
675 for (int i = bigint.Length() - 1; i >= 0; i--) { 675 for (intptr_t i = bigint.Length() - 1; i >= 0; i--) {
676 value <<= kDigitBitSize; 676 value <<= kDigitBitSize;
677 value += static_cast<intptr_t>(bigint.GetChunkAt(i)); 677 value += static_cast<intptr_t>(bigint.GetChunkAt(i));
678 } 678 }
679 return value; 679 return value;
680 } 680 }
681 681
682 682
683 int64_t BigintOperations::ToInt64(const Bigint& bigint) { 683 int64_t BigintOperations::ToInt64(const Bigint& bigint) {
684 if (bigint.IsZero()) { 684 if (bigint.IsZero()) {
685 return 0; 685 return 0;
686 } 686 }
687 ASSERT(FitsIntoInt64(bigint)); 687 ASSERT(FitsIntoInt64(bigint));
688 int64_t value = AbsToUint64(bigint); 688 int64_t value = AbsToUint64(bigint);
689 if (bigint.IsNegative()) { 689 if (bigint.IsNegative()) {
690 value = -value; 690 value = -value;
691 } 691 }
692 return value; 692 return value;
693 } 693 }
694 694
695 695
696 bool BigintOperations::AbsFitsIntoUint64(const Bigint& bigint) { 696 bool BigintOperations::AbsFitsIntoUint64(const Bigint& bigint) {
697 intptr_t b_length = bigint.Length(); 697 intptr_t b_length = bigint.Length();
698 int num_bits = CountBits(bigint.GetChunkAt(b_length - 1)); 698 intptr_t num_bits = CountBits(bigint.GetChunkAt(b_length - 1));
699 num_bits += (kDigitBitSize * (b_length - 1)); 699 num_bits += (kDigitBitSize * (b_length - 1));
700 if (num_bits > 64) return false; 700 if (num_bits > 64) return false;
701 return true; 701 return true;
702 } 702 }
703 703
704 704
705 bool BigintOperations::FitsIntoUint64(const Bigint& bigint) { 705 bool BigintOperations::FitsIntoUint64(const Bigint& bigint) {
706 if (bigint.IsNegative()) return false; 706 if (bigint.IsNegative()) return false;
707 return AbsFitsIntoUint64(bigint); 707 return AbsFitsIntoUint64(bigint);
708 } 708 }
(...skipping 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after
1788 intptr_t bigint_length = bigint.Length(); 1788 intptr_t bigint_length = bigint.Length();
1789 Bigint& copy = Bigint::Handle(Bigint::Allocate(bigint_length)); 1789 Bigint& copy = Bigint::Handle(Bigint::Allocate(bigint_length));
1790 for (intptr_t i = 0; i < bigint_length; i++) { 1790 for (intptr_t i = 0; i < bigint_length; i++) {
1791 copy.SetChunkAt(i, bigint.GetChunkAt(i)); 1791 copy.SetChunkAt(i, bigint.GetChunkAt(i));
1792 } 1792 }
1793 copy.SetSign(bigint.IsNegative()); 1793 copy.SetSign(bigint.IsNegative());
1794 return copy.raw(); 1794 return copy.raw();
1795 } 1795 }
1796 1796
1797 1797
1798 int BigintOperations::CountBits(Chunk digit) { 1798 intptr_t BigintOperations::CountBits(Chunk digit) {
1799 int result = 0; 1799 intptr_t result = 0;
1800 while (digit != 0) { 1800 while (digit != 0) {
1801 digit >>= 1; 1801 digit >>= 1;
1802 result++; 1802 result++;
1803 } 1803 }
1804 return result; 1804 return result;
1805 } 1805 }
1806 1806
1807 } // namespace dart 1807 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/bigint_operations.h ('k') | runtime/vm/bit_vector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698