| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | |
| 2 | |
| 3 #include "vm/bigint_operations.h" | |
| 4 | |
| 5 #include "platform/assert.h" | |
| 6 #include "platform/utils.h" | |
| 7 | |
| 8 #include "vm/double_internals.h" | |
| 9 #include "vm/exceptions.h" | |
| 10 #include "vm/object_store.h" | |
| 11 #include "vm/zone.h" | |
| 12 | |
| 13 namespace dart { | |
| 14 | |
| 15 RawBigint* BigintOperations::NewFromSmi(const Smi& smi, Heap::Space space) { | |
| 16 intptr_t value = smi.Value(); | |
| 17 if (value == 0) { | |
| 18 return Zero(); | |
| 19 } | |
| 20 | |
| 21 bool is_negative = (value < 0); | |
| 22 if (is_negative) { | |
| 23 value = -value; | |
| 24 } | |
| 25 // Assert that there are no overflows. Smis reserve a bit for themselves, but | |
| 26 // protect against future changes. | |
| 27 ASSERT(-Smi::kMinValue > 0); | |
| 28 | |
| 29 // A single digit of a Bigint might not be sufficient to store a Smi. | |
| 30 // Count number of needed Digits. | |
| 31 intptr_t digit_count = 0; | |
| 32 intptr_t count_value = value; | |
| 33 while (count_value > 0) { | |
| 34 digit_count++; | |
| 35 count_value >>= kDigitBitSize; | |
| 36 } | |
| 37 | |
| 38 // Allocate a bigint of the correct size and copy the bits. | |
| 39 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space)); | |
| 40 for (intptr_t i = 0; i < digit_count; i++) { | |
| 41 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask)); | |
| 42 value >>= kDigitBitSize; | |
| 43 } | |
| 44 result.SetSign(is_negative); | |
| 45 ASSERT(IsClamped(result)); | |
| 46 return result.raw(); | |
| 47 } | |
| 48 | |
| 49 | |
| 50 RawBigint* BigintOperations::NewFromInt64(int64_t value, Heap::Space space) { | |
| 51 bool is_negative = value < 0; | |
| 52 | |
| 53 if (is_negative) { | |
| 54 value = -value; | |
| 55 } | |
| 56 | |
| 57 const Bigint& result = Bigint::Handle(NewFromUint64(value, space)); | |
| 58 result.SetSign(is_negative); | |
| 59 | |
| 60 return result.raw(); | |
| 61 } | |
| 62 | |
| 63 | |
| 64 RawBigint* BigintOperations::NewFromUint64(uint64_t value, Heap::Space space) { | |
| 65 if (value == 0) { | |
| 66 return Zero(); | |
| 67 } | |
| 68 // A single digit of a Bigint might not be sufficient to store the value. | |
| 69 // Count number of needed Digits. | |
| 70 intptr_t digit_count = 0; | |
| 71 uint64_t count_value = value; | |
| 72 while (count_value > 0) { | |
| 73 digit_count++; | |
| 74 count_value >>= kDigitBitSize; | |
| 75 } | |
| 76 | |
| 77 // Allocate a bigint of the correct size and copy the bits. | |
| 78 const Bigint& result = Bigint::Handle(Bigint::Allocate(digit_count, space)); | |
| 79 for (intptr_t i = 0; i < digit_count; i++) { | |
| 80 result.SetChunkAt(i, static_cast<Chunk>(value & kDigitMask)); | |
| 81 value >>= kDigitBitSize; | |
| 82 } | |
| 83 result.SetSign(false); | |
| 84 ASSERT(IsClamped(result)); | |
| 85 return result.raw(); | |
| 86 } | |
| 87 | |
| 88 | |
| 89 RawBigint* BigintOperations::NewFromCString(const char* str, | |
| 90 Heap::Space space) { | |
| 91 ASSERT(str != NULL); | |
| 92 if (str[0] == '\0') { | |
| 93 return Zero(); | |
| 94 } | |
| 95 | |
| 96 // If the string starts with '-' recursively restart the whole operation | |
| 97 // without the character and then toggle the sign. | |
| 98 // This allows multiple leading '-' (which will cancel each other out), but | |
| 99 // we have added an assert, to make sure that the returned result of the | |
| 100 // recursive call is not negative. | |
| 101 // We don't catch leading '-'s for zero. Ex: "--0", or "---". | |
| 102 if (str[0] == '-') { | |
| 103 const Bigint& result = Bigint::Handle(NewFromCString(&str[1], space)); | |
| 104 result.ToggleSign(); | |
| 105 ASSERT(result.IsZero() || result.IsNegative()); | |
| 106 ASSERT(IsClamped(result)); | |
| 107 return result.raw(); | |
| 108 } | |
| 109 | |
| 110 // No overflow check needed since overflowing str_length implies that we take | |
| 111 // the branch to FromDecimalCString() which contains a check itself. | |
| 112 const intptr_t str_length = strlen(str); | |
| 113 if ((str_length > 2) && | |
| 114 (str[0] == '0') && | |
| 115 ((str[1] == 'x') || (str[1] == 'X'))) { | |
| 116 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); | |
| 117 ASSERT(IsClamped(result)); | |
| 118 return result.raw(); | |
| 119 } else { | |
| 120 return FromDecimalCString(str, space); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 | |
| 125 intptr_t BigintOperations::ComputeChunkLength(const char* hex_string) { | |
| 126 ASSERT(kDigitBitSize % 4 == 0); | |
| 127 const intptr_t hex_length = strlen(hex_string); | |
| 128 if (hex_length < 0) { | |
| 129 FATAL("Fatal error in BigintOperations::ComputeChunkLength: " | |
| 130 "string too long"); | |
| 131 } | |
| 132 // Round up. | |
| 133 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; | |
| 134 return bigint_length; | |
| 135 } | |
| 136 | |
| 137 | |
| 138 RawBigint* BigintOperations::FromHexCString(const char* hex_string, | |
| 139 Heap::Space space) { | |
| 140 // If the string starts with '-' recursively restart the whole operation | |
| 141 // without the character and then toggle the sign. | |
| 142 // This allows multiple leading '-' (which will cancel each other out), but | |
| 143 // we have added an assert, to make sure that the returned result of the | |
| 144 // recursive call is not negative. | |
| 145 // We don't catch leading '-'s for zero. Ex: "--0", or "---". | |
| 146 if (hex_string[0] == '-') { | |
| 147 const Bigint& value = Bigint::Handle(FromHexCString(&hex_string[1], space)); | |
| 148 value.ToggleSign(); | |
| 149 ASSERT(value.IsZero() || value.IsNegative()); | |
| 150 ASSERT(IsClamped(value)); | |
| 151 return value.raw(); | |
| 152 } | |
| 153 intptr_t bigint_length = ComputeChunkLength(hex_string); | |
| 154 const Bigint& result = Bigint::Handle(Bigint::Allocate(bigint_length, space)); | |
| 155 FromHexCString(hex_string, result); | |
| 156 return result.raw(); | |
| 157 } | |
| 158 | |
| 159 | |
| 160 RawBigint* BigintOperations::FromDecimalCString(const char* str, | |
| 161 Heap::Space space) { | |
| 162 Isolate* isolate = Isolate::Current(); | |
| 163 // Read 8 digits a time. 10^8 < 2^27. | |
| 164 const int kDigitsPerIteration = 8; | |
| 165 const Chunk kTenMultiplier = 100000000; | |
| 166 ASSERT(kDigitBitSize >= 27); | |
| 167 | |
| 168 const intptr_t str_length = strlen(str); | |
| 169 if (str_length < 0) { | |
| 170 FATAL("Fatal error in BigintOperations::FromDecimalCString: " | |
| 171 "string too long"); | |
| 172 } | |
| 173 intptr_t str_pos = 0; | |
| 174 | |
| 175 // Read first digit separately. This avoids a multiplication and addition. | |
| 176 // The first digit might also not have kDigitsPerIteration decimal digits. | |
| 177 intptr_t first_digit_decimal_digits = str_length % kDigitsPerIteration; | |
| 178 Chunk digit = 0; | |
| 179 for (intptr_t i = 0; i < first_digit_decimal_digits; i++) { | |
| 180 char c = str[str_pos++]; | |
| 181 ASSERT(('0' <= c) && (c <= '9')); | |
| 182 digit = digit * 10 + c - '0'; | |
| 183 } | |
| 184 Bigint& result = Bigint::Handle(Bigint::Allocate(1)); | |
| 185 result.SetChunkAt(0, digit); | |
| 186 Clamp(result); // Multiplication requires the inputs to be clamped. | |
| 187 | |
| 188 // Read kDigitsPerIteration at a time, and store it in 'increment'. | |
| 189 // Then multiply the temporary result by 10^kDigitsPerIteration and add | |
| 190 // 'increment' to the new result. | |
| 191 const Bigint& increment = Bigint::Handle(Bigint::Allocate(1)); | |
| 192 while (str_pos < str_length - 1) { | |
| 193 HANDLESCOPE(isolate); | |
| 194 Chunk digit = 0; | |
| 195 for (intptr_t i = 0; i < kDigitsPerIteration; i++) { | |
| 196 char c = str[str_pos++]; | |
| 197 ASSERT(('0' <= c) && (c <= '9')); | |
| 198 digit = digit * 10 + c - '0'; | |
| 199 } | |
| 200 result = MultiplyWithDigit(result, kTenMultiplier); | |
| 201 if (digit != 0) { | |
| 202 increment.SetChunkAt(0, digit); | |
| 203 result = Add(result, increment); | |
| 204 } | |
| 205 } | |
| 206 Clamp(result); | |
| 207 if ((space == Heap::kOld) && !result.IsOld()) { | |
| 208 result ^= Object::Clone(result, Heap::kOld); | |
| 209 } | |
| 210 return result.raw(); | |
| 211 } | |
| 212 | |
| 213 | |
| 214 RawBigint* BigintOperations::NewFromDouble(double d, Heap::Space space) { | |
| 215 if ((-1.0 < d) && (d < 1.0)) { | |
| 216 // Shortcut for small numbers. Also makes the right-shift below | |
| 217 // well specified. | |
| 218 Smi& zero = Smi::Handle(Smi::New(0)); | |
| 219 return NewFromSmi(zero, space); | |
| 220 } | |
| 221 DoubleInternals internals = DoubleInternals(d); | |
| 222 if (internals.IsSpecial()) { | |
| 223 const Array& exception_arguments = Array::Handle(Array::New(1)); | |
| 224 exception_arguments.SetAt( | |
| 225 0, | |
| 226 PassiveObject::Handle(String::New("BigintOperations::NewFromDouble"))); | |
| 227 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); | |
| 228 } | |
| 229 uint64_t significand = internals.Significand(); | |
| 230 intptr_t exponent = internals.Exponent(); | |
| 231 intptr_t sign = internals.Sign(); | |
| 232 if (exponent <= 0) { | |
| 233 significand >>= -exponent; | |
| 234 exponent = 0; | |
| 235 } else if (exponent <= 10) { | |
| 236 // A double significand has at most 53 bits. The following shift will | |
| 237 // hence not overflow, and yield an integer of at most 63 bits. | |
| 238 significand <<= exponent; | |
| 239 exponent = 0; | |
| 240 } | |
| 241 // A significand has at most 63 bits (after the shift above). | |
| 242 // The cast to int64_t is hence safe. | |
| 243 const Bigint& result = | |
| 244 Bigint::Handle(NewFromInt64(static_cast<int64_t>(significand), space)); | |
| 245 result.SetSign(sign < 0); | |
| 246 if (exponent > 0) { | |
| 247 return ShiftLeft(result, exponent); | |
| 248 } else { | |
| 249 return result.raw(); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 | |
| 254 const char* BigintOperations::ToHexCString(intptr_t length, | |
| 255 bool is_negative, | |
| 256 void* data, | |
| 257 uword (*allocator)(intptr_t size)) { | |
| 258 NoGCScope no_gc; | |
| 259 | |
| 260 ASSERT(kDigitBitSize % 4 == 0); | |
| 261 | |
| 262 // Conservative maximum chunk length. | |
| 263 const intptr_t kMaxChunkLen = | |
| 264 (kIntptrMax - 2 /* 0x */ | |
| 265 - 1 /* trailing '\0' */ | |
| 266 - 1 /* leading '-' */) / kHexCharsPerDigit; | |
| 267 const intptr_t chunk_length = length; | |
| 268 // Conservative check assuming leading bigint-digit also takes up | |
| 269 // kHexCharsPerDigit. | |
| 270 if (chunk_length > kMaxChunkLen) { | |
| 271 FATAL("Fatal error in BigintOperations::ToHexCString: string too long"); | |
| 272 } | |
| 273 Chunk* chunk_data = reinterpret_cast<Chunk*>(data); | |
| 274 if (length == 0) { | |
| 275 const char* zero = "0x0"; | |
| 276 const intptr_t kLength = strlen(zero); | |
| 277 char* result = reinterpret_cast<char*>(allocator(kLength + 1)); | |
| 278 ASSERT(result != NULL); | |
| 279 memmove(result, zero, kLength); | |
| 280 result[kLength] = '\0'; | |
| 281 return result; | |
| 282 } | |
| 283 ASSERT(chunk_data != NULL); | |
| 284 | |
| 285 // Compute the number of hex-digits that are needed to represent the | |
| 286 // leading bigint-digit. All other digits need exactly kHexCharsPerDigit | |
| 287 // characters. | |
| 288 intptr_t leading_hex_digits = 0; | |
| 289 Chunk leading_digit = chunk_data[chunk_length - 1]; | |
| 290 while (leading_digit != 0) { | |
| 291 leading_hex_digits++; | |
| 292 leading_digit >>= 4; | |
| 293 } | |
| 294 // Sum up the space that is needed for the string-representation. | |
| 295 intptr_t required_size = 0; | |
| 296 if (is_negative) { | |
| 297 required_size++; // For the leading "-". | |
| 298 } | |
| 299 required_size += 2; // For the "0x". | |
| 300 required_size += leading_hex_digits; | |
| 301 required_size += (chunk_length - 1) * kHexCharsPerDigit; | |
| 302 required_size++; // For the trailing '\0'. | |
| 303 char* result = reinterpret_cast<char*>(allocator(required_size)); | |
| 304 // Print the number into the string. | |
| 305 // Start from the last position. | |
| 306 intptr_t pos = required_size - 1; | |
| 307 result[pos--] = '\0'; | |
| 308 for (intptr_t i = 0; i < (chunk_length - 1); i++) { | |
| 309 // Print all non-leading characters (which are printed with | |
| 310 // kHexCharsPerDigit characters. | |
| 311 Chunk digit = chunk_data[i]; | |
| 312 for (intptr_t j = 0; j < kHexCharsPerDigit; j++) { | |
| 313 result[pos--] = Utils::IntToHexDigit(static_cast<int>(digit & 0xF)); | |
| 314 digit >>= 4; | |
| 315 } | |
| 316 } | |
| 317 // Print the leading digit. | |
| 318 leading_digit = chunk_data[chunk_length - 1]; | |
| 319 while (leading_digit != 0) { | |
| 320 result[pos--] = Utils::IntToHexDigit(static_cast<int>(leading_digit & 0xF)); | |
| 321 leading_digit >>= 4; | |
| 322 } | |
| 323 result[pos--] = 'x'; | |
| 324 result[pos--] = '0'; | |
| 325 if (is_negative) { | |
| 326 result[pos--] = '-'; | |
| 327 } | |
| 328 ASSERT(pos == -1); | |
| 329 return result; | |
| 330 } | |
| 331 | |
| 332 | |
| 333 const char* BigintOperations::ToHexCString(const Bigint& bigint, | |
| 334 uword (*allocator)(intptr_t size)) { | |
| 335 NoGCScope no_gc; | |
| 336 | |
| 337 intptr_t length = bigint.Length(); | |
| 338 return ToHexCString(length, | |
| 339 bigint.IsNegative(), | |
| 340 length ? bigint.ChunkAddr(0) : NULL, | |
| 341 allocator); | |
| 342 } | |
| 343 | |
| 344 | |
| 345 const char* BigintOperations::ToDecimalCString( | |
| 346 const Bigint& bigint, uword (*allocator)(intptr_t size)) { | |
| 347 // log10(2) ~= 0.30102999566398114. | |
| 348 const intptr_t kLog2Dividend = 30103; | |
| 349 const intptr_t kLog2Divisor = 100000; | |
| 350 // We remove a small constant for rounding imprecision, the \0 character and | |
| 351 // the negative sign. | |
| 352 const intptr_t kMaxAllowedDigitLength = | |
| 353 (kIntptrMax - 10) / kLog2Dividend / kDigitBitSize * kLog2Divisor; | |
| 354 | |
| 355 const intptr_t length = bigint.Length(); | |
| 356 Isolate* isolate = Isolate::Current(); | |
| 357 if (length >= kMaxAllowedDigitLength) { | |
| 358 // Use the preallocated out of memory exception to avoid calling | |
| 359 // into dart code or allocating any code. | |
| 360 const Instance& exception = | |
| 361 Instance::Handle(isolate->object_store()->out_of_memory()); | |
| 362 Exceptions::Throw(isolate, exception); | |
| 363 UNREACHABLE(); | |
| 364 } | |
| 365 | |
| 366 // Approximate the size of the resulting string. We prefer overestimating | |
| 367 // to not allocating enough. | |
| 368 int64_t bit_length = length * kDigitBitSize; | |
| 369 ASSERT(bit_length > length || length == 0); | |
| 370 int64_t decimal_length = (bit_length * kLog2Dividend / kLog2Divisor) + 1; | |
| 371 // Add one byte for the trailing \0 character. | |
| 372 int64_t required_size = decimal_length + 1; | |
| 373 if (bigint.IsNegative()) { | |
| 374 required_size++; | |
| 375 } | |
| 376 ASSERT(required_size == static_cast<intptr_t>(required_size)); | |
| 377 // We will fill the result in the inverse order and then exchange at the end. | |
| 378 char* result = | |
| 379 reinterpret_cast<char*>(allocator(static_cast<intptr_t>(required_size))); | |
| 380 ASSERT(result != NULL); | |
| 381 intptr_t result_pos = 0; | |
| 382 | |
| 383 // We divide the input into pieces of ~27 bits which can be efficiently | |
| 384 // handled. | |
| 385 const intptr_t kChunkDivisor = 100000000; | |
| 386 const int kChunkDigits = 8; | |
| 387 ASSERT(pow(10.0, kChunkDigits) == kChunkDivisor); | |
| 388 ASSERT(static_cast<Chunk>(kChunkDivisor) < kDigitMaxValue); | |
| 389 ASSERT(Smi::IsValid(kChunkDivisor)); | |
| 390 const Chunk divisor = static_cast<Chunk>(kChunkDivisor); | |
| 391 | |
| 392 // Rest contains the remaining bigint that needs to be printed. | |
| 393 const Bigint& rest = Bigint::Handle(Copy(bigint)); | |
| 394 while (!rest.IsZero()) { | |
| 395 Chunk remainder = InplaceUnsignedDivideRemainderDigit(rest, divisor); | |
| 396 intptr_t part = static_cast<intptr_t>(remainder); | |
| 397 for (int i = 0; i < kChunkDigits; i++) { | |
| 398 result[result_pos++] = '0' + (part % 10); | |
| 399 part /= 10; | |
| 400 } | |
| 401 ASSERT(part == 0); | |
| 402 } | |
| 403 // Add a leading zero, so that we have at least one digit. | |
| 404 result[result_pos++] = '0'; | |
| 405 // Move the resulting position back until we don't have any zeroes anymore | |
| 406 // or we reach the first digit. This is done so that we can remove all | |
| 407 // redundant leading zeroes. | |
| 408 while (result_pos > 1 && result[result_pos - 1] == '0') { | |
| 409 result_pos--; | |
| 410 } | |
| 411 if (bigint.IsNegative()) { | |
| 412 result[result_pos++] = '-'; | |
| 413 } | |
| 414 // Reverse the string. | |
| 415 int i = 0; | |
| 416 int j = result_pos - 1; | |
| 417 while (i < j) { | |
| 418 char tmp = result[i]; | |
| 419 result[i] = result[j]; | |
| 420 result[j] = tmp; | |
| 421 i++; | |
| 422 j--; | |
| 423 } | |
| 424 ASSERT(result_pos >= 0); | |
| 425 result[result_pos] = '\0'; | |
| 426 return result; | |
| 427 } | |
| 428 | |
| 429 | |
| 430 bool BigintOperations::FitsIntoSmi(const Bigint& bigint) { | |
| 431 intptr_t bigint_length = bigint.Length(); | |
| 432 if (bigint_length == 0) { | |
| 433 return true; | |
| 434 } | |
| 435 if ((bigint_length == 1) && | |
| 436 (static_cast<size_t>(kDigitBitSize) < | |
| 437 (sizeof(intptr_t) * kBitsPerByte))) { | |
| 438 return true; | |
| 439 } | |
| 440 | |
| 441 uintptr_t limit; | |
| 442 if (bigint.IsNegative()) { | |
| 443 limit = static_cast<uintptr_t>(-Smi::kMinValue); | |
| 444 } else { | |
| 445 limit = static_cast<uintptr_t>(Smi::kMaxValue); | |
| 446 } | |
| 447 bool bigint_is_greater = false; | |
| 448 // Consume the least-significant digits of the bigint. | |
| 449 // If bigint_is_greater is set, then the processed sub-part of the bigint is | |
| 450 // greater than the corresponding part of the limit. | |
| 451 for (intptr_t i = 0; i < bigint_length - 1; i++) { | |
| 452 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask); | |
| 453 Chunk bigint_digit = bigint.GetChunkAt(i); | |
| 454 if (limit_digit < bigint_digit) { | |
| 455 bigint_is_greater = true; | |
| 456 } else if (limit_digit > bigint_digit) { | |
| 457 bigint_is_greater = false; | |
| 458 } // else don't change the boolean. | |
| 459 limit >>= kDigitBitSize; | |
| 460 | |
| 461 // Bail out if the bigint is definitely too big. | |
| 462 if (limit == 0) { | |
| 463 return false; | |
| 464 } | |
| 465 } | |
| 466 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1); | |
| 467 if (limit > most_significant_digit) { | |
| 468 return true; | |
| 469 } | |
| 470 if (limit < most_significant_digit) { | |
| 471 return false; | |
| 472 } | |
| 473 return !bigint_is_greater; | |
| 474 } | |
| 475 | |
| 476 | |
| 477 RawSmi* BigintOperations::ToSmi(const Bigint& bigint) { | |
| 478 ASSERT(FitsIntoSmi(bigint)); | |
| 479 intptr_t value = 0; | |
| 480 for (intptr_t i = bigint.Length() - 1; i >= 0; i--) { | |
| 481 value <<= kDigitBitSize; | |
| 482 value += static_cast<intptr_t>(bigint.GetChunkAt(i)); | |
| 483 } | |
| 484 if (bigint.IsNegative()) { | |
| 485 value = -value; | |
| 486 } | |
| 487 return Smi::New(value); | |
| 488 } | |
| 489 | |
| 490 | |
| 491 static double Uint64ToDouble(uint64_t x) { | |
| 492 #if _WIN64 | |
| 493 // For static_cast<double>(x) MSVC x64 generates | |
| 494 // | |
| 495 // cvtsi2sd xmm0, rax | |
| 496 // test rax, rax | |
| 497 // jns done | |
| 498 // addsd xmm0, static_cast<double>(2^64) | |
| 499 // done: | |
| 500 // | |
| 501 // while GCC -m64 generates | |
| 502 // | |
| 503 // test rax, rax | |
| 504 // js negative | |
| 505 // cvtsi2sd xmm0, rax | |
| 506 // jmp done | |
| 507 // negative: | |
| 508 // mov rdx, rax | |
| 509 // shr rdx, 1 | |
| 510 // and eax, 0x1 | |
| 511 // or rdx, rax | |
| 512 // cvtsi2sd xmm0, rdx | |
| 513 // addsd xmm0, xmm0 | |
| 514 // done: | |
| 515 // | |
| 516 // which results in a different rounding. | |
| 517 // | |
| 518 // For consistency between platforms fallback to GCC style converstion | |
| 519 // on Win64. | |
| 520 // | |
| 521 const int64_t y = static_cast<int64_t>(x); | |
| 522 if (y > 0) { | |
| 523 return static_cast<double>(y); | |
| 524 } else { | |
| 525 const double half = static_cast<double>( | |
| 526 static_cast<int64_t>(x >> 1) | (y & 1)); | |
| 527 return half + half; | |
| 528 } | |
| 529 #else | |
| 530 return static_cast<double>(x); | |
| 531 #endif | |
| 532 } | |
| 533 | |
| 534 | |
| 535 RawDouble* BigintOperations::ToDouble(const Bigint& bigint) { | |
| 536 ASSERT(IsClamped(bigint)); | |
| 537 if (bigint.IsZero()) { | |
| 538 return Double::New(0.0); | |
| 539 } | |
| 540 if (AbsFitsIntoUint64(bigint)) { | |
| 541 double absolute_value = Uint64ToDouble(AbsToUint64(bigint)); | |
| 542 double result = bigint.IsNegative() ? -absolute_value : absolute_value; | |
| 543 return Double::New(result); | |
| 544 } | |
| 545 | |
| 546 static const int kPhysicalSignificandSize = 52; | |
| 547 // The significand size has an additional hidden bit. | |
| 548 static const int kSignificandSize = kPhysicalSignificandSize + 1; | |
| 549 static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; | |
| 550 static const int kMaxExponent = 0x7FF - kExponentBias; | |
| 551 static const uint64_t kOne64 = 1; | |
| 552 static const uint64_t kInfinityBits = | |
| 553 DART_2PART_UINT64_C(0x7FF00000, 00000000); | |
| 554 | |
| 555 // A double is composed of an exponent e and a significand s. Its value equals | |
| 556 // s * 2^e. The significand has 53 bits of which the first one must always be | |
| 557 // 1 (at least for then numbers we are working with here) and is therefore | |
| 558 // omitted. The physical size of the significand is thus 52 bits. | |
| 559 // The exponent has 11 bits and is biased by 0x3FF + 52. For example an | |
| 560 // exponent e = 10 is written as 0x3FF + 52 + 10 (in the 11 bits that are | |
| 561 // reserved for the exponent). | |
| 562 // When converting the given bignum to a double we have to pay attention to | |
| 563 // the rounding. In particular we have to decide which double to pick if an | |
| 564 // input lies exactly between two doubles. As usual with double operations | |
| 565 // we pick the double with an even significand in such cases. | |
| 566 // | |
| 567 // General approach of this algorithm: Get 54 bits (one more than the | |
| 568 // significand size) of the bigint. If the last bit is then 1, then (without | |
| 569 // knowledge of the remaining bits) we could have a half-way number. | |
| 570 // If the second-to-last bit is odd then we know that we have to round up: | |
| 571 // if the remaining bits are not zero then the input lies closer to the higher | |
| 572 // double. If the remaining bits are zero then we have a half-way case and | |
| 573 // we need to round up too (rounding to the even double). | |
| 574 // If the second-to-last bit is even then we need to look at the remaining | |
| 575 // bits to determine if any of them is not zero. If that's the case then the | |
| 576 // number lies closer to the next-higher double. Otherwise we round the | |
| 577 // half-way case down to even. | |
| 578 | |
| 579 intptr_t length = bigint.Length(); | |
| 580 if (((length - 1) * kDigitBitSize) > (kMaxExponent + kSignificandSize)) { | |
| 581 // Does not fit into a double. | |
| 582 double infinity = bit_cast<double>(kInfinityBits); | |
| 583 return Double::New(bigint.IsNegative() ? -infinity : infinity); | |
| 584 } | |
| 585 | |
| 586 | |
| 587 intptr_t digit_index = length - 1; | |
| 588 // In order to round correctly we need to look at half-way cases. Therefore we | |
| 589 // get kSignificandSize + 1 bits. If the last bit is 1 then we have to look | |
| 590 // at the remaining bits to know if we have to round up. | |
| 591 int needed_bits = kSignificandSize + 1; | |
| 592 ASSERT((kDigitBitSize < needed_bits) && (2 * kDigitBitSize >= needed_bits)); | |
| 593 bool discarded_bits_were_zero = true; | |
| 594 | |
| 595 Chunk firstDigit = bigint.GetChunkAt(digit_index--); | |
| 596 uint64_t twice_significand_floor = firstDigit; | |
| 597 intptr_t twice_significant_exponent = (digit_index + 1) * kDigitBitSize; | |
| 598 needed_bits -= CountBits(firstDigit); | |
| 599 | |
| 600 if (needed_bits >= kDigitBitSize) { | |
| 601 twice_significand_floor <<= kDigitBitSize; | |
| 602 twice_significand_floor |= bigint.GetChunkAt(digit_index--); | |
| 603 twice_significant_exponent -= kDigitBitSize; | |
| 604 needed_bits -= kDigitBitSize; | |
| 605 } | |
| 606 if (needed_bits > 0) { | |
| 607 ASSERT(needed_bits <= kDigitBitSize); | |
| 608 Chunk digit = bigint.GetChunkAt(digit_index--); | |
| 609 int discarded_bits_count = kDigitBitSize - needed_bits; | |
| 610 twice_significand_floor <<= needed_bits; | |
| 611 twice_significand_floor |= digit >> discarded_bits_count; | |
| 612 twice_significant_exponent -= needed_bits; | |
| 613 uint64_t discarded_bits_mask = (kOne64 << discarded_bits_count) - 1; | |
| 614 discarded_bits_were_zero = ((digit & discarded_bits_mask) == 0); | |
| 615 } | |
| 616 ASSERT((twice_significand_floor >> kSignificandSize) == 1); | |
| 617 | |
| 618 // We might need to round up the significand later. | |
| 619 uint64_t significand = twice_significand_floor >> 1; | |
| 620 intptr_t exponent = twice_significant_exponent + 1; | |
| 621 | |
| 622 if (exponent >= kMaxExponent) { | |
| 623 // Infinity. | |
| 624 // Does not fit into a double. | |
| 625 double infinity = bit_cast<double>(kInfinityBits); | |
| 626 return Double::New(bigint.IsNegative() ? -infinity : infinity); | |
| 627 } | |
| 628 | |
| 629 if ((twice_significand_floor & 1) == 1) { | |
| 630 bool round_up = false; | |
| 631 | |
| 632 if ((significand & 1) != 0 || !discarded_bits_were_zero) { | |
| 633 // Even if the remaining bits are zero we still need to round up since we | |
| 634 // want to round to even for half-way cases. | |
| 635 round_up = true; | |
| 636 } else { | |
| 637 // Could be a half-way case. See if the remaining bits are non-zero. | |
| 638 for (intptr_t i = 0; i <= digit_index; i++) { | |
| 639 if (bigint.GetChunkAt(i) != 0) { | |
| 640 round_up = true; | |
| 641 break; | |
| 642 } | |
| 643 } | |
| 644 } | |
| 645 | |
| 646 if (round_up) { | |
| 647 significand++; | |
| 648 // It might be that we just went from 53 bits to 54 bits. | |
| 649 // Example: After adding 1 to 1FFF..FF (with 53 bits set to 1) we have | |
| 650 // 2000..00 (= 2 ^ 54). When adding the exponent and significand together | |
| 651 // this will increase the exponent by 1 which is exactly what we want. | |
| 652 } | |
| 653 } | |
| 654 | |
| 655 ASSERT((significand >> (kSignificandSize - 1)) == 1 | |
| 656 || significand == kOne64 << kSignificandSize); | |
| 657 uint64_t biased_exponent = exponent + kExponentBias; | |
| 658 // The significand still has the hidden bit. We simply decrement the biased | |
| 659 // exponent by one instead of playing around with the significand. | |
| 660 biased_exponent--; | |
| 661 // Note that we must use the plus operator instead of bit-or. | |
| 662 uint64_t double_bits = | |
| 663 (biased_exponent << kPhysicalSignificandSize) + significand; | |
| 664 | |
| 665 double value = bit_cast<double>(double_bits); | |
| 666 if (bigint.IsNegative()) { | |
| 667 value = -value; | |
| 668 } | |
| 669 return Double::New(value); | |
| 670 } | |
| 671 | |
| 672 | |
| 673 bool BigintOperations::FitsIntoInt64(const Bigint& bigint) { | |
| 674 intptr_t bigint_length = bigint.Length(); | |
| 675 if (bigint_length == 0) { | |
| 676 return true; | |
| 677 } | |
| 678 if ((bigint_length < 3) && | |
| 679 (static_cast<size_t>(kDigitBitSize) < | |
| 680 (sizeof(intptr_t) * kBitsPerByte))) { | |
| 681 return true; | |
| 682 } | |
| 683 | |
| 684 uint64_t limit; | |
| 685 if (bigint.IsNegative()) { | |
| 686 limit = static_cast<uint64_t>(Mint::kMinValue); | |
| 687 } else { | |
| 688 limit = static_cast<uint64_t>(Mint::kMaxValue); | |
| 689 } | |
| 690 bool bigint_is_greater = false; | |
| 691 // Consume the least-significant digits of the bigint. | |
| 692 // If bigint_is_greater is set, then the processed sub-part of the bigint is | |
| 693 // greater than the corresponding part of the limit. | |
| 694 for (intptr_t i = 0; i < bigint_length - 1; i++) { | |
| 695 Chunk limit_digit = static_cast<Chunk>(limit & kDigitMask); | |
| 696 Chunk bigint_digit = bigint.GetChunkAt(i); | |
| 697 if (limit_digit < bigint_digit) { | |
| 698 bigint_is_greater = true; | |
| 699 } else if (limit_digit > bigint_digit) { | |
| 700 bigint_is_greater = false; | |
| 701 } // else don't change the boolean. | |
| 702 limit >>= kDigitBitSize; | |
| 703 | |
| 704 // Bail out if the bigint is definitely too big. | |
| 705 if (limit == 0) { | |
| 706 return false; | |
| 707 } | |
| 708 } | |
| 709 Chunk most_significant_digit = bigint.GetChunkAt(bigint_length - 1); | |
| 710 if (limit > most_significant_digit) { | |
| 711 return true; | |
| 712 } | |
| 713 if (limit < most_significant_digit) { | |
| 714 return false; | |
| 715 } | |
| 716 return !bigint_is_greater; | |
| 717 } | |
| 718 | |
| 719 | |
| 720 uint64_t BigintOperations::AbsToUint64(const Bigint& bigint) { | |
| 721 ASSERT(AbsFitsIntoUint64(bigint)); | |
| 722 uint64_t value = 0; | |
| 723 for (intptr_t i = bigint.Length() - 1; i >= 0; i--) { | |
| 724 value <<= kDigitBitSize; | |
| 725 value += static_cast<intptr_t>(bigint.GetChunkAt(i)); | |
| 726 } | |
| 727 return value; | |
| 728 } | |
| 729 | |
| 730 | |
| 731 int64_t BigintOperations::ToInt64(const Bigint& bigint) { | |
| 732 if (bigint.IsZero()) { | |
| 733 return 0; | |
| 734 } | |
| 735 ASSERT(FitsIntoInt64(bigint)); | |
| 736 int64_t value = AbsToUint64(bigint); | |
| 737 if (bigint.IsNegative()) { | |
| 738 value = -value; | |
| 739 } | |
| 740 return value; | |
| 741 } | |
| 742 | |
| 743 | |
| 744 uint32_t BigintOperations::TruncateToUint32(const Bigint& bigint) { | |
| 745 uint32_t value = 0; | |
| 746 for (intptr_t i = bigint.Length() - 1; i >= 0; i--) { | |
| 747 value <<= kDigitBitSize; | |
| 748 value += static_cast<uint32_t>(bigint.GetChunkAt(i)); | |
| 749 } | |
| 750 return value; | |
| 751 } | |
| 752 | |
| 753 | |
| 754 bool BigintOperations::AbsFitsIntoUint64(const Bigint& bigint) { | |
| 755 if (bigint.IsZero()) { | |
| 756 return true; | |
| 757 } | |
| 758 intptr_t b_length = bigint.Length(); | |
| 759 intptr_t num_bits = CountBits(bigint.GetChunkAt(b_length - 1)); | |
| 760 num_bits += (kDigitBitSize * (b_length - 1)); | |
| 761 if (num_bits > 64) return false; | |
| 762 return true; | |
| 763 } | |
| 764 | |
| 765 | |
| 766 bool BigintOperations::FitsIntoUint64(const Bigint& bigint) { | |
| 767 if (bigint.IsNegative()) return false; | |
| 768 return AbsFitsIntoUint64(bigint); | |
| 769 } | |
| 770 | |
| 771 | |
| 772 uint64_t BigintOperations::ToUint64(const Bigint& bigint) { | |
| 773 ASSERT(FitsIntoUint64(bigint)); | |
| 774 return AbsToUint64(bigint); | |
| 775 } | |
| 776 | |
| 777 | |
| 778 RawBigint* BigintOperations::Multiply(const Bigint& a, const Bigint& b) { | |
| 779 ASSERT(IsClamped(a)); | |
| 780 ASSERT(IsClamped(b)); | |
| 781 | |
| 782 intptr_t a_length = a.Length(); | |
| 783 intptr_t b_length = b.Length(); | |
| 784 intptr_t result_length = a_length + b_length; | |
| 785 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 786 | |
| 787 if (a.IsNegative() != b.IsNegative()) { | |
| 788 result.ToggleSign(); | |
| 789 } | |
| 790 | |
| 791 // Comba multiplication: compute each column separately. | |
| 792 // Example: r = a2a1a0 * b2b1b0. | |
| 793 // r = 1 * a0b0 + | |
| 794 // 10 * (a1b0 + a0b1) + | |
| 795 // 100 * (a2b0 + a1b1 + a0b2) + | |
| 796 // 1000 * (a2b1 + a1b2) + | |
| 797 // 10000 * a2b2 | |
| 798 // | |
| 799 // Each column will be accumulated in an integer of type DoubleChunk. We must | |
| 800 // guarantee that the column-sum will not overflow. We achieve this by | |
| 801 // 'blocking' the sum into overflow-free sums followed by propagating the | |
| 802 // overflow. | |
| 803 // | |
| 804 // Each bigint digit fits in kDigitBitSize bits. | |
| 805 // Each product fits in 2*kDigitBitSize bits. | |
| 806 // The accumulator is 8 * sizeof(DoubleChunk) == 2*kDigitBitSize + kCarryBits. | |
| 807 // | |
| 808 // Each time we add a product to the accumulator it could carry one bit into | |
| 809 // the carry bits, supporting kBlockSize = 2^kCarryBits - 1 addition | |
| 810 // operations before the DoubleChunk overflows. | |
| 811 // | |
| 812 // At the end of the column sum and after each batch of kBlockSize additions | |
| 813 // the high kCarryBits+kDigitBitSize of accumulator are flushed to | |
| 814 // accumulator_overflow. | |
| 815 // | |
| 816 // Diagramatically, using one char per 4 bits: | |
| 817 // | |
| 818 // 0aaaaaaa * 0bbbbbbb -> 00pppppppppppppp product of 2 digits | |
| 819 // | | |
| 820 // + ...added to | |
| 821 // v | |
| 822 // ccSSSSSSSsssssss accumulator | |
| 823 // ...flushed to | |
| 824 // 000000000sssssss accumulator | |
| 825 // vvvvvvvvvVVVVVVV accumulator_overflow | |
| 826 // | |
| 827 // 'sssssss' becomes the column sum an overflow is carried to next column: | |
| 828 // | |
| 829 // 000000000VVVVVVV accumulator | |
| 830 // 0000000vvvvvvvvv accumulator_overflow | |
| 831 // | |
| 832 // accumulator_overflow supports 2^(kDigitBitSize + kCarryBits) additions of | |
| 833 // products. | |
| 834 // | |
| 835 // Since the bottom (kDigitBitSize + kCarryBits) bits of accumulator_overflow | |
| 836 // are initialized from the previous column, that uses up the capacity to | |
| 837 // absorb 2^kCarryBits additions. The accumulator_overflow can overflow if | |
| 838 // the column has more than 2^(kDigitBitSize + kCarryBits) - 2^kCarryBits | |
| 839 // elements With current configuration that is 2^36-2^8 elements. That is too | |
| 840 // high to happen in practice. Comba multiplication is O(N^2) so overflow | |
| 841 // won't happen during a human lifespan. | |
| 842 | |
| 843 const intptr_t kCarryBits = 8 * sizeof(DoubleChunk) - 2 * kDigitBitSize; | |
| 844 const intptr_t kBlockSize = (1 << kCarryBits) - 1; | |
| 845 | |
| 846 DoubleChunk accumulator = 0; // Accumulates the result of one column. | |
| 847 DoubleChunk accumulator_overflow = 0; | |
| 848 for (intptr_t i = 0; i < result_length; i++) { | |
| 849 // Example: r = a2a1a0 * b2b1b0. | |
| 850 // For i == 0, compute a0b0. | |
| 851 // i == 1, a1b0 + a0b1 + overflow from i == 0. | |
| 852 // i == 2, a2b0 + a1b1 + a0b2 + overflow from i == 1. | |
| 853 // ... | |
| 854 // The indices into a and b are such that their sum equals i. | |
| 855 intptr_t a_index = Utils::Minimum(a_length - 1, i); | |
| 856 intptr_t b_index = i - a_index; | |
| 857 ASSERT(a_index + b_index == i); | |
| 858 | |
| 859 // Instead of testing for a_index >= 0 && b_index < b_length we compute the | |
| 860 // number of iterations first. | |
| 861 intptr_t iterations = Utils::Minimum(b_length - b_index, a_index + 1); | |
| 862 | |
| 863 // For large products we need extra bit for the overflow. The sum is broken | |
| 864 // into blocks to avoid dealing with the overflow on each iteration. | |
| 865 for (intptr_t j_block = 0; j_block < iterations; j_block += kBlockSize) { | |
| 866 intptr_t j_end = Utils::Minimum(j_block + kBlockSize, iterations); | |
| 867 for (intptr_t j = j_block; j < j_end; j++) { | |
| 868 DoubleChunk chunk_a = a.GetChunkAt(a_index); | |
| 869 DoubleChunk chunk_b = b.GetChunkAt(b_index); | |
| 870 accumulator += chunk_a * chunk_b; | |
| 871 a_index--; | |
| 872 b_index++; | |
| 873 } | |
| 874 accumulator_overflow += (accumulator >> kDigitBitSize); | |
| 875 accumulator &= kDigitMask; | |
| 876 } | |
| 877 result.SetChunkAt(i, static_cast<Chunk>(accumulator)); | |
| 878 // Overflow becomes the initial accumulator for the next column. | |
| 879 accumulator = accumulator_overflow & kDigitMask; | |
| 880 // And the overflow from the overflow becomes the new overflow. | |
| 881 accumulator_overflow = (accumulator_overflow >> kDigitBitSize); | |
| 882 } | |
| 883 ASSERT(accumulator == 0); | |
| 884 ASSERT(accumulator_overflow == 0); | |
| 885 | |
| 886 Clamp(result); | |
| 887 return result.raw(); | |
| 888 } | |
| 889 | |
| 890 | |
| 891 RawBigint* BigintOperations::Divide(const Bigint& a, const Bigint& b) { | |
| 892 Bigint& quotient = Bigint::Handle(); | |
| 893 Bigint& remainder = Bigint::Handle(); | |
| 894 DivideRemainder(a, b, "ient, &remainder); | |
| 895 return quotient.raw(); | |
| 896 } | |
| 897 | |
| 898 | |
| 899 RawBigint* BigintOperations::Modulo(const Bigint& a, const Bigint& b) { | |
| 900 Bigint& quotient = Bigint::Handle(); | |
| 901 Bigint& remainder = Bigint::Handle(); | |
| 902 DivideRemainder(a, b, "ient, &remainder); | |
| 903 // Emulating code in Integer::ArithmeticOp (Euclidian modulo). | |
| 904 if (remainder.IsNegative()) { | |
| 905 if (b.IsNegative()) { | |
| 906 return BigintOperations::Subtract(remainder, b); | |
| 907 } else { | |
| 908 return BigintOperations::Add(remainder, b); | |
| 909 } | |
| 910 } | |
| 911 return remainder.raw(); | |
| 912 } | |
| 913 | |
| 914 | |
| 915 RawBigint* BigintOperations::Remainder(const Bigint& a, const Bigint& b) { | |
| 916 Bigint& quotient = Bigint::Handle(); | |
| 917 Bigint& remainder = Bigint::Handle(); | |
| 918 DivideRemainder(a, b, "ient, &remainder); | |
| 919 return remainder.raw(); | |
| 920 } | |
| 921 | |
| 922 | |
| 923 RawBigint* BigintOperations::ShiftLeft(const Bigint& bigint, intptr_t amount) { | |
| 924 ASSERT(IsClamped(bigint)); | |
| 925 ASSERT(amount >= 0); | |
| 926 intptr_t bigint_length = bigint.Length(); | |
| 927 if (bigint.IsZero()) { | |
| 928 return Zero(); | |
| 929 } | |
| 930 // TODO(floitsch): can we reuse the input? | |
| 931 if (amount == 0) { | |
| 932 return Copy(bigint); | |
| 933 } | |
| 934 intptr_t digit_shift = amount / kDigitBitSize; | |
| 935 intptr_t bit_shift = amount % kDigitBitSize; | |
| 936 if (bit_shift == 0) { | |
| 937 const Bigint& result = | |
| 938 Bigint::Handle(Bigint::Allocate(bigint_length + digit_shift)); | |
| 939 for (intptr_t i = 0; i < digit_shift; i++) { | |
| 940 result.SetChunkAt(i, 0); | |
| 941 } | |
| 942 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 943 result.SetChunkAt(i + digit_shift, bigint.GetChunkAt(i)); | |
| 944 } | |
| 945 if (bigint.IsNegative()) { | |
| 946 result.ToggleSign(); | |
| 947 } | |
| 948 return result.raw(); | |
| 949 } else { | |
| 950 const Bigint& result = | |
| 951 Bigint::Handle(Bigint::Allocate(bigint_length + digit_shift + 1)); | |
| 952 for (intptr_t i = 0; i < digit_shift; i++) { | |
| 953 result.SetChunkAt(i, 0); | |
| 954 } | |
| 955 Chunk carry = 0; | |
| 956 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 957 Chunk digit = bigint.GetChunkAt(i); | |
| 958 Chunk shifted_digit = ((digit << bit_shift) & kDigitMask) + carry; | |
| 959 result.SetChunkAt(i + digit_shift, shifted_digit); | |
| 960 carry = digit >> (kDigitBitSize - bit_shift); | |
| 961 } | |
| 962 result.SetChunkAt(bigint_length + digit_shift, carry); | |
| 963 if (bigint.IsNegative()) { | |
| 964 result.ToggleSign(); | |
| 965 } | |
| 966 Clamp(result); | |
| 967 return result.raw(); | |
| 968 } | |
| 969 } | |
| 970 | |
| 971 | |
| 972 RawBigint* BigintOperations::ShiftRight(const Bigint& bigint, intptr_t amount) { | |
| 973 ASSERT(IsClamped(bigint)); | |
| 974 ASSERT(amount >= 0); | |
| 975 intptr_t bigint_length = bigint.Length(); | |
| 976 if (bigint.IsZero()) { | |
| 977 return Zero(); | |
| 978 } | |
| 979 // TODO(floitsch): can we reuse the input? | |
| 980 if (amount == 0) { | |
| 981 return Copy(bigint); | |
| 982 } | |
| 983 intptr_t digit_shift = amount / kDigitBitSize; | |
| 984 intptr_t bit_shift = amount % kDigitBitSize; | |
| 985 if (digit_shift >= bigint_length) { | |
| 986 return bigint.IsNegative() ? MinusOne() : Zero(); | |
| 987 } | |
| 988 | |
| 989 const Bigint& result = | |
| 990 Bigint::Handle(Bigint::Allocate(bigint_length - digit_shift)); | |
| 991 if (bit_shift == 0) { | |
| 992 for (intptr_t i = 0; i < bigint_length - digit_shift; i++) { | |
| 993 result.SetChunkAt(i, bigint.GetChunkAt(i + digit_shift)); | |
| 994 } | |
| 995 } else { | |
| 996 Chunk carry = 0; | |
| 997 for (intptr_t i = bigint_length - 1; i >= digit_shift; i--) { | |
| 998 Chunk digit = bigint.GetChunkAt(i); | |
| 999 Chunk shifted_digit = (digit >> bit_shift) + carry; | |
| 1000 result.SetChunkAt(i - digit_shift, shifted_digit); | |
| 1001 carry = (digit << (kDigitBitSize - bit_shift)) & kDigitMask; | |
| 1002 } | |
| 1003 Clamp(result); | |
| 1004 } | |
| 1005 | |
| 1006 if (bigint.IsNegative()) { | |
| 1007 result.ToggleSign(); | |
| 1008 // If the input is negative then the result needs to be rounded down. | |
| 1009 // Example: -5 >> 2 => -2 | |
| 1010 bool needs_rounding = false; | |
| 1011 for (intptr_t i = 0; i < digit_shift; i++) { | |
| 1012 if (bigint.GetChunkAt(i) != 0) { | |
| 1013 needs_rounding = true; | |
| 1014 break; | |
| 1015 } | |
| 1016 } | |
| 1017 if (!needs_rounding && (bit_shift > 0)) { | |
| 1018 Chunk digit = bigint.GetChunkAt(digit_shift); | |
| 1019 needs_rounding = (digit << (kChunkBitSize - bit_shift)) != 0; | |
| 1020 } | |
| 1021 if (needs_rounding) { | |
| 1022 Bigint& one = Bigint::Handle(One()); | |
| 1023 return Subtract(result, one); | |
| 1024 } | |
| 1025 } | |
| 1026 | |
| 1027 return result.raw(); | |
| 1028 } | |
| 1029 | |
| 1030 | |
| 1031 RawBigint* BigintOperations::BitAnd(const Bigint& a, const Bigint& b) { | |
| 1032 ASSERT(IsClamped(a)); | |
| 1033 ASSERT(IsClamped(b)); | |
| 1034 | |
| 1035 if (a.IsZero() || b.IsZero()) { | |
| 1036 return Zero(); | |
| 1037 } | |
| 1038 if (a.IsNegative() && !b.IsNegative()) { | |
| 1039 return BitAnd(b, a); | |
| 1040 } | |
| 1041 if ((a.IsNegative() == b.IsNegative()) && (a.Length() < b.Length())) { | |
| 1042 return BitAnd(b, a); | |
| 1043 } | |
| 1044 | |
| 1045 intptr_t a_length = a.Length(); | |
| 1046 intptr_t b_length = b.Length(); | |
| 1047 intptr_t min_length = Utils::Minimum(a_length, b_length); | |
| 1048 intptr_t max_length = Utils::Maximum(a_length, b_length); | |
| 1049 if (!b.IsNegative()) { | |
| 1050 ASSERT(!a.IsNegative()); | |
| 1051 intptr_t result_length = min_length; | |
| 1052 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1053 | |
| 1054 for (intptr_t i = 0; i < min_length; i++) { | |
| 1055 result.SetChunkAt(i, a.GetChunkAt(i) & b.GetChunkAt(i)); | |
| 1056 } | |
| 1057 Clamp(result); | |
| 1058 return result.raw(); | |
| 1059 } | |
| 1060 | |
| 1061 // Bigints encode negative values by storing the absolute value and the sign | |
| 1062 // separately. To do bit operations we need to simulate numbers that are | |
| 1063 // implemented as two's complement. | |
| 1064 // The negation of a positive number x would be encoded as follows in | |
| 1065 // two's complement: n = ~(x - 1). | |
| 1066 // The inverse transformation is hence (~n) + 1. | |
| 1067 | |
| 1068 if (!a.IsNegative()) { | |
| 1069 ASSERT(b.IsNegative()); | |
| 1070 // The result will be positive. | |
| 1071 intptr_t result_length = a_length; | |
| 1072 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1073 Chunk borrow = 1; | |
| 1074 for (intptr_t i = 0; i < min_length; i++) { | |
| 1075 Chunk b_digit = b.GetChunkAt(i) - borrow; | |
| 1076 result.SetChunkAt(i, a.GetChunkAt(i) & (~b_digit) & kDigitMask); | |
| 1077 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1078 } | |
| 1079 for (intptr_t i = min_length; i < a_length; i++) { | |
| 1080 result.SetChunkAt(i, a.GetChunkAt(i) & (kDigitMaxValue - borrow)); | |
| 1081 borrow = 0; | |
| 1082 } | |
| 1083 Clamp(result); | |
| 1084 return result.raw(); | |
| 1085 } | |
| 1086 | |
| 1087 ASSERT(a.IsNegative()); | |
| 1088 ASSERT(b.IsNegative()); | |
| 1089 // The result will be negative. | |
| 1090 // We need to convert a and b to two's complement. Do the bit-operation there, | |
| 1091 // and transform the resulting bits from two's complement back to separated | |
| 1092 // magnitude and sign. | |
| 1093 // a & b is therefore computed as ~((~(a - 1)) & (~(b - 1))) + 1 which is | |
| 1094 // equal to ((a-1) | (b-1)) + 1. | |
| 1095 intptr_t result_length = max_length + 1; | |
| 1096 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1097 result.ToggleSign(); | |
| 1098 Chunk a_borrow = 1; | |
| 1099 Chunk b_borrow = 1; | |
| 1100 Chunk result_carry = 1; | |
| 1101 ASSERT(a_length >= b_length); | |
| 1102 for (intptr_t i = 0; i < b_length; i++) { | |
| 1103 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | |
| 1104 Chunk b_digit = b.GetChunkAt(i) - b_borrow; | |
| 1105 Chunk result_chunk = ((a_digit | b_digit) & kDigitMask) + result_carry; | |
| 1106 result.SetChunkAt(i, result_chunk & kDigitMask); | |
| 1107 a_borrow = a_digit >> (kChunkBitSize - 1); | |
| 1108 b_borrow = b_digit >> (kChunkBitSize - 1); | |
| 1109 result_carry = result_chunk >> kDigitBitSize; | |
| 1110 } | |
| 1111 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1112 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | |
| 1113 Chunk b_digit = -b_borrow; | |
| 1114 Chunk result_chunk = ((a_digit | b_digit) & kDigitMask) + result_carry; | |
| 1115 result.SetChunkAt(i, result_chunk & kDigitMask); | |
| 1116 a_borrow = a_digit >> (kChunkBitSize - 1); | |
| 1117 b_borrow = 0; | |
| 1118 result_carry = result_chunk >> kDigitBitSize; | |
| 1119 } | |
| 1120 Chunk a_digit = -a_borrow; | |
| 1121 Chunk b_digit = -b_borrow; | |
| 1122 Chunk result_chunk = ((a_digit | b_digit) & kDigitMask) + result_carry; | |
| 1123 result.SetChunkAt(a_length, result_chunk & kDigitMask); | |
| 1124 Clamp(result); | |
| 1125 return result.raw(); | |
| 1126 } | |
| 1127 | |
| 1128 | |
| 1129 RawBigint* BigintOperations::BitOr(const Bigint& a, const Bigint& b) { | |
| 1130 ASSERT(IsClamped(a)); | |
| 1131 ASSERT(IsClamped(b)); | |
| 1132 | |
| 1133 if (a.IsNegative() && !b.IsNegative()) { | |
| 1134 return BitOr(b, a); | |
| 1135 } | |
| 1136 if ((a.IsNegative() == b.IsNegative()) && (a.Length() < b.Length())) { | |
| 1137 return BitOr(b, a); | |
| 1138 } | |
| 1139 | |
| 1140 intptr_t a_length = a.Length(); | |
| 1141 intptr_t b_length = b.Length(); | |
| 1142 intptr_t min_length = Utils::Minimum(a_length, b_length); | |
| 1143 intptr_t max_length = Utils::Maximum(a_length, b_length); | |
| 1144 if (!b.IsNegative()) { | |
| 1145 ASSERT(!a.IsNegative()); | |
| 1146 intptr_t result_length = max_length; | |
| 1147 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1148 | |
| 1149 ASSERT(a_length >= b_length); | |
| 1150 for (intptr_t i = 0; i < b_length; i++) { | |
| 1151 result.SetChunkAt(i, a.GetChunkAt(i) | b.GetChunkAt(i)); | |
| 1152 } | |
| 1153 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1154 result.SetChunkAt(i, a.GetChunkAt(i)); | |
| 1155 } | |
| 1156 return result.raw(); | |
| 1157 } | |
| 1158 | |
| 1159 // Bigints encode negative values by storing the absolute value and the sign | |
| 1160 // separately. To do bit operations we need to simulate numbers that are | |
| 1161 // implemented as two's complement. | |
| 1162 // The negation of a positive number x would be encoded as follows in | |
| 1163 // two's complement: n = ~(x - 1). | |
| 1164 // The inverse transformation is hence (~n) + 1. | |
| 1165 | |
| 1166 if (!a.IsNegative()) { | |
| 1167 ASSERT(b.IsNegative()); | |
| 1168 if (a.IsZero()) { | |
| 1169 return Copy(b); | |
| 1170 } | |
| 1171 // The result will be negative. | |
| 1172 // We need to convert b to two's complement. Do the bit-operation there, | |
| 1173 // and transform the resulting bits from two's complement back to separated | |
| 1174 // magnitude and sign. | |
| 1175 // a | b is therefore computed as ~((a & (~(b - 1))) + 1 which is | |
| 1176 // equal to ((~a) & (b-1)) + 1. | |
| 1177 intptr_t result_length = b_length; | |
| 1178 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1179 result.ToggleSign(); | |
| 1180 Chunk borrow = 1; | |
| 1181 Chunk result_carry = 1; | |
| 1182 for (intptr_t i = 0; i < min_length; i++) { | |
| 1183 Chunk a_digit = a.GetChunkAt(i); | |
| 1184 Chunk b_digit = b.GetChunkAt(i) - borrow; | |
| 1185 Chunk result_digit = ((~a_digit) & b_digit & kDigitMask) + result_carry; | |
| 1186 result.SetChunkAt(i, result_digit & kDigitMask); | |
| 1187 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1188 result_carry = result_digit >> kDigitBitSize; | |
| 1189 } | |
| 1190 ASSERT(result_carry == 0); | |
| 1191 for (intptr_t i = min_length; i < b_length; i++) { | |
| 1192 Chunk b_digit = b.GetChunkAt(i) - borrow; | |
| 1193 Chunk result_digit = (b_digit & kDigitMask) + result_carry; | |
| 1194 result.SetChunkAt(i, result_digit & kDigitMask); | |
| 1195 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1196 result_carry = result_digit >> kDigitBitSize; | |
| 1197 } | |
| 1198 ASSERT(result_carry == 0); | |
| 1199 Clamp(result); | |
| 1200 return result.raw(); | |
| 1201 } | |
| 1202 | |
| 1203 ASSERT(a.IsNegative()); | |
| 1204 ASSERT(b.IsNegative()); | |
| 1205 // The result will be negative. | |
| 1206 // We need to convert a and b to two's complement. Do the bit-operation there, | |
| 1207 // and transform the resulting bits from two's complement back to separated | |
| 1208 // magnitude and sign. | |
| 1209 // a & b is therefore computed as ~((~(a - 1)) | (~(b - 1))) + 1 which is | |
| 1210 // equal to ((a-1) & (b-1)) + 1. | |
| 1211 ASSERT(a_length >= b_length); | |
| 1212 ASSERT(min_length == b_length); | |
| 1213 intptr_t result_length = min_length + 1; | |
| 1214 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1215 result.ToggleSign(); | |
| 1216 Chunk a_borrow = 1; | |
| 1217 Chunk b_borrow = 1; | |
| 1218 Chunk result_carry = 1; | |
| 1219 for (intptr_t i = 0; i < b_length; i++) { | |
| 1220 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | |
| 1221 Chunk b_digit = b.GetChunkAt(i) - b_borrow; | |
| 1222 Chunk result_chunk = ((a_digit & b_digit) & kDigitMask) + result_carry; | |
| 1223 result.SetChunkAt(i, result_chunk & kDigitMask); | |
| 1224 a_borrow = a_digit >> (kChunkBitSize - 1); | |
| 1225 b_borrow = b_digit >> (kChunkBitSize - 1); | |
| 1226 result_carry = result_chunk >> kDigitBitSize; | |
| 1227 } | |
| 1228 result.SetChunkAt(b_length, result_carry); | |
| 1229 Clamp(result); | |
| 1230 return result.raw(); | |
| 1231 } | |
| 1232 | |
| 1233 | |
| 1234 RawBigint* BigintOperations::BitXor(const Bigint& a, const Bigint& b) { | |
| 1235 ASSERT(IsClamped(a)); | |
| 1236 ASSERT(IsClamped(b)); | |
| 1237 | |
| 1238 if (a.IsZero()) { | |
| 1239 return Copy(b); | |
| 1240 } | |
| 1241 if (b.IsZero()) { | |
| 1242 return Copy(a); | |
| 1243 } | |
| 1244 if (a.IsNegative() && !b.IsNegative()) { | |
| 1245 return BitXor(b, a); | |
| 1246 } | |
| 1247 if ((a.IsNegative() == b.IsNegative()) && (a.Length() < b.Length())) { | |
| 1248 return BitXor(b, a); | |
| 1249 } | |
| 1250 | |
| 1251 intptr_t a_length = a.Length(); | |
| 1252 intptr_t b_length = b.Length(); | |
| 1253 intptr_t min_length = Utils::Minimum(a_length, b_length); | |
| 1254 intptr_t max_length = Utils::Maximum(a_length, b_length); | |
| 1255 if (!b.IsNegative()) { | |
| 1256 ASSERT(!a.IsNegative()); | |
| 1257 intptr_t result_length = max_length; | |
| 1258 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1259 | |
| 1260 ASSERT(a_length >= b_length); | |
| 1261 for (intptr_t i = 0; i < b_length; i++) { | |
| 1262 result.SetChunkAt(i, a.GetChunkAt(i) ^ b.GetChunkAt(i)); | |
| 1263 } | |
| 1264 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1265 result.SetChunkAt(i, a.GetChunkAt(i)); | |
| 1266 } | |
| 1267 Clamp(result); | |
| 1268 return result.raw(); | |
| 1269 } | |
| 1270 | |
| 1271 // Bigints encode negative values by storing the absolute value and the sign | |
| 1272 // separately. To do bit operations we need to simulate numbers that are | |
| 1273 // implemented as two's complement. | |
| 1274 // The negation of a positive number x would be encoded as follows in | |
| 1275 // two's complement: n = ~(x - 1). | |
| 1276 // The inverse transformation is hence (~n) + 1. | |
| 1277 | |
| 1278 if (!a.IsNegative()) { | |
| 1279 ASSERT(b.IsNegative()); | |
| 1280 // The result will be negative. | |
| 1281 // We need to convert b to two's complement. Do the bit-operation there, | |
| 1282 // and transform the resulting bits from two's complement back to separated | |
| 1283 // magnitude and sign. | |
| 1284 // a ^ b is therefore computed as ~((a ^ (~(b - 1))) + 1. | |
| 1285 intptr_t result_length = max_length + 1; | |
| 1286 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1287 result.ToggleSign(); | |
| 1288 Chunk borrow = 1; | |
| 1289 Chunk result_carry = 1; | |
| 1290 for (intptr_t i = 0; i < min_length; i++) { | |
| 1291 Chunk a_digit = a.GetChunkAt(i); | |
| 1292 Chunk b_digit = b.GetChunkAt(i) - borrow; | |
| 1293 Chunk result_digit = | |
| 1294 ((~(a_digit ^ ~b_digit)) & kDigitMask) + result_carry; | |
| 1295 result.SetChunkAt(i, result_digit & kDigitMask); | |
| 1296 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1297 result_carry = result_digit >> kDigitBitSize; | |
| 1298 } | |
| 1299 for (intptr_t i = min_length; i < a_length; i++) { | |
| 1300 Chunk a_digit = a.GetChunkAt(i); | |
| 1301 Chunk b_digit = -borrow; | |
| 1302 Chunk result_digit = | |
| 1303 ((~(a_digit ^ ~b_digit)) & kDigitMask) + result_carry; | |
| 1304 result.SetChunkAt(i, result_digit & kDigitMask); | |
| 1305 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1306 result_carry = result_digit >> kDigitBitSize; | |
| 1307 } | |
| 1308 for (intptr_t i = min_length; i < b_length; i++) { | |
| 1309 // a_digit = 0. | |
| 1310 Chunk b_digit = b.GetChunkAt(i) - borrow; | |
| 1311 Chunk result_digit = (b_digit & kDigitMask) + result_carry; | |
| 1312 result.SetChunkAt(i, result_digit & kDigitMask); | |
| 1313 borrow = b_digit >> (kChunkBitSize - 1); | |
| 1314 result_carry = result_digit >> kDigitBitSize; | |
| 1315 } | |
| 1316 result.SetChunkAt(max_length, result_carry); | |
| 1317 Clamp(result); | |
| 1318 return result.raw(); | |
| 1319 } | |
| 1320 | |
| 1321 ASSERT(a.IsNegative()); | |
| 1322 ASSERT(b.IsNegative()); | |
| 1323 // The result will be positive. | |
| 1324 // We need to convert a and b to two's complement, do the bit-operation there, | |
| 1325 // and simply store the result. | |
| 1326 // a ^ b is therefore computed as (~(a - 1)) ^ (~(b - 1)). | |
| 1327 ASSERT(a_length >= b_length); | |
| 1328 ASSERT(max_length == a_length); | |
| 1329 intptr_t result_length = max_length; | |
| 1330 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1331 Chunk a_borrow = 1; | |
| 1332 Chunk b_borrow = 1; | |
| 1333 for (intptr_t i = 0; i < b_length; i++) { | |
| 1334 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | |
| 1335 Chunk b_digit = b.GetChunkAt(i) - b_borrow; | |
| 1336 Chunk result_chunk = (~a_digit) ^ (~b_digit); | |
| 1337 result.SetChunkAt(i, result_chunk & kDigitMask); | |
| 1338 a_borrow = a_digit >> (kChunkBitSize - 1); | |
| 1339 b_borrow = b_digit >> (kChunkBitSize - 1); | |
| 1340 } | |
| 1341 ASSERT(b_borrow == 0); | |
| 1342 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1343 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | |
| 1344 // (~a_digit) ^ 0xFFF..FFF == a_digit. | |
| 1345 result.SetChunkAt(i, a_digit & kDigitMask); | |
| 1346 a_borrow = a_digit >> (kChunkBitSize - 1); | |
| 1347 } | |
| 1348 ASSERT(a_borrow == 0); | |
| 1349 Clamp(result); | |
| 1350 return result.raw(); | |
| 1351 } | |
| 1352 | |
| 1353 | |
| 1354 RawBigint* BigintOperations::BitNot(const Bigint& bigint) { | |
| 1355 if (bigint.IsZero()) { | |
| 1356 return MinusOne(); | |
| 1357 } | |
| 1358 const Bigint& one_bigint = Bigint::Handle(One()); | |
| 1359 if (bigint.IsNegative()) { | |
| 1360 return UnsignedSubtract(bigint, one_bigint); | |
| 1361 } else { | |
| 1362 const Bigint& result = Bigint::Handle(UnsignedAdd(bigint, one_bigint)); | |
| 1363 result.ToggleSign(); | |
| 1364 return result.raw(); | |
| 1365 } | |
| 1366 } | |
| 1367 | |
| 1368 | |
| 1369 int64_t BigintOperations::BitLength(const Bigint& bigint) { | |
| 1370 ASSERT(IsClamped(bigint)); | |
| 1371 intptr_t length = bigint.Length(); | |
| 1372 if (length == 0) return 0; | |
| 1373 intptr_t last = length - 1; | |
| 1374 | |
| 1375 Chunk high_chunk = bigint.GetChunkAt(last); | |
| 1376 ASSERT(high_chunk != 0); | |
| 1377 int64_t bit_length = | |
| 1378 static_cast<int64_t>(kDigitBitSize) * last + CountBits(high_chunk); | |
| 1379 | |
| 1380 if (bigint.IsNegative()) { | |
| 1381 // We are calculating the 2's complement bitlength but we have a sign and | |
| 1382 // magnitude representation. The length is the same except when the | |
| 1383 // magnitude is an exact power of two, 2^k. In 2's complement format, | |
| 1384 // -(2^k) takes one fewer bit than (2^k). | |
| 1385 | |
| 1386 if ((high_chunk & (high_chunk - 1)) == 0) { // Single bit set? | |
| 1387 for (intptr_t i = 0; i < last; i++) { | |
| 1388 if (bigint.GetChunkAt(i) != 0) return bit_length; | |
| 1389 } | |
| 1390 bit_length -= 1; | |
| 1391 } | |
| 1392 } | |
| 1393 return bit_length; | |
| 1394 } | |
| 1395 | |
| 1396 | |
| 1397 int BigintOperations::Compare(const Bigint& a, const Bigint& b) { | |
| 1398 bool a_is_negative = a.IsNegative(); | |
| 1399 bool b_is_negative = b.IsNegative(); | |
| 1400 if (a_is_negative != b_is_negative) { | |
| 1401 return a_is_negative ? -1 : 1; | |
| 1402 } | |
| 1403 | |
| 1404 if (a_is_negative) { | |
| 1405 return -UnsignedCompare(a, b); | |
| 1406 } | |
| 1407 return UnsignedCompare(a, b); | |
| 1408 } | |
| 1409 | |
| 1410 | |
| 1411 void BigintOperations::FromHexCString(const char* hex_string, | |
| 1412 const Bigint& value) { | |
| 1413 ASSERT(hex_string[0] != '-'); | |
| 1414 intptr_t bigint_length = ComputeChunkLength(hex_string); | |
| 1415 // The bigint's least significant digit (lsd) is at position 0, whereas the | |
| 1416 // given string has it's lsd at the last position. | |
| 1417 // The hex_i index, pointing into the string, starts therefore at the end, | |
| 1418 // whereas the bigint-index (i) starts at 0. | |
| 1419 const intptr_t hex_length = strlen(hex_string); | |
| 1420 if (hex_length < 0) { | |
| 1421 FATAL("Fatal error in BigintOperations::FromHexCString: string too long"); | |
| 1422 } | |
| 1423 intptr_t hex_i = hex_length - 1; | |
| 1424 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 1425 Chunk digit = 0; | |
| 1426 int shift = 0; | |
| 1427 for (int j = 0; j < kHexCharsPerDigit; j++) { | |
| 1428 // Reads a block of hexadecimal digits and stores it in 'digit'. | |
| 1429 // Ex: "0123456" with kHexCharsPerDigit == 3, hex_i == 6, reads "456". | |
| 1430 if (hex_i < 0) { | |
| 1431 break; | |
| 1432 } | |
| 1433 ASSERT(hex_i >= 0); | |
| 1434 char c = hex_string[hex_i--]; | |
| 1435 ASSERT(Utils::IsHexDigit(c)); | |
| 1436 digit += static_cast<Chunk>(Utils::HexDigitToInt(c)) << shift; | |
| 1437 shift += 4; | |
| 1438 } | |
| 1439 value.SetChunkAt(i, digit); | |
| 1440 } | |
| 1441 ASSERT(hex_i == -1); | |
| 1442 Clamp(value); | |
| 1443 } | |
| 1444 | |
| 1445 | |
| 1446 RawBigint* BigintOperations::AddSubtract(const Bigint& a, | |
| 1447 const Bigint& b, | |
| 1448 bool negate_b) { | |
| 1449 ASSERT(IsClamped(a)); | |
| 1450 ASSERT(IsClamped(b)); | |
| 1451 Bigint& result = Bigint::Handle(); | |
| 1452 // We perform the subtraction by simulating a negation of the b-argument. | |
| 1453 bool b_is_negative = negate_b ? !b.IsNegative() : b.IsNegative(); | |
| 1454 | |
| 1455 // If both are of the same sign, then we can compute the unsigned addition | |
| 1456 // and then simply adjust the sign (if necessary). | |
| 1457 // Ex: -3 + -5 -> -(3 + 5) | |
| 1458 if (a.IsNegative() == b_is_negative) { | |
| 1459 result = UnsignedAdd(a, b); | |
| 1460 result.SetSign(b_is_negative); | |
| 1461 ASSERT(IsClamped(result)); | |
| 1462 return result.raw(); | |
| 1463 } | |
| 1464 | |
| 1465 // The signs differ. | |
| 1466 // Take the number with small magnitude and subtract its absolute value from | |
| 1467 // the absolute value of the other number. Then adjust the sign, if necessary. | |
| 1468 // The sign is the same as for the number with the greater magnitude. | |
| 1469 // Ex: -8 + 3 -> -(8 - 3) | |
| 1470 // 8 + -3 -> (8 - 3) | |
| 1471 // -3 + 8 -> (8 - 3) | |
| 1472 // 3 + -8 -> -(8 - 3) | |
| 1473 int comp = UnsignedCompare(a, b); | |
| 1474 if (comp < 0) { | |
| 1475 result = UnsignedSubtract(b, a); | |
| 1476 result.SetSign(b_is_negative); | |
| 1477 } else if (comp > 0) { | |
| 1478 result = UnsignedSubtract(a, b); | |
| 1479 result.SetSign(a.IsNegative()); | |
| 1480 } else { | |
| 1481 return Zero(); | |
| 1482 } | |
| 1483 ASSERT(IsClamped(result)); | |
| 1484 return result.raw(); | |
| 1485 } | |
| 1486 | |
| 1487 | |
| 1488 int BigintOperations::UnsignedCompare(const Bigint& a, const Bigint& b) { | |
| 1489 ASSERT(IsClamped(a)); | |
| 1490 ASSERT(IsClamped(b)); | |
| 1491 intptr_t a_length = a.Length(); | |
| 1492 intptr_t b_length = b.Length(); | |
| 1493 if (a_length < b_length) return -1; | |
| 1494 if (a_length > b_length) return 1; | |
| 1495 for (intptr_t i = a_length - 1; i >= 0; i--) { | |
| 1496 Chunk digit_a = a.GetChunkAt(i); | |
| 1497 Chunk digit_b = b.GetChunkAt(i); | |
| 1498 if (digit_a < digit_b) return -1; | |
| 1499 if (digit_a > digit_b) return 1; | |
| 1500 // Else look at the next digit. | |
| 1501 } | |
| 1502 return 0; // They are equal. | |
| 1503 } | |
| 1504 | |
| 1505 | |
| 1506 int BigintOperations::UnsignedCompareNonClamped( | |
| 1507 const Bigint& a, const Bigint& b) { | |
| 1508 intptr_t a_length = a.Length(); | |
| 1509 intptr_t b_length = b.Length(); | |
| 1510 while (a_length > b_length) { | |
| 1511 if (a.GetChunkAt(a_length - 1) != 0) return 1; | |
| 1512 a_length--; | |
| 1513 } | |
| 1514 while (b_length > a_length) { | |
| 1515 if (b.GetChunkAt(b_length - 1) != 0) return -1; | |
| 1516 b_length--; | |
| 1517 } | |
| 1518 for (intptr_t i = a_length - 1; i >= 0; i--) { | |
| 1519 Chunk digit_a = a.GetChunkAt(i); | |
| 1520 Chunk digit_b = b.GetChunkAt(i); | |
| 1521 if (digit_a < digit_b) return -1; | |
| 1522 if (digit_a > digit_b) return 1; | |
| 1523 // Else look at the next digit. | |
| 1524 } | |
| 1525 return 0; // They are equal. | |
| 1526 } | |
| 1527 | |
| 1528 | |
| 1529 RawBigint* BigintOperations::UnsignedAdd(const Bigint& a, const Bigint& b) { | |
| 1530 ASSERT(IsClamped(a)); | |
| 1531 ASSERT(IsClamped(b)); | |
| 1532 | |
| 1533 intptr_t a_length = a.Length(); | |
| 1534 intptr_t b_length = b.Length(); | |
| 1535 if (a_length < b_length) { | |
| 1536 return UnsignedAdd(b, a); | |
| 1537 } | |
| 1538 | |
| 1539 // We might request too much space, in which case we will adjust the length | |
| 1540 // afterwards. | |
| 1541 intptr_t result_length = a_length + 1; | |
| 1542 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1543 | |
| 1544 Chunk carry = 0; | |
| 1545 // b has fewer digits than a. | |
| 1546 ASSERT(b_length <= a_length); | |
| 1547 for (intptr_t i = 0; i < b_length; i++) { | |
| 1548 Chunk sum = a.GetChunkAt(i) + b.GetChunkAt(i) + carry; | |
| 1549 result.SetChunkAt(i, sum & kDigitMask); | |
| 1550 carry = sum >> kDigitBitSize; | |
| 1551 } | |
| 1552 // Copy over the remaining digits of a, but don't forget the carry. | |
| 1553 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1554 Chunk sum = a.GetChunkAt(i) + carry; | |
| 1555 result.SetChunkAt(i, sum & kDigitMask); | |
| 1556 carry = sum >> kDigitBitSize; | |
| 1557 } | |
| 1558 // Shrink the result if there was no overflow. Otherwise apply the carry. | |
| 1559 if (carry == 0) { | |
| 1560 // TODO(floitsch): We change the size of bigint-objects here. | |
| 1561 result.SetLength(a_length); | |
| 1562 } else { | |
| 1563 result.SetChunkAt(a_length, carry); | |
| 1564 } | |
| 1565 ASSERT(IsClamped(result)); | |
| 1566 return result.raw(); | |
| 1567 } | |
| 1568 | |
| 1569 | |
| 1570 RawBigint* BigintOperations::UnsignedSubtract(const Bigint& a, | |
| 1571 const Bigint& b) { | |
| 1572 ASSERT(IsClamped(a)); | |
| 1573 ASSERT(IsClamped(b)); | |
| 1574 ASSERT(UnsignedCompare(a, b) >= 0); | |
| 1575 | |
| 1576 const int kSignBitPos = Bigint::kChunkSize * kBitsPerByte - 1; | |
| 1577 | |
| 1578 intptr_t a_length = a.Length(); | |
| 1579 intptr_t b_length = b.Length(); | |
| 1580 | |
| 1581 // We might request too much space, in which case we will adjust the length | |
| 1582 // afterwards. | |
| 1583 intptr_t result_length = a_length; | |
| 1584 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1585 | |
| 1586 Chunk borrow = 0; | |
| 1587 ASSERT(b_length <= a_length); | |
| 1588 for (intptr_t i = 0; i < b_length; i++) { | |
| 1589 Chunk difference = a.GetChunkAt(i) - b.GetChunkAt(i) - borrow; | |
| 1590 result.SetChunkAt(i, difference & kDigitMask); | |
| 1591 borrow = difference >> kSignBitPos; | |
| 1592 ASSERT((borrow == 0) || (borrow == 1)); | |
| 1593 } | |
| 1594 // Copy over the remaining digits of a, but don't forget the borrow. | |
| 1595 for (intptr_t i = b_length; i < a_length; i++) { | |
| 1596 Chunk difference = a.GetChunkAt(i) - borrow; | |
| 1597 result.SetChunkAt(i, difference & kDigitMask); | |
| 1598 borrow = (difference >> kSignBitPos); | |
| 1599 ASSERT((borrow == 0) || (borrow == 1)); | |
| 1600 } | |
| 1601 ASSERT(borrow == 0); | |
| 1602 Clamp(result); | |
| 1603 return result.raw(); | |
| 1604 } | |
| 1605 | |
| 1606 | |
| 1607 RawBigint* BigintOperations::MultiplyWithDigit( | |
| 1608 const Bigint& bigint, Chunk digit) { | |
| 1609 ASSERT(digit <= kDigitMaxValue); | |
| 1610 if (digit == 0) return Zero(); | |
| 1611 if (bigint.IsZero()) return Zero(); | |
| 1612 | |
| 1613 intptr_t length = bigint.Length(); | |
| 1614 intptr_t result_length = length + 1; | |
| 1615 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | |
| 1616 | |
| 1617 Chunk carry = 0; | |
| 1618 for (intptr_t i = 0; i < length; i++) { | |
| 1619 Chunk chunk = bigint.GetChunkAt(i); | |
| 1620 DoubleChunk product = (static_cast<DoubleChunk>(chunk) * digit) + carry; | |
| 1621 result.SetChunkAt(i, static_cast<Chunk>(product & kDigitMask)); | |
| 1622 carry = static_cast<Chunk>(product >> kDigitBitSize); | |
| 1623 } | |
| 1624 result.SetChunkAt(length, carry); | |
| 1625 | |
| 1626 result.SetSign(bigint.IsNegative()); | |
| 1627 Clamp(result); | |
| 1628 return result.raw(); | |
| 1629 } | |
| 1630 | |
| 1631 | |
| 1632 void BigintOperations::DivideRemainder( | |
| 1633 const Bigint& a, const Bigint& b, Bigint* quotient, Bigint* remainder) { | |
| 1634 // TODO(floitsch): This function is very memory-intensive since all | |
| 1635 // intermediate bigint results are allocated in new memory. It would be | |
| 1636 // much more efficient to reuse the space of temporary intermediate variables. | |
| 1637 ASSERT(IsClamped(a)); | |
| 1638 ASSERT(IsClamped(b)); | |
| 1639 ASSERT(!b.IsZero()); | |
| 1640 | |
| 1641 int comp = UnsignedCompare(a, b); | |
| 1642 if (comp < 0) { | |
| 1643 (*quotient) = Zero(); | |
| 1644 (*remainder) = Copy(a); // TODO(floitsch): can we reuse the input? | |
| 1645 return; | |
| 1646 } else if (comp == 0) { | |
| 1647 (*quotient) = One(); | |
| 1648 quotient->SetSign(a.IsNegative() != b.IsNegative()); | |
| 1649 (*remainder) = Zero(); | |
| 1650 return; | |
| 1651 } | |
| 1652 | |
| 1653 intptr_t b_length = b.Length(); | |
| 1654 | |
| 1655 if (b_length == 1) { | |
| 1656 const Bigint& dividend_quotient = Bigint::Handle(Copy(a)); | |
| 1657 Chunk remainder_digit = | |
| 1658 BigintOperations::InplaceUnsignedDivideRemainderDigit( | |
| 1659 dividend_quotient, b.GetChunkAt(0)); | |
| 1660 dividend_quotient.SetSign(a.IsNegative() != b.IsNegative()); | |
| 1661 *quotient = dividend_quotient.raw(); | |
| 1662 *remainder = Bigint::Allocate(1); | |
| 1663 remainder->SetChunkAt(0, remainder_digit); | |
| 1664 remainder->SetSign(a.IsNegative()); | |
| 1665 Clamp(*remainder); | |
| 1666 return; | |
| 1667 } | |
| 1668 | |
| 1669 // High level description: | |
| 1670 // The algorithm is basically the algorithm that is taught in school: | |
| 1671 // Let a the dividend and b the divisor. We are looking for | |
| 1672 // the quotient q = truncate(a / b), and | |
| 1673 // the remainder r = a - q * b. | |
| 1674 // School algorithm: | |
| 1675 // q = 0 | |
| 1676 // n = number_of_digits(a) - number_of_digits(b) | |
| 1677 // for (i = n; i >= 0; i--) { | |
| 1678 // Maximize k such that k*y*10^i is less than or equal to a and | |
| 1679 // (k + 1)*y*10^i is greater. | |
| 1680 // q = q + k * 10^i // Add new digit to result. | |
| 1681 // a = a - k * b * 10^i | |
| 1682 // } | |
| 1683 // r = a | |
| 1684 // | |
| 1685 // Instead of working in base 10 we work in base kDigitBitSize. | |
| 1686 | |
| 1687 int normalization_shift = | |
| 1688 kDigitBitSize - CountBits(b.GetChunkAt(b_length - 1)); | |
| 1689 Bigint& dividend = Bigint::Handle(ShiftLeft(a, normalization_shift)); | |
| 1690 const Bigint& divisor = Bigint::Handle(ShiftLeft(b, normalization_shift)); | |
| 1691 dividend.SetSign(false); | |
| 1692 divisor.SetSign(false); | |
| 1693 | |
| 1694 intptr_t dividend_length = dividend.Length(); | |
| 1695 intptr_t divisor_length = b_length; | |
| 1696 ASSERT(divisor_length == divisor.Length()); | |
| 1697 | |
| 1698 intptr_t quotient_length = dividend_length - divisor_length + 1; | |
| 1699 *quotient = Bigint::Allocate(quotient_length); | |
| 1700 quotient->SetSign(a.IsNegative() != b.IsNegative()); | |
| 1701 | |
| 1702 intptr_t quotient_pos = dividend_length - divisor_length; | |
| 1703 // Find the first quotient-digit. | |
| 1704 // The first digit must be computed separately from the other digits because | |
| 1705 // the preconditions for the loop are not yet satisfied. | |
| 1706 // For simplicity use a shifted divisor, so that the comparison and | |
| 1707 // subtraction are easier. | |
| 1708 int divisor_shift_amount = dividend_length - divisor_length; | |
| 1709 Bigint& shifted_divisor = | |
| 1710 Bigint::Handle(DigitsShiftLeft(divisor, divisor_shift_amount)); | |
| 1711 Chunk first_quotient_digit = 0; | |
| 1712 Isolate* isolate = Isolate::Current(); | |
| 1713 while (UnsignedCompare(dividend, shifted_divisor) >= 0) { | |
| 1714 HANDLESCOPE(isolate); | |
| 1715 first_quotient_digit++; | |
| 1716 dividend = Subtract(dividend, shifted_divisor); | |
| 1717 } | |
| 1718 quotient->SetChunkAt(quotient_pos--, first_quotient_digit); | |
| 1719 | |
| 1720 // Find the remainder of the digits. | |
| 1721 | |
| 1722 Chunk first_divisor_digit = divisor.GetChunkAt(divisor_length - 1); | |
| 1723 // The short divisor only represents the first two digits of the divisor. | |
| 1724 // If the divisor has only one digit, then the second part is zeroed out. | |
| 1725 Bigint& short_divisor = Bigint::Handle(Bigint::Allocate(2)); | |
| 1726 if (divisor_length > 1) { | |
| 1727 short_divisor.SetChunkAt(0, divisor.GetChunkAt(divisor_length - 2)); | |
| 1728 } else { | |
| 1729 short_divisor.SetChunkAt(0, 0); | |
| 1730 } | |
| 1731 short_divisor.SetChunkAt(1, first_divisor_digit); | |
| 1732 // The following bigint will be used inside the loop. It is allocated outside | |
| 1733 // the loop to avoid repeated allocations. | |
| 1734 Bigint& target = Bigint::Handle(Bigint::Allocate(3)); | |
| 1735 // The dividend_length here must be from the initial dividend. | |
| 1736 for (intptr_t i = dividend_length - 1; i >= divisor_length; i--) { | |
| 1737 // Invariant: let t = i - divisor_length | |
| 1738 // then dividend / (divisor << (t * kDigitBitSize)) <= kDigitMaxValue. | |
| 1739 // Ex: dividend: 53451232, and divisor: 535 (with t == 5) is ok. | |
| 1740 // dividend: 56822123, and divisor: 563 (with t == 5) is bad. | |
| 1741 // dividend: 6822123, and divisor: 563 (with t == 5) is ok. | |
| 1742 | |
| 1743 HANDLESCOPE(isolate); | |
| 1744 // The dividend has changed. So recompute its length. | |
| 1745 dividend_length = dividend.Length(); | |
| 1746 Chunk dividend_digit; | |
| 1747 if (i > dividend_length) { | |
| 1748 quotient->SetChunkAt(quotient_pos--, 0); | |
| 1749 continue; | |
| 1750 } else if (i == dividend_length) { | |
| 1751 dividend_digit = 0; | |
| 1752 } else { | |
| 1753 ASSERT(i + 1 == dividend_length); | |
| 1754 dividend_digit = dividend.GetChunkAt(i); | |
| 1755 } | |
| 1756 Chunk quotient_digit; | |
| 1757 // Compute an estimate of the quotient_digit. The estimate will never | |
| 1758 // be too small. | |
| 1759 if (dividend_digit == first_divisor_digit) { | |
| 1760 // Small shortcut: the else-branch would compute a value > kDigitMaxValue. | |
| 1761 // However, by hypothesis, we know that the quotient_digit must fit into | |
| 1762 // a digit. Avoid going through repeated iterations of the adjustment | |
| 1763 // loop by directly assigning kDigitMaxValue to the quotient_digit. | |
| 1764 // Ex: 51235 / 523. | |
| 1765 // 51 / 5 would yield 10 (if computed in the else branch). | |
| 1766 // However we know that 9 is the maximal value. | |
| 1767 quotient_digit = kDigitMaxValue; | |
| 1768 } else { | |
| 1769 // Compute the estimate by using two digits of the dividend and one of | |
| 1770 // the divisor. | |
| 1771 // Ex: 32421 / 535 | |
| 1772 // 32 / 5 -> 6 | |
| 1773 // The estimate would hence be 6. | |
| 1774 DoubleChunk two_dividend_digits = dividend_digit; | |
| 1775 two_dividend_digits <<= kDigitBitSize; | |
| 1776 two_dividend_digits += dividend.GetChunkAt(i - 1); | |
| 1777 DoubleChunk q = two_dividend_digits / first_divisor_digit; | |
| 1778 if (q > kDigitMaxValue) q = kDigitMaxValue; | |
| 1779 quotient_digit = static_cast<Chunk>(q); | |
| 1780 } | |
| 1781 | |
| 1782 // Refine estimation. | |
| 1783 quotient_digit++; // The following loop will start by decrementing. | |
| 1784 Bigint& estimation_product = Bigint::Handle(); | |
| 1785 target.SetChunkAt(0, ((i - 2) < 0) ? 0 : dividend.GetChunkAt(i - 2)); | |
| 1786 target.SetChunkAt(1, ((i - 1) < 0) ? 0 : dividend.GetChunkAt(i - 1)); | |
| 1787 target.SetChunkAt(2, dividend_digit); | |
| 1788 do { | |
| 1789 HANDLESCOPE(isolate); | |
| 1790 quotient_digit = (quotient_digit - 1) & kDigitMask; | |
| 1791 estimation_product = MultiplyWithDigit(short_divisor, quotient_digit); | |
| 1792 } while (UnsignedCompareNonClamped(estimation_product, target) > 0); | |
| 1793 // At this point the quotient_digit is fairly accurate. | |
| 1794 // At the worst it is off by one. | |
| 1795 // Remove a multiple of the divisor. If the estimate is incorrect we will | |
| 1796 // subtract the divisor another time. | |
| 1797 // Let t = i - divisor_length. | |
| 1798 // dividend -= (quotient_digit * divisor) << (t * kDigitBitSize); | |
| 1799 shifted_divisor = MultiplyWithDigit(divisor, quotient_digit); | |
| 1800 shifted_divisor = DigitsShiftLeft(shifted_divisor, i - divisor_length); | |
| 1801 dividend = Subtract(dividend, shifted_divisor); | |
| 1802 if (dividend.IsNegative()) { | |
| 1803 // The estimation was still too big. | |
| 1804 quotient_digit--; | |
| 1805 // TODO(floitsch): allocate space for the shifted_divisor once and reuse | |
| 1806 // it at every iteration. | |
| 1807 shifted_divisor = DigitsShiftLeft(divisor, i - divisor_length); | |
| 1808 // TODO(floitsch): reuse the space of the previous dividend. | |
| 1809 dividend = Add(dividend, shifted_divisor); | |
| 1810 } | |
| 1811 quotient->SetChunkAt(quotient_pos--, quotient_digit); | |
| 1812 } | |
| 1813 ASSERT(quotient_pos == -1); | |
| 1814 Clamp(*quotient); | |
| 1815 *remainder = ShiftRight(dividend, normalization_shift); | |
| 1816 remainder->SetSign(a.IsNegative()); | |
| 1817 } | |
| 1818 | |
| 1819 | |
| 1820 BigintOperations::Chunk BigintOperations::InplaceUnsignedDivideRemainderDigit( | |
| 1821 const Bigint& dividend_quotient, Chunk divisor_digit) { | |
| 1822 Chunk remainder = 0; | |
| 1823 for (intptr_t i = dividend_quotient.Length() - 1; i >= 0; i--) { | |
| 1824 DoubleChunk dividend_digit = | |
| 1825 (static_cast<DoubleChunk>(remainder) << kDigitBitSize) + | |
| 1826 dividend_quotient.GetChunkAt(i); | |
| 1827 Chunk quotient_digit = static_cast<Chunk>(dividend_digit / divisor_digit); | |
| 1828 remainder = static_cast<Chunk>( | |
| 1829 dividend_digit - | |
| 1830 static_cast<DoubleChunk>(quotient_digit) * divisor_digit); | |
| 1831 dividend_quotient.SetChunkAt(i, quotient_digit); | |
| 1832 } | |
| 1833 Clamp(dividend_quotient); | |
| 1834 return remainder; | |
| 1835 } | |
| 1836 | |
| 1837 | |
| 1838 void BigintOperations::Clamp(const Bigint& bigint) { | |
| 1839 intptr_t length = bigint.Length(); | |
| 1840 while (length > 0 && (bigint.GetChunkAt(length - 1) == 0)) { | |
| 1841 length--; | |
| 1842 } | |
| 1843 // TODO(floitsch): We change the size of bigint-objects here. | |
| 1844 bigint.SetLength(length); | |
| 1845 } | |
| 1846 | |
| 1847 | |
| 1848 RawBigint* BigintOperations::Copy(const Bigint& bigint) { | |
| 1849 intptr_t bigint_length = bigint.Length(); | |
| 1850 Bigint& copy = Bigint::Handle(Bigint::Allocate(bigint_length)); | |
| 1851 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 1852 copy.SetChunkAt(i, bigint.GetChunkAt(i)); | |
| 1853 } | |
| 1854 copy.SetSign(bigint.IsNegative()); | |
| 1855 return copy.raw(); | |
| 1856 } | |
| 1857 | |
| 1858 | |
| 1859 intptr_t BigintOperations::CountBits(Chunk digit) { | |
| 1860 intptr_t result = 0; | |
| 1861 while (digit != 0) { | |
| 1862 digit >>= 1; | |
| 1863 result++; | |
| 1864 } | |
| 1865 return result; | |
| 1866 } | |
| 1867 | |
| 1868 } // namespace dart | |
| OLD | NEW |