| 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/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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |