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 25 matching lines...) Expand all Loading... |
36 namespace v8 { | 36 namespace v8 { |
37 namespace internal { | 37 namespace internal { |
38 | 38 |
39 // 2^53 = 9007199254740992. | 39 // 2^53 = 9007199254740992. |
40 // Any integer with at most 15 decimal digits will hence fit into a double | 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. | 41 // (which has a 53bit significand) without loss of precision. |
42 static const int kMaxExactDoubleIntegerDecimalDigits = 15; | 42 static const int kMaxExactDoubleIntegerDecimalDigits = 15; |
43 // 2^64 = 18446744073709551616 | 43 // 2^64 = 18446744073709551616 |
44 // Any integer with at most 19 digits will hence fit into a 64bit datatype. | 44 // Any integer with at most 19 digits will hence fit into a 64bit datatype. |
45 static const int kMaxUint64DecimalDigits = 19; | 45 static const int kMaxUint64DecimalDigits = 19; |
| 46 // Max double: 1.7976931348623157 x 10^308 |
| 47 // Min non-zero double: 4.9406564584124654 x 10^-324 |
| 48 // Any x >= 10^309 is interpreted as +infinity. |
| 49 // Any x <= 10^-324 is interpreted as 0. |
| 50 // Note that 2.5e-324 (despite being smaller than the min double) will be read |
| 51 // as non-zero (equal to the min non-zero double). |
| 52 static const int kMaxDecimalPower = 309; |
| 53 static const int kMinDecimalPower = -324; |
46 | 54 |
47 static const double exact_powers_of_ten[] = { | 55 static const double exact_powers_of_ten[] = { |
48 1.0, // 10^0 | 56 1.0, // 10^0 |
49 10.0, | 57 10.0, |
50 100.0, | 58 100.0, |
51 1000.0, | 59 1000.0, |
52 10000.0, | 60 10000.0, |
53 100000.0, | 61 100000.0, |
54 1000000.0, | 62 1000000.0, |
55 10000000.0, | 63 10000000.0, |
(...skipping 13 matching lines...) Expand all Loading... |
69 1000000000000000000000.0, | 77 1000000000000000000000.0, |
70 // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 | 78 // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 |
71 10000000000000000000000.0 | 79 10000000000000000000000.0 |
72 }; | 80 }; |
73 | 81 |
74 static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); | 82 static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); |
75 | 83 |
76 | 84 |
77 extern "C" double gay_strtod(const char* s00, const char** se); | 85 extern "C" double gay_strtod(const char* s00, const char** se); |
78 | 86 |
79 static double old_strtod(Vector<char> buffer, int exponent) { | 87 static double old_strtod(Vector<const char> buffer, int exponent) { |
80 char gay_buffer[1024]; | 88 char gay_buffer[1024]; |
81 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); | 89 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); |
82 buffer.start()[buffer.length()] = '\0'; | 90 int pos = 0; |
83 OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent); | 91 for (int i = 0; i < buffer.length(); ++i) { |
| 92 gay_buffer_vector[pos++] = buffer[i]; |
| 93 } |
| 94 gay_buffer_vector[pos++] = 'e'; |
| 95 if (exponent < 0) { |
| 96 gay_buffer_vector[pos++] = '-'; |
| 97 exponent = -exponent; |
| 98 } |
| 99 const int kNumberOfExponentDigits = 5; |
| 100 for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) { |
| 101 gay_buffer_vector[pos + i] = exponent % 10 + '0'; |
| 102 exponent /= 10; |
| 103 } |
| 104 pos += kNumberOfExponentDigits; |
| 105 gay_buffer_vector[pos] = '\0'; |
84 return gay_strtod(gay_buffer, NULL); | 106 return gay_strtod(gay_buffer, NULL); |
85 } | 107 } |
86 | 108 |
87 | 109 |
88 static Vector<char> TrimTrailingZeros(Vector<char> buffer) { | 110 static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) { |
89 for (int i = buffer.length() - 1; i >= 0; --i) { | 111 for (int i = 0; i < buffer.length(); i++) { |
90 if (buffer[i] != '0') { | 112 if (buffer[i] != '0') { |
91 return Vector<char>(buffer.start(), i + 1); | 113 return Vector<const char>(buffer.start() + i, buffer.length() - i); |
92 } | 114 } |
93 } | 115 } |
94 return Vector<char>(buffer.start(), 0); | 116 return Vector<const char>(buffer.start(), 0); |
95 } | 117 } |
96 | 118 |
97 | 119 |
98 uint64_t ReadUint64(Vector<char> buffer) { | 120 static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { |
| 121 for (int i = buffer.length() - 1; i >= 0; --i) { |
| 122 if (buffer[i] != '0') { |
| 123 return Vector<const char>(buffer.start(), i + 1); |
| 124 } |
| 125 } |
| 126 return Vector<const char>(buffer.start(), 0); |
| 127 } |
| 128 |
| 129 |
| 130 uint64_t ReadUint64(Vector<const char> buffer) { |
99 ASSERT(buffer.length() <= kMaxUint64DecimalDigits); | 131 ASSERT(buffer.length() <= kMaxUint64DecimalDigits); |
100 uint64_t result = 0; | 132 uint64_t result = 0; |
101 for (int i = 0; i < buffer.length(); ++i) { | 133 for (int i = 0; i < buffer.length(); ++i) { |
102 int digit = buffer[i] - '0'; | 134 int digit = buffer[i] - '0'; |
103 ASSERT(0 <= digit && digit <= 9); | 135 ASSERT(0 <= digit && digit <= 9); |
104 result = 10 * result + digit; | 136 result = 10 * result + digit; |
105 } | 137 } |
106 return result; | 138 return result; |
107 } | 139 } |
108 | 140 |
109 | 141 |
110 double Strtod(Vector<char> buffer, int exponent) { | 142 double Strtod(Vector<const char> buffer, int exponent) { |
111 Vector<char> trimmed = TrimTrailingZeros(buffer); | 143 Vector<const char> left_trimmed = TrimLeadingZeros(buffer); |
| 144 Vector<const char> trimmed = TrimTrailingZeros(left_trimmed); |
| 145 exponent += left_trimmed.length() - trimmed.length(); |
112 if (trimmed.length() == 0) return 0.0; | 146 if (trimmed.length() == 0) return 0.0; |
113 exponent += buffer.length() - trimmed.length(); | 147 if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY; |
| 148 if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0; |
114 if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { | 149 if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { |
115 // The trimmed input fits into a double. | 150 // The trimmed input fits into a double. |
116 // If the 10^exponent (resp. 10^-exponent) fits into a double too then we | 151 // 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 | 152 // can compute the result-double simply by multiplying (resp. dividing) the |
118 // two numbers. | 153 // two numbers. |
119 // This is possible because IEEE guarantees that floating-point operations | 154 // This is possible because IEEE guarantees that floating-point operations |
120 // return the best possible approximation. | 155 // return the best possible approximation. |
121 if (exponent < 0 && -exponent < kExactPowersOfTenSize) { | 156 if (exponent < 0 && -exponent < kExactPowersOfTenSize) { |
122 // 10^-exponent fits into a double. | 157 // 10^-exponent fits into a double. |
123 double buffer_d = static_cast<double>(ReadUint64(trimmed)); | 158 double buffer_d = static_cast<double>(ReadUint64(trimmed)); |
(...skipping 13 matching lines...) Expand all Loading... |
137 // into a double too. | 172 // into a double too. |
138 double buffer_d = static_cast<double>(ReadUint64(trimmed)); | 173 double buffer_d = static_cast<double>(ReadUint64(trimmed)); |
139 buffer_d *= exact_powers_of_ten[remaining_digits]; | 174 buffer_d *= exact_powers_of_ten[remaining_digits]; |
140 return buffer_d * exact_powers_of_ten[exponent - remaining_digits]; | 175 return buffer_d * exact_powers_of_ten[exponent - remaining_digits]; |
141 } | 176 } |
142 } | 177 } |
143 return old_strtod(trimmed, exponent); | 178 return old_strtod(trimmed, exponent); |
144 } | 179 } |
145 | 180 |
146 } } // namespace v8::internal | 181 } } // namespace v8::internal |
OLD | NEW |