Flutter Engine
The Flutter Engine
strtod.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 <climits>
29#include <cstdarg>
30
31#include "bignum.h"
32#include "cached-powers.h"
33#include "ieee.h"
34#include "strtod.h"
35
36namespace double_conversion {
37
38#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
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.
42static const int kMaxExactDoubleIntegerDecimalDigits = 15;
43#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
44// 2^64 = 18446744073709551616 > 10^19
45static const int kMaxUint64DecimalDigits = 19;
46
47// Max double: 1.7976931348623157 x 10^308
48// Min non-zero double: 4.9406564584124654 x 10^-324
49// Any x >= 10^309 is interpreted as +infinity.
50// Any x <= 10^-324 is interpreted as 0.
51// Note that 2.5e-324 (despite being smaller than the min double) will be read
52// as non-zero (equal to the min non-zero double).
53static const int kMaxDecimalPower = 309;
54static const int kMinDecimalPower = -324;
55
56// 2^64 = 18446744073709551616
57static const uint64_t kMaxUint64 = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
58
59
60#if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
61static const double exact_powers_of_ten[] = {
62 1.0, // 10^0
63 10.0,
64 100.0,
65 1000.0,
66 10000.0,
67 100000.0,
68 1000000.0,
69 10000000.0,
70 100000000.0,
71 1000000000.0,
72 10000000000.0, // 10^10
73 100000000000.0,
74 1000000000000.0,
75 10000000000000.0,
76 100000000000000.0,
77 1000000000000000.0,
78 10000000000000000.0,
79 100000000000000000.0,
80 1000000000000000000.0,
81 10000000000000000000.0,
82 100000000000000000000.0, // 10^20
83 1000000000000000000000.0,
84 // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
85 10000000000000000000000.0
86};
87static const int kExactPowersOfTenSize = DOUBLE_CONVERSION_ARRAY_SIZE(exact_powers_of_ten);
88#endif // #if defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
89
90// Maximum number of significant digits in the decimal representation.
91// In fact the value is 772 (see conversions.cc), but to give us some margin
92// we round up to 780.
93static const int kMaxSignificantDecimalDigits = 780;
94
96 for (int i = 0; i < buffer.length(); i++) {
97 if (buffer[i] != '0') {
98 return buffer.SubVector(i, buffer.length());
99 }
100 }
101 return Vector<const char>(buffer.start(), 0);
102}
103
105 int exponent,
106 char* significant_buffer,
107 int* significant_exponent) {
108 for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
109 significant_buffer[i] = buffer[i];
110 }
111 // The input buffer has been trimmed. Therefore the last digit must be
112 // different from '0'.
113 DOUBLE_CONVERSION_ASSERT(buffer[buffer.length() - 1] != '0');
114 // Set the last digit to be non-zero. This is sufficient to guarantee
115 // correct rounding.
116 significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
117 *significant_exponent =
118 exponent + (buffer.length() - kMaxSignificantDecimalDigits);
119}
120
121
122// Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits.
123// If possible the input-buffer is reused, but if the buffer needs to be
124// modified (due to cutting), then the input needs to be copied into the
125// buffer_copy_space.
126static void TrimAndCut(Vector<const char> buffer, int exponent,
127 char* buffer_copy_space, int space_size,
128 Vector<const char>* trimmed, int* updated_exponent) {
130 Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
131 exponent += left_trimmed.length() - right_trimmed.length();
132 if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
133 (void) space_size; // Mark variable as used.
135 CutToMaxSignificantDigits(right_trimmed, exponent,
136 buffer_copy_space, updated_exponent);
137 *trimmed = Vector<const char>(buffer_copy_space,
139 } else {
140 *trimmed = right_trimmed;
141 *updated_exponent = exponent;
142 }
143}
144
145
146// Reads digits from the buffer and converts them to a uint64.
147// Reads in as many digits as fit into a uint64.
148// When the string starts with "1844674407370955161" no further digit is read.
149// Since 2^64 = 18446744073709551616 it would still be possible read another
150// digit if it was less or equal than 6, but this would complicate the code.
152 int* number_of_read_digits) {
153 uint64_t result = 0;
154 int i = 0;
155 while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
156 int digit = buffer[i++] - '0';
157 DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
158 result = 10 * result + digit;
159 }
160 *number_of_read_digits = i;
161 return result;
162}
163
164
165// Reads a DiyFp from the buffer.
166// The returned DiyFp is not necessarily normalized.
167// If remaining_decimals is zero then the returned DiyFp is accurate.
168// Otherwise it has been rounded and has error of at most 1/2 ulp.
170 DiyFp* result,
171 int* remaining_decimals) {
172 int read_digits;
173 uint64_t significand = ReadUint64(buffer, &read_digits);
174 if (buffer.length() == read_digits) {
175 *result = DiyFp(significand, 0);
176 *remaining_decimals = 0;
177 } else {
178 // Round the significand.
179 if (buffer[read_digits] >= '5') {
180 significand++;
181 }
182 // Compute the binary exponent.
183 int exponent = 0;
184 *result = DiyFp(significand, exponent);
185 *remaining_decimals = buffer.length() - read_digits;
186 }
187}
188
189
191 int exponent,
192 double* result) {
193#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
194 // Avoid "unused parameter" warnings
195 (void) trimmed;
196 (void) exponent;
197 (void) result;
198 // On x86 the floating-point stack can be 64 or 80 bits wide. If it is
199 // 80 bits wide (as is the case on Linux) then double-rounding occurs and the
200 // result is not accurate.
201 // We know that Windows32 uses 64 bits and is therefore accurate.
202 return false;
203#else
204 if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
205 int read_digits;
206 // The trimmed input fits into a double.
207 // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
208 // can compute the result-double simply by multiplying (resp. dividing) the
209 // two numbers.
210 // This is possible because IEEE guarantees that floating-point operations
211 // return the best possible approximation.
212 if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
213 // 10^-exponent fits into a double.
214 *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
215 DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
216 *result /= exact_powers_of_ten[-exponent];
217 return true;
218 }
219 if (0 <= exponent && exponent < kExactPowersOfTenSize) {
220 // 10^exponent fits into a double.
221 *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
222 DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
223 *result *= exact_powers_of_ten[exponent];
224 return true;
225 }
226 int remaining_digits =
227 kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
228 if ((0 <= exponent) &&
229 (exponent - remaining_digits < kExactPowersOfTenSize)) {
230 // The trimmed string was short and we can multiply it with
231 // 10^remaining_digits. As a result the remaining exponent now fits
232 // into a double too.
233 *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
234 DOUBLE_CONVERSION_ASSERT(read_digits == trimmed.length());
235 *result *= exact_powers_of_ten[remaining_digits];
236 *result *= exact_powers_of_ten[exponent - remaining_digits];
237 return true;
238 }
239 }
240 return false;
241#endif
242}
243
244
245// Returns 10^exponent as an exact DiyFp.
246// The given exponent must be in the range [1; kDecimalExponentDistance[.
247static DiyFp AdjustmentPowerOfTen(int exponent) {
248 DOUBLE_CONVERSION_ASSERT(0 < exponent);
250 // Simply hardcode the remaining powers for the given decimal exponent
251 // distance.
253 switch (exponent) {
254 case 1: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xa0000000, 00000000), -60);
255 case 2: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc8000000, 00000000), -57);
256 case 3: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xfa000000, 00000000), -54);
257 case 4: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x9c400000, 00000000), -50);
258 case 5: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xc3500000, 00000000), -47);
259 case 6: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xf4240000, 00000000), -44);
260 case 7: return DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x98968000, 00000000), -40);
261 default:
263 }
264}
265
266
267// If the function returns true then the result is the correct double.
268// Otherwise it is either the correct double or the double that is just below
269// the correct double.
271 int exponent,
272 double* result) {
273 DiyFp input;
274 int remaining_decimals;
275 ReadDiyFp(buffer, &input, &remaining_decimals);
276 // Since we may have dropped some digits the input is not accurate.
277 // If remaining_decimals is different than 0 than the error is at most
278 // .5 ulp (unit in the last place).
279 // We don't want to deal with fractions and therefore keep a common
280 // denominator.
281 const int kDenominatorLog = 3;
282 const int kDenominator = 1 << kDenominatorLog;
283 // Move the remaining decimals into the exponent.
284 exponent += remaining_decimals;
285 uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
286
287 int old_e = input.e();
288 input.Normalize();
289 error <<= old_e - input.e();
290
293 *result = 0.0;
294 return true;
295 }
296 DiyFp cached_power;
297 int cached_decimal_exponent;
299 &cached_power,
300 &cached_decimal_exponent);
301
302 if (cached_decimal_exponent != exponent) {
303 int adjustment_exponent = exponent - cached_decimal_exponent;
304 DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
305 input.Multiply(adjustment_power);
306 if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
307 // The product of input with the adjustment power fits into a 64 bit
308 // integer.
310 } else {
311 // The adjustment power is exact. There is hence only an error of 0.5.
312 error += kDenominator / 2;
313 }
314 }
315
316 input.Multiply(cached_power);
317 // The error introduced by a multiplication of a*b equals
318 // error_a + error_b + error_a*error_b/2^64 + 0.5
319 // Substituting a with 'input' and b with 'cached_power' we have
320 // error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
321 // error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
322 int error_b = kDenominator / 2;
323 int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
324 int fixed_error = kDenominator / 2;
325 error += error_b + error_ab + fixed_error;
326
327 old_e = input.e();
328 input.Normalize();
329 error <<= old_e - input.e();
330
331 // See if the double's significand changes if we add/subtract the error.
332 int order_of_magnitude = DiyFp::kSignificandSize + input.e();
333 int effective_significand_size =
335 int precision_digits_count =
336 DiyFp::kSignificandSize - effective_significand_size;
337 if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
338 // This can only happen for very small denormals. In this case the
339 // half-way multiplied by the denominator exceeds the range of an uint64.
340 // Simply shift everything to the right.
341 int shift_amount = (precision_digits_count + kDenominatorLog) -
343 input.set_f(input.f() >> shift_amount);
344 input.set_e(input.e() + shift_amount);
345 // We add 1 for the lost precision of error, and kDenominator for
346 // the lost precision of input.f().
347 error = (error >> shift_amount) + 1 + kDenominator;
348 precision_digits_count -= shift_amount;
349 }
350 // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
352 DOUBLE_CONVERSION_ASSERT(precision_digits_count < 64);
353 uint64_t one64 = 1;
354 uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
355 uint64_t precision_bits = input.f() & precision_bits_mask;
356 uint64_t half_way = one64 << (precision_digits_count - 1);
357 precision_bits *= kDenominator;
358 half_way *= kDenominator;
359 DiyFp rounded_input(input.f() >> precision_digits_count,
360 input.e() + precision_digits_count);
361 if (precision_bits >= half_way + error) {
362 rounded_input.set_f(rounded_input.f() + 1);
363 }
364 // If the last_bits are too close to the half-way case than we are too
365 // inaccurate and round down. In this case we return false so that we can
366 // fall back to a more precise algorithm.
367
368 *result = Double(rounded_input).value();
369 if (half_way - error < precision_bits && precision_bits < half_way + error) {
370 // Too imprecise. The caller will have to fall back to a slower version.
371 // However the returned number is guaranteed to be either the correct
372 // double, or the next-lower double.
373 return false;
374 } else {
375 return true;
376 }
377}
378
379
380// Returns
381// - -1 if buffer*10^exponent < diy_fp.
382// - 0 if buffer*10^exponent == diy_fp.
383// - +1 if buffer*10^exponent > diy_fp.
384// Preconditions:
385// buffer.length() + exponent <= kMaxDecimalPower + 1
386// buffer.length() + exponent > kMinDecimalPower
387// buffer.length() <= kMaxDecimalSignificantDigits
389 int exponent,
390 DiyFp diy_fp) {
391 DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
392 DOUBLE_CONVERSION_ASSERT(buffer.length() + exponent > kMinDecimalPower);
394 // Make sure that the Bignum will be able to hold all our numbers.
395 // Our Bignum implementation has a separate field for exponents. Shifts will
396 // consume at most one bigit (< 64 bits).
397 // ln(10) == 3.3219...
399 Bignum buffer_bignum;
400 Bignum diy_fp_bignum;
401 buffer_bignum.AssignDecimalString(buffer);
402 diy_fp_bignum.AssignUInt64(diy_fp.f());
403 if (exponent >= 0) {
404 buffer_bignum.MultiplyByPowerOfTen(exponent);
405 } else {
406 diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
407 }
408 if (diy_fp.e() > 0) {
409 diy_fp_bignum.ShiftLeft(diy_fp.e());
410 } else {
411 buffer_bignum.ShiftLeft(-diy_fp.e());
412 }
413 return Bignum::Compare(buffer_bignum, diy_fp_bignum);
414}
415
416
417// Returns true if the guess is the correct double.
418// Returns false, when guess is either correct or the next-lower double.
419static bool ComputeGuess(Vector<const char> trimmed, int exponent,
420 double* guess) {
421 if (trimmed.length() == 0) {
422 *guess = 0.0;
423 return true;
424 }
425 if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
426 *guess = Double::Infinity();
427 return true;
428 }
429 if (exponent + trimmed.length() <= kMinDecimalPower) {
430 *guess = 0.0;
431 return true;
432 }
433
434 if (DoubleStrtod(trimmed, exponent, guess) ||
435 DiyFpStrtod(trimmed, exponent, guess)) {
436 return true;
437 }
438 if (*guess == Double::Infinity()) {
439 return true;
440 }
441 return false;
442}
443
444static bool IsDigit(const char d) {
445 return ('0' <= d) && (d <= '9');
446}
447
448static bool IsNonZeroDigit(const char d) {
449 return ('1' <= d) && (d <= '9');
450}
451
452#ifdef __has_cpp_attribute
453#if __has_cpp_attribute(maybe_unused)
454[[maybe_unused]]
455#endif
456#endif
458 for(int i = 0; i < buffer.length(); ++i) {
459 if(!IsDigit(buffer[i])) {
460 return false;
461 }
462 }
463 return (buffer.length() == 0) || (IsNonZeroDigit(buffer[0]) && IsNonZeroDigit(buffer[buffer.length()-1]));
464}
465
466double StrtodTrimmed(Vector<const char> trimmed, int exponent) {
469 double guess;
470 const bool is_correct = ComputeGuess(trimmed, exponent, &guess);
471 if (is_correct) {
472 return guess;
473 }
474 DiyFp upper_boundary = Double(guess).UpperBoundary();
475 int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
476 if (comparison < 0) {
477 return guess;
478 } else if (comparison > 0) {
479 return Double(guess).NextDouble();
480 } else if ((Double(guess).Significand() & 1) == 0) {
481 // Round towards even.
482 return guess;
483 } else {
484 return Double(guess).NextDouble();
485 }
486}
487
488double Strtod(Vector<const char> buffer, int exponent) {
489 char copy_buffer[kMaxSignificantDecimalDigits];
490 Vector<const char> trimmed;
491 int updated_exponent;
492 TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
493 &trimmed, &updated_exponent);
494 return StrtodTrimmed(trimmed, updated_exponent);
495}
496
497static float SanitizedDoubletof(double d) {
499 // ASAN has a sanitize check that disallows casting doubles to floats if
500 // they are too big.
501 // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
502 // The behavior should be covered by IEEE 754, but some projects use this
503 // flag, so work around it.
504 float max_finite = 3.4028234663852885981170418348451692544e+38;
505 // The half-way point between the max-finite and infinity value.
506 // Since infinity has an even significand everything equal or greater than
507 // this value should become infinity.
508 double half_max_finite_infinity =
509 3.40282356779733661637539395458142568448e+38;
510 if (d >= max_finite) {
511 if (d >= half_max_finite_infinity) {
512 return Single::Infinity();
513 } else {
514 return max_finite;
515 }
516 } else {
517 return static_cast<float>(d);
518 }
519}
520
521float Strtof(Vector<const char> buffer, int exponent) {
522 char copy_buffer[kMaxSignificantDecimalDigits];
523 Vector<const char> trimmed;
524 int updated_exponent;
525 TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
526 &trimmed, &updated_exponent);
527 exponent = updated_exponent;
528 return StrtofTrimmed(trimmed, exponent);
529}
530
531float StrtofTrimmed(Vector<const char> trimmed, int exponent) {
534
535 double double_guess;
536 bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
537
538 float float_guess = SanitizedDoubletof(double_guess);
539 if (float_guess == double_guess) {
540 // This shortcut triggers for integer values.
541 return float_guess;
542 }
543
544 // We must catch double-rounding. Say the double has been rounded up, and is
545 // now a boundary of a float, and rounds up again. This is why we have to
546 // look at previous too.
547 // Example (in decimal numbers):
548 // input: 12349
549 // high-precision (4 digits): 1235
550 // low-precision (3 digits):
551 // when read from input: 123
552 // when rounded from high precision: 124.
553 // To do this we simply look at the neighbors of the correct result and see
554 // if they would round to the same float. If the guess is not correct we have
555 // to look at four values (since two different doubles could be the correct
556 // double).
557
558 double double_next = Double(double_guess).NextDouble();
559 double double_previous = Double(double_guess).PreviousDouble();
560
561 float f1 = SanitizedDoubletof(double_previous);
562 float f2 = float_guess;
563 float f3 = SanitizedDoubletof(double_next);
564 float f4;
565 if (is_correct) {
566 f4 = f3;
567 } else {
568 double double_next2 = Double(double_next).NextDouble();
569 f4 = SanitizedDoubletof(double_next2);
570 }
571 (void) f2; // Mark variable as used.
572 DOUBLE_CONVERSION_ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
573
574 // If the guess doesn't lie near a single-precision boundary we can simply
575 // return its float-value.
576 if (f1 == f4) {
577 return float_guess;
578 }
579
580 DOUBLE_CONVERSION_ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
581 (f1 == f2 && f2 != f3 && f3 == f4) ||
582 (f1 == f2 && f2 == f3 && f3 != f4));
583
584 // guess and next are the two possible candidates (in the same way that
585 // double_guess was the lower candidate for a double-precision guess).
586 float guess = f1;
587 float next = f4;
588 DiyFp upper_boundary;
589 if (guess == 0.0f) {
590 float min_float = 1e-45f;
591 upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp();
592 } else {
593 upper_boundary = Single(guess).UpperBoundary();
594 }
595 int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
596 if (comparison < 0) {
597 return guess;
598 } else if (comparison > 0) {
599 return next;
600 } else if ((Single(guess).Significand() & 1) == 0) {
601 // Round towards even.
602 return guess;
603 } else {
604 return next;
605 }
606}
607
608} // namespace double_conversion
static float next(float f)
static const int kMaxSignificantBits
Definition: bignum.h:40
static int Compare(const Bignum &a, const Bignum &b)
Definition: bignum.cc:644
void ShiftLeft(const int shift_amount)
Definition: bignum.cc:239
void AssignDecimalString(const Vector< const char > value)
Definition: bignum.cc:97
void MultiplyByPowerOfTen(const int exponent)
Definition: bignum.cc:311
void AssignUInt64(uint64_t value)
Definition: bignum.cc:65
int32_t e() const
Definition: diy-fp.h:123
uint64_t f() const
Definition: diy-fp.h:122
void set_f(uint64_t new_value)
Definition: diy-fp.h:125
void Multiply(const DiyFp &other)
Definition: diy-fp.h:68
void set_e(int32_t new_value)
Definition: diy-fp.h:126
static const int kSignificandSize
Definition: diy-fp.h:43
DiyFp AsDiyFp() const
Definition: ieee.h:62
static double Infinity()
Definition: ieee.h:236
DiyFp UpperBoundary() const
Definition: ieee.h:182
static int SignificandSizeForOrderOfMagnitude(int order)
Definition: ieee.h:228
double PreviousDouble() const
Definition: ieee.h:104
double NextDouble() const
Definition: ieee.h:91
double value() const
Definition: ieee.h:220
DiyFp UpperBoundary() const
Definition: ieee.h:401
static float Infinity()
Definition: ieee.h:421
int length() const
Definition: utils.h:266
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
static const int kDecimalExponentDistance
Definition: cached-powers.h:39
void GetCachedPowerForDecimalExponent(int requested_exponent, DiyFp *power, int *found_exponent)
static const int kMinDecimalPower
Definition: strtod.cc:54
static bool IsDigit(const char d)
Definition: strtod.cc:444
static uint64_t ReadUint64(Vector< const char > buffer, int *number_of_read_digits)
Definition: strtod.cc:151
double Strtod(Vector< const char > buffer, int exponent)
Definition: strtod.cc:488
static const uint64_t kMaxUint64
Definition: strtod.cc:57
static DiyFp AdjustmentPowerOfTen(int exponent)
Definition: strtod.cc:247
static const int kMaxSignificantDecimalDigits
Definition: strtod.cc:93
static bool DiyFpStrtod(Vector< const char > buffer, int exponent, double *result)
Definition: strtod.cc:270
static bool ComputeGuess(Vector< const char > trimmed, int exponent, double *guess)
Definition: strtod.cc:419
float StrtofTrimmed(Vector< const char > trimmed, int exponent)
Definition: strtod.cc:531
float Strtof(Vector< const char > buffer, int exponent)
Definition: strtod.cc:521
static void CutToMaxSignificantDigits(Vector< const char > buffer, int exponent, char *significant_buffer, int *significant_exponent)
Definition: strtod.cc:104
static float SanitizedDoubletof(double d)
Definition: strtod.cc:497
double StrtodTrimmed(Vector< const char > trimmed, int exponent)
Definition: strtod.cc:466
static int CompareBufferWithDiyFp(Vector< const char > buffer, int exponent, DiyFp diy_fp)
Definition: strtod.cc:388
static bool DoubleStrtod(Vector< const char > trimmed, int exponent, double *result)
Definition: strtod.cc:190
static bool IsNonZeroDigit(const char d)
Definition: strtod.cc:448
static const int kMaxDecimalPower
Definition: strtod.cc:53
static Vector< const char > TrimLeadingZeros(Vector< const char > buffer)
Definition: strtod.cc:95
static const int kMaxUint64DecimalDigits
Definition: strtod.cc:45
static void TrimAndCut(Vector< const char > buffer, int exponent, char *buffer_copy_space, int space_size, Vector< const char > *trimmed, int *updated_exponent)
Definition: strtod.cc:126
static bool AssertTrimmedDigits(const Vector< const char > &buffer)
Definition: strtod.cc:457
Vector< const char > TrimTrailingZeros(Vector< const char > buffer)
Definition: strtod.h:53
static void ReadDiyFp(Vector< const char > buffer, DiyFp *result, int *remaining_decimals)
Definition: strtod.cc:169
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
#define DOUBLE_CONVERSION_UNREACHABLE()
Definition: utils.h:77
#define DOUBLE_CONVERSION_ARRAY_SIZE(a)
Definition: utils.h:205