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 | |
77 extern "C" double gay_strtod(const char* s00, const char** se); | 39 extern "C" double gay_strtod(const char* s00, const char** se); |
78 | 40 |
79 static double old_strtod(Vector<char> buffer, int exponent) { | 41 double strtod(Vector<char> buffer, int exponent) { |
80 char gay_buffer[1024]; | 42 char gay_buffer[1024]; |
81 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); | 43 Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer)); |
82 buffer.start()[buffer.length()] = '\0'; | 44 buffer.start()[buffer.length()] = '\0'; |
83 OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent); | 45 OS::SNPrintF(gay_buffer_vector, "%se%d", buffer.start(), exponent); |
84 return gay_strtod(gay_buffer, NULL); | 46 return gay_strtod(gay_buffer, NULL); |
85 } | 47 } |
86 | 48 |
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 | |
146 } } // namespace v8::internal | 49 } } // namespace v8::internal |
OLD | NEW |