Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Unified Diff: src/bignum-dtoa.cc

Issue 3468003: Add bignum fall-back when the fast dtoa doesn't succeed. This removes Gay's d... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/bignum-dtoa.cc
===================================================================
--- src/bignum-dtoa.cc (revision 0)
+++ src/bignum-dtoa.cc (revision 0)
@@ -0,0 +1,549 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <math.h>
+
+#include "v8.h"
+#include "bignum-dtoa.h"
+
+#include "bignum.h"
+#include "double.h"
+
+namespace v8 {
+namespace internal {
+
+// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
William Hesse 2010/11/15 15:48:30 This is unclear. Explains that the input is the ex
Florian Loitsch 2010/11/16 14:32:06 Done.
+// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
+// Note: the same is true for v + wiggle_plus (instead of simply v) (see
William Hesse 2010/11/15 15:48:30 What is wiggle_plus?
Florian Loitsch 2010/11/16 14:32:06 Changed to v+ (v's positive boundary).
+// explanation below).
+// Examples:
+// EstimatePower(0) => 16
+// EstimatePower(-52) => 0
+//
+// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
+static int EstimatePower(int exponent) {
+ // This function estimates log10 of v where v = f*2^e (with e == exponent).
+ // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
+ // Note that f is bounded by its container size. Let p = 53 (the double's
+ // significand size). Then 2^(p-1) <= f < 2^p.
+ //
+ // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
+ // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
+ // The computed number undershoots by less than 0.631 (when we compute log3
+ // and not log10).
+ //
+ // Optimization: since we only need an approximated result this computation
+ // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
+ // not really measurable, though.
+ //
+ // Since we want to avoid overshooting we decrement by 1e10 so that
+ // floating-point imprecisions don't affect us.
+ //
+ // Explanation for (v + wiggle_plus): the computation takes advantage of the
William Hesse 2010/11/15 15:48:30 Can the wiggle stuff be put where wiggle is used?
Florian Loitsch 2010/11/16 14:32:06 Reworked comment.
+ // fact that 2^(p-1) <= f < 2^p. However even after adding the wiggle this
+ // property is still true (even for denormals where the wiggle can be much
+ // more important).
+
+ const double k1Log10 = 0.30102999566398114; // 1/lg(10)
+
+ // For doubles len(f) == 53 (don't forget the hidden bit).
+ const int kSignificandSize = 53;
+ double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
+ return static_cast<int>(estimate);
+}
+
+
+// See comments for InitialScaledStartValues.
+static void InitialScaledStartValuesPositiveExponent(
+ double v, int estimated_power, bool need_wiggles,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* wiggle_minus, Bignum* wiggle_plus) {
+ // A positive exponent implies a positive power.
+ ASSERT(estimated_power >= 0);
+ // Since the estimated_power is positive we simply multiply the denominator
+ // by 10^estimated_power.
+
+ // The common case first. We later (10 lines below) correct the values for
+ // the special case where the boundaries are different.
+ // denominator = 2 * 10^estimated_power;
+ denominator->AssignPowerUInt16(10, estimated_power);
+ denominator->ShiftLeft(1);
+ // numerator = v * 2 (2 for the common denominator).
+ numerator->AssignUInt64(Double(v).Significand());
+ numerator->ShiftLeft(Double(v).Exponent() + 1);
+
+ if (need_wiggles) {
William Hesse 2010/11/15 15:48:30 Call these delta_plus and delta_minus, or somethin
Florian Loitsch 2010/11/16 14:32:06 Refactored (slightly) method and comments.
+ // Let v = f * 2^e, then wiggle_plus = 2^e;
+ wiggle_plus->AssignUInt16(1);
+ wiggle_plus->ShiftLeft(Double(v).Exponent());
+ // Same for wiggle_minus.
+ wiggle_minus->AssignUInt16(1);
+ wiggle_minus->ShiftLeft(Double(v).Exponent());
+
+ // If the significand (without the hidden bit) is 0, then the lower
+ // boundary is closer than just one ulp (unit in the last place).
+ // There is only one exception: if the next lower number is a denormal then
+ // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we
+ // have to test it in the other function where exponent < 0).
+ uint64_t v_bits = Double(v).AsUint64();
+ if ((v_bits & Double::kSignificandMask) == 0) {
+ // The lower boundary is closer at half the distance of "normal" numbers.
+ // Increase the denominator and adapt all but the wiggle_minus.
+ denominator->ShiftLeft(1); // *2
+ numerator->ShiftLeft(1); // *2
+ wiggle_plus->ShiftLeft(1); // *2
+ }
+ }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentPositivePower(
+ double v, int estimated_power, bool need_wiggles,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* wiggle_minus, Bignum* wiggle_plus) {
+ uint64_t significand = Double(v).Significand();
+ int exponent = Double(v).Exponent();
+ // v = f * 2^e with e < 0, and with estimated_power >= 0.
+ // This means that e is close to 0 (have a look at how estimated_power is
+ // computed).
+
+ // The common case first. We later (10 lines below) correct the values for
+ // the special case where the boundaries are different.
+ // denominator = 10^estimated_power * 2 * 2^-exponent (with exponent < 0)
+ denominator->AssignPowerUInt16(10, estimated_power);
+ denominator->ShiftLeft(1 - exponent);
+ // numerator = 2 * significand
+ // since v = significand * 2^exponent this is equivalent to
+ // numerator = v * 2 / 2^-exponent
+ numerator->AssignUInt64(significand);
+ numerator->ShiftLeft(1);
+
+ if (need_wiggles) {
+ // Given that the denominator already includes v's exponent the wiggle
+ // room is simply 1.
+ wiggle_plus->AssignUInt16(1);
+ // Same for wiggle_minus.
+ wiggle_minus->AssignUInt16(1);
+
+ // If the significand (without the hidden bit) is 0, then the lower
+ // boundary is closer than just one ulp (unit in the last place).
+ // There is only one exception: if the next lower number is a denormal
+ // then the distance is 1 ulp. Since the exponent is close to zero
+ // (otherwise estimated_power would have been negative) this cannot happen
+ // here either.
+ uint64_t v_bits = Double(v).AsUint64();
+ if ((v_bits & Double::kSignificandMask) == 0) {
+ // The lower boundary is closer at half the distance of "normal" numbers.
+ // Increase the denominator and adapt all but the wiggle_minus.
+ denominator->ShiftLeft(1); // *2
+ numerator->ShiftLeft(1); // *2
+ wiggle_plus->ShiftLeft(1); // *2
+ }
+ }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentNegativePower(
+ double v, int estimated_power, bool need_wiggles,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* wiggle_minus, Bignum* wiggle_plus) {
+ const uint64_t kMinimalNormalizedExponent =
+ V8_2PART_UINT64_C(0x00100000, 00000000);
+ uint64_t significand = Double(v).Significand();
+ int exponent = Double(v).Exponent();
+ // Instead of multiplying the denominator with 10^estimated_power we
+ // multiply all values (numerator and wiggles) by 10^-estimated_power.
+
+ // Use numerator as temporary container for power_ten
+ Bignum* power_ten = numerator;
+ power_ten->AssignPowerUInt16(10, -estimated_power);
+
+ // The common case first. The special case is handled soon.
+
+ if (need_wiggles) {
+ // wiggle_plus = wiggle_minus = 10^estimated_power
+ wiggle_plus->AssignBignum(*power_ten);
+ wiggle_minus->AssignBignum(*power_ten);
+ }
+ // denominator = 2 * 2^-exponent with exponent < 0.
+ denominator->AssignUInt16(1);
+ denominator->ShiftLeft(1 - exponent);
+ // numerator = significand * 2 * 10^-estimated_power
+ // since v = significand * 2^exponent this is equivalent to
+ // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
+ // Remember: numerator has been abused as power_ten. So no need to assign it
+ // to itself.
+ numerator->MultiplyByUInt64(significand);
+ numerator->ShiftLeft(1);
+
+ if (need_wiggles) {
+ // The special case where the lower boundary is twice as close.
+ // This time we have to look out for the exception too.
+ uint64_t v_bits = Double(v).AsUint64();
+ if ((v_bits & Double::kSignificandMask) == 0 &&
+ // The only exception where a significand == 0 has its boundaries at
+ // "normal" distances:
+ (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
+ numerator->ShiftLeft(1); // *2
+ denominator->ShiftLeft(1); // *2
+ wiggle_plus->ShiftLeft(1); // *2
+ }
+ }
+}
+
+
+// v = significand * 2^exponent
+// The initial start values consist of:
+// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
+// - a scaled (common) denominator.
+// - the scaled range a double has towards -infinity while still being
+// considered to be equal to v. In other words: the difference between v and
+// its lower boundary.
+// - the same room towards +infinity.
+// The scaling consist of multiplying the numerator by 10^estimated_power, or
+// (if the estimated_power is negative) by multiplying the denominator
+// by 10^-estimated_power.
+// Note that the wiggle-room is scaled too. If the common denominator has been
+// scaled, then the wiggles are automatically scaled. Otherwise they are
+// multiplied by the scaling factor, too.
+//
+// Let ep == estimated_power, then the returned values will satisfy:
+// v / 10^ep = numerator / denominator.
+// v's boundarys m- and m+:
+// m- / 10^ep == v / 10^ep - wiggle_minus / denominator
+// m+ / 10^ep == v / 10^ep + wiggle_plus / denominator
+// Or in other words:
+// m- == v - wiggle_minus * 10^ep / denominator;
+// m+ == v + wiggle_plus * 10^ep / denominator;
+//
+// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
+// or 10^k <= v < 10^(k+1)
+// we then have 0.1 <= numerator/denominator < 1
+// or 1 <= numerator/denominator < 10
+//
+// It is then easy to kickstart the digit-generation routine.
+static void InitialScaledStartValues(double v, int estimated_power,
+ bool need_wiggles,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* wiggle_minus,
+ Bignum* wiggle_plus) {
+ if (Double(v).Exponent() >= 0) {
+ InitialScaledStartValuesPositiveExponent(
+ v, estimated_power, need_wiggles,
+ numerator, denominator, wiggle_minus, wiggle_plus);
+ } else if (estimated_power >= 0) {
+ InitialScaledStartValuesNegativeExponentPositivePower(
+ v, estimated_power, need_wiggles,
+ numerator, denominator, wiggle_minus, wiggle_plus);
+ } else {
+ InitialScaledStartValuesNegativeExponentNegativePower(
+ v, estimated_power, need_wiggles,
+ numerator, denominator, wiggle_minus, wiggle_plus);
+ }
+}
+
+
+// This routine multiplies numerator/denominator so that its values lies in the
+// range 1-10. That is after a call to this function we have:
+// 1 <= (numerator + wiggle_plus) /denominator < 10.
+// In some cases estimated_power was too low, and this is already the case. We
+// then simply adjust estimated_power so that 10^(k-1) <= v < 10^k (with k ==
+// estimated_power) but do not touch the numerator or denominator.
+// Otherwise the routine multiplies the numerator and the wiggles by 10.
+static void FixupMultiply10(int estimated_power, bool is_even,
+ int* power,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* wiggle_minus, Bignum* wiggle_plus) {
+ bool in_range;
+ if (is_even) {
+ // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
+ // are rounded to the closest floating-point number with even significand.
+ in_range = Bignum::PlusCompare(*numerator, *wiggle_plus, *denominator) >= 0;
+ } else {
+ in_range = Bignum::PlusCompare(*numerator, *wiggle_plus, *denominator) > 0;
+ }
+ if (in_range) {
+ // Since numerator + wiggle_plus >= denominator we already have
+ // 1 <= numerator/denominator < 10. Simply update the estimated_power.
+ *power = estimated_power + 1;
+ } else {
+ *power = estimated_power;
+ numerator->Times10();
+ if (Bignum::Equal(*wiggle_minus, *wiggle_plus)) {
+ wiggle_minus->Times10();
+ wiggle_plus->AssignBignum(*wiggle_minus);
+ } else {
+ wiggle_minus->Times10();
+ wiggle_plus->Times10();
+ }
+ }
+}
+
+
+// Precondition: 0 <= (numerator+wiggle_plus) / denominator < 10.
+// If 1 <= (numerator+wiggle_plus) / denominator < 10 then no leading 0 digit
+// will be produced. This should be the standard precondition.
+// Produces the least amount of digits so that the result lies in the wiggle
William Hesse 2010/11/15 15:48:30 Give more big picture comments - result lying in t
Florian Loitsch 2010/11/16 14:32:06 Done.
+// room. Let V the value written in the buffer, and
+// m- := (numerator - wiggle_minus) / denominator
+// m+ := (numerator + wiggle_plus) / denominator
+// <? := '<=' if is_even and '<' otherwise, then
+// m- <? V <? m+
+// In other words the written buffer would read as the input number.
+static void GenerateDigits(Bignum* numerator, Bignum* denominator,
William Hesse 2010/11/15 15:48:30 GenerateShortestDigits?
Florian Loitsch 2010/11/16 14:32:06 Done.
+ Bignum* wiggle_minus, Bignum* wiggle_plus,
+ bool is_even,
+ Vector<char> buffer, int* length) {
+ // Small optimization: if wiggle_minus and wiggle_plus are the same just reuse
+ // one of the two bignums.
+ if (Bignum::Equal(*wiggle_minus, *wiggle_plus)) {
+ wiggle_plus = wiggle_minus;
+ }
+ *length = 0;
+ while (true) {
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ // digit = numerator / denominator (integer division).
+ // numerator = numerator % denominator.
+ buffer[(*length)++] = digit + '0';
+
+ // Can we stop already?
+ bool in_wiggle_room_minus;
+ bool in_wiggle_room_plus;
+ if (is_even) {
+ in_wiggle_room_minus = Bignum::LessEqual(*numerator, *wiggle_minus);
+ } else {
+ in_wiggle_room_minus = Bignum::Less(*numerator, *wiggle_minus);
+ }
+ if (is_even) {
+ in_wiggle_room_plus =
+ Bignum::PlusCompare(*numerator, *wiggle_plus, *denominator) >= 0;
+ } else {
+ in_wiggle_room_plus =
+ Bignum::PlusCompare(*numerator, *wiggle_plus, *denominator) > 0;
+ }
+ if (!in_wiggle_room_minus && !in_wiggle_room_plus) {
+ // Prepare for next iteration.
+ numerator->Times10();
+ wiggle_minus->Times10();
+ // We optimized wiggle_plus to be equal to wiggle_minus (if they share the
+ // same value). So don't multiply wiggle_plus if they point to the same
+ // object.
+ if (wiggle_minus != wiggle_plus) {
+ wiggle_plus->Times10();
+ }
+ } else if (in_wiggle_room_minus && in_wiggle_room_plus) {
+ // Let's see if 2*numerator < denominator.
+ // If yes, then the next digit would be < 5 and we can round down.
+ int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
+ if (compare < 0) {
+ // Remaining digits are less than .5. -> Round down (== do nothing).
+ } else if (compare > 0) {
+ // Remaining digits are more than .5 of denominator. -> Round up.
+ // Note that the last digit could not be a '9' as otherwise the whole
+ // loop would have stopped earlier.
+ // We still have an assert here in case the preconditions were not
+ // satisfied.
+ ASSERT(buffer[(*length) - 1] != '9');
+ buffer[(*length) - 1]++;
+ } else {
+ // Halfway case.
+ // TODO(floitsch): need a way to solve half-way cases.
+ // For now let's round towards even (since this is what Gay seems to
+ // do).
+
+ if ((buffer[(*length) - 1] - '0') % 2 == 0) {
+ // Round down => Do nothing.
+ } else {
+ ASSERT(buffer[(*length) - 1] != '9');
+ buffer[(*length) - 1]++;
+ }
+ }
+ return;
+ } else if (in_wiggle_room_minus) {
+ // Round down (== do nothing).
+ return;
+ } else { // in_wiggle_room_plus
+ // Round up.
+ // Note again that the last digit could not be '9' since this would have
+ // stopped the loop earlier.
+ // We still have an ASSERT here, in case the preconditions were not
+ // satisfied.
+ ASSERT(buffer[(*length) -1] != '9');
+ buffer[(*length) - 1]++;
+ return;
+ }
+ }
+}
+
+
+static int NormalizedExponent(uint64_t significand, int exponent) {
+ ASSERT(significand != 0);
+ while ((significand & Double::kHiddenBit) == 0) {
+ significand = significand << 1;
+ exponent = exponent - 1;
+ }
+ return exponent;
+}
+
+
+static void GenerateCountedDigits(int count, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char>(buffer), int* length) {
+ ASSERT(count >= 0);
+ for (int i = 0; i < count - 1; ++i) {
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ // digit = numerator / denominator (integer division).
William Hesse 2010/11/15 15:48:30 Include "Assumes numerator / denominator < 10" (or
Florian Loitsch 2010/11/16 14:32:06 added ASSERT.
+ // numerator = numerator % denominator.
+ buffer[i] = digit + '0';
+ // Prepare for next iteration.
+ numerator->Times10();
+ }
+ // Generate the last digit.
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+ digit++;
+ }
+ buffer[count - 1] = digit + '0';
+ // Correct bad digits (in case we had a sequence of '9's).
William Hesse 2010/11/15 15:48:30 Propagate the carry until we hit a non-'9' or til
Florian Loitsch 2010/11/16 14:32:06 Done.
+ for (int i = count - 1; i > 0; --i) {
+ if (buffer[i] != '0' + 10) break;
+ buffer[i] = '0';
+ buffer[i - 1]++;
+ }
+ if (buffer[0] == '0' + 10) {
William Hesse 2010/11/15 15:48:30 Propagate a carry past the top place.
Florian Loitsch 2010/11/16 14:32:06 Done.
+ buffer[0] = '1';
+ (*decimal_point)++;
+ }
+ *length = count;
+}
+
+
+static void BignumToFixed(int requested_digits, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char>(buffer), int* length) {
+ // The requested digits correspond to the digits after the point.
+ // The variable 'needed_digits' includes the digits before the point.
+ int needed_digits;
+ // Note that we have to look at more than just the requested_digits, since
+ // a number could be rounded up. Example: v=0.5 with requested_digits=0.
+ // Even though the power of v equals 0 we can't just stop here.
+ if (-(*decimal_point) > requested_digits) {
William Hesse 2010/11/15 15:48:30 Explain this. People don't know what all these qu
Florian Loitsch 2010/11/16 14:32:06 Done.
+ *decimal_point = -requested_digits;
+ *length = 0;
+ return;
+ } else if (-(*decimal_point) == requested_digits) {
+ *decimal_point = -requested_digits;
+ denominator->Times10(); // Bring fraction back to range 0.1 - 1.
William Hesse 2010/11/15 15:48:30 Why does this bring the fraction to that range?
Florian Loitsch 2010/11/16 14:32:06 Done.
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+ // If the fraction is >= 0.5 then we have to include the rounded
+ // digit.
+ buffer[0] = '1';
+ *length = 1;
+ (*decimal_point)++;
+ } else {
+ // Note that we caught most of similar cases earlier.
+ *length = 0;
+ }
+ return;
+ } else {
+ needed_digits = (*decimal_point) + requested_digits;
+ }
+ GenerateCountedDigits(needed_digits, decimal_point,
+ numerator, denominator,
+ buffer, length);
+}
+
+
+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
+ Vector<char> buffer, int* length, int* decimal_point) {
+ ASSERT(v > 0);
+ ASSERT(!Double(v).IsSpecial());
+ uint64_t significand = Double(v).Significand();
+ bool is_even = (significand & 1) == 0;
+ int exponent = Double(v).Exponent();
+ int normalized_exponent = NormalizedExponent(significand, exponent);
+ // estimated_power might be too low by 1.
+ int estimated_power = EstimatePower(normalized_exponent);
+ bool need_wiggles = (mode == BIGNUM_DTOA_SHORTEST);
William Hesse 2010/11/15 15:48:30 bool compute_shortest_approximation =, instead of
Florian Loitsch 2010/11/16 14:32:06 renamed to need_boundary_deltas.
+
+ // Shortcut for Fixed.
+ // The requested digits correspond to the digits after the point. If the
+ // number is much too small, then there is no need in trying to get any
+ // digits.
+ if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
+ buffer[0] = '\0';
+ *length = 0;
+ // Set decimal-point to -requested_digits. This is what Gay does.
+ // Note that it should not have any effect anyways since the string is
+ // empty.
+ *decimal_point = -requested_digits;
+ return;
+ }
+
+ Bignum numerator;
+ Bignum denominator;
+ Bignum wiggle_minus;
+ Bignum wiggle_plus;
+ // Make sure the bignum can grow large enough. The smallest double equals
+ // 4e-324. In this case the denominator needs less than 324*4 binary digits.
William Hesse 2010/11/15 15:48:30 fewer than
Florian Loitsch 2010/11/16 14:32:06 Done.
+ // The maximum double is 1.7976931348623157e308 which needs less than
William Hesse 2010/11/15 15:48:30 fewer
Florian Loitsch 2010/11/16 14:32:06 Done.
+ // 308*4 binary digits.
+ ASSERT(Bignum::kMaxSignificantBits >= 324*4);
+ InitialScaledStartValues(v, estimated_power, need_wiggles,
+ &numerator, &denominator,
+ &wiggle_minus, &wiggle_plus);
+ FixupMultiply10(estimated_power, is_even, decimal_point,
+ &numerator, &denominator,
+ &wiggle_minus, &wiggle_plus);
+ switch (mode) {
+ case BIGNUM_DTOA_SHORTEST:
+ GenerateDigits(&numerator, &denominator,
+ &wiggle_minus, &wiggle_plus,
+ is_even, buffer, length);
+ break;
+ case BIGNUM_DTOA_FIXED:
+ BignumToFixed(requested_digits, decimal_point,
+ &numerator, &denominator,
+ buffer, length);
+ break;
+ case BIGNUM_DTOA_PRECISION:
+ GenerateCountedDigits(requested_digits, decimal_point,
+ &numerator, &denominator,
+ buffer, length);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ buffer[*length] = '\0';
+}
+
+} } // namespace v8::internal

Powered by Google App Engine
This is Rietveld 408576698