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 10 matching lines...) Expand all Loading... |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
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 <math.h> | 28 #include <math.h> |
29 | 29 |
30 #include "fixed-dtoa.h" | 30 #include "fixed-dtoa.h" |
31 #include "double.h" | 31 #include "ieee.h" |
32 | 32 |
33 namespace double_conversion { | 33 namespace double_conversion { |
34 | 34 |
35 // Represents a 128bit type. This class should be replaced by a native type on | 35 // Represents a 128bit type. This class should be replaced by a native type on |
36 // platforms that support 128bit integers. | 36 // platforms that support 128bit integers. |
37 class UInt128 { | 37 class UInt128 { |
38 public: | 38 public: |
39 UInt128() : high_bits_(0), low_bits_(0) { } | 39 UInt128() : high_bits_(0), low_bits_(0) { } |
40 UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { } | 40 UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { } |
41 | 41 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 *length += requested_length; | 126 *length += requested_length; |
127 } | 127 } |
128 | 128 |
129 | 129 |
130 static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) { | 130 static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) { |
131 int number_length = 0; | 131 int number_length = 0; |
132 // We fill the digits in reverse order and exchange them afterwards. | 132 // We fill the digits in reverse order and exchange them afterwards. |
133 while (number != 0) { | 133 while (number != 0) { |
134 int digit = number % 10; | 134 int digit = number % 10; |
135 number /= 10; | 135 number /= 10; |
136 buffer[(*length) + number_length] = '0' + digit; | 136 buffer[(*length) + number_length] = static_cast<char>('0' + digit); |
137 number_length++; | 137 number_length++; |
138 } | 138 } |
139 // Exchange the digits. | 139 // Exchange the digits. |
140 int i = *length; | 140 int i = *length; |
141 int j = *length + number_length - 1; | 141 int j = *length + number_length - 1; |
142 while (i < j) { | 142 while (i < j) { |
143 char tmp = buffer[i]; | 143 char tmp = buffer[i]; |
144 buffer[i] = buffer[j]; | 144 buffer[i] = buffer[j]; |
145 buffer[j] = tmp; | 145 buffer[j] = tmp; |
146 i++; | 146 i++; |
147 j--; | 147 j--; |
148 } | 148 } |
149 *length += number_length; | 149 *length += number_length; |
150 } | 150 } |
151 | 151 |
152 | 152 |
153 static void FillDigits64FixedLength(uint64_t number, int requested_length, | 153 static void FillDigits64FixedLength(uint64_t number, |
154 Vector<char> buffer, int* length) { | 154 Vector<char> buffer, int* length) { |
155 const uint32_t kTen7 = 10000000; | 155 const uint32_t kTen7 = 10000000; |
156 // For efficiency cut the number into 3 uint32_t parts, and print those. | 156 // For efficiency cut the number into 3 uint32_t parts, and print those. |
157 uint32_t part2 = static_cast<uint32_t>(number % kTen7); | 157 uint32_t part2 = static_cast<uint32_t>(number % kTen7); |
158 number /= kTen7; | 158 number /= kTen7; |
159 uint32_t part1 = static_cast<uint32_t>(number % kTen7); | 159 uint32_t part1 = static_cast<uint32_t>(number % kTen7); |
160 uint32_t part0 = static_cast<uint32_t>(number / kTen7); | 160 uint32_t part0 = static_cast<uint32_t>(number / kTen7); |
161 | 161 |
162 FillDigits32FixedLength(part0, 3, buffer, length); | 162 FillDigits32FixedLength(part0, 3, buffer, length); |
163 FillDigits32FixedLength(part1, 7, buffer, length); | 163 FillDigits32FixedLength(part1, 7, buffer, length); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 // Initially we have: point <= 64 and fractionals < 2^56 | 246 // Initially we have: point <= 64 and fractionals < 2^56 |
247 // After each iteration the point is decremented by one. | 247 // After each iteration the point is decremented by one. |
248 // Note that 5^3 = 125 < 128 = 2^7. | 248 // Note that 5^3 = 125 < 128 = 2^7. |
249 // Therefore three iterations of this loop will not overflow fractionals | 249 // Therefore three iterations of this loop will not overflow fractionals |
250 // (even without the subtraction at the end of the loop body). At this | 250 // (even without the subtraction at the end of the loop body). At this |
251 // time point will satisfy point <= 61 and therefore fractionals < 2^point | 251 // time point will satisfy point <= 61 and therefore fractionals < 2^point |
252 // and any further multiplication of fractionals by 5 will not overflow. | 252 // and any further multiplication of fractionals by 5 will not overflow. |
253 fractionals *= 5; | 253 fractionals *= 5; |
254 point--; | 254 point--; |
255 int digit = static_cast<int>(fractionals >> point); | 255 int digit = static_cast<int>(fractionals >> point); |
256 buffer[*length] = '0' + digit; | 256 ASSERT(digit <= 9); |
| 257 buffer[*length] = static_cast<char>('0' + digit); |
257 (*length)++; | 258 (*length)++; |
258 fractionals -= static_cast<uint64_t>(digit) << point; | 259 fractionals -= static_cast<uint64_t>(digit) << point; |
259 } | 260 } |
260 // If the first bit after the point is set we have to round up. | 261 // If the first bit after the point is set we have to round up. |
261 if (((fractionals >> (point - 1)) & 1) == 1) { | 262 if (((fractionals >> (point - 1)) & 1) == 1) { |
262 RoundUp(buffer, length, decimal_point); | 263 RoundUp(buffer, length, decimal_point); |
263 } | 264 } |
264 } else { // We need 128 bits. | 265 } else { // We need 128 bits. |
265 ASSERT(64 < -exponent && -exponent <= 128); | 266 ASSERT(64 < -exponent && -exponent <= 128); |
266 UInt128 fractionals128 = UInt128(fractionals, 0); | 267 UInt128 fractionals128 = UInt128(fractionals, 0); |
267 fractionals128.Shift(-exponent - 64); | 268 fractionals128.Shift(-exponent - 64); |
268 int point = 128; | 269 int point = 128; |
269 for (int i = 0; i < fractional_count; ++i) { | 270 for (int i = 0; i < fractional_count; ++i) { |
270 if (fractionals128.IsZero()) break; | 271 if (fractionals128.IsZero()) break; |
271 // As before: instead of multiplying by 10 we multiply by 5 and adjust the | 272 // As before: instead of multiplying by 10 we multiply by 5 and adjust the |
272 // point location. | 273 // point location. |
273 // This multiplication will not overflow for the same reasons as before. | 274 // This multiplication will not overflow for the same reasons as before. |
274 fractionals128.Multiply(5); | 275 fractionals128.Multiply(5); |
275 point--; | 276 point--; |
276 int digit = fractionals128.DivModPowerOf2(point); | 277 int digit = fractionals128.DivModPowerOf2(point); |
277 buffer[*length] = '0' + digit; | 278 ASSERT(digit <= 9); |
| 279 buffer[*length] = static_cast<char>('0' + digit); |
278 (*length)++; | 280 (*length)++; |
279 } | 281 } |
280 if (fractionals128.BitAt(point - 1) == 1) { | 282 if (fractionals128.BitAt(point - 1) == 1) { |
281 RoundUp(buffer, length, decimal_point); | 283 RoundUp(buffer, length, decimal_point); |
282 } | 284 } |
283 } | 285 } |
284 } | 286 } |
285 | 287 |
286 | 288 |
287 // Removes leading and trailing zeros. | 289 // Removes leading and trailing zeros. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // We only allow exponents of up to 20 and therefore (17 - e) <= 3 | 353 // We only allow exponents of up to 20 and therefore (17 - e) <= 3 |
352 dividend <<= exponent - divisor_power; | 354 dividend <<= exponent - divisor_power; |
353 quotient = static_cast<uint32_t>(dividend / divisor); | 355 quotient = static_cast<uint32_t>(dividend / divisor); |
354 remainder = (dividend % divisor) << divisor_power; | 356 remainder = (dividend % divisor) << divisor_power; |
355 } else { | 357 } else { |
356 divisor <<= divisor_power - exponent; | 358 divisor <<= divisor_power - exponent; |
357 quotient = static_cast<uint32_t>(dividend / divisor); | 359 quotient = static_cast<uint32_t>(dividend / divisor); |
358 remainder = (dividend % divisor) << exponent; | 360 remainder = (dividend % divisor) << exponent; |
359 } | 361 } |
360 FillDigits32(quotient, buffer, length); | 362 FillDigits32(quotient, buffer, length); |
361 FillDigits64FixedLength(remainder, divisor_power, buffer, length); | 363 FillDigits64FixedLength(remainder, buffer, length); |
362 *decimal_point = *length; | 364 *decimal_point = *length; |
363 } else if (exponent >= 0) { | 365 } else if (exponent >= 0) { |
364 // 0 <= exponent <= 11 | 366 // 0 <= exponent <= 11 |
365 significand <<= exponent; | 367 significand <<= exponent; |
366 FillDigits64(significand, buffer, length); | 368 FillDigits64(significand, buffer, length); |
367 *decimal_point = *length; | 369 *decimal_point = *length; |
368 } else if (exponent > -kDoubleSignificandSize) { | 370 } else if (exponent > -kDoubleSignificandSize) { |
369 // We have to cut the number. | 371 // We have to cut the number. |
370 uint64_t integrals = significand >> -exponent; | 372 uint64_t integrals = significand >> -exponent; |
371 uint64_t fractionals = significand - (integrals << -exponent); | 373 uint64_t fractionals = significand - (integrals << -exponent); |
(...skipping 21 matching lines...) Expand all Loading... |
393 buffer[*length] = '\0'; | 395 buffer[*length] = '\0'; |
394 if ((*length) == 0) { | 396 if ((*length) == 0) { |
395 // The string is empty and the decimal_point thus has no importance. Mimick | 397 // The string is empty and the decimal_point thus has no importance. Mimick |
396 // Gay's dtoa and and set it to -fractional_count. | 398 // Gay's dtoa and and set it to -fractional_count. |
397 *decimal_point = -fractional_count; | 399 *decimal_point = -fractional_count; |
398 } | 400 } |
399 return true; | 401 return true; |
400 } | 402 } |
401 | 403 |
402 } // namespace double_conversion | 404 } // namespace double_conversion |
OLD | NEW |