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 18 matching lines...) Expand all Loading... |
29 #include <limits.h> | 29 #include <limits.h> |
30 | 30 |
31 #include "v8.h" | 31 #include "v8.h" |
32 | 32 |
33 #include "strtod.h" | 33 #include "strtod.h" |
34 // #include "cached-powers.h" | 34 // #include "cached-powers.h" |
35 | 35 |
36 namespace v8 { | 36 namespace v8 { |
37 namespace internal { | 37 namespace internal { |
38 | 38 |
| 39 // 2^53 = 9007199254740992. |
| 40 // Any integer with at most 15 decimal digits will hence fit into a double |
| 41 // (which has a 53bit significand) without loss of precision. |
| 42 static const int kMaxExactDoubleIntegerDecimalDigits = 15; |
| 43 // 2^64 = 18446744073709551616 |
| 44 // Any integer with at most 19 digits will hence fit into a 64bit datatype. |
| 45 static const int kMaxUint64DecimalDigits = 19; |
| 46 |
| 47 static const double exact_powers_of_ten[] = { |
| 48 1.0, // 10^0 |
| 49 10.0, |
| 50 100.0, |
| 51 1000.0, |
| 52 10000.0, |
| 53 100000.0, |
| 54 1000000.0, |
| 55 10000000.0, |
| 56 100000000.0, |
| 57 1000000000.0, |
| 58 10000000000.0, // 10^10 |
| 59 100000000000.0, |
| 60 1000000000000.0, |
| 61 10000000000000.0, |
| 62 100000000000000.0, |
| 63 1000000000000000.0, |
| 64 10000000000000000.0, |
| 65 100000000000000000.0, |
| 66 1000000000000000000.0, |
| 67 10000000000000000000.0, |
| 68 100000000000000000000.0, // 10^20 |
| 69 1000000000000000000000.0, |
| 70 // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 |
| 71 10000000000000000000000.0 |
| 72 }; |
| 73 |
| 74 static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); |
| 75 |
| 76 |
39 extern "C" double gay_strtod(const char* s00, const char** se); | 77 extern "C" double gay_strtod(const char* s00, const char** se); |
40 | 78 |
41 double strtod(Vector<char> buffer, int exponent) { | 79 static double old_strtod(Vector<char> buffer, int exponent) { |
42 char gay_buffer[1024]; | 80 char gay_buffer[1024]; |
43 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); | 81 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); |
44 buffer.start()[buffer.length()] = '\0'; | 82 buffer.start()[buffer.length()] = '\0'; |
45 OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent); | 83 OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent); |
46 return gay_strtod(gay_buffer, NULL); | 84 return gay_strtod(gay_buffer, NULL); |
47 } | 85 } |
48 | 86 |
| 87 |
| 88 static Vector<char> TrimTrailingZeros(Vector<char> buffer) { |
| 89 for (int i = buffer.length() - 1; i >= 0; --i) { |
| 90 if (buffer[i] != '0') { |
| 91 return Vector<char>(buffer.start(), i + 1); |
| 92 } |
| 93 } |
| 94 return Vector<char>(buffer.start(), 0); |
| 95 } |
| 96 |
| 97 |
| 98 uint64_t ReadUint64(Vector<char> buffer) { |
| 99 ASSERT(buffer.length() <= kMaxUint64DecimalDigits); |
| 100 uint64_t result = 0; |
| 101 for (int i = 0; i < buffer.length(); ++i) { |
| 102 int digit = buffer[i] - '0'; |
| 103 ASSERT(0 <= digit && digit <= 9); |
| 104 result = 10 * result + digit; |
| 105 } |
| 106 return result; |
| 107 } |
| 108 |
| 109 |
| 110 double Strtod(Vector<char> buffer, int exponent) { |
| 111 Vector<char> trimmed = TrimTrailingZeros(buffer); |
| 112 if (trimmed.length() == 0) return 0.0; |
| 113 exponent += buffer.length() - trimmed.length(); |
| 114 if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { |
| 115 // The trimmed input fits into a double. |
| 116 // If the 10^exponent (resp. 10^-exponent) fits into a double too then we |
| 117 // can compute the result-double simply by multiplying (resp. dividing) the |
| 118 // two numbers. |
| 119 // This is possible because IEEE guarantees that floating-point operations |
| 120 // return the best possible approximation. |
| 121 if (exponent < 0 && -exponent < kExactPowersOfTenSize) { |
| 122 // 10^-exponent fits into a double. |
| 123 double buffer_d = static_cast<double>(ReadUint64(trimmed)); |
| 124 return buffer_d / exact_powers_of_ten[-exponent]; |
| 125 } |
| 126 if (0 <= exponent && exponent < kExactPowersOfTenSize) { |
| 127 // 10^exponent fits into a double. |
| 128 double buffer_d = static_cast<double>(ReadUint64(trimmed)); |
| 129 return buffer_d * exact_powers_of_ten[exponent]; |
| 130 } |
| 131 int remaining_digits = |
| 132 kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); |
| 133 if ((0 <= exponent) && |
| 134 (exponent - remaining_digits < kExactPowersOfTenSize)) { |
| 135 // The trimmed string was short and we can multiply it with |
| 136 // 10^remaining_digits. As a result the remaining exponent now fits |
| 137 // into a double too. |
| 138 double buffer_d = static_cast<double>(ReadUint64(trimmed)); |
| 139 buffer_d *= exact_powers_of_ten[remaining_digits]; |
| 140 return buffer_d * exact_powers_of_ten[exponent - remaining_digits]; |
| 141 } |
| 142 } |
| 143 return old_strtod(trimmed, exponent); |
| 144 } |
| 145 |
49 } } // namespace v8::internal | 146 } } // namespace v8::internal |
OLD | NEW |