Flutter Engine
The Flutter Engine
bignum-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 "bignum-dtoa.h"
31
32#include "bignum.h"
33#include "ieee.h"
34
36
37static int NormalizedExponent(uint64_t significand, int exponent) {
38 DOUBLE_CONVERSION_ASSERT(significand != 0);
39 while ((significand & Double::kHiddenBit) == 0) {
40 significand = significand << 1;
41 exponent = exponent - 1;
42 }
43 return exponent;
44}
45
46
47// Forward declarations:
48// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
49static int EstimatePower(int exponent);
50// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
51// and denominator.
52static void InitialScaledStartValues(uint64_t significand,
53 int exponent,
54 bool lower_boundary_is_closer,
55 int estimated_power,
56 bool need_boundary_deltas,
57 Bignum* numerator,
58 Bignum* denominator,
59 Bignum* delta_minus,
60 Bignum* delta_plus);
61// Multiplies numerator/denominator so that its values lies in the range 1-10.
62// Returns decimal_point s.t.
63// v = numerator'/denominator' * 10^(decimal_point-1)
64// where numerator' and denominator' are the values of numerator and
65// denominator after the call to this function.
66static void FixupMultiply10(int estimated_power, bool is_even,
67 int* decimal_point,
68 Bignum* numerator, Bignum* denominator,
69 Bignum* delta_minus, Bignum* delta_plus);
70// Generates digits from the left to the right and stops when the generated
71// digits yield the shortest decimal representation of v.
72static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
73 Bignum* delta_minus, Bignum* delta_plus,
74 bool is_even,
75 Vector<char> buffer, int* length);
76// Generates 'requested_digits' after the decimal point.
77static void BignumToFixed(int requested_digits, int* decimal_point,
78 Bignum* numerator, Bignum* denominator,
79 Vector<char> buffer, int* length);
80// Generates 'count' digits of numerator/denominator.
81// Once 'count' digits have been produced rounds the result depending on the
82// remainder (remainders of exactly .5 round upwards). Might update the
83// decimal_point when rounding up (for example for 0.9999).
84static void GenerateCountedDigits(int count, int* decimal_point,
85 Bignum* numerator, Bignum* denominator,
86 Vector<char> buffer, int* length);
87
88
89void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
90 Vector<char> buffer, int* length, int* decimal_point) {
92 DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
93 uint64_t significand;
94 int exponent;
95 bool lower_boundary_is_closer;
97 float f = static_cast<float>(v);
99 significand = Single(f).Significand();
100 exponent = Single(f).Exponent();
101 lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
102 } else {
103 significand = Double(v).Significand();
104 exponent = Double(v).Exponent();
105 lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
106 }
107 bool need_boundary_deltas =
109
110 bool is_even = (significand & 1) == 0;
111 int normalized_exponent = NormalizedExponent(significand, exponent);
112 // estimated_power might be too low by 1.
113 int estimated_power = EstimatePower(normalized_exponent);
114
115 // Shortcut for Fixed.
116 // The requested digits correspond to the digits after the point. If the
117 // number is much too small, then there is no need in trying to get any
118 // digits.
119 if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
120 buffer[0] = '\0';
121 *length = 0;
122 // Set decimal-point to -requested_digits. This is what Gay does.
123 // Note that it should not have any effect anyways since the string is
124 // empty.
125 *decimal_point = -requested_digits;
126 return;
127 }
128
129 Bignum numerator;
130 Bignum denominator;
131 Bignum delta_minus;
132 Bignum delta_plus;
133 // Make sure the bignum can grow large enough. The smallest double equals
134 // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
135 // The maximum double is 1.7976931348623157e308 which needs fewer than
136 // 308*4 binary digits.
138 InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
139 estimated_power, need_boundary_deltas,
140 &numerator, &denominator,
141 &delta_minus, &delta_plus);
142 // We now have v = (numerator / denominator) * 10^estimated_power.
143 FixupMultiply10(estimated_power, is_even, decimal_point,
144 &numerator, &denominator,
145 &delta_minus, &delta_plus);
146 // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
147 // 1 <= (numerator + delta_plus) / denominator < 10
148 switch (mode) {
151 GenerateShortestDigits(&numerator, &denominator,
152 &delta_minus, &delta_plus,
154 break;
156 BignumToFixed(requested_digits, decimal_point,
157 &numerator, &denominator,
158 buffer, length);
159 break;
161 GenerateCountedDigits(requested_digits, decimal_point,
162 &numerator, &denominator,
163 buffer, length);
164 break;
165 default:
167 }
168 buffer[*length] = '\0';
169}
170
171
172// The procedure starts generating digits from the left to the right and stops
173// when the generated digits yield the shortest decimal representation of v. A
174// decimal representation of v is a number lying closer to v than to any other
175// double, so it converts to v when read.
176//
177// This is true if d, the decimal representation, is between m- and m+, the
178// upper and lower boundaries. d must be strictly between them if !is_even.
179// m- := (numerator - delta_minus) / denominator
180// m+ := (numerator + delta_plus) / denominator
181//
182// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
183// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
184// will be produced. This should be the standard precondition.
185static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
186 Bignum* delta_minus, Bignum* delta_plus,
187 bool is_even,
188 Vector<char> buffer, int* length) {
189 // Small optimization: if delta_minus and delta_plus are the same just reuse
190 // one of the two bignums.
191 if (Bignum::Equal(*delta_minus, *delta_plus)) {
192 delta_plus = delta_minus;
193 }
194 *length = 0;
195 for (;;) {
196 uint16_t digit;
197 digit = numerator->DivideModuloIntBignum(*denominator);
198 DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
199 // digit = numerator / denominator (integer division).
200 // numerator = numerator % denominator.
201 buffer[(*length)++] = static_cast<char>(digit + '0');
202
203 // Can we stop already?
204 // If the remainder of the division is less than the distance to the lower
205 // boundary we can stop. In this case we simply round down (discarding the
206 // remainder).
207 // Similarly we test if we can round up (using the upper boundary).
208 bool in_delta_room_minus;
209 bool in_delta_room_plus;
210 if (is_even) {
211 in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
212 } else {
213 in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
214 }
215 if (is_even) {
216 in_delta_room_plus =
217 Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
218 } else {
219 in_delta_room_plus =
220 Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
221 }
222 if (!in_delta_room_minus && !in_delta_room_plus) {
223 // Prepare for next iteration.
224 numerator->Times10();
225 delta_minus->Times10();
226 // We optimized delta_plus to be equal to delta_minus (if they share the
227 // same value). So don't multiply delta_plus if they point to the same
228 // object.
229 if (delta_minus != delta_plus) {
230 delta_plus->Times10();
231 }
232 } else if (in_delta_room_minus && in_delta_room_plus) {
233 // Let's see if 2*numerator < denominator.
234 // If yes, then the next digit would be < 5 and we can round down.
235 int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
236 if (compare < 0) {
237 // Remaining digits are less than .5. -> Round down (== do nothing).
238 } else if (compare > 0) {
239 // Remaining digits are more than .5 of denominator. -> Round up.
240 // Note that the last digit could not be a '9' as otherwise the whole
241 // loop would have stopped earlier.
242 // We still have an assert here in case the preconditions were not
243 // satisfied.
244 DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
245 buffer[(*length) - 1]++;
246 } else {
247 // Halfway case.
248 // TODO(floitsch): need a way to solve half-way cases.
249 // For now let's round towards even (since this is what Gay seems to
250 // do).
251
252 if ((buffer[(*length) - 1] - '0') % 2 == 0) {
253 // Round down => Do nothing.
254 } else {
255 DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
256 buffer[(*length) - 1]++;
257 }
258 }
259 return;
260 } else if (in_delta_room_minus) {
261 // Round down (== do nothing).
262 return;
263 } else { // in_delta_room_plus
264 // Round up.
265 // Note again that the last digit could not be '9' since this would have
266 // stopped the loop earlier.
267 // We still have an DOUBLE_CONVERSION_ASSERT here, in case the preconditions were not
268 // satisfied.
270 buffer[(*length) - 1]++;
271 return;
272 }
273 }
274}
275
276
277// Let v = numerator / denominator < 10.
278// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
279// from left to right. Once 'count' digits have been produced we decide whether
280// to round up or down. Remainders of exactly .5 round upwards. Numbers such
281// as 9.999999 propagate a carry all the way, and change the
282// exponent (decimal_point), when rounding upwards.
283static void GenerateCountedDigits(int count, int* decimal_point,
284 Bignum* numerator, Bignum* denominator,
285 Vector<char> buffer, int* length) {
287 for (int i = 0; i < count - 1; ++i) {
288 uint16_t digit;
289 digit = numerator->DivideModuloIntBignum(*denominator);
290 DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
291 // digit = numerator / denominator (integer division).
292 // numerator = numerator % denominator.
293 buffer[i] = static_cast<char>(digit + '0');
294 // Prepare for next iteration.
295 numerator->Times10();
296 }
297 // Generate the last digit.
298 uint16_t digit;
299 digit = numerator->DivideModuloIntBignum(*denominator);
300 if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
301 digit++;
302 }
303 DOUBLE_CONVERSION_ASSERT(digit <= 10);
304 buffer[count - 1] = static_cast<char>(digit + '0');
305 // Correct bad digits (in case we had a sequence of '9's). Propagate the
306 // carry until we hat a non-'9' or til we reach the first digit.
307 for (int i = count - 1; i > 0; --i) {
308 if (buffer[i] != '0' + 10) break;
309 buffer[i] = '0';
310 buffer[i - 1]++;
311 }
312 if (buffer[0] == '0' + 10) {
313 // Propagate a carry past the top place.
314 buffer[0] = '1';
315 (*decimal_point)++;
316 }
317 *length = count;
318}
319
320
321// Generates 'requested_digits' after the decimal point. It might omit
322// trailing '0's. If the input number is too small then no digits at all are
323// generated (ex.: 2 fixed digits for 0.00001).
324//
325// Input verifies: 1 <= (numerator + delta) / denominator < 10.
326static void BignumToFixed(int requested_digits, int* decimal_point,
327 Bignum* numerator, Bignum* denominator,
328 Vector<char> buffer, int* length) {
329 // Note that we have to look at more than just the requested_digits, since
330 // a number could be rounded up. Example: v=0.5 with requested_digits=0.
331 // Even though the power of v equals 0 we can't just stop here.
332 if (-(*decimal_point) > requested_digits) {
333 // The number is definitively too small.
334 // Ex: 0.001 with requested_digits == 1.
335 // Set decimal-point to -requested_digits. This is what Gay does.
336 // Note that it should not have any effect anyways since the string is
337 // empty.
338 *decimal_point = -requested_digits;
339 *length = 0;
340 return;
341 } else if (-(*decimal_point) == requested_digits) {
342 // We only need to verify if the number rounds down or up.
343 // Ex: 0.04 and 0.06 with requested_digits == 1.
344 DOUBLE_CONVERSION_ASSERT(*decimal_point == -requested_digits);
345 // Initially the fraction lies in range (1, 10]. Multiply the denominator
346 // by 10 so that we can compare more easily.
347 denominator->Times10();
348 if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
349 // If the fraction is >= 0.5 then we have to include the rounded
350 // digit.
351 buffer[0] = '1';
352 *length = 1;
353 (*decimal_point)++;
354 } else {
355 // Note that we caught most of similar cases earlier.
356 *length = 0;
357 }
358 return;
359 } else {
360 // The requested digits correspond to the digits after the point.
361 // The variable 'needed_digits' includes the digits before the point.
362 int needed_digits = (*decimal_point) + requested_digits;
363 GenerateCountedDigits(needed_digits, decimal_point,
364 numerator, denominator,
365 buffer, length);
366 }
367}
368
369
370// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
371// v = f * 2^exponent and 2^52 <= f < 2^53.
372// v is hence a normalized double with the given exponent. The output is an
373// approximation for the exponent of the decimal approximation .digits * 10^k.
374//
375// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
376// Note: this property holds for v's upper boundary m+ too.
377// 10^k <= m+ < 10^k+1.
378// (see explanation below).
379//
380// Examples:
381// EstimatePower(0) => 16
382// EstimatePower(-52) => 0
383//
384// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
385static int EstimatePower(int exponent) {
386 // This function estimates log10 of v where v = f*2^e (with e == exponent).
387 // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
388 // Note that f is bounded by its container size. Let p = 53 (the double's
389 // significand size). Then 2^(p-1) <= f < 2^p.
390 //
391 // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
392 // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
393 // The computed number undershoots by less than 0.631 (when we compute log3
394 // and not log10).
395 //
396 // Optimization: since we only need an approximated result this computation
397 // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
398 // not really measurable, though.
399 //
400 // Since we want to avoid overshooting we decrement by 1e10 so that
401 // floating-point imprecisions don't affect us.
402 //
403 // Explanation for v's boundary m+: the computation takes advantage of
404 // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
405 // (even for denormals where the delta can be much more important).
406
407 const double k1Log10 = 0.30102999566398114; // 1/lg(10)
408
409 // For doubles len(f) == 53 (don't forget the hidden bit).
410 const int kSignificandSize = Double::kSignificandSize;
411 double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
412 return static_cast<int>(estimate);
413}
414
415
416// See comments for InitialScaledStartValues.
418 uint64_t significand, int exponent,
419 int estimated_power, bool need_boundary_deltas,
420 Bignum* numerator, Bignum* denominator,
421 Bignum* delta_minus, Bignum* delta_plus) {
422 // A positive exponent implies a positive power.
423 DOUBLE_CONVERSION_ASSERT(estimated_power >= 0);
424 // Since the estimated_power is positive we simply multiply the denominator
425 // by 10^estimated_power.
426
427 // numerator = v.
428 numerator->AssignUInt64(significand);
429 numerator->ShiftLeft(exponent);
430 // denominator = 10^estimated_power.
431 denominator->AssignPowerUInt16(10, estimated_power);
432
433 if (need_boundary_deltas) {
434 // Introduce a common denominator so that the deltas to the boundaries are
435 // integers.
436 denominator->ShiftLeft(1);
437 numerator->ShiftLeft(1);
438 // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
439 // denominator (of 2) delta_plus equals 2^e.
440 delta_plus->AssignUInt16(1);
441 delta_plus->ShiftLeft(exponent);
442 // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
443 delta_minus->AssignUInt16(1);
444 delta_minus->ShiftLeft(exponent);
445 }
446}
447
448
449// See comments for InitialScaledStartValues
451 uint64_t significand, int exponent,
452 int estimated_power, bool need_boundary_deltas,
453 Bignum* numerator, Bignum* denominator,
454 Bignum* delta_minus, Bignum* delta_plus) {
455 // v = f * 2^e with e < 0, and with estimated_power >= 0.
456 // This means that e is close to 0 (have a look at how estimated_power is
457 // computed).
458
459 // numerator = significand
460 // since v = significand * 2^exponent this is equivalent to
461 // numerator = v * / 2^-exponent
462 numerator->AssignUInt64(significand);
463 // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
464 denominator->AssignPowerUInt16(10, estimated_power);
465 denominator->ShiftLeft(-exponent);
466
467 if (need_boundary_deltas) {
468 // Introduce a common denominator so that the deltas to the boundaries are
469 // integers.
470 denominator->ShiftLeft(1);
471 numerator->ShiftLeft(1);
472 // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
473 // denominator (of 2) delta_plus equals 2^e.
474 // Given that the denominator already includes v's exponent the distance
475 // to the boundaries is simply 1.
476 delta_plus->AssignUInt16(1);
477 // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
478 delta_minus->AssignUInt16(1);
479 }
480}
481
482
483// See comments for InitialScaledStartValues
485 uint64_t significand, int exponent,
486 int estimated_power, bool need_boundary_deltas,
487 Bignum* numerator, Bignum* denominator,
488 Bignum* delta_minus, Bignum* delta_plus) {
489 // Instead of multiplying the denominator with 10^estimated_power we
490 // multiply all values (numerator and deltas) by 10^-estimated_power.
491
492 // Use numerator as temporary container for power_ten.
493 Bignum* power_ten = numerator;
494 power_ten->AssignPowerUInt16(10, -estimated_power);
495
496 if (need_boundary_deltas) {
497 // Since power_ten == numerator we must make a copy of 10^estimated_power
498 // before we complete the computation of the numerator.
499 // delta_plus = delta_minus = 10^estimated_power
500 delta_plus->AssignBignum(*power_ten);
501 delta_minus->AssignBignum(*power_ten);
502 }
503
504 // numerator = significand * 2 * 10^-estimated_power
505 // since v = significand * 2^exponent this is equivalent to
506 // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
507 // Remember: numerator has been abused as power_ten. So no need to assign it
508 // to itself.
509 DOUBLE_CONVERSION_ASSERT(numerator == power_ten);
510 numerator->MultiplyByUInt64(significand);
511
512 // denominator = 2 * 2^-exponent with exponent < 0.
513 denominator->AssignUInt16(1);
514 denominator->ShiftLeft(-exponent);
515
516 if (need_boundary_deltas) {
517 // Introduce a common denominator so that the deltas to the boundaries are
518 // integers.
519 numerator->ShiftLeft(1);
520 denominator->ShiftLeft(1);
521 // With this shift the boundaries have their correct value, since
522 // delta_plus = 10^-estimated_power, and
523 // delta_minus = 10^-estimated_power.
524 // These assignments have been done earlier.
525 // The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
526 }
527}
528
529
530// Let v = significand * 2^exponent.
531// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
532// and denominator. The functions GenerateShortestDigits and
533// GenerateCountedDigits will then convert this ratio to its decimal
534// representation d, with the required accuracy.
535// Then d * 10^estimated_power is the representation of v.
536// (Note: the fraction and the estimated_power might get adjusted before
537// generating the decimal representation.)
538//
539// The initial start values consist of:
540// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
541// - a scaled (common) denominator.
542// optionally (used by GenerateShortestDigits to decide if it has the shortest
543// decimal converting back to v):
544// - v - m-: the distance to the lower boundary.
545// - m+ - v: the distance to the upper boundary.
546//
547// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
548//
549// Let ep == estimated_power, then the returned values will satisfy:
550// v / 10^ep = numerator / denominator.
551// v's boundaries m- and m+:
552// m- / 10^ep == v / 10^ep - delta_minus / denominator
553// m+ / 10^ep == v / 10^ep + delta_plus / denominator
554// Or in other words:
555// m- == v - delta_minus * 10^ep / denominator;
556// m+ == v + delta_plus * 10^ep / denominator;
557//
558// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
559// or 10^k <= v < 10^(k+1)
560// we then have 0.1 <= numerator/denominator < 1
561// or 1 <= numerator/denominator < 10
562//
563// It is then easy to kickstart the digit-generation routine.
564//
565// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
566// or BIGNUM_DTOA_SHORTEST_SINGLE.
567
568static void InitialScaledStartValues(uint64_t significand,
569 int exponent,
570 bool lower_boundary_is_closer,
571 int estimated_power,
572 bool need_boundary_deltas,
573 Bignum* numerator,
574 Bignum* denominator,
575 Bignum* delta_minus,
576 Bignum* delta_plus) {
577 if (exponent >= 0) {
579 significand, exponent, estimated_power, need_boundary_deltas,
580 numerator, denominator, delta_minus, delta_plus);
581 } else if (estimated_power >= 0) {
583 significand, exponent, estimated_power, need_boundary_deltas,
584 numerator, denominator, delta_minus, delta_plus);
585 } else {
587 significand, exponent, estimated_power, need_boundary_deltas,
588 numerator, denominator, delta_minus, delta_plus);
589 }
590
591 if (need_boundary_deltas && lower_boundary_is_closer) {
592 // The lower boundary is closer at half the distance of "normal" numbers.
593 // Increase the common denominator and adapt all but the delta_minus.
594 denominator->ShiftLeft(1); // *2
595 numerator->ShiftLeft(1); // *2
596 delta_plus->ShiftLeft(1); // *2
597 }
598}
599
600
601// This routine multiplies numerator/denominator so that its values lies in the
602// range 1-10. That is after a call to this function we have:
603// 1 <= (numerator + delta_plus) /denominator < 10.
604// Let numerator the input before modification and numerator' the argument
605// after modification, then the output-parameter decimal_point is such that
606// numerator / denominator * 10^estimated_power ==
607// numerator' / denominator' * 10^(decimal_point - 1)
608// In some cases estimated_power was too low, and this is already the case. We
609// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
610// estimated_power) but do not touch the numerator or denominator.
611// Otherwise the routine multiplies the numerator and the deltas by 10.
612static void FixupMultiply10(int estimated_power, bool is_even,
613 int* decimal_point,
614 Bignum* numerator, Bignum* denominator,
615 Bignum* delta_minus, Bignum* delta_plus) {
616 bool in_range;
617 if (is_even) {
618 // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
619 // are rounded to the closest floating-point number with even significand.
620 in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
621 } else {
622 in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
623 }
624 if (in_range) {
625 // Since numerator + delta_plus >= denominator we already have
626 // 1 <= numerator/denominator < 10. Simply update the estimated_power.
627 *decimal_point = estimated_power + 1;
628 } else {
629 *decimal_point = estimated_power;
630 numerator->Times10();
631 if (Bignum::Equal(*delta_minus, *delta_plus)) {
632 delta_minus->Times10();
633 delta_plus->AssignBignum(*delta_minus);
634 } else {
635 delta_minus->Times10();
636 delta_plus->Times10();
637 }
638 }
639}
640
641} // namespace double_conversion
int count
Definition: FontMgrTest.cpp:50
static int is_even(int x)
Definition: SkDashPath.cpp:31
static const int kMaxSignificantBits
Definition: bignum.h:40
void AssignBignum(const Bignum &other)
Definition: bignum.cc:75
void ShiftLeft(const int shift_amount)
Definition: bignum.cc:239
static bool Equal(const Bignum &a, const Bignum &b)
Definition: bignum.h:77
void AssignUInt64(uint64_t value)
Definition: bignum.cc:65
uint16_t DivideModuloIntBignum(const Bignum &other)
Definition: bignum.cc:502
static bool LessEqual(const Bignum &a, const Bignum &b)
Definition: bignum.h:80
static bool Less(const Bignum &a, const Bignum &b)
Definition: bignum.h:83
void AssignPowerUInt16(uint16_t base, const int exponent)
Definition: bignum.cc:427
void AssignUInt16(const uint16_t value)
Definition: bignum.cc:55
void MultiplyByUInt64(const uint64_t factor)
Definition: bignum.cc:279
static int PlusCompare(const Bignum &a, const Bignum &b, const Bignum &c)
Definition: bignum.cc:670
bool LowerBoundaryIsCloser() const
Definition: ieee.h:207
uint64_t Significand() const
Definition: ieee.h:123
int Exponent() const
Definition: ieee.h:114
static const uint64_t kHiddenBit
Definition: ieee.h:47
static const int kSignificandSize
Definition: ieee.h:50
int Exponent() const
Definition: ieee.h:313
uint32_t Significand() const
Definition: ieee.h:322
bool LowerBoundaryIsCloser() const
Definition: ieee.h:406
size_t length
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, Vector< char > buffer, int *length, int *decimal_point)
Definition: bignum-dtoa.cc:89
static void InitialScaledStartValuesNegativeExponentPositivePower(uint64_t significand, int exponent, int estimated_power, bool need_boundary_deltas, Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus)
Definition: bignum-dtoa.cc:450
static int EstimatePower(int exponent)
Definition: bignum-dtoa.cc:385
static void GenerateShortestDigits(Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus, bool is_even, Vector< char > buffer, int *length)
Definition: bignum-dtoa.cc:185
static void BignumToFixed(int requested_digits, int *decimal_point, Bignum *numerator, Bignum *denominator, Vector< char > buffer, int *length)
Definition: bignum-dtoa.cc:326
static void InitialScaledStartValues(uint64_t significand, int exponent, bool lower_boundary_is_closer, int estimated_power, bool need_boundary_deltas, Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus)
Definition: bignum-dtoa.cc:568
static void InitialScaledStartValuesPositiveExponent(uint64_t significand, int exponent, int estimated_power, bool need_boundary_deltas, Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus)
Definition: bignum-dtoa.cc:417
static void FixupMultiply10(int estimated_power, bool is_even, int *decimal_point, Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus)
Definition: bignum-dtoa.cc:612
static int NormalizedExponent(uint64_t significand, int exponent)
Definition: bignum-dtoa.cc:37
static void GenerateCountedDigits(int count, int *decimal_point, Bignum *numerator, Bignum *denominator, Vector< char > buffer, int *length)
Definition: bignum-dtoa.cc:283
static void InitialScaledStartValuesNegativeExponentNegativePower(uint64_t significand, int exponent, int estimated_power, bool need_boundary_deltas, Bignum *numerator, Bignum *denominator, Bignum *delta_minus, Bignum *delta_plus)
Definition: bignum-dtoa.cc:484
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition: SkVx.h:702
int compare(const void *untyped_lhs, const void *untyped_rhs)
Definition: skdiff.h:161
#define DOUBLE_CONVERSION_ASSERT(condition)
Definition: utils.h:46
#define DOUBLE_CONVERSION_UNREACHABLE()
Definition: utils.h:77