OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include <stdarg.h> | 28 #include <stdarg.h> |
29 #include <limits.h> | 29 #include <limits.h> |
30 | 30 |
31 #include "strtod.h" | 31 #include "strtod.h" |
32 #include "bignum.h" | 32 #include "bignum.h" |
33 #include "cached-powers.h" | 33 #include "cached-powers.h" |
34 #include "double.h" | 34 #include "ieee.h" |
35 | 35 |
36 namespace double_conversion { | 36 namespace double_conversion { |
37 | 37 |
38 // 2^53 = 9007199254740992. | 38 // 2^53 = 9007199254740992. |
39 // Any integer with at most 15 decimal digits will hence fit into a double | 39 // Any integer with at most 15 decimal digits will hence fit into a double |
40 // (which has a 53bit significand) without loss of precision. | 40 // (which has a 53bit significand) without loss of precision. |
41 static const int kMaxExactDoubleIntegerDecimalDigits = 15; | 41 static const int kMaxExactDoubleIntegerDecimalDigits = 15; |
42 // 2^64 = 18446744073709551616 > 10^19 | 42 // 2^64 = 18446744073709551616 > 10^19 |
43 static const int kMaxUint64DecimalDigits = 19; | 43 static const int kMaxUint64DecimalDigits = 19; |
44 | 44 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { | 101 static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { |
102 for (int i = buffer.length() - 1; i >= 0; --i) { | 102 for (int i = buffer.length() - 1; i >= 0; --i) { |
103 if (buffer[i] != '0') { | 103 if (buffer[i] != '0') { |
104 return buffer.SubVector(0, i + 1); | 104 return buffer.SubVector(0, i + 1); |
105 } | 105 } |
106 } | 106 } |
107 return Vector<const char>(buffer.start(), 0); | 107 return Vector<const char>(buffer.start(), 0); |
108 } | 108 } |
109 | 109 |
110 | 110 |
111 static void TrimToMaxSignificantDigits(Vector<const char> buffer, | 111 static void CutToMaxSignificantDigits(Vector<const char> buffer, |
112 int exponent, | 112 int exponent, |
113 char* significant_buffer, | 113 char* significant_buffer, |
114 int* significant_exponent) { | 114 int* significant_exponent) { |
115 for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { | 115 for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { |
116 significant_buffer[i] = buffer[i]; | 116 significant_buffer[i] = buffer[i]; |
117 } | 117 } |
118 // The input buffer has been trimmed. Therefore the last digit must be | 118 // The input buffer has been trimmed. Therefore the last digit must be |
119 // different from '0'. | 119 // different from '0'. |
120 ASSERT(buffer[buffer.length() - 1] != '0'); | 120 ASSERT(buffer[buffer.length() - 1] != '0'); |
121 // Set the last digit to be non-zero. This is sufficient to guarantee | 121 // Set the last digit to be non-zero. This is sufficient to guarantee |
122 // correct rounding. | 122 // correct rounding. |
123 significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; | 123 significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; |
124 *significant_exponent = | 124 *significant_exponent = |
125 exponent + (buffer.length() - kMaxSignificantDecimalDigits); | 125 exponent + (buffer.length() - kMaxSignificantDecimalDigits); |
126 } | 126 } |
127 | 127 |
| 128 |
| 129 // Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits. |
| 130 // If possible the input-buffer is reused, but if the buffer needs to be |
| 131 // modified (due to cutting), then the input needs to be copied into the |
| 132 // buffer_copy_space. |
| 133 static void TrimAndCut(Vector<const char> buffer, int exponent, |
| 134 char* buffer_copy_space, int space_size, |
| 135 Vector<const char>* trimmed, int* updated_exponent) { |
| 136 Vector<const char> left_trimmed = TrimLeadingZeros(buffer); |
| 137 Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed); |
| 138 exponent += left_trimmed.length() - right_trimmed.length(); |
| 139 if (right_trimmed.length() > kMaxSignificantDecimalDigits) { |
| 140 (void) space_size; // Mark variable as used. |
| 141 ASSERT(space_size >= kMaxSignificantDecimalDigits); |
| 142 CutToMaxSignificantDigits(right_trimmed, exponent, |
| 143 buffer_copy_space, updated_exponent); |
| 144 *trimmed = Vector<const char>(buffer_copy_space, |
| 145 kMaxSignificantDecimalDigits); |
| 146 } else { |
| 147 *trimmed = right_trimmed; |
| 148 *updated_exponent = exponent; |
| 149 } |
| 150 } |
| 151 |
| 152 |
128 // Reads digits from the buffer and converts them to a uint64. | 153 // Reads digits from the buffer and converts them to a uint64. |
129 // Reads in as many digits as fit into a uint64. | 154 // Reads in as many digits as fit into a uint64. |
130 // When the string starts with "1844674407370955161" no further digit is read. | 155 // When the string starts with "1844674407370955161" no further digit is read. |
131 // Since 2^64 = 18446744073709551616 it would still be possible read another | 156 // Since 2^64 = 18446744073709551616 it would still be possible read another |
132 // digit if it was less or equal than 6, but this would complicate the code. | 157 // digit if it was less or equal than 6, but this would complicate the code. |
133 static uint64_t ReadUint64(Vector<const char> buffer, | 158 static uint64_t ReadUint64(Vector<const char> buffer, |
134 int* number_of_read_digits) { | 159 int* number_of_read_digits) { |
135 uint64_t result = 0; | 160 uint64_t result = 0; |
136 int i = 0; | 161 int i = 0; |
137 while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { | 162 while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 switch (exponent) { | 257 switch (exponent) { |
233 case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); | 258 case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); |
234 case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); | 259 case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); |
235 case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); | 260 case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); |
236 case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); | 261 case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); |
237 case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); | 262 case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); |
238 case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); | 263 case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); |
239 case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); | 264 case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); |
240 default: | 265 default: |
241 UNREACHABLE(); | 266 UNREACHABLE(); |
242 return DiyFp(0, 0); | |
243 } | 267 } |
244 } | 268 } |
245 | 269 |
246 | 270 |
247 // If the function returns true then the result is the correct double. | 271 // If the function returns true then the result is the correct double. |
248 // Otherwise it is either the correct double or the double that is just below | 272 // Otherwise it is either the correct double or the double that is just below |
249 // the correct double. | 273 // the correct double. |
250 static bool DiyFpStrtod(Vector<const char> buffer, | 274 static bool DiyFpStrtod(Vector<const char> buffer, |
251 int exponent, | 275 int exponent, |
252 double* result) { | 276 double* result) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // Too imprecise. The caller will have to fall back to a slower version. | 374 // Too imprecise. The caller will have to fall back to a slower version. |
351 // However the returned number is guaranteed to be either the correct | 375 // However the returned number is guaranteed to be either the correct |
352 // double, or the next-lower double. | 376 // double, or the next-lower double. |
353 return false; | 377 return false; |
354 } else { | 378 } else { |
355 return true; | 379 return true; |
356 } | 380 } |
357 } | 381 } |
358 | 382 |
359 | 383 |
360 // Returns the correct double for the buffer*10^exponent. | 384 // Returns |
361 // The variable guess should be a close guess that is either the correct double | 385 // - -1 if buffer*10^exponent < diy_fp. |
362 // or its lower neighbor (the nearest double less than the correct one). | 386 // - 0 if buffer*10^exponent == diy_fp. |
| 387 // - +1 if buffer*10^exponent > diy_fp. |
363 // Preconditions: | 388 // Preconditions: |
364 // buffer.length() + exponent <= kMaxDecimalPower + 1 | 389 // buffer.length() + exponent <= kMaxDecimalPower + 1 |
365 // buffer.length() + exponent > kMinDecimalPower | 390 // buffer.length() + exponent > kMinDecimalPower |
366 // buffer.length() <= kMaxDecimalSignificantDigits | 391 // buffer.length() <= kMaxDecimalSignificantDigits |
367 static double BignumStrtod(Vector<const char> buffer, | 392 static int CompareBufferWithDiyFp(Vector<const char> buffer, |
368 int exponent, | 393 int exponent, |
369 double guess) { | 394 DiyFp diy_fp) { |
370 if (guess == Double::Infinity()) { | |
371 return guess; | |
372 } | |
373 | |
374 DiyFp upper_boundary = Double(guess).UpperBoundary(); | |
375 | |
376 ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); | 395 ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); |
377 ASSERT(buffer.length() + exponent > kMinDecimalPower); | 396 ASSERT(buffer.length() + exponent > kMinDecimalPower); |
378 ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); | 397 ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); |
379 // Make sure that the Bignum will be able to hold all our numbers. | 398 // Make sure that the Bignum will be able to hold all our numbers. |
380 // Our Bignum implementation has a separate field for exponents. Shifts will | 399 // Our Bignum implementation has a separate field for exponents. Shifts will |
381 // consume at most one bigit (< 64 bits). | 400 // consume at most one bigit (< 64 bits). |
382 // ln(10) == 3.3219... | 401 // ln(10) == 3.3219... |
383 ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); | 402 ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); |
384 Bignum input; | 403 Bignum buffer_bignum; |
385 Bignum boundary; | 404 Bignum diy_fp_bignum; |
386 input.AssignDecimalString(buffer); | 405 buffer_bignum.AssignDecimalString(buffer); |
387 boundary.AssignUInt64(upper_boundary.f()); | 406 diy_fp_bignum.AssignUInt64(diy_fp.f()); |
388 if (exponent >= 0) { | 407 if (exponent >= 0) { |
389 input.MultiplyByPowerOfTen(exponent); | 408 buffer_bignum.MultiplyByPowerOfTen(exponent); |
390 } else { | 409 } else { |
391 boundary.MultiplyByPowerOfTen(-exponent); | 410 diy_fp_bignum.MultiplyByPowerOfTen(-exponent); |
392 } | 411 } |
393 if (upper_boundary.e() > 0) { | 412 if (diy_fp.e() > 0) { |
394 boundary.ShiftLeft(upper_boundary.e()); | 413 diy_fp_bignum.ShiftLeft(diy_fp.e()); |
395 } else { | 414 } else { |
396 input.ShiftLeft(-upper_boundary.e()); | 415 buffer_bignum.ShiftLeft(-diy_fp.e()); |
397 } | 416 } |
398 int comparison = Bignum::Compare(input, boundary); | 417 return Bignum::Compare(buffer_bignum, diy_fp_bignum); |
| 418 } |
| 419 |
| 420 |
| 421 // Returns true if the guess is the correct double. |
| 422 // Returns false, when guess is either correct or the next-lower double. |
| 423 static bool ComputeGuess(Vector<const char> trimmed, int exponent, |
| 424 double* guess) { |
| 425 if (trimmed.length() == 0) { |
| 426 *guess = 0.0; |
| 427 return true; |
| 428 } |
| 429 if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { |
| 430 *guess = Double::Infinity(); |
| 431 return true; |
| 432 } |
| 433 if (exponent + trimmed.length() <= kMinDecimalPower) { |
| 434 *guess = 0.0; |
| 435 return true; |
| 436 } |
| 437 |
| 438 if (DoubleStrtod(trimmed, exponent, guess) || |
| 439 DiyFpStrtod(trimmed, exponent, guess)) { |
| 440 return true; |
| 441 } |
| 442 if (*guess == Double::Infinity()) { |
| 443 return true; |
| 444 } |
| 445 return false; |
| 446 } |
| 447 |
| 448 double Strtod(Vector<const char> buffer, int exponent) { |
| 449 char copy_buffer[kMaxSignificantDecimalDigits]; |
| 450 Vector<const char> trimmed; |
| 451 int updated_exponent; |
| 452 TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, |
| 453 &trimmed, &updated_exponent); |
| 454 exponent = updated_exponent; |
| 455 |
| 456 double guess; |
| 457 bool is_correct = ComputeGuess(trimmed, exponent, &guess); |
| 458 if (is_correct) return guess; |
| 459 |
| 460 DiyFp upper_boundary = Double(guess).UpperBoundary(); |
| 461 int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); |
399 if (comparison < 0) { | 462 if (comparison < 0) { |
400 return guess; | 463 return guess; |
401 } else if (comparison > 0) { | 464 } else if (comparison > 0) { |
402 return Double(guess).NextDouble(); | 465 return Double(guess).NextDouble(); |
403 } else if ((Double(guess).Significand() & 1) == 0) { | 466 } else if ((Double(guess).Significand() & 1) == 0) { |
404 // Round towards even. | 467 // Round towards even. |
405 return guess; | 468 return guess; |
406 } else { | 469 } else { |
407 return Double(guess).NextDouble(); | 470 return Double(guess).NextDouble(); |
408 } | 471 } |
409 } | 472 } |
410 | 473 |
| 474 float Strtof(Vector<const char> buffer, int exponent) { |
| 475 char copy_buffer[kMaxSignificantDecimalDigits]; |
| 476 Vector<const char> trimmed; |
| 477 int updated_exponent; |
| 478 TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, |
| 479 &trimmed, &updated_exponent); |
| 480 exponent = updated_exponent; |
411 | 481 |
412 double Strtod(Vector<const char> buffer, int exponent) { | 482 double double_guess; |
413 Vector<const char> left_trimmed = TrimLeadingZeros(buffer); | 483 bool is_correct = ComputeGuess(trimmed, exponent, &double_guess); |
414 Vector<const char> trimmed = TrimTrailingZeros(left_trimmed); | 484 |
415 exponent += left_trimmed.length() - trimmed.length(); | 485 float float_guess = static_cast<float>(double_guess); |
416 if (trimmed.length() == 0) return 0.0; | 486 if (float_guess == double_guess) { |
417 if (trimmed.length() > kMaxSignificantDecimalDigits) { | 487 // This shortcut triggers for integer values. |
418 char significant_buffer[kMaxSignificantDecimalDigits]; | 488 return float_guess; |
419 int significant_exponent; | |
420 TrimToMaxSignificantDigits(trimmed, exponent, | |
421 significant_buffer, &significant_exponent); | |
422 return Strtod(Vector<const char>(significant_buffer, | |
423 kMaxSignificantDecimalDigits), | |
424 significant_exponent); | |
425 } | |
426 if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { | |
427 return Double::Infinity(); | |
428 } | |
429 if (exponent + trimmed.length() <= kMinDecimalPower) { | |
430 return 0.0; | |
431 } | 489 } |
432 | 490 |
433 double guess; | 491 // We must catch double-rounding. Say the double has been rounded up, and is |
434 if (DoubleStrtod(trimmed, exponent, &guess) || | 492 // now a boundary of a float, and rounds up again. This is why we have to |
435 DiyFpStrtod(trimmed, exponent, &guess)) { | 493 // look at previous too. |
| 494 // Example (in decimal numbers): |
| 495 // input: 12349 |
| 496 // high-precision (4 digits): 1235 |
| 497 // low-precision (3 digits): |
| 498 // when read from input: 123 |
| 499 // when rounded from high precision: 124. |
| 500 // To do this we simply look at the neigbors of the correct result and see |
| 501 // if they would round to the same float. If the guess is not correct we have |
| 502 // to look at four values (since two different doubles could be the correct |
| 503 // double). |
| 504 |
| 505 double double_next = Double(double_guess).NextDouble(); |
| 506 double double_previous = Double(double_guess).PreviousDouble(); |
| 507 |
| 508 float f1 = static_cast<float>(double_previous); |
| 509 float f2 = float_guess; |
| 510 float f3 = static_cast<float>(double_next); |
| 511 float f4; |
| 512 if (is_correct) { |
| 513 f4 = f3; |
| 514 } else { |
| 515 double double_next2 = Double(double_next).NextDouble(); |
| 516 f4 = static_cast<float>(double_next2); |
| 517 } |
| 518 (void) f2; // Mark variable as used. |
| 519 ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); |
| 520 |
| 521 // If the guess doesn't lie near a single-precision boundary we can simply |
| 522 // return its float-value. |
| 523 if (f1 == f4) { |
| 524 return float_guess; |
| 525 } |
| 526 |
| 527 ASSERT((f1 != f2 && f2 == f3 && f3 == f4) || |
| 528 (f1 == f2 && f2 != f3 && f3 == f4) || |
| 529 (f1 == f2 && f2 == f3 && f3 != f4)); |
| 530 |
| 531 // guess and next are the two possible canditates (in the same way that |
| 532 // double_guess was the lower candidate for a double-precision guess). |
| 533 float guess = f1; |
| 534 float next = f4; |
| 535 DiyFp upper_boundary; |
| 536 if (guess == 0.0f) { |
| 537 float min_float = 1e-45f; |
| 538 upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp(); |
| 539 } else { |
| 540 upper_boundary = Single(guess).UpperBoundary(); |
| 541 } |
| 542 int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); |
| 543 if (comparison < 0) { |
436 return guess; | 544 return guess; |
| 545 } else if (comparison > 0) { |
| 546 return next; |
| 547 } else if ((Single(guess).Significand() & 1) == 0) { |
| 548 // Round towards even. |
| 549 return guess; |
| 550 } else { |
| 551 return next; |
437 } | 552 } |
438 return BignumStrtod(trimmed, exponent, guess); | |
439 } | 553 } |
440 | 554 |
441 } // namespace double_conversion | 555 } // namespace double_conversion |
OLD | NEW |