Flutter Engine
The Flutter Engine
fixed-dtoa.cc
Go to the documentation of this file.
1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28#include <cmath>
29
30#include "fixed-dtoa.h"
31#include "ieee.h"
32
33namespace double_conversion {
34
35// Represents a 128bit type. This class should be replaced by a native type on
36// platforms that support 128bit integers.
37class UInt128 {
38 public:
39 UInt128() : high_bits_(0), low_bits_(0) { }
40 UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
41
42 void Multiply(uint32_t multiplicand) {
43 uint64_t accumulator;
44
45 accumulator = (low_bits_ & kMask32) * multiplicand;
46 uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
47 accumulator >>= 32;
48 accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
49 low_bits_ = (accumulator << 32) + part;
50 accumulator >>= 32;
51 accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
52 part = static_cast<uint32_t>(accumulator & kMask32);
53 accumulator >>= 32;
54 accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
55 high_bits_ = (accumulator << 32) + part;
56 DOUBLE_CONVERSION_ASSERT((accumulator >> 32) == 0);
57 }
58
59 void Shift(int shift_amount) {
60 DOUBLE_CONVERSION_ASSERT(-64 <= shift_amount && shift_amount <= 64);
61 if (shift_amount == 0) {
62 return;
63 } else if (shift_amount == -64) {
64 high_bits_ = low_bits_;
65 low_bits_ = 0;
66 } else if (shift_amount == 64) {
67 low_bits_ = high_bits_;
68 high_bits_ = 0;
69 } else if (shift_amount <= 0) {
70 high_bits_ <<= -shift_amount;
71 high_bits_ += low_bits_ >> (64 + shift_amount);
72 low_bits_ <<= -shift_amount;
73 } else {
74 low_bits_ >>= shift_amount;
75 low_bits_ += high_bits_ << (64 - shift_amount);
76 high_bits_ >>= shift_amount;
77 }
78 }
79
80 // Modifies *this to *this MOD (2^power).
81 // Returns *this DIV (2^power).
82 int DivModPowerOf2(int power) {
83 if (power >= 64) {
84 int result = static_cast<int>(high_bits_ >> (power - 64));
85 high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
86 return result;
87 } else {
88 uint64_t part_low = low_bits_ >> power;
89 uint64_t part_high = high_bits_ << (64 - power);
90 int result = static_cast<int>(part_low + part_high);
91 high_bits_ = 0;
92 low_bits_ -= part_low << power;
93 return result;
94 }
95 }
96
97 bool IsZero() const {
98 return high_bits_ == 0 && low_bits_ == 0;
99 }
100
101 int BitAt(int position) const {
102 if (position >= 64) {
103 return static_cast<int>(high_bits_ >> (position - 64)) & 1;
104 } else {
105 return static_cast<int>(low_bits_ >> position) & 1;
106 }
107 }
108
109 private:
110 static const uint64_t kMask32 = 0xFFFFFFFF;
111 // Value == (high_bits_ << 64) + low_bits_
112 uint64_t high_bits_;
113 uint64_t low_bits_;
114};
115
116
117static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
118
119
120static void FillDigits32FixedLength(uint32_t number, int requested_length,
121 Vector<char> buffer, int* length) {
122 for (int i = requested_length - 1; i >= 0; --i) {
123 buffer[(*length) + i] = '0' + number % 10;
124 number /= 10;
125 }
126 *length += requested_length;
127}
128
129
130static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
131 int number_length = 0;
132 // We fill the digits in reverse order and exchange them afterwards.
133 while (number != 0) {
134 int digit = number % 10;
135 number /= 10;
136 buffer[(*length) + number_length] = static_cast<char>('0' + digit);
137 number_length++;
138 }
139 // Exchange the digits.
140 int i = *length;
141 int j = *length + number_length - 1;
142 while (i < j) {
143 char tmp = buffer[i];
144 buffer[i] = buffer[j];
145 buffer[j] = tmp;
146 i++;
147 j--;
148 }
149 *length += number_length;
150}
151
152
153static void FillDigits64FixedLength(uint64_t number,
154 Vector<char> buffer, int* length) {
155 const uint32_t kTen7 = 10000000;
156 // For efficiency cut the number into 3 uint32_t parts, and print those.
157 uint32_t part2 = static_cast<uint32_t>(number % kTen7);
158 number /= kTen7;
159 uint32_t part1 = static_cast<uint32_t>(number % kTen7);
160 uint32_t part0 = static_cast<uint32_t>(number / kTen7);
161
165}
166
167
168static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
169 const uint32_t kTen7 = 10000000;
170 // For efficiency cut the number into 3 uint32_t parts, and print those.
171 uint32_t part2 = static_cast<uint32_t>(number % kTen7);
172 number /= kTen7;
173 uint32_t part1 = static_cast<uint32_t>(number % kTen7);
174 uint32_t part0 = static_cast<uint32_t>(number / kTen7);
175
176 if (part0 != 0) {
177 FillDigits32(part0, buffer, length);
180 } else if (part1 != 0) {
181 FillDigits32(part1, buffer, length);
183 } else {
184 FillDigits32(part2, buffer, length);
185 }
186}
187
188
189static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
190 // An empty buffer represents 0.
191 if (*length == 0) {
192 buffer[0] = '1';
193 *decimal_point = 1;
194 *length = 1;
195 return;
196 }
197 // Round the last digit until we either have a digit that was not '9' or until
198 // we reached the first digit.
199 buffer[(*length) - 1]++;
200 for (int i = (*length) - 1; i > 0; --i) {
201 if (buffer[i] != '0' + 10) {
202 return;
203 }
204 buffer[i] = '0';
205 buffer[i - 1]++;
206 }
207 // If the first digit is now '0' + 10, we would need to set it to '0' and add
208 // a '1' in front. However we reach the first digit only if all following
209 // digits had been '9' before rounding up. Now all trailing digits are '0' and
210 // we simply switch the first digit to '1' and update the decimal-point
211 // (indicating that the point is now one digit to the right).
212 if (buffer[0] == '0' + 10) {
213 buffer[0] = '1';
214 (*decimal_point)++;
215 }
216}
217
218
219// The given fractionals number represents a fixed-point number with binary
220// point at bit (-exponent).
221// Preconditions:
222// -128 <= exponent <= 0.
223// 0 <= fractionals * 2^exponent < 1
224// The buffer holds the result.
225// The function will round its result. During the rounding-process digits not
226// generated by this function might be updated, and the decimal-point variable
227// might be updated. If this function generates the digits 99 and the buffer
228// already contained "199" (thus yielding a buffer of "19999") then a
229// rounding-up will change the contents of the buffer to "20000".
230static void FillFractionals(uint64_t fractionals, int exponent,
231 int fractional_count, Vector<char> buffer,
232 int* length, int* decimal_point) {
233 DOUBLE_CONVERSION_ASSERT(-128 <= exponent && exponent <= 0);
234 // 'fractionals' is a fixed-point number, with binary point at bit
235 // (-exponent). Inside the function the non-converted remainder of fractionals
236 // is a fixed-point number, with binary point at bit 'point'.
237 if (-exponent <= 64) {
238 // One 64 bit number is sufficient.
239 DOUBLE_CONVERSION_ASSERT(fractionals >> 56 == 0);
240 int point = -exponent;
241 for (int i = 0; i < fractional_count; ++i) {
242 if (fractionals == 0) break;
243 // Instead of multiplying by 10 we multiply by 5 and adjust the point
244 // location. This way the fractionals variable will not overflow.
245 // Invariant at the beginning of the loop: fractionals < 2^point.
246 // Initially we have: point <= 64 and fractionals < 2^56
247 // After each iteration the point is decremented by one.
248 // Note that 5^3 = 125 < 128 = 2^7.
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
251 // time point will satisfy point <= 61 and therefore fractionals < 2^point
252 // and any further multiplication of fractionals by 5 will not overflow.
253 fractionals *= 5;
254 point--;
255 int digit = static_cast<int>(fractionals >> point);
256 DOUBLE_CONVERSION_ASSERT(digit <= 9);
257 buffer[*length] = static_cast<char>('0' + digit);
258 (*length)++;
259 fractionals -= static_cast<uint64_t>(digit) << point;
260 }
261 // If the first bit after the point is set we have to round up.
262 DOUBLE_CONVERSION_ASSERT(fractionals == 0 || point - 1 >= 0);
263 if ((fractionals != 0) && ((fractionals >> (point - 1)) & 1) == 1) {
264 RoundUp(buffer, length, decimal_point);
265 }
266 } else { // We need 128 bits.
267 DOUBLE_CONVERSION_ASSERT(64 < -exponent && -exponent <= 128);
268 UInt128 fractionals128 = UInt128(fractionals, 0);
269 fractionals128.Shift(-exponent - 64);
270 int point = 128;
271 for (int i = 0; i < fractional_count; ++i) {
272 if (fractionals128.IsZero()) break;
273 // As before: instead of multiplying by 10 we multiply by 5 and adjust the
274 // point location.
275 // This multiplication will not overflow for the same reasons as before.
276 fractionals128.Multiply(5);
277 point--;
278 int digit = fractionals128.DivModPowerOf2(point);
279 DOUBLE_CONVERSION_ASSERT(digit <= 9);
280 buffer[*length] = static_cast<char>('0' + digit);
281 (*length)++;
282 }
283 if (fractionals128.BitAt(point - 1) == 1) {
284 RoundUp(buffer, length, decimal_point);
285 }
286 }
287}
288
289
290// Removes leading and trailing zeros.
291// If leading zeros are removed then the decimal point position is adjusted.
292static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
293 while (*length > 0 && buffer[(*length) - 1] == '0') {
294 (*length)--;
295 }
296 int first_non_zero = 0;
297 while (first_non_zero < *length && buffer[first_non_zero] == '0') {
298 first_non_zero++;
299 }
300 if (first_non_zero != 0) {
301 for (int i = first_non_zero; i < *length; ++i) {
302 buffer[i - first_non_zero] = buffer[i];
303 }
304 *length -= first_non_zero;
305 *decimal_point -= first_non_zero;
306 }
307}
308
309
310bool FastFixedDtoa(double v,
311 int fractional_count,
313 int* length,
314 int* decimal_point) {
315 const uint32_t kMaxUInt32 = 0xFFFFFFFF;
316 uint64_t significand = Double(v).Significand();
317 int exponent = Double(v).Exponent();
318 // v = significand * 2^exponent (with significand a 53bit integer).
319 // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
320 // don't know how to compute the representation. 2^73 ~= 9.5*10^21.
321 // If necessary this limit could probably be increased, but we don't need
322 // more.
323 if (exponent > 20) return false;
324 if (fractional_count > 20) return false;
325 *length = 0;
326 // At most kDoubleSignificandSize bits of the significand are non-zero.
327 // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
328 // bits: 0..11*..0xxx..53*..xx
329 if (exponent + kDoubleSignificandSize > 64) {
330 // The exponent must be > 11.
331 //
332 // We know that v = significand * 2^exponent.
333 // And the exponent > 11.
334 // We simplify the task by dividing v by 10^17.
335 // The quotient delivers the first digits, and the remainder fits into a 64
336 // bit number.
337 // Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
338 const uint64_t kFive17 = DOUBLE_CONVERSION_UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
339 uint64_t divisor = kFive17;
340 int divisor_power = 17;
341 uint64_t dividend = significand;
342 uint32_t quotient;
343 uint64_t remainder;
344 // Let v = f * 2^e with f == significand and e == exponent.
345 // Then need q (quotient) and r (remainder) as follows:
346 // v = q * 10^17 + r
347 // f * 2^e = q * 10^17 + r
348 // f * 2^e = q * 5^17 * 2^17 + r
349 // If e > 17 then
350 // f * 2^(e-17) = q * 5^17 + r/2^17
351 // else
352 // f = q * 5^17 * 2^(17-e) + r/2^e
353 if (exponent > divisor_power) {
354 // We only allow exponents of up to 20 and therefore (17 - e) <= 3
355 dividend <<= exponent - divisor_power;
356 quotient = static_cast<uint32_t>(dividend / divisor);
357 remainder = (dividend % divisor) << divisor_power;
358 } else {
359 divisor <<= divisor_power - exponent;
360 quotient = static_cast<uint32_t>(dividend / divisor);
361 remainder = (dividend % divisor) << exponent;
362 }
363 FillDigits32(quotient, buffer, length);
365 *decimal_point = *length;
366 } else if (exponent >= 0) {
367 // 0 <= exponent <= 11
368 significand <<= exponent;
369 FillDigits64(significand, buffer, length);
370 *decimal_point = *length;
371 } else if (exponent > -kDoubleSignificandSize) {
372 // We have to cut the number.
373 uint64_t integrals = significand >> -exponent;
374 uint64_t fractionals = significand - (integrals << -exponent);
375 if (integrals > kMaxUInt32) {
376 FillDigits64(integrals, buffer, length);
377 } else {
378 FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
379 }
380 *decimal_point = *length;
381 FillFractionals(fractionals, exponent, fractional_count,
382 buffer, length, decimal_point);
383 } else if (exponent < -128) {
384 // This configuration (with at most 20 digits) means that all digits must be
385 // 0.
386 DOUBLE_CONVERSION_ASSERT(fractional_count <= 20);
387 buffer[0] = '\0';
388 *length = 0;
389 *decimal_point = -fractional_count;
390 } else {
391 *decimal_point = 0;
392 FillFractionals(significand, exponent, fractional_count,
393 buffer, length, decimal_point);
394 }
395 TrimZeros(buffer, length, decimal_point);
396 buffer[*length] = '\0';
397 if ((*length) == 0) {
398 // The string is empty and the decimal_point thus has no importance. Mimic
399 // Gay's dtoa and set it to -fractional_count.
400 *decimal_point = -fractional_count;
401 }
402 return true;
403}
404
405} // namespace double_conversion
uint64_t Significand() const
Definition: ieee.h:123
int Exponent() const
Definition: ieee.h:114
UInt128(uint64_t high, uint64_t low)
Definition: fixed-dtoa.cc:40
void Shift(int shift_amount)
Definition: fixed-dtoa.cc:59
int DivModPowerOf2(int power)
Definition: fixed-dtoa.cc:82
void Multiply(uint32_t multiplicand)
Definition: fixed-dtoa.cc:42
int BitAt(int position) const
Definition: fixed-dtoa.cc:101
GAsyncResult * result
size_t length
static void FillDigits64FixedLength(uint64_t number, Vector< char > buffer, int *length)
Definition: fixed-dtoa.cc:153
static void FillDigits32FixedLength(uint32_t number, int requested_length, Vector< char > buffer, int *length)
Definition: fixed-dtoa.cc:120
static void FillFractionals(uint64_t fractionals, int exponent, int fractional_count, Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:230
static const int kDoubleSignificandSize
Definition: fixed-dtoa.cc:117
bool FastFixedDtoa(double v, int fractional_count, Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:310
static void FillDigits32(uint32_t number, Vector< char > buffer, int *length)
Definition: fixed-dtoa.cc:130
static void TrimZeros(Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:292
static void RoundUp(Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:189
static void FillDigits64(uint64_t number, Vector< char > buffer, int *length)
Definition: fixed-dtoa.cc:168
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define DOUBLE_CONVERSION_ASSERT(condition)
Definition: utils.h:46
#define DOUBLE_CONVERSION_UINT64_2PART_C(a, b)
Definition: utils.h:195