packages feed

double-conversion (empty) → 0.1.0.0

raw patch · 54 files changed

+13796/−0 lines, 54 filesdep +basedep +ghc-primdep +integersetup-changed

Dependencies added: base, ghc-prim, integer, integer-gmp, text

Files

+ Data/Double/Conversion.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE ForeignFunctionInterface, MagicHash, Rank2Types,+    UnliftedFFITypes #-}++-- |+-- Module      : Data.Double.Conversion+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@mailrank.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast, efficient support for converting between double precision+-- floating point values and text.++module Data.Double.Conversion+    (+      toExponential+    , toFixed+    , toPrecision+    , toShortest+    ) where++import Control.Monad (when)+import Control.Monad.ST (unsafeIOToST, runST)+import Data.Text.Internal (Text(Text))+import Foreign.C.Types (CDouble, CInt)+import GHC.Prim (MutableByteArray#)+import qualified Data.Text.Array as A++-- | Compute a representation in exponential format with the requested+-- number of digits after the decimal point. The last emitted digit is+-- rounded.  If -1 digits are requested, then the shortest exponential+-- representation is computed.+toExponential :: Int -> Double -> Text+toExponential ndigits = convert "toExponential" len $ \val mba ->+                        c_ToExponential val mba (fromIntegral ndigits)+  where len = c_ToExponentialLength+        {-# NOINLINE len #-}++-- | Compute a decimal representation with a fixed number of digits+-- after the decimal point. The last emitted digit is rounded.+toFixed :: Int -> Double -> Text+toFixed ndigits = convert "toFixed" len $ \val mba ->+                  c_ToFixed val mba (fromIntegral ndigits)+  where len = c_ToFixedLength+        {-# NOINLINE len #-}++-- | Compute the shortest string of digits that correctly represent+-- the input number.+toShortest :: Double -> Text+toShortest = convert "toShortest" len c_ToShortest+  where len = c_ToShortestLength+        {-# NOINLINE len #-}++-- | Compute @precision@ leading digits of the given value either in+-- exponential or decimal format. The last computed digit is rounded.+toPrecision :: Int -> Double -> Text+toPrecision ndigits = convert "toPrecision" len $ \val mba ->+                      c_ToPrecision val mba (fromIntegral ndigits)+  where len = c_ToPrecisionLength+        {-# NOINLINE len #-}++convert :: String -> CInt+        -> (forall s. CDouble -> MutableByteArray# s -> IO CInt)+        -> Double -> Text+convert func len act val = runST go+  where+    go = do+      buf <- A.new (fromIntegral len)+      size <- unsafeIOToST $ act (realToFrac val) (A.maBA buf)+      when (size == -1) .+        fail $ "Data.Double.Conversion." ++ func +++               ": conversion failed (invalid precision requested)"+      frozen <- A.unsafeFreeze buf+      return $ Text frozen 0 (fromIntegral size)++foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortestLength"+    c_ToShortestLength :: CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortest"+    c_ToShortest :: CDouble -> MutableByteArray# s -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixedLength"+    c_ToFixedLength :: CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixed"+    c_ToFixed :: CDouble -> MutableByteArray# s -> CInt -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponentialLength"+    c_ToExponentialLength :: CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponential"+    c_ToExponential :: CDouble -> MutableByteArray# s -> CInt -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecisionLength"+    c_ToPrecisionLength :: CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecision"+    c_ToPrecision :: CDouble -> MutableByteArray# s -> CInt -> IO CInt
+ LICENSE view
@@ -0,0 +1,29 @@+See double-conversion/LICENSE for the license that applies to the C+++library.++Copyright (c) 2011 MailRank, Inc.+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.++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.
+ README.markdown view
@@ -0,0 +1,30 @@+# Welcome to double-conversion++double-conversion is a fast Haskell library for converting between+double precision floating point numbers and text strings.  It is+implemented as a binding to the V8-derived C++ [double-conversion+library](http://code.google.com/p/double-conversion/).++# Join in!++We are happy to receive bug reports, fixes, documentation enhancements,+and other improvements.++Please report bugs via the+[github issue tracker](https://github.com/mailrank/double-conversion/issues).++Master [git repository](https://github.com/mailrank/double-conversion):++* `git clone git://github.com/mailrank/double-conversion.git`++There's also a [Mercurial mirror](https://bitbucket.org/bos/double-conversion):++* `hg clone https://bitbucket.org/bos/double-conversion`++(You can create and contribute changes using either git or Mercurial.)++Authors+-------++This library is written and maintained by Bryan O'Sullivan,+<bos@mailrank.com>.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ benchmarks/Benchmarks.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE ForeignFunctionInterface, OverloadedStrings #-}++import Criterion.Main+import Data.Double.Conversion+import Foreign.C.Types (CInt, CDouble)+import qualified Data.Text as T++showText :: Double -> T.Text+showText d = T.pack (show d)++main = defaultMain [+         bgroup "haskell" [+           bench "show" $ whnf showText pi+         , bench "toShortest" $ whnf toShortest pi+         , bench "toExponential" $ whnf (toExponential 3) pi+         , bench "toPrecision" $ whnf (toExponential 8) pi+         , bench "toFixed" $ whnf (toFixed 8) pi+         ]+       , bgroup "sprintf" [+           bench "exact" $ whnf sprintf_exact pi+         , bench "exponential" $ whnf (sprintf_exponential 3) pi+         , bench "fixed" $ whnf (sprintf_fixed 8) pi+         , bench "generic" $ whnf (sprintf_generic 6) pi+         , bench "generic_default" $ whnf sprintf_generic_default pi+         ]+       ]++foreign import ccall unsafe sprintf_exact :: CDouble -> ()+foreign import ccall unsafe sprintf_exponential :: CInt -> CDouble -> ()+foreign import ccall unsafe sprintf_fixed :: CInt -> CDouble -> ()+foreign import ccall unsafe sprintf_generic :: CInt -> CDouble -> ()+foreign import ccall unsafe sprintf_generic_default :: CDouble -> ()
+ benchmarks/double-conversion-benchmarks.cabal view
@@ -0,0 +1,15 @@+name:           double-conversion-benchmarks+version:        0+cabal-version:  >= 1.8+build-type:     Simple++executable bm+  main-is: Benchmarks.hs++  c-sources: sprintf.c++  build-depends:+    base,+    criterion >= 0.5.0.10,+    double-conversion,+    text >= 0.11.0.8
+ cbits/hs-double-conversion.cc view
@@ -0,0 +1,113 @@+#include "double-conversion.h"+#include "hs-double-conversion.h"+#include <stdio.h>++using namespace double_conversion;++static const int kToShortestLength = 24;++extern "C"+int _hs_ToShortestLength(void)+{+  return kToShortestLength;+}++static const int kToFixedLength =+  1 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint ++  1 + DoubleToStringConverter::kMaxFixedDigitsAfterPoint;++extern "C"+int _hs_ToFixedLength(void)+{+  return kToFixedLength;+}++static const int kToExponentialLength =+  DoubleToStringConverter::kMaxExponentialDigits + 8;++extern "C"+int _hs_ToExponentialLength(void)+{+  return kToExponentialLength;+}++static const int kToPrecisionLength =+  DoubleToStringConverter::kMaxPrecisionDigits + 7;++extern "C"+int _hs_ToPrecisionLength(void)+{+  return kToPrecisionLength;+}++static int copy(uint16_t *buf, const StringBuilder& builder, const char *cbuf)+{+  const int pos = builder.position();+  for (int i = 0; i < pos; i++)+    buf[i] = cbuf[i];+  return pos;+}++static inline const DoubleToStringConverter& defaultConverter(void)+{+  const int flags = DoubleToStringConverter::UNIQUE_ZERO;+  static DoubleToStringConverter converter(flags,+                                           "Infinity",+                                           "NaN",+                                           'e',+                                           -6, 21,+                                           6, 0);+  return converter;+}++extern "C"+int _hs_ToShortest(double value, uint16_t *buf)+{+  char cbuf[kToShortestLength];+  StringBuilder builder(cbuf, kToShortestLength);+  bool ok = defaultConverter().ToShortest(value, &builder);++  if (!ok)+    return -1;++  return copy(buf, builder, cbuf);+}++extern "C"+int _hs_ToFixed(double value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToFixedLength];+  StringBuilder builder(cbuf, kToFixedLength);+  bool ok = defaultConverter().ToFixed(value, ndigits, &builder);++  if (!ok)+    return -1;+  +  return copy(buf, builder, cbuf);+}++extern "C"+int _hs_ToExponential(double value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToExponentialLength];+  StringBuilder builder(cbuf, kToExponentialLength);+  bool ok = defaultConverter().ToExponential(value, ndigits, &builder);++  if (!ok)+    return -1;+  +  return copy(buf, builder, cbuf);+}++extern "C"+int _hs_ToPrecision(double value, uint16_t *buf, const int precision)+{+  char cbuf[kToPrecisionLength];+  StringBuilder builder(cbuf, kToPrecisionLength);+  bool ok = defaultConverter().ToPrecision(value, precision, &builder);++  if (!ok)+    return -1;+  +  return copy(buf, builder, cbuf);+}
+ double-conversion.cabal view
@@ -0,0 +1,91 @@+name:           double-conversion+version:        0.1.0.0+license:        BSD3+license-file:   LICENSE+homepage:       https://github.com/mailrank/double-conversion+bug-reports:    https://github.com/mailrank/double-conversion/issues+category:       Text+author:         Bryan O'Sullivan <bos@mailrank.com>+maintainer:     Bryan O'Sullivan <bos@mailrank.com>+stability:      experimental+tested-with:    GHC == 7.0.3+synopsis:       Fast conversion between double precision floating point and text+cabal-version:  >= 1.8+build-type:     Simple+description:+    A library that performs fast conversion between double precision+    floating point and text, implemented as bindings to the C+++    double-conversion library written by Florian Loitsch at Google.++extra-source-files:+    README.markdown+    benchmarks/*.cabal+    benchmarks/*.hs+    double-conversion/COPYING+    double-conversion/LICENSE+    double-conversion/Makefile+    double-conversion/README+    double-conversion/SConstruct+    double-conversion/src/*.cc+    double-conversion/src/*.h+    double-conversion/src/SConscript+    double-conversion/test/cctest/*.cc+    double-conversion/test/cctest/*.h+    double-conversion/test/cctest/SConscript+    include/*.h+    tests/*.cabal+    tests/*.hs++flag developer+  description: operate in developer mode+  default: False++library+  c-sources:+    cbits/hs-double-conversion.cc+    double-conversion/src/bignum.cc+    double-conversion/src/bignum-dtoa.cc+    double-conversion/src/cached-powers.cc+    double-conversion/src/diy-fp.cc+    double-conversion/src/double-conversion.cc+    double-conversion/src/fast-dtoa.cc+    double-conversion/src/fixed-dtoa.cc+    double-conversion/src/strtod.cc++  extra-libraries: stdc++++  include-dirs:+    double-conversion/src+    include++  exposed-modules:+    Data.Double.Conversion++  build-depends:+    base == 4.*,+    ghc-prim,+    text >= 0.11.0.8++  if flag(developer)+    ghc-options: -Werror+    ghc-prof-options: -auto-all+  else+    cc-options: -DNDEBUG++  ghc-options: -Wall++  cpp-options: -DINTEGER_GMP++  if impl(ghc >= 6.11)+    build-depends: integer-gmp >= 0.2 && < 0.3++  if impl(ghc >= 6.9) && impl(ghc < 6.11)+    build-depends: integer >= 0.1 && < 0.2++source-repository head+  type:     git+  location: https://github.com/mailrank/double-conversion++source-repository head+  type:     mercurial+  location: https://bitbucket.org/bos/double-conversion
+ double-conversion/COPYING view
@@ -0,0 +1,26 @@+Copyright 2006-2011, 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.
+ double-conversion/LICENSE view
@@ -0,0 +1,26 @@+Copyright 2006-2011, 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.
+ double-conversion/Makefile view
@@ -0,0 +1,7 @@+all:+	scons debug=1++test:+	./run_tests --list | tr -d '<' | xargs ./run_tests++.PHONY: test all
+ double-conversion/README view
@@ -0,0 +1,11 @@+http://code.google.com/p/double-conversion++This project (double-conversion) provides binary-decimal and decimal-binary+routines for IEEE doubles.++The library consists of efficient conversion routines that have been extracted+from the V8 JavaScript engine. The code has been refactored and improved so that+it can be used more easily in other projects.++There is extensive documentation in src/double-conversion.h. Other examples can+be found in test/cctest/test-conversions.cc.
+ double-conversion/SConstruct view
@@ -0,0 +1,11 @@+double_conversion_sources = ['src/' + x for x in SConscript('src/SConscript')]+double_conversion_test_sources = ['test/cctest/' + x for x in SConscript('test/cctest/SConscript')]+test = double_conversion_sources + double_conversion_test_sources+print(test)+env = Environment(CPPPATH='#/src')+debug = ARGUMENTS.get('debug', 0)+if int(debug):+  env.Append(CCFLAGS = '-g')+print double_conversion_sources+print double_conversion_test_sources+env.Program('run_tests', double_conversion_sources + double_conversion_test_sources)
+ double-conversion/src/SConscript view
@@ -0,0 +1,12 @@+# -*- coding: utf-8 -*-+double_conversion_sources = [+    'bignum.cc',+    'bignum-dtoa.cc',+    'cached-powers.cc',+    'diy-fp.cc',+    'double-conversion.cc',+    'fast-dtoa.cc',+    'fixed-dtoa.cc',+    'strtod.cc'+  ]+Return('double_conversion_sources')
+ double-conversion/src/bignum-dtoa.cc view
@@ -0,0 +1,653 @@+// 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 "bignum-dtoa.h"++#include "bignum.h"+#include "double.h"++namespace double_conversion {++static int NormalizedExponent(uint64_t significand, int exponent) {+  ASSERT(significand != 0);+  while ((significand & Double::kHiddenBit) == 0) {+    significand = significand << 1;+    exponent = exponent - 1;+  }+  return exponent;+}+++// Forward declarations:+// Returns an estimation of k such that 10^(k-1) <= v < 10^k.+static int EstimatePower(int exponent);+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator+// and denominator.+static void InitialScaledStartValues(double v,+                                     int estimated_power,+                                     bool need_boundary_deltas,+                                     Bignum* numerator,+                                     Bignum* denominator,+                                     Bignum* delta_minus,+                                     Bignum* delta_plus);+// Multiplies numerator/denominator so that its values lies in the range 1-10.+// Returns decimal_point s.t.+//  v = numerator'/denominator' * 10^(decimal_point-1)+//     where numerator' and denominator' are the values of numerator and+//     denominator after the call to this function.+static void FixupMultiply10(int estimated_power, bool is_even,+                            int* decimal_point,+                            Bignum* numerator, Bignum* denominator,+                            Bignum* delta_minus, Bignum* delta_plus);+// Generates digits from the left to the right and stops when the generated+// digits yield the shortest decimal representation of v.+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,+                                   Bignum* delta_minus, Bignum* delta_plus,+                                   bool is_even,+                                   Vector<char> buffer, int* length);+// Generates 'requested_digits' after the decimal point.+static void BignumToFixed(int requested_digits, int* decimal_point,+                          Bignum* numerator, Bignum* denominator,+                          Vector<char>(buffer), int* length);+// Generates 'count' digits of numerator/denominator.+// Once 'count' digits have been produced rounds the result depending on the+// remainder (remainders of exactly .5 round upwards). Might update the+// decimal_point when rounding up (for example for 0.9999).+static void GenerateCountedDigits(int count, int* decimal_point,+                                  Bignum* numerator, Bignum* denominator,+                                  Vector<char>(buffer), int* 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);++  // 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 delta_minus;+  Bignum delta_plus;+  // Make sure the bignum can grow large enough. The smallest double equals+  // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.+  // The maximum double is 1.7976931348623157e308 which needs fewer than+  // 308*4 binary digits.+  ASSERT(Bignum::kMaxSignificantBits >= 324*4);+  bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);+  InitialScaledStartValues(v, estimated_power, need_boundary_deltas,+                           &numerator, &denominator,+                           &delta_minus, &delta_plus);+  // We now have v = (numerator / denominator) * 10^estimated_power.+  FixupMultiply10(estimated_power, is_even, decimal_point,+                  &numerator, &denominator,+                  &delta_minus, &delta_plus);+  // We now have v = (numerator / denominator) * 10^(decimal_point-1), and+  //  1 <= (numerator + delta_plus) / denominator < 10+  switch (mode) {+    case BIGNUM_DTOA_SHORTEST:+      GenerateShortestDigits(&numerator, &denominator,+                             &delta_minus, &delta_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';+}+++// The procedure starts generating digits from the left to the right and stops+// when the generated digits yield the shortest decimal representation of v. A+// decimal representation of v is a number lying closer to v than to any other+// double, so it converts to v when read.+//+// This is true if d, the decimal representation, is between m- and m+, the+// upper and lower boundaries. d must be strictly between them if !is_even.+//           m- := (numerator - delta_minus) / denominator+//           m+ := (numerator + delta_plus) / denominator+//+// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.+//   If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit+//   will be produced. This should be the standard precondition.+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,+                                   Bignum* delta_minus, Bignum* delta_plus,+                                   bool is_even,+                                   Vector<char> buffer, int* length) {+  // Small optimization: if delta_minus and delta_plus are the same just reuse+  // one of the two bignums.+  if (Bignum::Equal(*delta_minus, *delta_plus)) {+    delta_plus = delta_minus;+  }+  *length = 0;+  while (true) {+    uint16_t digit;+    digit = numerator->DivideModuloIntBignum(*denominator);+    ASSERT(digit <= 9);  // digit is a uint16_t and therefore always positive.+    // digit = numerator / denominator (integer division).+    // numerator = numerator % denominator.+    buffer[(*length)++] = digit + '0';++    // Can we stop already?+    // If the remainder of the division is less than the distance to the lower+    // boundary we can stop. In this case we simply round down (discarding the+    // remainder).+    // Similarly we test if we can round up (using the upper boundary).+    bool in_delta_room_minus;+    bool in_delta_room_plus;+    if (is_even) {+      in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);+    } else {+      in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);+    }+    if (is_even) {+      in_delta_room_plus =+          Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;+    } else {+      in_delta_room_plus =+          Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;+    }+    if (!in_delta_room_minus && !in_delta_room_plus) {+      // Prepare for next iteration.+      numerator->Times10();+      delta_minus->Times10();+      // We optimized delta_plus to be equal to delta_minus (if they share the+      // same value). So don't multiply delta_plus if they point to the same+      // object.+      if (delta_minus != delta_plus) {+        delta_plus->Times10();+      }+    } else if (in_delta_room_minus && in_delta_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_delta_room_minus) {+      // Round down (== do nothing).+      return;+    } else {  // in_delta_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;+    }+  }+}+++// Let v = numerator / denominator < 10.+// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)+// from left to right. Once 'count' digits have been produced we decide wether+// to round up or down. Remainders of exactly .5 round upwards. Numbers such+// as 9.999999 propagate a carry all the way, and change the+// exponent (decimal_point), when rounding upwards.+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);+    ASSERT(digit <= 9);  // digit is a uint16_t and therefore always positive.+    // digit = numerator / denominator (integer division).+    // 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). Propagate the+  // carry until we hat a non-'9' or til we reach the first digit.+  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) {+    // Propagate a carry past the top place.+    buffer[0] = '1';+    (*decimal_point)++;+  }+  *length = count;+}+++// Generates 'requested_digits' after the decimal point. It might omit+// trailing '0's. If the input number is too small then no digits at all are+// generated (ex.: 2 fixed digits for 0.00001).+//+// Input verifies:  1 <= (numerator + delta) / denominator < 10.+static void BignumToFixed(int requested_digits, int* decimal_point,+                          Bignum* numerator, Bignum* denominator,+                          Vector<char>(buffer), int* length) {+  // 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) {+    // The number is definitively too small.+    // Ex: 0.001 with requested_digits == 1.+    // 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;+    *length = 0;+    return;+  } else if (-(*decimal_point) == requested_digits) {+    // We only need to verify if the number rounds down or up.+    // Ex: 0.04 and 0.06 with requested_digits == 1.+    ASSERT(*decimal_point == -requested_digits);+    // Initially the fraction lies in range (1, 10]. Multiply the denominator+    // by 10 so that we can compare more easily.+    denominator->Times10();+    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 {+    // The requested digits correspond to the digits after the point.+    // The variable 'needed_digits' includes the digits before the point.+    int needed_digits = (*decimal_point) + requested_digits;+    GenerateCountedDigits(needed_digits, decimal_point,+                          numerator, denominator,+                          buffer, length);+  }+}+++// Returns an estimation of k such that 10^(k-1) <= v < 10^k where+// v = f * 2^exponent and 2^52 <= f < 2^53.+// v is hence a normalized double with the given exponent. The output is an+// approximation for the exponent of the decimal approimation .digits * 10^k.+//+// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.+// Note: this property holds for v's upper boundary m+ too.+//    10^k <= m+ < 10^k+1.+//   (see 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's boundary m+: the computation takes advantage of+  // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement+  // (even for denormals where the delta 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_boundary_deltas,+    Bignum* numerator, Bignum* denominator,+    Bignum* delta_minus, Bignum* delta_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.++  // numerator = v.+  numerator->AssignUInt64(Double(v).Significand());+  numerator->ShiftLeft(Double(v).Exponent());+  // denominator = 10^estimated_power.+  denominator->AssignPowerUInt16(10, estimated_power);++  if (need_boundary_deltas) {+    // Introduce a common denominator so that the deltas to the boundaries are+    // integers.+    denominator->ShiftLeft(1);+    numerator->ShiftLeft(1);+    // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common+    // denominator (of 2) delta_plus equals 2^e.+    delta_plus->AssignUInt16(1);+    delta_plus->ShiftLeft(Double(v).Exponent());+    // Same for delta_minus (with adjustments below if f == 2^p-1).+    delta_minus->AssignUInt16(1);+    delta_minus->ShiftLeft(Double(v).Exponent());++    // If the significand (without the hidden bit) is 0, then the lower+    // boundary is closer than just half a 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 common denominator and adapt all but the delta_minus.+      denominator->ShiftLeft(1);  // *2+      numerator->ShiftLeft(1);    // *2+      delta_plus->ShiftLeft(1);   // *2+    }+  }+}+++// See comments for InitialScaledStartValues+static void InitialScaledStartValuesNegativeExponentPositivePower(+    double v, int estimated_power, bool need_boundary_deltas,+    Bignum* numerator, Bignum* denominator,+    Bignum* delta_minus, Bignum* delta_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).++  // numerator = significand+  //  since v = significand * 2^exponent this is equivalent to+  //  numerator = v * / 2^-exponent+  numerator->AssignUInt64(significand);+  // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)+  denominator->AssignPowerUInt16(10, estimated_power);+  denominator->ShiftLeft(-exponent);++  if (need_boundary_deltas) {+    // Introduce a common denominator so that the deltas to the boundaries are+    // integers.+    denominator->ShiftLeft(1);+    numerator->ShiftLeft(1);+    // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common+    // denominator (of 2) delta_plus equals 2^e.+    // Given that the denominator already includes v's exponent the distance+    // to the boundaries is simply 1.+    delta_plus->AssignUInt16(1);+    // Same for delta_minus (with adjustments below if f == 2^p-1).+    delta_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 delta_minus.+      denominator->ShiftLeft(1);  // *2+      numerator->ShiftLeft(1);    // *2+      delta_plus->ShiftLeft(1);   // *2+    }+  }+}+++// See comments for InitialScaledStartValues+static void InitialScaledStartValuesNegativeExponentNegativePower(+    double v, int estimated_power, bool need_boundary_deltas,+    Bignum* numerator, Bignum* denominator,+    Bignum* delta_minus, Bignum* delta_plus) {+  const uint64_t kMinimalNormalizedExponent =+      UINT64_2PART_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 deltas) by 10^-estimated_power.++  // Use numerator as temporary container for power_ten.+  Bignum* power_ten = numerator;+  power_ten->AssignPowerUInt16(10, -estimated_power);++  if (need_boundary_deltas) {+    // Since power_ten == numerator we must make a copy of 10^estimated_power+    // before we complete the computation of the numerator.+    // delta_plus = delta_minus = 10^estimated_power+    delta_plus->AssignBignum(*power_ten);+    delta_minus->AssignBignum(*power_ten);+  }++  // 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.+  ASSERT(numerator == power_ten);+  numerator->MultiplyByUInt64(significand);++  // denominator = 2 * 2^-exponent with exponent < 0.+  denominator->AssignUInt16(1);+  denominator->ShiftLeft(-exponent);++  if (need_boundary_deltas) {+    // Introduce a common denominator so that the deltas to the boundaries are+    // integers.+    numerator->ShiftLeft(1);+    denominator->ShiftLeft(1);+    // With this shift the boundaries have their correct value, since+    // delta_plus = 10^-estimated_power, and+    // delta_minus = 10^-estimated_power.+    // These assignments have been done earlier.++    // 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+      delta_plus->ShiftLeft(1);   // *2+    }+  }+}+++// Let v = significand * 2^exponent.+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator+// and denominator. The functions GenerateShortestDigits and+// GenerateCountedDigits will then convert this ratio to its decimal+// representation d, with the required accuracy.+// Then d * 10^estimated_power is the representation of v.+// (Note: the fraction and the estimated_power might get adjusted before+// generating the decimal representation.)+//+// The initial start values consist of:+//  - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.+//  - a scaled (common) denominator.+//  optionally (used by GenerateShortestDigits to decide if it has the shortest+//  decimal converting back to v):+//  - v - m-: the distance to the lower boundary.+//  - m+ - v: the distance to the upper boundary.+//+// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.+//+// 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 - delta_minus / denominator+//    m+ / 10^ep == v / 10^ep + delta_plus / denominator+//  Or in other words:+//    m- == v - delta_minus * 10^ep / denominator;+//    m+ == v + delta_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.+//+// The boundary-deltas are only filled if need_boundary_deltas is set.+static void InitialScaledStartValues(double v,+                                     int estimated_power,+                                     bool need_boundary_deltas,+                                     Bignum* numerator,+                                     Bignum* denominator,+                                     Bignum* delta_minus,+                                     Bignum* delta_plus) {+  if (Double(v).Exponent() >= 0) {+    InitialScaledStartValuesPositiveExponent(+        v, estimated_power, need_boundary_deltas,+        numerator, denominator, delta_minus, delta_plus);+  } else if (estimated_power >= 0) {+    InitialScaledStartValuesNegativeExponentPositivePower(+        v, estimated_power, need_boundary_deltas,+        numerator, denominator, delta_minus, delta_plus);+  } else {+    InitialScaledStartValuesNegativeExponentNegativePower(+        v, estimated_power, need_boundary_deltas,+        numerator, denominator, delta_minus, delta_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 + delta_plus) /denominator < 10.+// Let numerator the input before modification and numerator' the argument+// after modification, then the output-parameter decimal_point is such that+//  numerator / denominator * 10^estimated_power ==+//    numerator' / denominator' * 10^(decimal_point - 1)+// In some cases estimated_power was too low, and this is already the case. We+// then simply adjust the 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 deltas by 10.+static void FixupMultiply10(int estimated_power, bool is_even,+                            int* decimal_point,+                            Bignum* numerator, Bignum* denominator,+                            Bignum* delta_minus, Bignum* delta_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, *delta_plus, *denominator) >= 0;+  } else {+    in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;+  }+  if (in_range) {+    // Since numerator + delta_plus >= denominator we already have+    // 1 <= numerator/denominator < 10. Simply update the estimated_power.+    *decimal_point = estimated_power + 1;+  } else {+    *decimal_point = estimated_power;+    numerator->Times10();+    if (Bignum::Equal(*delta_minus, *delta_plus)) {+      delta_minus->Times10();+      delta_plus->AssignBignum(*delta_minus);+    } else {+      delta_minus->Times10();+      delta_plus->Times10();+    }+  }+}++}  // namespace double_conversion
+ double-conversion/src/bignum-dtoa.h view
@@ -0,0 +1,82 @@+// 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.++#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_+#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_++#include "utils.h"++namespace double_conversion {++enum BignumDtoaMode {+  // Return the shortest correct representation.+  // For example the output of 0.299999999999999988897 is (the less accurate but+  // correct) 0.3.+  BIGNUM_DTOA_SHORTEST,+  // Return a fixed number of digits after the decimal point.+  // For instance fixed(0.1, 4) becomes 0.1000+  // If the input number is big, the output will be big.+  BIGNUM_DTOA_FIXED,+  // Return a fixed number of digits, no matter what the exponent is.+  BIGNUM_DTOA_PRECISION+};++// Converts the given double 'v' to ascii.+// The result should be interpreted as buffer * 10^(point-length).+// The buffer will be null-terminated.+//+// The input v must be > 0 and different from NaN, and Infinity.+//+// The output depends on the given mode:+//  - SHORTEST: produce the least amount of digits for which the internal+//   identity requirement is still satisfied. If the digits are printed+//   (together with the correct exponent) then reading this number will give+//   'v' again. The buffer will choose the representation that is closest to+//   'v'. If there are two at the same distance, than the number is round up.+//   In this mode the 'requested_digits' parameter is ignored.+//  - FIXED: produces digits necessary to print a given number with+//   'requested_digits' digits after the decimal point. The produced digits+//   might be too short in which case the caller has to fill the gaps with '0's.+//   Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.+//   Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns+//     buffer="2", point=0.+//   Note: the length of the returned buffer has no meaning wrt the significance+//   of its digits. That is, just because it contains '0's does not mean that+//   any other digit would not satisfy the internal identity requirement.+//  - PRECISION: produces 'requested_digits' where the first digit is not '0'.+//   Even though the length of produced digits usually equals+//   'requested_digits', the function is allowed to return fewer digits, in+//   which case the caller has to fill the missing digits with '0's.+//   Halfway cases are again rounded up.+// 'BignumDtoa' expects the given buffer to be big enough to hold all digits+// and a terminating null-character.+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,+                Vector<char> buffer, int* length, int* point);++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_BIGNUM_DTOA_H_
+ double-conversion/src/bignum.cc view
@@ -0,0 +1,764 @@+// 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 "bignum.h"+#include "utils.h"++namespace double_conversion {++Bignum::Bignum()+    : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {+  for (int i = 0; i < kBigitCapacity; ++i) {+    bigits_[i] = 0;+  }+}+++template<typename S>+static int BitSize(S value) {+  return 8 * sizeof(value);+}++// Guaranteed to lie in one Bigit.+void Bignum::AssignUInt16(uint16_t value) {+  ASSERT(kBigitSize >= BitSize(value));+  Zero();+  if (value == 0) return;++  EnsureCapacity(1);+  bigits_[0] = value;+  used_digits_ = 1;+}+++void Bignum::AssignUInt64(uint64_t value) {+  const int kUInt64Size = 64;++  Zero();+  if (value == 0) return;++  int needed_bigits = kUInt64Size / kBigitSize + 1;+  EnsureCapacity(needed_bigits);+  for (int i = 0; i < needed_bigits; ++i) {+    bigits_[i] = value & kBigitMask;+    value = value >> kBigitSize;+  }+  used_digits_ = needed_bigits;+  Clamp();+}+++void Bignum::AssignBignum(const Bignum& other) {+  exponent_ = other.exponent_;+  for (int i = 0; i < other.used_digits_; ++i) {+    bigits_[i] = other.bigits_[i];+  }+  // Clear the excess digits (if there were any).+  for (int i = other.used_digits_; i < used_digits_; ++i) {+    bigits_[i] = 0;+  }+  used_digits_ = other.used_digits_;+}+++static uint64_t ReadUInt64(Vector<const char> buffer,+                           int from,+                           int digits_to_read) {+  uint64_t result = 0;+  for (int i = from; i < from + digits_to_read; ++i) {+    int digit = buffer[i] - '0';+    ASSERT(0 <= digit && digit <= 9);+    result = result * 10 + digit;+  }+  return result;+}+++void Bignum::AssignDecimalString(Vector<const char> value) {+  // 2^64 = 18446744073709551616 > 10^19+  const int kMaxUint64DecimalDigits = 19;+  Zero();+  int length = value.length();+  int pos = 0;+  // Let's just say that each digit needs 4 bits.+  while (length >= kMaxUint64DecimalDigits) {+    uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);+    pos += kMaxUint64DecimalDigits;+    length -= kMaxUint64DecimalDigits;+    MultiplyByPowerOfTen(kMaxUint64DecimalDigits);+    AddUInt64(digits);+  }+  uint64_t digits = ReadUInt64(value, pos, length);+  MultiplyByPowerOfTen(length);+  AddUInt64(digits);+  Clamp();+}+++static int HexCharValue(char c) {+  if ('0' <= c && c <= '9') return c - '0';+  if ('a' <= c && c <= 'f') return 10 + c - 'a';+  if ('A' <= c && c <= 'F') return 10 + c - 'A';+  UNREACHABLE();+  return 0;  // To make compiler happy.+}+++void Bignum::AssignHexString(Vector<const char> value) {+  Zero();+  int length = value.length();++  int needed_bigits = length * 4 / kBigitSize + 1;+  EnsureCapacity(needed_bigits);+  int string_index = length - 1;+  for (int i = 0; i < needed_bigits - 1; ++i) {+    // These bigits are guaranteed to be "full".+    Chunk current_bigit = 0;+    for (int j = 0; j < kBigitSize / 4; j++) {+      current_bigit += HexCharValue(value[string_index--]) << (j * 4);+    }+    bigits_[i] = current_bigit;+  }+  used_digits_ = needed_bigits - 1;++  Chunk most_significant_bigit = 0;  // Could be = 0;+  for (int j = 0; j <= string_index; ++j) {+    most_significant_bigit <<= 4;+    most_significant_bigit += HexCharValue(value[j]);+  }+  if (most_significant_bigit != 0) {+    bigits_[used_digits_] = most_significant_bigit;+    used_digits_++;+  }+  Clamp();+}+++void Bignum::AddUInt64(uint64_t operand) {+  if (operand == 0) return;+  Bignum other;+  other.AssignUInt64(operand);+  AddBignum(other);+}+++void Bignum::AddBignum(const Bignum& other) {+  ASSERT(IsClamped());+  ASSERT(other.IsClamped());++  // If this has a greater exponent than other append zero-bigits to this.+  // After this call exponent_ <= other.exponent_.+  Align(other);++  // There are two possibilities:+  //   aaaaaaaaaaa 0000  (where the 0s represent a's exponent)+  //     bbbbb 00000000+  //   ----------------+  //   ccccccccccc 0000+  // or+  //    aaaaaaaaaa 0000+  //  bbbbbbbbb 0000000+  //  -----------------+  //  cccccccccccc 0000+  // In both cases we might need a carry bigit.++  EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);+  Chunk carry = 0;+  int bigit_pos = other.exponent_ - exponent_;+  ASSERT(bigit_pos >= 0);+  for (int i = 0; i < other.used_digits_; ++i) {+    Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;+    bigits_[bigit_pos] = sum & kBigitMask;+    carry = sum >> kBigitSize;+    bigit_pos++;+  }++  while (carry != 0) {+    Chunk sum = bigits_[bigit_pos] + carry;+    bigits_[bigit_pos] = sum & kBigitMask;+    carry = sum >> kBigitSize;+    bigit_pos++;+  }+  used_digits_ = Max(bigit_pos, used_digits_);+  ASSERT(IsClamped());+}+++void Bignum::SubtractBignum(const Bignum& other) {+  ASSERT(IsClamped());+  ASSERT(other.IsClamped());+  // We require this to be bigger than other.+  ASSERT(LessEqual(other, *this));++  Align(other);++  int offset = other.exponent_ - exponent_;+  Chunk borrow = 0;+  int i;+  for (i = 0; i < other.used_digits_; ++i) {+    ASSERT((borrow == 0) || (borrow == 1));+    Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;+    bigits_[i + offset] = difference & kBigitMask;+    borrow = difference >> (kChunkSize - 1);+  }+  while (borrow != 0) {+    Chunk difference = bigits_[i + offset] - borrow;+    bigits_[i + offset] = difference & kBigitMask;+    borrow = difference >> (kChunkSize - 1);+    ++i;+  }+  Clamp();+}+++void Bignum::ShiftLeft(int shift_amount) {+  if (used_digits_ == 0) return;+  exponent_ += shift_amount / kBigitSize;+  int local_shift = shift_amount % kBigitSize;+  EnsureCapacity(used_digits_ + 1);+  BigitsShiftLeft(local_shift);+}+++void Bignum::MultiplyByUInt32(uint32_t factor) {+  if (factor == 1) return;+  if (factor == 0) {+    Zero();+    return;+  }+  if (used_digits_ == 0) return;++  // The product of a bigit with the factor is of size kBigitSize + 32.+  // Assert that this number + 1 (for the carry) fits into double chunk.+  ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);+  DoubleChunk carry = 0;+  for (int i = 0; i < used_digits_; ++i) {+    DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;+    bigits_[i] = static_cast<Chunk>(product & kBigitMask);+    carry = (product >> kBigitSize);+  }+  while (carry != 0) {+    EnsureCapacity(used_digits_ + 1);+    bigits_[used_digits_] = carry & kBigitMask;+    used_digits_++;+    carry >>= kBigitSize;+  }+}+++void Bignum::MultiplyByUInt64(uint64_t factor) {+  if (factor == 1) return;+  if (factor == 0) {+    Zero();+    return;+  }+  ASSERT(kBigitSize < 32);+  uint64_t carry = 0;+  uint64_t low = factor & 0xFFFFFFFF;+  uint64_t high = factor >> 32;+  for (int i = 0; i < used_digits_; ++i) {+    uint64_t product_low = low * bigits_[i];+    uint64_t product_high = high * bigits_[i];+    uint64_t tmp = (carry & kBigitMask) + product_low;+    bigits_[i] = tmp & kBigitMask;+    carry = (carry >> kBigitSize) + (tmp >> kBigitSize) ++        (product_high << (32 - kBigitSize));+  }+  while (carry != 0) {+    EnsureCapacity(used_digits_ + 1);+    bigits_[used_digits_] = carry & kBigitMask;+    used_digits_++;+    carry >>= kBigitSize;+  }+}+++void Bignum::MultiplyByPowerOfTen(int exponent) {+  const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);+  const uint16_t kFive1 = 5;+  const uint16_t kFive2 = kFive1 * 5;+  const uint16_t kFive3 = kFive2 * 5;+  const uint16_t kFive4 = kFive3 * 5;+  const uint16_t kFive5 = kFive4 * 5;+  const uint16_t kFive6 = kFive5 * 5;+  const uint32_t kFive7 = kFive6 * 5;+  const uint32_t kFive8 = kFive7 * 5;+  const uint32_t kFive9 = kFive8 * 5;+  const uint32_t kFive10 = kFive9 * 5;+  const uint32_t kFive11 = kFive10 * 5;+  const uint32_t kFive12 = kFive11 * 5;+  const uint32_t kFive13 = kFive12 * 5;+  const uint32_t kFive1_to_12[] =+      { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,+        kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };++  ASSERT(exponent >= 0);+  if (exponent == 0) return;+  if (used_digits_ == 0) return;++  // We shift by exponent at the end just before returning.+  int remaining_exponent = exponent;+  while (remaining_exponent >= 27) {+    MultiplyByUInt64(kFive27);+    remaining_exponent -= 27;+  }+  while (remaining_exponent >= 13) {+    MultiplyByUInt32(kFive13);+    remaining_exponent -= 13;+  }+  if (remaining_exponent > 0) {+    MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);+  }+  ShiftLeft(exponent);+}+++void Bignum::Square() {+  ASSERT(IsClamped());+  int product_length = 2 * used_digits_;+  EnsureCapacity(product_length);++  // Comba multiplication: compute each column separately.+  // Example: r = a2a1a0 * b2b1b0.+  //    r =  1    * a0b0 ++  //        10    * (a1b0 + a0b1) ++  //        100   * (a2b0 + a1b1 + a0b2) ++  //        1000  * (a2b1 + a1b2) ++  //        10000 * a2b2+  //+  // In the worst case we have to accumulate nb-digits products of digit*digit.+  //+  // Assert that the additional number of bits in a DoubleChunk are enough to+  // sum up used_digits of Bigit*Bigit.+  if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {+    UNIMPLEMENTED();+  }+  DoubleChunk accumulator = 0;+  // First shift the digits so we don't overwrite them.+  int copy_offset = used_digits_;+  for (int i = 0; i < used_digits_; ++i) {+    bigits_[copy_offset + i] = bigits_[i];+  }+  // We have two loops to avoid some 'if's in the loop.+  for (int i = 0; i < used_digits_; ++i) {+    // Process temporary digit i with power i.+    // The sum of the two indices must be equal to i.+    int bigit_index1 = i;+    int bigit_index2 = 0;+    // Sum all of the sub-products.+    while (bigit_index1 >= 0) {+      Chunk chunk1 = bigits_[copy_offset + bigit_index1];+      Chunk chunk2 = bigits_[copy_offset + bigit_index2];+      accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;+      bigit_index1--;+      bigit_index2++;+    }+    bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;+    accumulator >>= kBigitSize;+  }+  for (int i = used_digits_; i < product_length; ++i) {+    int bigit_index1 = used_digits_ - 1;+    int bigit_index2 = i - bigit_index1;+    // Invariant: sum of both indices is again equal to i.+    // Inner loop runs 0 times on last iteration, emptying accumulator.+    while (bigit_index2 < used_digits_) {+      Chunk chunk1 = bigits_[copy_offset + bigit_index1];+      Chunk chunk2 = bigits_[copy_offset + bigit_index2];+      accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;+      bigit_index1--;+      bigit_index2++;+    }+    // The overwritten bigits_[i] will never be read in further loop iterations,+    // because bigit_index1 and bigit_index2 are always greater+    // than i - used_digits_.+    bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;+    accumulator >>= kBigitSize;+  }+  // Since the result was guaranteed to lie inside the number the+  // accumulator must be 0 now.+  ASSERT(accumulator == 0);++  // Don't forget to update the used_digits and the exponent.+  used_digits_ = product_length;+  exponent_ *= 2;+  Clamp();+}+++void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {+  ASSERT(base != 0);+  ASSERT(power_exponent >= 0);+  if (power_exponent == 0) {+    AssignUInt16(1);+    return;+  }+  Zero();+  int shifts = 0;+  // We expect base to be in range 2-32, and most often to be 10.+  // It does not make much sense to implement different algorithms for counting+  // the bits.+  while ((base & 1) == 0) {+    base >>= 1;+    shifts++;+  }+  int bit_size = 0;+  int tmp_base = base;+  while (tmp_base != 0) {+    tmp_base >>= 1;+    bit_size++;+  }+  int final_size = bit_size * power_exponent;+  // 1 extra bigit for the shifting, and one for rounded final_size.+  EnsureCapacity(final_size / kBigitSize + 2);++  // Left to Right exponentiation.+  int mask = 1;+  while (power_exponent >= mask) mask <<= 1;++  // The mask is now pointing to the bit above the most significant 1-bit of+  // power_exponent.+  // Get rid of first 1-bit;+  mask >>= 2;+  uint64_t this_value = base;++  bool delayed_multipliciation = false;+  const uint64_t max_32bits = 0xFFFFFFFF;+  while (mask != 0 && this_value <= max_32bits) {+    this_value = this_value * this_value;+    // Verify that there is enough space in this_value to perform the+    // multiplication.  The first bit_size bits must be 0.+    if ((power_exponent & mask) != 0) {+      uint64_t base_bits_mask =+          ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);+      bool high_bits_zero = (this_value & base_bits_mask) == 0;+      if (high_bits_zero) {+        this_value *= base;+      } else {+        delayed_multipliciation = true;+      }+    }+    mask >>= 1;+  }+  AssignUInt64(this_value);+  if (delayed_multipliciation) {+    MultiplyByUInt32(base);+  }++  // Now do the same thing as a bignum.+  while (mask != 0) {+    Square();+    if ((power_exponent & mask) != 0) {+      MultiplyByUInt32(base);+    }+    mask >>= 1;+  }++  // And finally add the saved shifts.+  ShiftLeft(shifts * power_exponent);+}+++// Precondition: this/other < 16bit.+uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {+  ASSERT(IsClamped());+  ASSERT(other.IsClamped());+  ASSERT(other.used_digits_ > 0);++  // Easy case: if we have less digits than the divisor than the result is 0.+  // Note: this handles the case where this == 0, too.+  if (BigitLength() < other.BigitLength()) {+    return 0;+  }++  Align(other);++  uint16_t result = 0;++  // Start by removing multiples of 'other' until both numbers have the same+  // number of digits.+  while (BigitLength() > other.BigitLength()) {+    // This naive approach is extremely inefficient if the this divided other+    // might be big. This function is implemented for doubleToString where+    // the result should be small (less than 10).+    ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));+    // Remove the multiples of the first digit.+    // Example this = 23 and other equals 9. -> Remove 2 multiples.+    result += bigits_[used_digits_ - 1];+    SubtractTimes(other, bigits_[used_digits_ - 1]);+  }++  ASSERT(BigitLength() == other.BigitLength());++  // Both bignums are at the same length now.+  // Since other has more than 0 digits we know that the access to+  // bigits_[used_digits_ - 1] is safe.+  Chunk this_bigit = bigits_[used_digits_ - 1];+  Chunk other_bigit = other.bigits_[other.used_digits_ - 1];++  if (other.used_digits_ == 1) {+    // Shortcut for easy (and common) case.+    int quotient = this_bigit / other_bigit;+    bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;+    result += quotient;+    Clamp();+    return result;+  }++  int division_estimate = this_bigit / (other_bigit + 1);+  result += division_estimate;+  SubtractTimes(other, division_estimate);++  if (other_bigit * (division_estimate + 1) > this_bigit) {+    // No need to even try to subtract. Even if other's remaining digits were 0+    // another subtraction would be too much.+    return result;+  }++  while (LessEqual(other, *this)) {+    SubtractBignum(other);+    result++;+  }+  return result;+}+++template<typename S>+static int SizeInHexChars(S number) {+  ASSERT(number > 0);+  int result = 0;+  while (number != 0) {+    number >>= 4;+    result++;+  }+  return result;+}+++static char HexCharOfValue(int value) {+  ASSERT(0 <= value && value <= 16);+  if (value < 10) return value + '0';+  return value - 10 + 'A';+}+++bool Bignum::ToHexString(char* buffer, int buffer_size) const {+  ASSERT(IsClamped());+  // Each bigit must be printable as separate hex-character.+  ASSERT(kBigitSize % 4 == 0);+  const int kHexCharsPerBigit = kBigitSize / 4;++  if (used_digits_ == 0) {+    if (buffer_size < 2) return false;+    buffer[0] = '0';+    buffer[1] = '\0';+    return true;+  }+  // We add 1 for the terminating '\0' character.+  int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit ++      SizeInHexChars(bigits_[used_digits_ - 1]) + 1;+  if (needed_chars > buffer_size) return false;+  int string_index = needed_chars - 1;+  buffer[string_index--] = '\0';+  for (int i = 0; i < exponent_; ++i) {+    for (int j = 0; j < kHexCharsPerBigit; ++j) {+      buffer[string_index--] = '0';+    }+  }+  for (int i = 0; i < used_digits_ - 1; ++i) {+    Chunk current_bigit = bigits_[i];+    for (int j = 0; j < kHexCharsPerBigit; ++j) {+      buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);+      current_bigit >>= 4;+    }+  }+  // And finally the last bigit.+  Chunk most_significant_bigit = bigits_[used_digits_ - 1];+  while (most_significant_bigit != 0) {+    buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);+    most_significant_bigit >>= 4;+  }+  return true;+}+++Bignum::Chunk Bignum::BigitAt(int index) const {+  if (index >= BigitLength()) return 0;+  if (index < exponent_) return 0;+  return bigits_[index - exponent_];+}+++int Bignum::Compare(const Bignum& a, const Bignum& b) {+  ASSERT(a.IsClamped());+  ASSERT(b.IsClamped());+  int bigit_length_a = a.BigitLength();+  int bigit_length_b = b.BigitLength();+  if (bigit_length_a < bigit_length_b) return -1;+  if (bigit_length_a > bigit_length_b) return +1;+  for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {+    Chunk bigit_a = a.BigitAt(i);+    Chunk bigit_b = b.BigitAt(i);+    if (bigit_a < bigit_b) return -1;+    if (bigit_a > bigit_b) return +1;+    // Otherwise they are equal up to this digit. Try the next digit.+  }+  return 0;+}+++int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {+  ASSERT(a.IsClamped());+  ASSERT(b.IsClamped());+  ASSERT(c.IsClamped());+  if (a.BigitLength() < b.BigitLength()) {+    return PlusCompare(b, a, c);+  }+  if (a.BigitLength() + 1 < c.BigitLength()) return -1;+  if (a.BigitLength() > c.BigitLength()) return +1;+  // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than+  // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one+  // of 'a'.+  if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {+    return -1;+  }++  Chunk borrow = 0;+  // Starting at min_exponent all digits are == 0. So no need to compare them.+  int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);+  for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {+    Chunk chunk_a = a.BigitAt(i);+    Chunk chunk_b = b.BigitAt(i);+    Chunk chunk_c = c.BigitAt(i);+    Chunk sum = chunk_a + chunk_b;+    if (sum > chunk_c + borrow) {+      return +1;+    } else {+      borrow = chunk_c + borrow - sum;+      if (borrow > 1) return -1;+      borrow <<= kBigitSize;+    }+  }+  if (borrow == 0) return 0;+  return -1;+}+++void Bignum::Clamp() {+  while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {+    used_digits_--;+  }+  if (used_digits_ == 0) {+    // Zero.+    exponent_ = 0;+  }+}+++bool Bignum::IsClamped() const {+  return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;+}+++void Bignum::Zero() {+  for (int i = 0; i < used_digits_; ++i) {+    bigits_[i] = 0;+  }+  used_digits_ = 0;+  exponent_ = 0;+}+++void Bignum::Align(const Bignum& other) {+  if (exponent_ > other.exponent_) {+    // If "X" represents a "hidden" digit (by the exponent) then we are in the+    // following case (a == this, b == other):+    // a:  aaaaaaXXXX   or a:   aaaaaXXX+    // b:     bbbbbbX      b: bbbbbbbbXX+    // We replace some of the hidden digits (X) of a with 0 digits.+    // a:  aaaaaa000X   or a:   aaaaa0XX+    int zero_digits = exponent_ - other.exponent_;+    EnsureCapacity(used_digits_ + zero_digits);+    for (int i = used_digits_ - 1; i >= 0; --i) {+      bigits_[i + zero_digits] = bigits_[i];+    }+    for (int i = 0; i < zero_digits; ++i) {+      bigits_[i] = 0;+    }+    used_digits_ += zero_digits;+    exponent_ -= zero_digits;+    ASSERT(used_digits_ >= 0);+    ASSERT(exponent_ >= 0);+  }+}+++void Bignum::BigitsShiftLeft(int shift_amount) {+  ASSERT(shift_amount < kBigitSize);+  ASSERT(shift_amount >= 0);+  Chunk carry = 0;+  for (int i = 0; i < used_digits_; ++i) {+    Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);+    bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;+    carry = new_carry;+  }+  if (carry != 0) {+    bigits_[used_digits_] = carry;+    used_digits_++;+  }+}+++void Bignum::SubtractTimes(const Bignum& other, int factor) {+  ASSERT(exponent_ <= other.exponent_);+  if (factor < 3) {+    for (int i = 0; i < factor; ++i) {+      SubtractBignum(other);+    }+    return;+  }+  Chunk borrow = 0;+  int exponent_diff = other.exponent_ - exponent_;+  for (int i = 0; i < other.used_digits_; ++i) {+    DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];+    DoubleChunk remove = borrow + product;+    Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);+    bigits_[i + exponent_diff] = difference & kBigitMask;+    borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) ++                                (remove >> kBigitSize));+  }+  for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {+    if (borrow == 0) return;+    Chunk difference = bigits_[i] - borrow;+    bigits_[i] = difference & kBigitMask;+    borrow = difference >> (kChunkSize - 1);+    ++i;+  }+  Clamp();+}+++}  // namespace double_conversion
+ double-conversion/src/bignum.h view
@@ -0,0 +1,141 @@+// 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.++#ifndef DOUBLE_CONVERSION_BIGNUM_H_+#define DOUBLE_CONVERSION_BIGNUM_H_++#include "utils.h"++namespace double_conversion {++class Bignum {+ public:+  // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.+  // This bignum can encode much bigger numbers, since it contains an+  // exponent.+  static const int kMaxSignificantBits = 3584;++  Bignum();+  void AssignUInt16(uint16_t value);+  void AssignUInt64(uint64_t value);+  void AssignBignum(const Bignum& other);++  void AssignDecimalString(Vector<const char> value);+  void AssignHexString(Vector<const char> value);++  void AssignPowerUInt16(uint16_t base, int exponent);++  void AddUInt16(uint16_t operand);+  void AddUInt64(uint64_t operand);+  void AddBignum(const Bignum& other);+  // Precondition: this >= other.+  void SubtractBignum(const Bignum& other);++  void Square();+  void ShiftLeft(int shift_amount);+  void MultiplyByUInt32(uint32_t factor);+  void MultiplyByUInt64(uint64_t factor);+  void MultiplyByPowerOfTen(int exponent);+  void Times10() { return MultiplyByUInt32(10); }+  // Pseudocode:+  //  int result = this / other;+  //  this = this % other;+  // In the worst case this function is in O(this/other).+  uint16_t DivideModuloIntBignum(const Bignum& other);++  bool ToHexString(char* buffer, int buffer_size) const;++  static int Compare(const Bignum& a, const Bignum& b);+  static bool Equal(const Bignum& a, const Bignum& b) {+    return Compare(a, b) == 0;+  }+  static bool LessEqual(const Bignum& a, const Bignum& b) {+    return Compare(a, b) <= 0;+  }+  static bool Less(const Bignum& a, const Bignum& b) {+    return Compare(a, b) < 0;+  }+  // Returns Compare(a + b, c);+  static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);+  // Returns a + b == c+  static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {+    return PlusCompare(a, b, c) == 0;+  }+  // Returns a + b <= c+  static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {+    return PlusCompare(a, b, c) <= 0;+  }+  // Returns a + b < c+  static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {+    return PlusCompare(a, b, c) < 0;+  }+ private:+  typedef uint32_t Chunk;+  typedef uint64_t DoubleChunk;++  static const int kChunkSize = sizeof(Chunk) * 8;+  static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;+  // With bigit size of 28 we loose some bits, but a double still fits easily+  // into two chunks, and more importantly we can use the Comba multiplication.+  static const int kBigitSize = 28;+  static const Chunk kBigitMask = (1 << kBigitSize) - 1;+  // Every instance allocates kBigitLength chunks on the stack. Bignums cannot+  // grow. There are no checks if the stack-allocated space is sufficient.+  static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;++  void EnsureCapacity(int size) {+    if (size > kBigitCapacity) {+      UNREACHABLE();+    }+  }+  void Align(const Bignum& other);+  void Clamp();+  bool IsClamped() const;+  void Zero();+  // Requires this to have enough capacity (no tests done).+  // Updates used_digits_ if necessary.+  // shift_amount must be < kBigitSize.+  void BigitsShiftLeft(int shift_amount);+  // BigitLength includes the "hidden" digits encoded in the exponent.+  int BigitLength() const { return used_digits_ + exponent_; }+  Chunk BigitAt(int index) const;+  void SubtractTimes(const Bignum& other, int factor);++  Chunk bigits_buffer_[kBigitCapacity];+  // A vector backed by bigits_buffer_. This way accesses to the array are+  // checked for out-of-bounds errors.+  Vector<Chunk> bigits_;+  int used_digits_;+  // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).+  int exponent_;++  DISALLOW_COPY_AND_ASSIGN(Bignum);+};++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_BIGNUM_H_
+ double-conversion/src/cached-powers.cc view
@@ -0,0 +1,177 @@+// Copyright 2006-2008 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 <stdarg.h>+#include <limits.h>+#include <math.h>++#include "utils.h"++#include "cached-powers.h"++namespace double_conversion {++struct CachedPower {+  uint64_t significand;+  int16_t binary_exponent;+  int16_t decimal_exponent;+};++static const CachedPower kCachedPowers[] = {+  {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},+  {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},+  {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},+  {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},+  {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},+  {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},+  {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},+  {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},+  {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},+  {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},+  {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},+  {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},+  {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},+  {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},+  {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},+  {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},+  {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},+  {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},+  {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},+  {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},+  {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},+  {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},+  {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},+  {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},+  {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},+  {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},+  {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},+  {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},+  {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},+  {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},+  {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},+  {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},+  {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},+  {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},+  {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},+  {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},+  {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},+  {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},+  {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},+  {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},+  {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},+  {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},+  {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},+  {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},+  {UINT64_2PART_C(0x9c400000, 00000000), -50, 4},+  {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},+  {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},+  {UINT64_2PART_C(0x813f3978, f8940984), 30, 28},+  {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},+  {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},+  {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},+  {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},+  {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},+  {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},+  {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},+  {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},+  {UINT64_2PART_C(0x924d692c, a61be758), 269, 100},+  {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},+  {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},+  {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},+  {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},+  {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},+  {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},+  {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},+  {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},+  {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},+  {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},+  {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},+  {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},+  {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},+  {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},+  {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},+  {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},+  {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},+  {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},+  {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},+  {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},+  {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},+  {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},+  {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},+  {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},+  {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},+  {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},+  {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},+  {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},+  {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},+  {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},+};++static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);+static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent;+static const double kD_1_LOG2_10 = 0.30102999566398114;  //  1 / lg(10)+const int PowersOfTenCache::kDecimalExponentDistance =+    kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent;+const int PowersOfTenCache::kMinDecimalExponent =+    kCachedPowers[0].decimal_exponent;+const int PowersOfTenCache::kMaxDecimalExponent =+    kCachedPowers[kCachedPowersLength - 1].decimal_exponent;++void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(+    int min_exponent,+    int max_exponent,+    DiyFp* power,+    int* decimal_exponent) {+  int kQ = DiyFp::kSignificandSize;+  double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);+  int foo = kCachedPowersOffset;+  int index =+      (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;+  ASSERT(0 <= index && index < kCachedPowersLength);+  CachedPower cached_power = kCachedPowers[index];+  ASSERT(min_exponent <= cached_power.binary_exponent);+  ASSERT(cached_power.binary_exponent <= max_exponent);+  *decimal_exponent = cached_power.decimal_exponent;+  *power = DiyFp(cached_power.significand, cached_power.binary_exponent);+}+++void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,+                                                        DiyFp* power,+                                                        int* found_exponent) {+  ASSERT(kMinDecimalExponent <= requested_exponent);+  ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);+  int index =+      (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;+  CachedPower cached_power = kCachedPowers[index];+  *power = DiyFp(cached_power.significand, cached_power.binary_exponent);+  *found_exponent = cached_power.decimal_exponent;+  ASSERT(*found_exponent <= requested_exponent);+  ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);+}++}  // namespace double_conversion
+ double-conversion/src/cached-powers.h view
@@ -0,0 +1,64 @@+// 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.++#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_+#define DOUBLE_CONVERSION_CACHED_POWERS_H_++#include "diy-fp.h"++namespace double_conversion {++class PowersOfTenCache {+ public:++  // Not all powers of ten are cached. The decimal exponent of two neighboring+  // cached numbers will differ by kDecimalExponentDistance.+  static const int kDecimalExponentDistance;++  static const int kMinDecimalExponent;+  static const int kMaxDecimalExponent;++  // Returns a cached power-of-ten with a binary exponent in the range+  // [min_exponent; max_exponent] (boundaries included).+  static void GetCachedPowerForBinaryExponentRange(int min_exponent,+                                                   int max_exponent,+                                                   DiyFp* power,+                                                   int* decimal_exponent);++  // Returns a cached power of ten x ~= 10^k such that+  //   k <= decimal_exponent < k + kCachedPowersDecimalDistance.+  // The given decimal_exponent must satisfy+  //   kMinDecimalExponent <= requested_exponent, and+  //   requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.+  static void GetCachedPowerForDecimalExponent(int requested_exponent,+                                               DiyFp* power,+                                               int* found_exponent);+};++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_CACHED_POWERS_H_
+ double-conversion/src/diy-fp.cc view
@@ -0,0 +1,57 @@+// 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 "diy-fp.h"+#include "utils.h"++namespace double_conversion {++void DiyFp::Multiply(const DiyFp& other) {+  // Simply "emulates" a 128 bit multiplication.+  // However: the resulting number only contains 64 bits. The least+  // significant 64 bits are only used for rounding the most significant 64+  // bits.+  const uint64_t kM32 = 0xFFFFFFFFU;+  uint64_t a = f_ >> 32;+  uint64_t b = f_ & kM32;+  uint64_t c = other.f_ >> 32;+  uint64_t d = other.f_ & kM32;+  uint64_t ac = a * c;+  uint64_t bc = b * c;+  uint64_t ad = a * d;+  uint64_t bd = b * d;+  uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);+  // By adding 1U << 31 to tmp we round the final result.+  // Halfway cases will be round up.+  tmp += 1U << 31;+  uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);+  e_ += other.e_ + 64;+  f_ = result_f;+}++}  // namespace double_conversion
+ double-conversion/src/diy-fp.h view
@@ -0,0 +1,118 @@+// 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.++#ifndef DOUBLE_CONVERSION_DIY_FP_H_+#define DOUBLE_CONVERSION_DIY_FP_H_++#include "utils.h"++namespace double_conversion {++// This "Do It Yourself Floating Point" class implements a floating-point number+// with a uint64 significand and an int exponent. Normalized DiyFp numbers will+// have the most significant bit of the significand set.+// Multiplication and Subtraction do not normalize their results.+// DiyFp are not designed to contain special doubles (NaN and Infinity).+class DiyFp {+ public:+  static const int kSignificandSize = 64;++  DiyFp() : f_(0), e_(0) {}+  DiyFp(uint64_t f, int e) : f_(f), e_(e) {}++  // this = this - other.+  // The exponents of both numbers must be the same and the significand of this+  // must be bigger than the significand of other.+  // The result will not be normalized.+  void Subtract(const DiyFp& other) {+    ASSERT(e_ == other.e_);+    ASSERT(f_ >= other.f_);+    f_ -= other.f_;+  }++  // Returns a - b.+  // The exponents of both numbers must be the same and this must be bigger+  // than other. The result will not be normalized.+  static DiyFp Minus(const DiyFp& a, const DiyFp& b) {+    DiyFp result = a;+    result.Subtract(b);+    return result;+  }+++  // this = this * other.+  void Multiply(const DiyFp& other);++  // returns a * b;+  static DiyFp Times(const DiyFp& a, const DiyFp& b) {+    DiyFp result = a;+    result.Multiply(b);+    return result;+  }++  void Normalize() {+    ASSERT(f_ != 0);+    uint64_t f = f_;+    int e = e_;++    // This method is mainly called for normalizing boundaries. In general+    // boundaries need to be shifted by 10 bits. We thus optimize for this case.+    const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);+    while ((f & k10MSBits) == 0) {+      f <<= 10;+      e -= 10;+    }+    while ((f & kUint64MSB) == 0) {+      f <<= 1;+      e--;+    }+    f_ = f;+    e_ = e;+  }++  static DiyFp Normalize(const DiyFp& a) {+    DiyFp result = a;+    result.Normalize();+    return result;+  }++  uint64_t f() const { return f_; }+  int e() const { return e_; }++  void set_f(uint64_t new_value) { f_ = new_value; }+  void set_e(int new_value) { e_ = new_value; }++ private:+  static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);++  uint64_t f_;+  int e_;+};++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_DIY_FP_H_
+ double-conversion/src/double-conversion.cc view
@@ -0,0 +1,869 @@+// 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 <limits.h>+#include <math.h>++#include "double-conversion.h"++#include "bignum-dtoa.h"+#include "double.h"+#include "fast-dtoa.h"+#include "fixed-dtoa.h"+#include "strtod.h"+#include "utils.h"++namespace double_conversion {++const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {+  int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;+  static DoubleToStringConverter converter(flags,+                                           "Infinity",+                                           "NaN",+                                           'e',+                                           -6, 21,+                                           6, 0);+  return converter;+}+++bool DoubleToStringConverter::HandleSpecialValues(+    double value,+    StringBuilder* result_builder) const {+  Double double_inspect(value);+  if (double_inspect.IsInfinite()) {+    if (infinity_symbol_ == NULL) return false;+    if (value < 0) {+      result_builder->AddCharacter('-');+    }+    result_builder->AddString(infinity_symbol_);+    return true;+  }+  if (double_inspect.IsNan()) {+    if (nan_symbol_ == NULL) return false;+    result_builder->AddString(nan_symbol_);+    return true;+  }+  return false;+}+++void DoubleToStringConverter::CreateExponentialRepresentation(+    const char* decimal_digits,+    int length,+    int exponent,+    StringBuilder* result_builder) const {+  ASSERT(length != 0);+  result_builder->AddCharacter(decimal_digits[0]);+  if (length != 1) {+    result_builder->AddCharacter('.');+    result_builder->AddSubstring(&decimal_digits[1], length-1);+  }+  result_builder->AddCharacter(exponent_character_);+  if (exponent < 0) {+    result_builder->AddCharacter('-');+    exponent = -exponent;+  } else {+    if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {+      result_builder->AddCharacter('+');+    }+  }+  if (exponent == 0) {+    result_builder->AddCharacter('0');+    return;+  }+  ASSERT(exponent < 1e4);+  const int kMaxExponentLength = 5;+  char buffer[kMaxExponentLength];+  int first_char_pos = kMaxExponentLength;+  while (exponent > 0) {+    buffer[--first_char_pos] = '0' + (exponent % 10);+    exponent /= 10;+  }+  result_builder->AddSubstring(&buffer[first_char_pos],+                               kMaxExponentLength - first_char_pos);+}+++void DoubleToStringConverter::CreateDecimalRepresentation(+    const char* decimal_digits,+    int length,+    int decimal_point,+    int digits_after_point,+    StringBuilder* result_builder) const {+  // Create a representation that is padded with zeros if needed.+  if (decimal_point <= 0) {+      // "0.00000decimal_rep".+    result_builder->AddCharacter('0');+    if (digits_after_point > 0) {+      result_builder->AddCharacter('.');+      result_builder->AddPadding('0', -decimal_point);+      ASSERT(length <= digits_after_point - (-decimal_point));+      result_builder->AddSubstring(decimal_digits, length);+      int remaining_digits = digits_after_point - (-decimal_point) - length;+      result_builder->AddPadding('0', remaining_digits);+    }+  } else if (decimal_point >= length) {+    // "decimal_rep0000.00000" or "decimal_rep.0000"+    result_builder->AddSubstring(decimal_digits, length);+    result_builder->AddPadding('0', decimal_point - length);+    if (digits_after_point > 0) {+      result_builder->AddCharacter('.');+      result_builder->AddPadding('0', digits_after_point);+    }+  } else {+    // "decima.l_rep000"+    ASSERT(digits_after_point > 0);+    result_builder->AddSubstring(decimal_digits, decimal_point);+    result_builder->AddCharacter('.');+    ASSERT(length - decimal_point <= digits_after_point);+    result_builder->AddSubstring(&decimal_digits[decimal_point],+                                 length - decimal_point);+    int remaining_digits = digits_after_point - (length - decimal_point);+    result_builder->AddPadding('0', remaining_digits);+  }+  if (digits_after_point == 0) {+    if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {+      result_builder->AddCharacter('.');+    }+    if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {+      result_builder->AddCharacter('0');+    }+  }+}+++bool DoubleToStringConverter::ToShortest(double value,+                                         StringBuilder* result_builder) const {+  if (Double(value).IsSpecial()) {+    return HandleSpecialValues(value, result_builder);+  }++  int decimal_point;+  bool sign;+  const int kDecimalRepCapacity = kBase10MaximalLength + 1;+  char decimal_rep[kDecimalRepCapacity];+  int decimal_rep_length;++  DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity,+                &sign, &decimal_rep_length, &decimal_point);++  bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;+  if (sign && (value != 0.0 || !unique_zero)) {+    result_builder->AddCharacter('-');+  }++  int exponent = decimal_point - 1;+  if ((decimal_in_shortest_low_ <= exponent) &&+      (exponent < decimal_in_shortest_high_)) {+    CreateDecimalRepresentation(decimal_rep, decimal_rep_length,+                                decimal_point,+                                Max(0, decimal_rep_length - decimal_point),+                                result_builder);+  } else {+    CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,+                                    result_builder);+  }+  return true;+}+++bool DoubleToStringConverter::ToFixed(double value,+                                      int requested_digits,+                                      StringBuilder* result_builder) const {+  ASSERT(kMaxFixedDigitsBeforePoint == 60);+  const double kFirstNonFixed = 1e60;++  if (Double(value).IsSpecial()) {+    return HandleSpecialValues(value, result_builder);+  }++  if (requested_digits > kMaxFixedDigitsAfterPoint) return false;+  if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;++  // Find a sufficiently precise decimal representation of n.+  int decimal_point;+  bool sign;+  // Add space for the '\0' byte.+  const int kDecimalRepCapacity =+      kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;+  char decimal_rep[kDecimalRepCapacity];+  int decimal_rep_length;+  DoubleToAscii(value, FIXED, requested_digits,+                decimal_rep, kDecimalRepCapacity,+                &sign, &decimal_rep_length, &decimal_point);++  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);+  if (sign && (value != 0.0 || !unique_zero)) {+    result_builder->AddCharacter('-');+  }++  CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,+                              requested_digits, result_builder);+  return true;+}+++bool DoubleToStringConverter::ToExponential(+    double value,+    int requested_digits,+    StringBuilder* result_builder) const {+  if (Double(value).IsSpecial()) {+    return HandleSpecialValues(value, result_builder);+  }++  if (requested_digits < -1) return false;+  if (requested_digits > kMaxExponentialDigits) return false;++  int decimal_point;+  bool sign;+  // Add space for digit before the decimal point and the '\0' character.+  const int kDecimalRepCapacity = kMaxExponentialDigits + 2;+  ASSERT(kDecimalRepCapacity > kBase10MaximalLength);+  char decimal_rep[kDecimalRepCapacity];+  int decimal_rep_length;++  if (requested_digits == -1) {+    DoubleToAscii(value, SHORTEST, 0,+                  decimal_rep, kDecimalRepCapacity,+                  &sign, &decimal_rep_length, &decimal_point);+  } else {+    DoubleToAscii(value, PRECISION, requested_digits + 1,+                  decimal_rep, kDecimalRepCapacity,+                  &sign, &decimal_rep_length, &decimal_point);+    ASSERT(decimal_rep_length <= requested_digits + 1);++    for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {+      decimal_rep[i] = '0';+    }+    decimal_rep_length = requested_digits + 1;+  }++  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);+  if (sign && (value != 0.0 || !unique_zero)) {+    result_builder->AddCharacter('-');+  }++  int exponent = decimal_point - 1;+  CreateExponentialRepresentation(decimal_rep,+                                  decimal_rep_length,+                                  exponent,+                                  result_builder);+  return true;+}+++bool DoubleToStringConverter::ToPrecision(double value,+                                          int precision,+                                          StringBuilder* result_builder) const {+  if (Double(value).IsSpecial()) {+    return HandleSpecialValues(value, result_builder);+  }++  if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {+    return false;+  }++  // Find a sufficiently precise decimal representation of n.+  int decimal_point;+  bool sign;+  // Add one for the terminating null character.+  const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;+  char decimal_rep[kDecimalRepCapacity];+  int decimal_rep_length;++  DoubleToAscii(value, PRECISION, precision,+                decimal_rep, kDecimalRepCapacity,+                &sign, &decimal_rep_length, &decimal_point);+  ASSERT(decimal_rep_length <= precision);++  bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);+  if (sign && (value != 0.0 || !unique_zero)) {+    result_builder->AddCharacter('-');+  }++  // The exponent if we print the number as x.xxeyyy. That is with the+  // decimal point after the first digit.+  int exponent = decimal_point - 1;++  int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;+  if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||+      (decimal_point - precision + extra_zero >+       max_trailing_padding_zeroes_in_precision_mode_)) {+    // Fill buffer to contain 'precision' digits.+    // Usually the buffer is already at the correct length, but 'DoubleToAscii'+    // is allowed to return less characters.+    for (int i = decimal_rep_length; i < precision; ++i) {+      decimal_rep[i] = '0';+    }++    CreateExponentialRepresentation(decimal_rep,+                                    precision,+                                    exponent,+                                    result_builder);+  } else {+    CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,+                                Max(0, precision - decimal_point),+                                result_builder);+  }+  return true;+}+++static BignumDtoaMode DtoaToBignumDtoaMode(+    DoubleToStringConverter::DtoaMode dtoa_mode) {+  switch (dtoa_mode) {+    case DoubleToStringConverter::SHORTEST:  return BIGNUM_DTOA_SHORTEST;+    case DoubleToStringConverter::FIXED:     return BIGNUM_DTOA_FIXED;+    case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;+    default:+      UNREACHABLE();+      return BIGNUM_DTOA_SHORTEST;  // To silence compiler.+  }+}+++void DoubleToStringConverter::DoubleToAscii(double v,+                                            DtoaMode mode,+                                            int requested_digits,+                                            char* buffer,+                                            int buffer_length,+                                            bool* sign,+                                            int* length,+                                            int* point) {+  Vector<char> vector(buffer, buffer_length);+  ASSERT(!Double(v).IsSpecial());+  ASSERT(mode == SHORTEST || requested_digits >= 0);++  if (Double(v).Sign() < 0) {+    *sign = true;+    v = -v;+  } else {+    *sign = false;+  }++  if (mode == PRECISION && requested_digits == 0) {+    vector[0] = '\0';+    *length = 0;+    return;+  }++  if (v == 0) {+    vector[0] = '0';+    vector[1] = '\0';+    *length = 1;+    *point = 1;+    return;+  }++  bool fast_worked;+  switch (mode) {+    case SHORTEST:+      fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);+      break;+    case FIXED:+      fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);+      break;+    case PRECISION:+      fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,+                             vector, length, point);+      break;+    default:+      UNREACHABLE();+      fast_worked = false;+  }+  if (fast_worked) return;++  // If the fast dtoa didn't succeed use the slower bignum version.+  BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);+  BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);+  vector[*length] = '\0';+}+++// Consumes the given substring from the iterator.+// Returns false, if the substring does not match.+static bool ConsumeSubString(const char** current,+                             const char* end,+                             const char* substring) {+  ASSERT(**current == *substring);+  for (substring++; *substring != '\0'; substring++) {+    ++*current;+    if (*current == end || **current != *substring) return false;+  }+  ++*current;+  return true;+}+++// Maximum number of significant digits in decimal representation.+// The longest possible double in decimal representation is+// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074+// (768 digits). If we parse a number whose first digits are equal to a+// mean of 2 adjacent doubles (that could have up to 769 digits) the result+// must be rounded to the bigger one unless the tail consists of zeros, so+// we don't need to preserve all the digits.+const int kMaxSignificantDigits = 772;+++// Returns true if a nonspace found and false if the end has reached.+static inline bool AdvanceToNonspace(const char** current, const char* end) {+  while (*current != end) {+    if (**current != ' ') return true;+    ++*current;+  }+  return false;+}+++static bool isDigit(int x, int radix) {+  return (x >= '0' && x <= '9' && x < '0' + radix)+      || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)+      || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);+}+++static double SignedZero(bool sign) {+  return sign ? -0.0 : 0.0;+}+++// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.+template <int radix_log_2>+static double RadixStringToDouble(const char* current,+                                  const char* end,+                                  bool sign,+                                  bool allow_trailing_junk,+                                  double junk_string_value,+                                  const char** trailing_pointer) {+  ASSERT(current != end);++  // Skip leading 0s.+  while (*current == '0') {+    ++current;+    if (current == end) {+      *trailing_pointer = end;+      return SignedZero(sign);+    }+  }++  int64_t number = 0;+  int exponent = 0;+  const int radix = (1 << radix_log_2);++  do {+    int digit;+    if (*current >= '0' && *current <= '9' && *current < '0' + radix) {+      digit = static_cast<char>(*current) - '0';+    } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {+      digit = static_cast<char>(*current) - 'a' + 10;+    } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {+      digit = static_cast<char>(*current) - 'A' + 10;+    } else {+      if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {+        break;+      } else {+        return junk_string_value;+      }+    }++    number = number * radix + digit;+    int overflow = static_cast<int>(number >> 53);+    if (overflow != 0) {+      // Overflow occurred. Need to determine which direction to round the+      // result.+      int overflow_bits_count = 1;+      while (overflow > 1) {+        overflow_bits_count++;+        overflow >>= 1;+      }++      int dropped_bits_mask = ((1 << overflow_bits_count) - 1);+      int dropped_bits = static_cast<int>(number) & dropped_bits_mask;+      number >>= overflow_bits_count;+      exponent = overflow_bits_count;++      bool zero_tail = true;+      while (true) {+        ++current;+        if (current == end || !isDigit(*current, radix)) break;+        zero_tail = zero_tail && *current == '0';+        exponent += radix_log_2;+      }++      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {+        return junk_string_value;+      }++      int middle_value = (1 << (overflow_bits_count - 1));+      if (dropped_bits > middle_value) {+        number++;  // Rounding up.+      } else if (dropped_bits == middle_value) {+        // Rounding to even to consistency with decimals: half-way case rounds+        // up if significant part is odd and down otherwise.+        if ((number & 1) != 0 || !zero_tail) {+          number++;  // Rounding up.+        }+      }++      // Rounding up may cause overflow.+      if ((number & ((int64_t)1 << 53)) != 0) {+        exponent++;+        number >>= 1;+      }+      break;+    }+    ++current;+  } while (current != end);++  ASSERT(number < ((int64_t)1 << 53));+  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);++  *trailing_pointer = current;++  if (exponent == 0) {+    if (sign) {+      if (number == 0) return -0.0;+      number = -number;+    }+    return static_cast<double>(number);+  }++  ASSERT(number != 0);+  return Double(DiyFp(number, exponent)).value();+}+++double StringToDoubleConverter::StringToDouble(+    const char* input,+    int length,+    int* processed_characters_count) {+  const char* current = input;+  const char* end = input + length;++  *processed_characters_count = 0;++  const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;+  const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;+  const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;+  const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;++  // To make sure that iterator dereferencing is valid the following+  // convention is used:+  // 1. Each '++current' statement is followed by check for equality to 'end'.+  // 2. If AdvanceToNonspace returned false then current == end.+  // 3. If 'current' becomes equal to 'end' the function returns or goes to+  // 'parsing_done'.+  // 4. 'current' is not dereferenced after the 'parsing_done' label.+  // 5. Code before 'parsing_done' may rely on 'current != end'.+  if (current == end) return empty_string_value_;++  if (allow_leading_spaces || allow_trailing_spaces) {+    if (!AdvanceToNonspace(&current, end)) {+      *processed_characters_count = current - input;+      return empty_string_value_;+    }+    if (!allow_leading_spaces && (input != current)) {+      // No leading spaces allowed, but AdvanceToNonspace moved forward.+      return junk_string_value_;+    }+  }++  // The longest form of simplified number is: "-<significant digits>.1eXXX\0".+  const int kBufferSize = kMaxSignificantDigits + 10;+  char buffer[kBufferSize];  // NOLINT: size is known at compile time.+  int buffer_pos = 0;++  // Exponent will be adjusted if insignificant digits of the integer part+  // or insignificant leading zeros of the fractional part are dropped.+  int exponent = 0;+  int significant_digits = 0;+  int insignificant_digits = 0;+  bool nonzero_digit_dropped = false;+  bool fractional_part = false;++  bool sign = false;++  if (*current == '+' || *current == '-') {+    sign = (*current == '-');+    ++current;+    const char* next_non_space = current;+    // Skip following spaces (if allowed).+    if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;+    if (!allow_spaces_after_sign && (current != next_non_space)) {+      return junk_string_value_;+    }+    current = next_non_space;+  }++  if (infinity_symbol_ != NULL) {+    if (*current == infinity_symbol_[0]) {+      if (!ConsumeSubString(&current, end, infinity_symbol_)) {+        return junk_string_value_;+      }++      if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {+        return junk_string_value_;+      }+      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {+        return junk_string_value_;+      }++      ASSERT(buffer_pos == 0);+      *processed_characters_count = current - input;+      return sign ? -Double::Infinity() : Double::Infinity();+    }+  }++  if (nan_symbol_ != NULL) {+    if (*current == nan_symbol_[0]) {+      if (!ConsumeSubString(&current, end, nan_symbol_)) {+        return junk_string_value_;+      }++      if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {+        return junk_string_value_;+      }+      if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {+        return junk_string_value_;+      }++      ASSERT(buffer_pos == 0);+      *processed_characters_count = current - input;+      return sign ? -Double::NaN() : Double::NaN();+    }+  }++  bool leading_zero = false;+  if (*current == '0') {+    ++current;+    if (current == end) {+      *processed_characters_count = current - input;+      return SignedZero(sign);+    }++    leading_zero = true;++    // It could be hexadecimal value.+    if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {+      ++current;+      if (current == end || !isDigit(*current, 16)) {+        return junk_string_value_;  // "0x".+      }++      const char* tail_pointer = NULL;+      double result = RadixStringToDouble<4>(current,+                                             end,+                                             sign,+                                             allow_trailing_junk,+                                             junk_string_value_,+                                             &tail_pointer);+      if (tail_pointer != NULL) {+        if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);+        *processed_characters_count = tail_pointer - input;+      }+      return result;+    }++    // Ignore leading zeros in the integer part.+    while (*current == '0') {+      ++current;+      if (current == end) {+        *processed_characters_count = current - input;+        return SignedZero(sign);+      }+    }+  }++  bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;++  // Copy significant digits of the integer part (if any) to the buffer.+  while (*current >= '0' && *current <= '9') {+    if (significant_digits < kMaxSignificantDigits) {+      ASSERT(buffer_pos < kBufferSize);+      buffer[buffer_pos++] = static_cast<char>(*current);+      significant_digits++;+      // Will later check if it's an octal in the buffer.+    } else {+      insignificant_digits++;  // Move the digit into the exponential part.+      nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';+    }+    octal = octal && *current < '8';+    ++current;+    if (current == end) goto parsing_done;+  }++  if (significant_digits == 0) {+    octal = false;+  }++  if (*current == '.') {+    if (octal && !allow_trailing_junk) return junk_string_value_;+    if (octal) goto parsing_done;++    ++current;+    if (current == end) {+      if (significant_digits == 0 && !leading_zero) {+        return junk_string_value_;+      } else {+        goto parsing_done;+      }+    }++    if (significant_digits == 0) {+      // octal = false;+      // Integer part consists of 0 or is absent. Significant digits start after+      // leading zeros (if any).+      while (*current == '0') {+        ++current;+        if (current == end) {+          *processed_characters_count = current - input;+          return SignedZero(sign);+        }+        exponent--;  // Move this 0 into the exponent.+      }+    }++    // We don't emit a '.', but adjust the exponent instead.+    fractional_part = true;++    // There is a fractional part.+    while (*current >= '0' && *current <= '9') {+      if (significant_digits < kMaxSignificantDigits) {+        ASSERT(buffer_pos < kBufferSize);+        buffer[buffer_pos++] = static_cast<char>(*current);+        significant_digits++;+        exponent--;+      } else {+        // Ignore insignificant digits in the fractional part.+        nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';+      }+      ++current;+      if (current == end) goto parsing_done;+    }+  }++  if (!leading_zero && exponent == 0 && significant_digits == 0) {+    // If leading_zeros is true then the string contains zeros.+    // If exponent < 0 then string was [+-]\.0*...+    // If significant_digits != 0 the string is not equal to 0.+    // Otherwise there are no digits in the string.+    return junk_string_value_;+  }++  // Parse exponential part.+  if (*current == 'e' || *current == 'E') {+    if (octal && !allow_trailing_junk) return junk_string_value_;+    if (octal) goto parsing_done;+    ++current;+    if (current == end) {+      if (allow_trailing_junk) {+        goto parsing_done;+      } else {+        return junk_string_value_;+      }+    }+    char sign = '+';+    if (*current == '+' || *current == '-') {+      sign = static_cast<char>(*current);+      ++current;+      if (current == end) {+        if (allow_trailing_junk) {+          goto parsing_done;+        } else {+          return junk_string_value_;+        }+      }+    }++    if (current == end || *current < '0' || *current > '9') {+      if (allow_trailing_junk) {+        goto parsing_done;+      } else {+        return junk_string_value_;+      }+    }++    const int max_exponent = INT_MAX / 2;+    ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);+    int num = 0;+    do {+      // Check overflow.+      int digit = *current - '0';+      if (num >= max_exponent / 10+          && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {+        num = max_exponent;+      } else {+        num = num * 10 + digit;+      }+      ++current;+    } while (current != end && *current >= '0' && *current <= '9');++    exponent += (sign == '-' ? -num : num);+  }++  if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {+    return junk_string_value_;+  }+  if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {+    return junk_string_value_;+  }+  if (allow_trailing_spaces) {+    AdvanceToNonspace(&current, end);+  }++  parsing_done:+  exponent += insignificant_digits;++  if (octal) {+    double result;+    const char* tail_pointer = NULL;+    result = RadixStringToDouble<3>(buffer,+                                    buffer + buffer_pos,+                                    sign,+                                    allow_trailing_junk,+                                    junk_string_value_,+                                    &tail_pointer);+    ASSERT(tail_pointer != NULL);+    *processed_characters_count = current - input;+    return result;+  }++  if (nonzero_digit_dropped) {+    buffer[buffer_pos++] = '1';+    exponent--;+  }++  ASSERT(buffer_pos < kBufferSize);+  buffer[buffer_pos] = '\0';++  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);+  *processed_characters_count = current - input;+  return sign? -converted: converted;+}++}  // namespace double_conversion
+ double-conversion/src/double-conversion.h view
@@ -0,0 +1,498 @@+// 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.++#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_+#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_++#include "utils.h"++namespace double_conversion {++class DoubleToStringConverter {+ public:+  // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint+  // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the+  // function returns false.+  static const int kMaxFixedDigitsBeforePoint = 60;+  static const int kMaxFixedDigitsAfterPoint = 60;++  // When calling ToExponential with a requested_digits+  // parameter > kMaxExponentialDigits then the function returns false.+  static const int kMaxExponentialDigits = 120;++  // When calling ToPrecision with a requested_digits+  // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits+  // then the function returns false.+  static const int kMinPrecisionDigits = 1;+  static const int kMaxPrecisionDigits = 120;++  enum Flags {+    NO_FLAGS = 0,+    EMIT_POSITIVE_EXPONENT_SIGN = 1,+    EMIT_TRAILING_DECIMAL_POINT = 2,+    EMIT_TRAILING_ZERO_AFTER_POINT = 4,+    UNIQUE_ZERO = 8+  };++  // Flags should be a bit-or combination of the possible Flags-enum.+  //  - NO_FLAGS: no special flags.+  //  - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent+  //    form, emits a '+' for positive exponents. Example: 1.2e+2.+  //  - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is+  //    converted into decimal format then a trailing decimal point is appended.+  //    Example: 2345.0 is converted to "2345.".+  //  - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point+  //    emits a trailing '0'-character. This flag requires the+  //    EXMIT_TRAILING_DECIMAL_POINT flag.+  //    Example: 2345.0 is converted to "2345.0".+  //  - UNIQUE_ZERO: "-0.0" is converted to "0.0".+  //+  // Infinity symbol and nan_symbol provide the string representation for these+  // special values. If the string is NULL and the special value is encountered+  // then the conversion functions return false.+  //+  // The exponent_character is used in exponential representations. It is+  // usually 'e' or 'E'.+  //+  // When converting to the shortest representation the converter will+  // represent input numbers in decimal format if they are in the interval+  // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[+  //    (lower boundary included, greater boundary excluded).+  // Example: with decimal_in_shortest_low = -6 and+  //               decimal_in_shortest_high = 21:+  //   ToShortest(0.000001)  -> "0.000001"+  //   ToShortest(0.0000001) -> "1e-7"+  //   ToShortest(111111111111111111111.0)  -> "111111111111111110000"+  //   ToShortest(100000000000000000000.0)  -> "100000000000000000000"+  //   ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"+  //+  // When converting to precision mode the converter may add+  // max_leading_padding_zeroes before returning the number in exponential+  // format.+  // Example with max_leading_padding_zeroes_in_precision_mode = 6.+  //   ToPrecision(0.0000012345, 2) -> "0.0000012"+  //   ToPrecision(0.00000012345, 2) -> "1.2e-7"+  // Similarily the converter may add up to+  // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid+  // returning an exponential representation. A zero added by the+  // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.+  // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:+  //   ToPrecision(230.0, 2) -> "230"+  //   ToPrecision(230.0, 2) -> "230."  with EMIT_TRAILING_DECIMAL_POINT.+  //   ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.+  DoubleToStringConverter(int flags,+                          const char* infinity_symbol,+                          const char* nan_symbol,+                          char exponent_character,+                          int decimal_in_shortest_low,+                          int decimal_in_shortest_high,+                          int max_leading_padding_zeroes_in_precision_mode,+                          int max_trailing_padding_zeroes_in_precision_mode)+      : flags_(flags),+        infinity_symbol_(infinity_symbol),+        nan_symbol_(nan_symbol),+        exponent_character_(exponent_character),+        decimal_in_shortest_low_(decimal_in_shortest_low),+        decimal_in_shortest_high_(decimal_in_shortest_high),+        max_leading_padding_zeroes_in_precision_mode_(+            max_leading_padding_zeroes_in_precision_mode),+        max_trailing_padding_zeroes_in_precision_mode_(+            max_trailing_padding_zeroes_in_precision_mode) {+    // When 'trailing zero after the point' is set, then 'trailing point'+    // must be set too.+    ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||+        !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));+  }++  // Returns a converter following the EcmaScript specification.+  static const DoubleToStringConverter& EcmaScriptConverter();++  // Computes the shortest string of digits that correctly represent the input+  // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high+  // (see constructor) it then either returns a decimal representation, or an+  // exponential representation.+  // Example with decimal_in_shortest_low = -6,+  //              decimal_in_shortest_high = 21,+  //              EMIT_POSITIVE_EXPONENT_SIGN activated, and+  //              EMIT_TRAILING_DECIMAL_POINT deactived:+  //   ToShortest(0.000001)  -> "0.000001"+  //   ToShortest(0.0000001) -> "1e-7"+  //   ToShortest(111111111111111111111.0)  -> "111111111111111110000"+  //   ToShortest(100000000000000000000.0)  -> "100000000000000000000"+  //   ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"+  //+  // Note: the conversion may round the output if the returned string+  // is accurate enough to uniquely identify the input-number.+  // For example the most precise representation of the double 9e59 equals+  // "899999999999999918767229449717619953810131273674690656206848", but+  // the converter will return the shorter (but still correct) "9e59".+  //+  // Returns true if the conversion succeeds. The conversion always succeeds+  // except when the input value is special and no infinity_symbol or+  // nan_symbol has been given to the constructor.+  bool ToShortest(double value, StringBuilder* result_builder) const;+++  // Computes a decimal representation with a fixed number of digits after the+  // decimal point. The last emitted digit is rounded.+  //+  // Examples:+  //   ToFixed(3.12, 1) -> "3.1"+  //   ToFixed(3.1415, 3) -> "3.142"+  //   ToFixed(1234.56789, 4) -> "1234.5679"+  //   ToFixed(1.23, 5) -> "1.23000"+  //   ToFixed(0.1, 4) -> "0.1000"+  //   ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"+  //   ToFixed(0.1, 30) -> "0.100000000000000005551115123126"+  //   ToFixed(0.1, 17) -> "0.10000000000000001"+  //+  // If requested_digits equals 0, then the tail of the result depends on+  // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.+  // Examples, for requested_digits == 0,+  //   let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be+  //    - false and false: then 123.45 -> 123+  //                             0.678 -> 1+  //    - true and false: then 123.45 -> 123.+  //                            0.678 -> 1.+  //    - true and true: then 123.45 -> 123.0+  //                           0.678 -> 1.0+  //+  // Returns true if the conversion succeeds. The conversion always succeeds+  // except for the following cases:+  //   - the input value is special and no infinity_symbol or nan_symbol has+  //     been provided to the constructor,+  //   - 'value' > 10^kMaxFixedDigitsBeforePoint, or+  //   - 'requested_digits' > kMaxFixedDigitsAfterPoint.+  // The last two conditions imply that the result will never contain more than+  // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters+  // (one additional character for the sign, and one for the decimal point).+  bool ToFixed(double value,+               int requested_digits,+               StringBuilder* result_builder) const;++  // Computes a representation in exponential format with requested_digits+  // after the decimal point. The last emitted digit is rounded.+  // If requested_digits equals -1, then the shortest exponential representation+  // is computed.+  //+  // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and+  //               exponent_character set to 'e'.+  //   ToExponential(3.12, 1) -> "3.1e0"+  //   ToExponential(5.0, 3) -> "5.000e0"+  //   ToExponential(0.001, 2) -> "1.00e-3"+  //   ToExponential(3.1415, -1) -> "3.1415e0"+  //   ToExponential(3.1415, 4) -> "3.1415e0"+  //   ToExponential(3.1415, 3) -> "3.142e0"+  //   ToExponential(123456789000000, 3) -> "1.235e14"+  //   ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"+  //   ToExponential(1000000000000000019884624838656.0, 32) ->+  //                     "1.00000000000000001988462483865600e30"+  //   ToExponential(1234, 0) -> "1e3"+  //+  // Returns true if the conversion succeeds. The conversion always succeeds+  // except for the following cases:+  //   - the input value is special and no infinity_symbol or nan_symbol has+  //     been provided to the constructor,+  //   - 'requested_digits' > kMaxExponentialDigits.+  // The last condition implies that the result will never contain more than+  // kMaxExponentialDigits + 8 characters (the sign, the digit before the+  // decimal point, the decimal point, the exponent character, the+  // exponent's sign, and at most 3 exponent digits).+  bool ToExponential(double value,+                     int requested_digits,+                     StringBuilder* result_builder) const;++  // Computes 'precision' leading digits of the given 'value' and returns them+  // either in exponential or decimal format, depending on+  // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the+  // constructor).+  // The last computed digit is rounded.+  //+  // Example with max_leading_padding_zeroes_in_precision_mode = 6.+  //   ToPrecision(0.0000012345, 2) -> "0.0000012"+  //   ToPrecision(0.00000012345, 2) -> "1.2e-7"+  // Similarily the converter may add up to+  // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid+  // returning an exponential representation. A zero added by the+  // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.+  // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:+  //   ToPrecision(230.0, 2) -> "230"+  //   ToPrecision(230.0, 2) -> "230."  with EMIT_TRAILING_DECIMAL_POINT.+  //   ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.+  // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no+  //    EMIT_TRAILING_ZERO_AFTER_POINT:+  //   ToPrecision(123450.0, 6) -> "123450"+  //   ToPrecision(123450.0, 5) -> "123450"+  //   ToPrecision(123450.0, 4) -> "123500"+  //   ToPrecision(123450.0, 3) -> "123000"+  //   ToPrecision(123450.0, 2) -> "1.2e5"+  //+  // Returns true if the conversion succeeds. The conversion always succeeds+  // except for the following cases:+  //   - the input value is special and no infinity_symbol or nan_symbol has+  //     been provided to the constructor,+  //   - precision < kMinPericisionDigits+  //   - precision > kMaxPrecisionDigits+  // The last condition implies that the result will never contain more than+  // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the+  // exponent character, the exponent's sign, and at most 3 exponent digits).+  bool ToPrecision(double value,+                   int precision,+                   StringBuilder* result_builder) const;++  enum DtoaMode {+    // Produce the shortest correct representation.+    // For example the output of 0.299999999999999988897 is (the less accurate+    // but correct) 0.3.+    SHORTEST,+    // Produce a fixed number of digits after the decimal point.+    // For instance fixed(0.1, 4) becomes 0.1000+    // If the input number is big, the output will be big.+    FIXED,+    // Fixed number of digits (independent of the decimal point).+    PRECISION+  };++  // The maximal number of digits that are needed to emit a double in base 10.+  // A higher precision can be achieved by using more digits, but the shortest+  // accurate representation of any double will never use more digits than+  // kBase10MaximalLength.+  // Note that DoubleToAscii null-terminates its input. So the given buffer+  // should be at least kBase10MaximalLength + 1 characters long.+  static const int kBase10MaximalLength = 17;++  // Converts the given double 'v' to ascii.+  // The result should be interpreted as buffer * 10^(point-length).+  //+  // The output depends on the given mode:+  //  - SHORTEST: produce the least amount of digits for which the internal+  //   identity requirement is still satisfied. If the digits are printed+  //   (together with the correct exponent) then reading this number will give+  //   'v' again. The buffer will choose the representation that is closest to+  //   'v'. If there are two at the same distance, than the one farther away+  //   from 0 is chosen (halfway cases - ending with 5 - are rounded up).+  //   In this mode the 'requested_digits' parameter is ignored.+  //  - FIXED: produces digits necessary to print a given number with+  //   'requested_digits' digits after the decimal point. The produced digits+  //   might be too short in which case the caller has to fill the remainder+  //   with '0's.+  //   Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.+  //   Halfway cases are rounded towards +/-Infinity (away from 0). The call+  //   toFixed(0.15, 2) thus returns buffer="2", point=0.+  //   The returned buffer may contain digits that would be truncated from the+  //   shortest representation of the input.+  //  - PRECISION: produces 'requested_digits' where the first digit is not '0'.+  //   Even though the length of produced digits usually equals+  //   'requested_digits', the function is allowed to return fewer digits, in+  //   which case the caller has to fill the missing digits with '0's.+  //   Halfway cases are again rounded away from 0.+  // DoubleToAscii expects the given buffer to be big enough to hold all+  // digits and a terminating null-character. In SHORTEST-mode it expects a+  // buffer of at least kBase10MaximalLength + 1. In all other modes the+  // requested_digits parameter (+ 1 for the null-character) limits the size of+  // the output. The given length is only used in debug mode to ensure the+  // buffer is big enough.+  static void DoubleToAscii(double v,+                            DtoaMode mode,+                            int requested_digits,+                            char* buffer,+                            int buffer_length,+                            bool* sign,+                            int* length,+                            int* point);++ private:+  // If the value is a special value (NaN or Infinity) constructs the+  // corresponding string using the configured infinity/nan-symbol.+  // If either of them is NULL or the value is not special then the+  // function returns false.+  bool HandleSpecialValues(double value, StringBuilder* result_builder) const;+  // Constructs an exponential representation (i.e. 1.234e56).+  // The given exponent assumes a decimal point after the first decimal digit.+  void CreateExponentialRepresentation(const char* decimal_digits,+                                       int length,+                                       int exponent,+                                       StringBuilder* result_builder) const;+  // Creates a decimal representation (i.e 1234.5678).+  void CreateDecimalRepresentation(const char* decimal_digits,+                                   int length,+                                   int decimal_point,+                                   int digits_after_point,+                                   StringBuilder* result_builder) const;++  const int flags_;+  const char* const infinity_symbol_;+  const char* const nan_symbol_;+  const char exponent_character_;+  const int decimal_in_shortest_low_;+  const int decimal_in_shortest_high_;+  const int max_leading_padding_zeroes_in_precision_mode_;+  const int max_trailing_padding_zeroes_in_precision_mode_;++  DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);+};+++class StringToDoubleConverter {+ public:+  // Enumeration for allowing octals and ignoring junk when converting+  // strings to numbers.+  enum Flags {+    NO_FLAGS = 0,+    ALLOW_HEX = 1,+    ALLOW_OCTALS = 2,+    ALLOW_TRAILING_JUNK = 4,+    ALLOW_LEADING_SPACES = 8,+    ALLOW_TRAILING_SPACES = 16,+    ALLOW_SPACES_AFTER_SIGN = 32+  };++  // Flags should be a bit-or combination of the possible Flags-enum.+  //  - NO_FLAGS: no special flags.+  //  - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.+  //      Ex: StringToDouble("0x1234") -> 4660.0+  //          In StringToDouble("0x1234.56") the characters ".56" are trailing+  //          junk. The result of the call is hence dependent on+  //          the ALLOW_TRAILING_JUNK flag and/or the junk value.+  //      With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,+  //      the string will not be parsed as "0" followed by junk.+  //+  //  - ALLOW_OCTALS: recognizes the prefix "0" for octals:+  //      If a sequence of octal digits starts with '0', then the number is+  //      read as octal integer. Octal numbers may only be integers.+  //      Ex: StringToDouble("01234") -> 668.0+  //          StringToDouble("012349") -> 12349.0  // Not a sequence of octal+  //                                               // digits.+  //          In StringToDouble("01234.56") the characters ".56" are trailing+  //          junk. The result of the call is hence dependent on+  //          the ALLOW_TRAILING_JUNK flag and/or the junk value.+  //          In StringToDouble("01234e56") the characters "e56" are trailing+  //          junk, too.+  //  - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of+  //      a double literal.+  //  - ALLOW_LEADING_SPACES: skip over leading spaces.+  //  - ALLOW_TRAILING_SPACES: ignore trailing spaces.+  //  - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.+  //       Ex: StringToDouble("-   123.2") -> -123.2.+  //           StringToDouble("+   123.2") -> 123.2+  //+  // empty_string_value is returned when an empty string is given as input.+  // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string+  // containing only spaces is converted to the 'empty_string_value', too.+  //+  // junk_string_value is returned when+  //  a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not+  //     part of a double-literal) is found.+  //  b) ALLOW_TRAILING_JUNK is set, but the string does not start with a+  //     double literal.+  //+  // infinity_symbol and nan_symbol are strings that are used to detect+  // inputs that represent infinity and NaN. They can be null, in which case+  // they are ignored.+  // The conversion routine first reads any possible signs. Then it compares the+  // following character of the input-string with the first character of+  // the infinity, and nan-symbol. If either matches, the function assumes, that+  // a match has been found, and expects the following input characters to match+  // the remaining characters of the special-value symbol.+  // This means that the following restrictions apply to special-value symbols:+  //  - they must not start with signs ('+', or '-'),+  //  - they must not have the same first character.+  //  - they must not start with digits.+  //+  // Examples:+  //  flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,+  //  empty_string_value = 0.0,+  //  junk_string_value = NaN,+  //  infinity_symbol = "infinity",+  //  nan_symbol = "nan":+  //    StringToDouble("0x1234") -> 4660.0.+  //    StringToDouble("0x1234K") -> 4660.0.+  //    StringToDouble("") -> 0.0  // empty_string_value.+  //    StringToDouble(" ") -> NaN  // junk_string_value.+  //    StringToDouble(" 1") -> NaN  // junk_string_value.+  //    StringToDouble("0x") -> NaN  // junk_string_value.+  //    StringToDouble("-123.45") -> -123.45.+  //    StringToDouble("--123.45") -> NaN  // junk_string_value.+  //    StringToDouble("123e45") -> 123e45.+  //    StringToDouble("123E45") -> 123e45.+  //    StringToDouble("123e+45") -> 123e45.+  //    StringToDouble("123E-45") -> 123e-45.+  //    StringToDouble("123e") -> 123.0  // trailing junk ignored.+  //    StringToDouble("123e-") -> 123.0  // trailing junk ignored.+  //    StringToDouble("+NaN") -> NaN  // NaN string literal.+  //    StringToDouble("-infinity") -> -inf.  // infinity literal.+  //    StringToDouble("Infinity") -> NaN  // junk_string_value.+  //+  //  flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,+  //  empty_string_value = 0.0,+  //  junk_string_value = NaN,+  //  infinity_symbol = NULL,+  //  nan_symbol = NULL:+  //    StringToDouble("0x1234") -> NaN  // junk_string_value.+  //    StringToDouble("01234") -> 668.0.+  //    StringToDouble("") -> 0.0  // empty_string_value.+  //    StringToDouble(" ") -> 0.0  // empty_string_value.+  //    StringToDouble(" 1") -> 1.0+  //    StringToDouble("0x") -> NaN  // junk_string_value.+  //    StringToDouble("0123e45") -> NaN  // junk_string_value.+  //    StringToDouble("01239E45") -> 1239e45.+  //    StringToDouble("-infinity") -> NaN  // junk_string_value.+  //    StringToDouble("NaN") -> NaN  // junk_string_value.+  StringToDoubleConverter(int flags,+                          double empty_string_value,+                          double junk_string_value,+                          const char* infinity_symbol,+                          const char* nan_symbol)+      : flags_(flags),+        empty_string_value_(empty_string_value),+        junk_string_value_(junk_string_value),+        infinity_symbol_(infinity_symbol),+        nan_symbol_(nan_symbol) {+  }++  // Performs the conversion.+  // The output parameter 'processed_characters_count' is set to the number+  // of characters that have been processed to read the number.+  // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included+  // in the 'processed_characters_count'. Trailing junk is never included.+  double StringToDouble(const char* buffer,+                        int length,+                        int* processed_characters_count);++ private:+  const int flags_;+  const double empty_string_value_;+  const double junk_string_value_;+  const char* const infinity_symbol_;+  const char* const nan_symbol_;++  DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);+};++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
+ double-conversion/src/double.h view
@@ -0,0 +1,245 @@+// 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.++#ifndef DOUBLE_CONVERSION_DOUBLE_H_+#define DOUBLE_CONVERSION_DOUBLE_H_++#include "diy-fp.h"++namespace double_conversion {++// We assume that doubles and uint64_t have the same endianness.+static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }+static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }++// Helper functions for doubles.+class Double {+ public:+  static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);+  static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);+  static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);+  static const int kPhysicalSignificandSize = 52;  // Excludes the hidden bit.+  static const int kSignificandSize = 53;++  Double() : d64_(0) {}+  explicit Double(double d) : d64_(double_to_uint64(d)) {}+  explicit Double(uint64_t d64) : d64_(d64) {}+  explicit Double(DiyFp diy_fp)+    : d64_(DiyFpToUint64(diy_fp)) {}++  // The value encoded by this Double must be greater or equal to +0.0.+  // It must not be special (infinity, or NaN).+  DiyFp AsDiyFp() const {+    ASSERT(Sign() > 0);+    ASSERT(!IsSpecial());+    return DiyFp(Significand(), Exponent());+  }++  // The value encoded by this Double must be strictly greater than 0.+  DiyFp AsNormalizedDiyFp() const {+    ASSERT(value() > 0.0);+    uint64_t f = Significand();+    int e = Exponent();++    // The current double could be a denormal.+    while ((f & kHiddenBit) == 0) {+      f <<= 1;+      e--;+    }+    // Do the final shifts in one go.+    f <<= DiyFp::kSignificandSize - kSignificandSize;+    e -= DiyFp::kSignificandSize - kSignificandSize;+    return DiyFp(f, e);+  }++  // Returns the double's bit as uint64.+  uint64_t AsUint64() const {+    return d64_;+  }++  // Returns the next greater double. Returns +infinity on input +infinity.+  double NextDouble() const {+    if (d64_ == kInfinity) return Double(kInfinity).value();+    if (Sign() < 0 && Significand() == 0) {+      // -0.0+      return 0.0;+    }+    if (Sign() < 0) {+      return Double(d64_ - 1).value();+    } else {+      return Double(d64_ + 1).value();+    }+  }++  int Exponent() const {+    if (IsDenormal()) return kDenormalExponent;++    uint64_t d64 = AsUint64();+    int biased_e =+        static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);+    return biased_e - kExponentBias;+  }++  uint64_t Significand() const {+    uint64_t d64 = AsUint64();+    uint64_t significand = d64 & kSignificandMask;+    if (!IsDenormal()) {+      return significand + kHiddenBit;+    } else {+      return significand;+    }+  }++  // Returns true if the double is a denormal.+  bool IsDenormal() const {+    uint64_t d64 = AsUint64();+    return (d64 & kExponentMask) == 0;+  }++  // We consider denormals not to be special.+  // Hence only Infinity and NaN are special.+  bool IsSpecial() const {+    uint64_t d64 = AsUint64();+    return (d64 & kExponentMask) == kExponentMask;+  }++  bool IsNan() const {+    uint64_t d64 = AsUint64();+    return ((d64 & kExponentMask) == kExponentMask) &&+        ((d64 & kSignificandMask) != 0);+  }++  bool IsInfinite() const {+    uint64_t d64 = AsUint64();+    return ((d64 & kExponentMask) == kExponentMask) &&+        ((d64 & kSignificandMask) == 0);+  }++  int Sign() const {+    uint64_t d64 = AsUint64();+    return (d64 & kSignMask) == 0? 1: -1;+  }++  // Precondition: the value encoded by this Double must be greater or equal+  // than +0.0.+  DiyFp UpperBoundary() const {+    ASSERT(Sign() > 0);+    return DiyFp(Significand() * 2 + 1, Exponent() - 1);+  }++  // Computes the two boundaries of this.+  // The bigger boundary (m_plus) is normalized. The lower boundary has the same+  // exponent as m_plus.+  // Precondition: the value encoded by this Double must be greater than 0.+  void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {+    ASSERT(value() > 0.0);+    DiyFp v = this->AsDiyFp();+    bool significand_is_zero = (v.f() == kHiddenBit);+    DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));+    DiyFp m_minus;+    if (significand_is_zero && v.e() != kDenormalExponent) {+      // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.+      // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but+      // at a distance of 1e8.+      // The only exception is for the smallest normal: the largest denormal is+      // at the same distance as its successor.+      // Note: denormals have the same exponent as the smallest normals.+      m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);+    } else {+      m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);+    }+    m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));+    m_minus.set_e(m_plus.e());+    *out_m_plus = m_plus;+    *out_m_minus = m_minus;+  }++  double value() const { return uint64_to_double(d64_); }++  // Returns the significand size for a given order of magnitude.+  // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.+  // This function returns the number of significant binary digits v will have+  // once it's encoded into a double. In almost all cases this is equal to+  // kSignificandSize. The only exceptions are denormals. They start with+  // leading zeroes and their effective significand-size is hence smaller.+  static int SignificandSizeForOrderOfMagnitude(int order) {+    if (order >= (kDenormalExponent + kSignificandSize)) {+      return kSignificandSize;+    }+    if (order <= kDenormalExponent) return 0;+    return order - kDenormalExponent;+  }++  static double Infinity() {+    return Double(kInfinity).value();+  }++  static double NaN() {+    return Double(kNaN).value();+  }++ private:+  static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;+  static const int kDenormalExponent = -kExponentBias + 1;+  static const int kMaxExponent = 0x7FF - kExponentBias;+  static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);+  static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);++  const uint64_t d64_;++  static uint64_t DiyFpToUint64(DiyFp diy_fp) {+    uint64_t significand = diy_fp.f();+    int exponent = diy_fp.e();+    while (significand > kHiddenBit + kSignificandMask) {+      significand >>= 1;+      exponent++;+    }+    if (exponent >= kMaxExponent) {+      return kInfinity;+    }+    if (exponent < kDenormalExponent) {+      return 0;+    }+    while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {+      significand <<= 1;+      exponent--;+    }+    uint64_t biased_exponent;+    if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {+      biased_exponent = 0;+    } else {+      biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);+    }+    return (significand & kSignificandMask) |+        (biased_exponent << kPhysicalSignificandSize);+  }+};++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_DOUBLE_H_
+ double-conversion/src/fast-dtoa.cc view
@@ -0,0 +1,735 @@+// 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 "fast-dtoa.h"++#include "cached-powers.h"+#include "diy-fp.h"+#include "double.h"++namespace double_conversion {++// The minimal and maximal target exponent define the range of w's binary+// exponent, where 'w' is the result of multiplying the input by a cached power+// of ten.+//+// A different range might be chosen on a different platform, to optimize digit+// generation, but a smaller range requires more powers of ten to be cached.+static const int kMinimalTargetExponent = -60;+static const int kMaximalTargetExponent = -32;+++// Adjusts the last digit of the generated number, and screens out generated+// solutions that may be inaccurate. A solution may be inaccurate if it is+// outside the safe interval, or if we cannot prove that it is closer to the+// input than a neighboring representation of the same length.+//+// Input: * buffer containing the digits of too_high / 10^kappa+//        * the buffer's length+//        * distance_too_high_w == (too_high - w).f() * unit+//        * unsafe_interval == (too_high - too_low).f() * unit+//        * rest = (too_high - buffer * 10^kappa).f() * unit+//        * ten_kappa = 10^kappa * unit+//        * unit = the common multiplier+// Output: returns true if the buffer is guaranteed to contain the closest+//    representable number to the input.+//  Modifies the generated digits in the buffer to approach (round towards) w.+static bool RoundWeed(Vector<char> buffer,+                      int length,+                      uint64_t distance_too_high_w,+                      uint64_t unsafe_interval,+                      uint64_t rest,+                      uint64_t ten_kappa,+                      uint64_t unit) {+  uint64_t small_distance = distance_too_high_w - unit;+  uint64_t big_distance = distance_too_high_w + unit;+  // Let w_low  = too_high - big_distance, and+  //     w_high = too_high - small_distance.+  // Note: w_low < w < w_high+  //+  // The real w (* unit) must lie somewhere inside the interval+  // ]w_low; w_high[ (often written as "(w_low; w_high)")++  // Basically the buffer currently contains a number in the unsafe interval+  // ]too_low; too_high[ with too_low < w < too_high+  //+  //  too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+  //                     ^v 1 unit            ^      ^                 ^      ^+  //  boundary_high ---------------------     .      .                 .      .+  //                     ^v 1 unit            .      .                 .      .+  //   - - - - - - - - - - - - - - - - - - -  +  - - + - - - - - -     .      .+  //                                          .      .         ^       .      .+  //                                          .  big_distance  .       .      .+  //                                          .      .         .       .    rest+  //                              small_distance     .         .       .      .+  //                                          v      .         .       .      .+  //  w_high - - - - - - - - - - - - - - - - - -     .         .       .      .+  //                     ^v 1 unit                   .         .       .      .+  //  w ----------------------------------------     .         .       .      .+  //                     ^v 1 unit                   v         .       .      .+  //  w_low  - - - - - - - - - - - - - - - - - - - - -         .       .      .+  //                                                           .       .      v+  //  buffer --------------------------------------------------+-------+--------+  //                                                           .       .+  //                                                  safe_interval    .+  //                                                           v       .+  //   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     .+  //                     ^v 1 unit                                     .+  //  boundary_low -------------------------                     unsafe_interval+  //                     ^v 1 unit                                     v+  //  too_low  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+  //+  //+  // Note that the value of buffer could lie anywhere inside the range too_low+  // to too_high.+  //+  // boundary_low, boundary_high and w are approximations of the real boundaries+  // and v (the input number). They are guaranteed to be precise up to one unit.+  // In fact the error is guaranteed to be strictly less than one unit.+  //+  // Anything that lies outside the unsafe interval is guaranteed not to round+  // to v when read again.+  // Anything that lies inside the safe interval is guaranteed to round to v+  // when read again.+  // If the number inside the buffer lies inside the unsafe interval but not+  // inside the safe interval then we simply do not know and bail out (returning+  // false).+  //+  // Similarly we have to take into account the imprecision of 'w' when finding+  // the closest representation of 'w'. If we have two potential+  // representations, and one is closer to both w_low and w_high, then we know+  // it is closer to the actual value v.+  //+  // By generating the digits of too_high we got the largest (closest to+  // too_high) buffer that is still in the unsafe interval. In the case where+  // w_high < buffer < too_high we try to decrement the buffer.+  // This way the buffer approaches (rounds towards) w.+  // There are 3 conditions that stop the decrementation process:+  //   1) the buffer is already below w_high+  //   2) decrementing the buffer would make it leave the unsafe interval+  //   3) decrementing the buffer would yield a number below w_high and farther+  //      away than the current number. In other words:+  //              (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high+  // Instead of using the buffer directly we use its distance to too_high.+  // Conceptually rest ~= too_high - buffer+  // We need to do the following tests in this order to avoid over- and+  // underflows.+  ASSERT(rest <= unsafe_interval);+  while (rest < small_distance &&  // Negated condition 1+         unsafe_interval - rest >= ten_kappa &&  // Negated condition 2+         (rest + ten_kappa < small_distance ||  // buffer{-1} > w_high+          small_distance - rest >= rest + ten_kappa - small_distance)) {+    buffer[length - 1]--;+    rest += ten_kappa;+  }++  // We have approached w+ as much as possible. We now test if approaching w-+  // would require changing the buffer. If yes, then we have two possible+  // representations close to w, but we cannot decide which one is closer.+  if (rest < big_distance &&+      unsafe_interval - rest >= ten_kappa &&+      (rest + ten_kappa < big_distance ||+       big_distance - rest > rest + ten_kappa - big_distance)) {+    return false;+  }++  // Weeding test.+  //   The safe interval is [too_low + 2 ulp; too_high - 2 ulp]+  //   Since too_low = too_high - unsafe_interval this is equivalent to+  //      [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]+  //   Conceptually we have: rest ~= too_high - buffer+  return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);+}+++// Rounds the buffer upwards if the result is closer to v by possibly adding+// 1 to the buffer. If the precision of the calculation is not sufficient to+// round correctly, return false.+// The rounding might shift the whole buffer in which case the kappa is+// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.+//+// If 2*rest > ten_kappa then the buffer needs to be round up.+// rest can have an error of +/- 1 unit. This function accounts for the+// imprecision and returns false, if the rounding direction cannot be+// unambiguously determined.+//+// Precondition: rest < ten_kappa.+static bool RoundWeedCounted(Vector<char> buffer,+                             int length,+                             uint64_t rest,+                             uint64_t ten_kappa,+                             uint64_t unit,+                             int* kappa) {+  ASSERT(rest < ten_kappa);+  // The following tests are done in a specific order to avoid overflows. They+  // will work correctly with any uint64 values of rest < ten_kappa and unit.+  //+  // If the unit is too big, then we don't know which way to round. For example+  // a unit of 50 means that the real number lies within rest +/- 50. If+  // 10^kappa == 40 then there is no way to tell which way to round.+  if (unit >= ten_kappa) return false;+  // Even if unit is just half the size of 10^kappa we are already completely+  // lost. (And after the previous test we know that the expression will not+  // over/underflow.)+  if (ten_kappa - unit <= unit) return false;+  // If 2 * (rest + unit) <= 10^kappa we can safely round down.+  if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {+    return true;+  }+  // If 2 * (rest - unit) >= 10^kappa, then we can safely round up.+  if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {+    // Increment the last digit recursively until we find a non '9' digit.+    buffer[length - 1]++;+    for (int i = length - 1; i > 0; --i) {+      if (buffer[i] != '0' + 10) break;+      buffer[i] = '0';+      buffer[i - 1]++;+    }+    // If the first digit is now '0'+ 10 we had a buffer with all '9's. With the+    // exception of the first digit all digits are now '0'. Simply switch the+    // first digit to '1' and adjust the kappa. Example: "99" becomes "10" and+    // the power (the kappa) is increased.+    if (buffer[0] == '0' + 10) {+      buffer[0] = '1';+      (*kappa) += 1;+    }+    return true;+  }+  return false;+}+++static const uint32_t kTen4 = 10000;+static const uint32_t kTen5 = 100000;+static const uint32_t kTen6 = 1000000;+static const uint32_t kTen7 = 10000000;+static const uint32_t kTen8 = 100000000;+static const uint32_t kTen9 = 1000000000;++// Returns the biggest power of ten that is less than or equal to the given+// number. We furthermore receive the maximum number of bits 'number' has.+// If number_bits == 0 then 0^-1 is returned+// The number of bits must be <= 32.+// Precondition: number < (1 << (number_bits + 1)).+static void BiggestPowerTen(uint32_t number,+                            int number_bits,+                            uint32_t* power,+                            int* exponent) {+  ASSERT(number < (1 << (number_bits + 1)));++  switch (number_bits) {+    case 32:+    case 31:+    case 30:+      if (kTen9 <= number) {+        *power = kTen9;+        *exponent = 9;+        break;+      }  // else fallthrough+    case 29:+    case 28:+    case 27:+      if (kTen8 <= number) {+        *power = kTen8;+        *exponent = 8;+        break;+      }  // else fallthrough+    case 26:+    case 25:+    case 24:+      if (kTen7 <= number) {+        *power = kTen7;+        *exponent = 7;+        break;+      }  // else fallthrough+    case 23:+    case 22:+    case 21:+    case 20:+      if (kTen6 <= number) {+        *power = kTen6;+        *exponent = 6;+        break;+      }  // else fallthrough+    case 19:+    case 18:+    case 17:+      if (kTen5 <= number) {+        *power = kTen5;+        *exponent = 5;+        break;+      }  // else fallthrough+    case 16:+    case 15:+    case 14:+      if (kTen4 <= number) {+        *power = kTen4;+        *exponent = 4;+        break;+      }  // else fallthrough+    case 13:+    case 12:+    case 11:+    case 10:+      if (1000 <= number) {+        *power = 1000;+        *exponent = 3;+        break;+      }  // else fallthrough+    case 9:+    case 8:+    case 7:+      if (100 <= number) {+        *power = 100;+        *exponent = 2;+        break;+      }  // else fallthrough+    case 6:+    case 5:+    case 4:+      if (10 <= number) {+        *power = 10;+        *exponent = 1;+        break;+      }  // else fallthrough+    case 3:+    case 2:+    case 1:+      if (1 <= number) {+        *power = 1;+        *exponent = 0;+        break;+      }  // else fallthrough+    case 0:+      *power = 0;+      *exponent = -1;+      break;+    default:+      // Following assignments are here to silence compiler warnings.+      *power = 0;+      *exponent = 0;+      UNREACHABLE();+  }+}+++// Generates the digits of input number w.+// w is a floating-point number (DiyFp), consisting of a significand and an+// exponent. Its exponent is bounded by kMinimalTargetExponent and+// kMaximalTargetExponent.+//       Hence -60 <= w.e() <= -32.+//+// Returns false if it fails, in which case the generated digits in the buffer+// should not be used.+// Preconditions:+//  * low, w and high are correct up to 1 ulp (unit in the last place). That+//    is, their error must be less than a unit of their last digits.+//  * low.e() == w.e() == high.e()+//  * low < w < high, and taking into account their error: low~ <= high~+//  * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent+// Postconditions: returns false if procedure fails.+//   otherwise:+//     * buffer is not null-terminated, but len contains the number of digits.+//     * buffer contains the shortest possible decimal digit-sequence+//       such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the+//       correct values of low and high (without their error).+//     * if more than one decimal representation gives the minimal number of+//       decimal digits then the one closest to W (where W is the correct value+//       of w) is chosen.+// Remark: this procedure takes into account the imprecision of its input+//   numbers. If the precision is not enough to guarantee all the postconditions+//   then false is returned. This usually happens rarely (~0.5%).+//+// Say, for the sake of example, that+//   w.e() == -48, and w.f() == 0x1234567890abcdef+// w's value can be computed by w.f() * 2^w.e()+// We can obtain w's integral digits by simply shifting w.f() by -w.e().+//  -> w's integral part is 0x1234+//  w's fractional part is therefore 0x567890abcdef.+// Printing w's integral part is easy (simply print 0x1234 in decimal).+// In order to print its fraction we repeatedly multiply the fraction by 10 and+// get each digit. Example the first digit after the point would be computed by+//   (0x567890abcdef * 10) >> 48. -> 3+// The whole thing becomes slightly more complicated because we want to stop+// once we have enough digits. That is, once the digits inside the buffer+// represent 'w' we can stop. Everything inside the interval low - high+// represents w. However we have to pay attention to low, high and w's+// imprecision.+static bool DigitGen(DiyFp low,+                     DiyFp w,+                     DiyFp high,+                     Vector<char> buffer,+                     int* length,+                     int* kappa) {+  ASSERT(low.e() == w.e() && w.e() == high.e());+  ASSERT(low.f() + 1 <= high.f() - 1);+  ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);+  // low, w and high are imprecise, but by less than one ulp (unit in the last+  // place).+  // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that+  // the new numbers are outside of the interval we want the final+  // representation to lie in.+  // Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield+  // numbers that are certain to lie in the interval. We will use this fact+  // later on.+  // We will now start by generating the digits within the uncertain+  // interval. Later we will weed out representations that lie outside the safe+  // interval and thus _might_ lie outside the correct interval.+  uint64_t unit = 1;+  DiyFp too_low = DiyFp(low.f() - unit, low.e());+  DiyFp too_high = DiyFp(high.f() + unit, high.e());+  // too_low and too_high are guaranteed to lie outside the interval we want the+  // generated number in.+  DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);+  // We now cut the input number into two parts: the integral digits and the+  // fractionals. We will not write any decimal separator though, but adapt+  // kappa instead.+  // Reminder: we are currently computing the digits (stored inside the buffer)+  // such that:   too_low < buffer * 10^kappa < too_high+  // We use too_high for the digit_generation and stop as soon as possible.+  // If we stop early we effectively round down.+  DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());+  // Division by one is a shift.+  uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());+  // Modulo by one is an and.+  uint64_t fractionals = too_high.f() & (one.f() - 1);+  uint32_t divisor;+  int divisor_exponent;+  BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),+                  &divisor, &divisor_exponent);+  *kappa = divisor_exponent + 1;+  *length = 0;+  // Loop invariant: buffer = too_high / 10^kappa  (integer division)+  // The invariant holds for the first iteration: kappa has been initialized+  // with the divisor exponent + 1. And the divisor is the biggest power of ten+  // that is smaller than integrals.+  while (*kappa > 0) {+    int digit = integrals / divisor;+    buffer[*length] = '0' + digit;+    (*length)++;+    integrals %= divisor;+    (*kappa)--;+    // Note that kappa now equals the exponent of the divisor and that the+    // invariant thus holds again.+    uint64_t rest =+        (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;+    // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())+    // Reminder: unsafe_interval.e() == one.e()+    if (rest < unsafe_interval.f()) {+      // Rounding down (by not emitting the remaining digits) yields a number+      // that lies within the unsafe interval.+      return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),+                       unsafe_interval.f(), rest,+                       static_cast<uint64_t>(divisor) << -one.e(), unit);+    }+    divisor /= 10;+  }++  // The integrals have been generated. We are at the point of the decimal+  // separator. In the following loop we simply multiply the remaining digits by+  // 10 and divide by one. We just need to pay attention to multiply associated+  // data (like the interval or 'unit'), too.+  // Note that the multiplication by 10 does not overflow, because w.e >= -60+  // and thus one.e >= -60.+  ASSERT(one.e() >= -60);+  ASSERT(fractionals < one.f());+  ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());+  while (true) {+    fractionals *= 10;+    unit *= 10;+    unsafe_interval.set_f(unsafe_interval.f() * 10);+    // Integer division by one.+    int digit = static_cast<int>(fractionals >> -one.e());+    buffer[*length] = '0' + digit;+    (*length)++;+    fractionals &= one.f() - 1;  // Modulo by one.+    (*kappa)--;+    if (fractionals < unsafe_interval.f()) {+      return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,+                       unsafe_interval.f(), fractionals, one.f(), unit);+    }+  }+}++++// Generates (at most) requested_digits digits of input number w.+// w is a floating-point number (DiyFp), consisting of a significand and an+// exponent. Its exponent is bounded by kMinimalTargetExponent and+// kMaximalTargetExponent.+//       Hence -60 <= w.e() <= -32.+//+// Returns false if it fails, in which case the generated digits in the buffer+// should not be used.+// Preconditions:+//  * w is correct up to 1 ulp (unit in the last place). That+//    is, its error must be strictly less than a unit of its last digit.+//  * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent+//+// Postconditions: returns false if procedure fails.+//   otherwise:+//     * buffer is not null-terminated, but length contains the number of+//       digits.+//     * the representation in buffer is the most precise representation of+//       requested_digits digits.+//     * buffer contains at most requested_digits digits of w. If there are less+//       than requested_digits digits then some trailing '0's have been removed.+//     * kappa is such that+//            w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.+//+// Remark: This procedure takes into account the imprecision of its input+//   numbers. If the precision is not enough to guarantee all the postconditions+//   then false is returned. This usually happens rarely, but the failure-rate+//   increases with higher requested_digits.+static bool DigitGenCounted(DiyFp w,+                            int requested_digits,+                            Vector<char> buffer,+                            int* length,+                            int* kappa) {+  ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);+  ASSERT(kMinimalTargetExponent >= -60);+  ASSERT(kMaximalTargetExponent <= -32);+  // w is assumed to have an error less than 1 unit. Whenever w is scaled we+  // also scale its error.+  uint64_t w_error = 1;+  // We cut the input number into two parts: the integral digits and the+  // fractional digits. We don't emit any decimal separator, but adapt kappa+  // instead. Example: instead of writing "1.2" we put "12" into the buffer and+  // increase kappa by 1.+  DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());+  // Division by one is a shift.+  uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e());+  // Modulo by one is an and.+  uint64_t fractionals = w.f() & (one.f() - 1);+  uint32_t divisor;+  int divisor_exponent;+  BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),+                  &divisor, &divisor_exponent);+  *kappa = divisor_exponent + 1;+  *length = 0;++  // Loop invariant: buffer = w / 10^kappa  (integer division)+  // The invariant holds for the first iteration: kappa has been initialized+  // with the divisor exponent + 1. And the divisor is the biggest power of ten+  // that is smaller than 'integrals'.+  while (*kappa > 0) {+    int digit = integrals / divisor;+    buffer[*length] = '0' + digit;+    (*length)++;+    requested_digits--;+    integrals %= divisor;+    (*kappa)--;+    // Note that kappa now equals the exponent of the divisor and that the+    // invariant thus holds again.+    if (requested_digits == 0) break;+    divisor /= 10;+  }++  if (requested_digits == 0) {+    uint64_t rest =+        (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;+    return RoundWeedCounted(buffer, *length, rest,+                            static_cast<uint64_t>(divisor) << -one.e(), w_error,+                            kappa);+  }++  // The integrals have been generated. We are at the point of the decimal+  // separator. In the following loop we simply multiply the remaining digits by+  // 10 and divide by one. We just need to pay attention to multiply associated+  // data (the 'unit'), too.+  // Note that the multiplication by 10 does not overflow, because w.e >= -60+  // and thus one.e >= -60.+  ASSERT(one.e() >= -60);+  ASSERT(fractionals < one.f());+  ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());+  while (requested_digits > 0 && fractionals > w_error) {+    fractionals *= 10;+    w_error *= 10;+    // Integer division by one.+    int digit = static_cast<int>(fractionals >> -one.e());+    buffer[*length] = '0' + digit;+    (*length)++;+    requested_digits--;+    fractionals &= one.f() - 1;  // Modulo by one.+    (*kappa)--;+  }+  if (requested_digits != 0) return false;+  return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error,+                          kappa);+}+++// Provides a decimal representation of v.+// Returns true if it succeeds, otherwise the result cannot be trusted.+// There will be *length digits inside the buffer (not null-terminated).+// If the function returns true then+//        v == (double) (buffer * 10^decimal_exponent).+// The digits in the buffer are the shortest representation possible: no+// 0.09999999999999999 instead of 0.1. The shorter representation will even be+// chosen even if the longer one would be closer to v.+// The last digit will be closest to the actual v. That is, even if several+// digits might correctly yield 'v' when read again, the closest will be+// computed.+static bool Grisu3(double v,+                   Vector<char> buffer,+                   int* length,+                   int* decimal_exponent) {+  DiyFp w = Double(v).AsNormalizedDiyFp();+  // boundary_minus and boundary_plus are the boundaries between v and its+  // closest floating-point neighbors. Any number strictly between+  // boundary_minus and boundary_plus will round to v when convert to a double.+  // Grisu3 will never output representations that lie exactly on a boundary.+  DiyFp boundary_minus, boundary_plus;+  Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);+  ASSERT(boundary_plus.e() == w.e());+  DiyFp ten_mk;  // Cached power of ten: 10^-k+  int mk;        // -k+  int ten_mk_minimal_binary_exponent =+     kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);+  int ten_mk_maximal_binary_exponent =+     kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);+  PowersOfTenCache::GetCachedPowerForBinaryExponentRange(+      ten_mk_minimal_binary_exponent,+      ten_mk_maximal_binary_exponent,+      &ten_mk, &mk);+  ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() ++          DiyFp::kSignificandSize) &&+         (kMaximalTargetExponent >= w.e() + ten_mk.e() ++          DiyFp::kSignificandSize));+  // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a+  // 64 bit significand and ten_mk is thus only precise up to 64 bits.++  // The DiyFp::Times procedure rounds its result, and ten_mk is approximated+  // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now+  // off by a small amount.+  // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.+  // In other words: let f = scaled_w.f() and e = scaled_w.e(), then+  //           (f-1) * 2^e < w*10^k < (f+1) * 2^e+  DiyFp scaled_w = DiyFp::Times(w, ten_mk);+  ASSERT(scaled_w.e() ==+         boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);+  // In theory it would be possible to avoid some recomputations by computing+  // the difference between w and boundary_minus/plus (a power of 2) and to+  // compute scaled_boundary_minus/plus by subtracting/adding from+  // scaled_w. However the code becomes much less readable and the speed+  // enhancements are not terriffic.+  DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);+  DiyFp scaled_boundary_plus  = DiyFp::Times(boundary_plus,  ten_mk);++  // DigitGen will generate the digits of scaled_w. Therefore we have+  // v == (double) (scaled_w * 10^-mk).+  // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an+  // integer than it will be updated. For instance if scaled_w == 1.23 then+  // the buffer will be filled with "123" und the decimal_exponent will be+  // decreased by 2.+  int kappa;+  bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,+                         buffer, length, &kappa);+  *decimal_exponent = -mk + kappa;+  return result;+}+++// The "counted" version of grisu3 (see above) only generates requested_digits+// number of digits. This version does not generate the shortest representation,+// and with enough requested digits 0.1 will at some point print as 0.9999999...+// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and+// therefore the rounding strategy for halfway cases is irrelevant.+static bool Grisu3Counted(double v,+                          int requested_digits,+                          Vector<char> buffer,+                          int* length,+                          int* decimal_exponent) {+  DiyFp w = Double(v).AsNormalizedDiyFp();+  DiyFp ten_mk;  // Cached power of ten: 10^-k+  int mk;        // -k+  int ten_mk_minimal_binary_exponent =+     kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);+  int ten_mk_maximal_binary_exponent =+     kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);+  PowersOfTenCache::GetCachedPowerForBinaryExponentRange(+      ten_mk_minimal_binary_exponent,+      ten_mk_maximal_binary_exponent,+      &ten_mk, &mk);+  ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() ++          DiyFp::kSignificandSize) &&+         (kMaximalTargetExponent >= w.e() + ten_mk.e() ++          DiyFp::kSignificandSize));+  // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a+  // 64 bit significand and ten_mk is thus only precise up to 64 bits.++  // The DiyFp::Times procedure rounds its result, and ten_mk is approximated+  // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now+  // off by a small amount.+  // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.+  // In other words: let f = scaled_w.f() and e = scaled_w.e(), then+  //           (f-1) * 2^e < w*10^k < (f+1) * 2^e+  DiyFp scaled_w = DiyFp::Times(w, ten_mk);++  // We now have (double) (scaled_w * 10^-mk).+  // DigitGen will generate the first requested_digits digits of scaled_w and+  // return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It+  // will not always be exactly the same since DigitGenCounted only produces a+  // limited number of digits.)+  int kappa;+  bool result = DigitGenCounted(scaled_w, requested_digits,+                                buffer, length, &kappa);+  *decimal_exponent = -mk + kappa;+  return result;+}+++bool FastDtoa(double v,+              FastDtoaMode mode,+              int requested_digits,+              Vector<char> buffer,+              int* length,+              int* decimal_point) {+  ASSERT(v > 0);+  ASSERT(!Double(v).IsSpecial());++  bool result = false;+  int decimal_exponent = 0;+  switch (mode) {+    case FAST_DTOA_SHORTEST:+      result = Grisu3(v, buffer, length, &decimal_exponent);+      break;+    case FAST_DTOA_PRECISION:+      result = Grisu3Counted(v, requested_digits,+                             buffer, length, &decimal_exponent);+      break;+    default:+      UNREACHABLE();+  }+  if (result) {+    *decimal_point = *length + decimal_exponent;+    buffer[*length] = '\0';+  }+  return result;+}++}  // namespace double_conversion
+ double-conversion/src/fast-dtoa.h view
@@ -0,0 +1,84 @@+// 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.++#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_+#define DOUBLE_CONVERSION_FAST_DTOA_H_++#include "utils.h"++namespace double_conversion {++enum FastDtoaMode {+  // Computes the shortest representation of the given input. The returned+  // result will be the most accurate number of this length. Longer+  // representations might be more accurate.+  FAST_DTOA_SHORTEST,+  // Computes a representation where the precision (number of digits) is+  // given as input. The precision is independent of the decimal point.+  FAST_DTOA_PRECISION+};++// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not+// include the terminating '\0' character.+static const int kFastDtoaMaximalLength = 17;++// Provides a decimal representation of v.+// The result should be interpreted as buffer * 10^(point - length).+//+// Precondition:+//   * v must be a strictly positive finite double.+//+// Returns true if it succeeds, otherwise the result can not be trusted.+// There will be *length digits inside the buffer followed by a null terminator.+// If the function returns true and mode equals+//   - FAST_DTOA_SHORTEST, then+//     the parameter requested_digits is ignored.+//     The result satisfies+//         v == (double) (buffer * 10^(point - length)).+//     The digits in the buffer are the shortest representation possible. E.g.+//     if 0.099999999999 and 0.1 represent the same double then "1" is returned+//     with point = 0.+//     The last digit will be closest to the actual v. That is, even if several+//     digits might correctly yield 'v' when read again, the buffer will contain+//     the one closest to v.+//   - FAST_DTOA_PRECISION, then+//     the buffer contains requested_digits digits.+//     the difference v - (buffer * 10^(point-length)) is closest to zero for+//     all possible representations of requested_digits digits.+//     If there are two values that are equally close, then FastDtoa returns+//     false.+// For both modes the buffer must be large enough to hold the result.+bool FastDtoa(double d,+              FastDtoaMode mode,+              int requested_digits,+              Vector<char> buffer,+              int* length,+              int* decimal_point);++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_FAST_DTOA_H_
+ double-conversion/src/fixed-dtoa.cc view
@@ -0,0 +1,402 @@+// 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 "fixed-dtoa.h"+#include "double.h"++namespace double_conversion {++// Represents a 128bit type. This class should be replaced by a native type on+// platforms that support 128bit integers.+class UInt128 {+ public:+  UInt128() : high_bits_(0), low_bits_(0) { }+  UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }++  void Multiply(uint32_t multiplicand) {+    uint64_t accumulator;++    accumulator = (low_bits_ & kMask32) * multiplicand;+    uint32_t part = static_cast<uint32_t>(accumulator & kMask32);+    accumulator >>= 32;+    accumulator = accumulator + (low_bits_ >> 32) * multiplicand;+    low_bits_ = (accumulator << 32) + part;+    accumulator >>= 32;+    accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;+    part = static_cast<uint32_t>(accumulator & kMask32);+    accumulator >>= 32;+    accumulator = accumulator + (high_bits_ >> 32) * multiplicand;+    high_bits_ = (accumulator << 32) + part;+    ASSERT((accumulator >> 32) == 0);+  }++  void Shift(int shift_amount) {+    ASSERT(-64 <= shift_amount && shift_amount <= 64);+    if (shift_amount == 0) {+      return;+    } else if (shift_amount == -64) {+      high_bits_ = low_bits_;+      low_bits_ = 0;+    } else if (shift_amount == 64) {+      low_bits_ = high_bits_;+      high_bits_ = 0;+    } else if (shift_amount <= 0) {+      high_bits_ <<= -shift_amount;+      high_bits_ += low_bits_ >> (64 + shift_amount);+      low_bits_ <<= -shift_amount;+    } else {+      low_bits_ >>= shift_amount;+      low_bits_ += high_bits_ << (64 - shift_amount);+      high_bits_ >>= shift_amount;+    }+  }++  // Modifies *this to *this MOD (2^power).+  // Returns *this DIV (2^power).+  int DivModPowerOf2(int power) {+    if (power >= 64) {+      int result = static_cast<int>(high_bits_ >> (power - 64));+      high_bits_ -= static_cast<uint64_t>(result) << (power - 64);+      return result;+    } else {+      uint64_t part_low = low_bits_ >> power;+      uint64_t part_high = high_bits_ << (64 - power);+      int result = static_cast<int>(part_low + part_high);+      high_bits_ = 0;+      low_bits_ -= part_low << power;+      return result;+    }+  }++  bool IsZero() const {+    return high_bits_ == 0 && low_bits_ == 0;+  }++  int BitAt(int position) {+    if (position >= 64) {+      return static_cast<int>(high_bits_ >> (position - 64)) & 1;+    } else {+      return static_cast<int>(low_bits_ >> position) & 1;+    }+  }++ private:+  static const uint64_t kMask32 = 0xFFFFFFFF;+  // Value == (high_bits_ << 64) + low_bits_+  uint64_t high_bits_;+  uint64_t low_bits_;+};+++static const int kDoubleSignificandSize = 53;  // Includes the hidden bit.+++static void FillDigits32FixedLength(uint32_t number, int requested_length,+                                    Vector<char> buffer, int* length) {+  for (int i = requested_length - 1; i >= 0; --i) {+    buffer[(*length) + i] = '0' + number % 10;+    number /= 10;+  }+  *length += requested_length;+}+++static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {+  int number_length = 0;+  // We fill the digits in reverse order and exchange them afterwards.+  while (number != 0) {+    int digit = number % 10;+    number /= 10;+    buffer[(*length) + number_length] = '0' + digit;+    number_length++;+  }+  // Exchange the digits.+  int i = *length;+  int j = *length + number_length - 1;+  while (i < j) {+    char tmp = buffer[i];+    buffer[i] = buffer[j];+    buffer[j] = tmp;+    i++;+    j--;+  }+  *length += number_length;+}+++static void FillDigits64FixedLength(uint64_t number, int requested_length,+                                    Vector<char> buffer, int* length) {+  const uint32_t kTen7 = 10000000;+  // For efficiency cut the number into 3 uint32_t parts, and print those.+  uint32_t part2 = static_cast<uint32_t>(number % kTen7);+  number /= kTen7;+  uint32_t part1 = static_cast<uint32_t>(number % kTen7);+  uint32_t part0 = static_cast<uint32_t>(number / kTen7);++  FillDigits32FixedLength(part0, 3, buffer, length);+  FillDigits32FixedLength(part1, 7, buffer, length);+  FillDigits32FixedLength(part2, 7, buffer, length);+}+++static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {+  const uint32_t kTen7 = 10000000;+  // For efficiency cut the number into 3 uint32_t parts, and print those.+  uint32_t part2 = static_cast<uint32_t>(number % kTen7);+  number /= kTen7;+  uint32_t part1 = static_cast<uint32_t>(number % kTen7);+  uint32_t part0 = static_cast<uint32_t>(number / kTen7);++  if (part0 != 0) {+    FillDigits32(part0, buffer, length);+    FillDigits32FixedLength(part1, 7, buffer, length);+    FillDigits32FixedLength(part2, 7, buffer, length);+  } else if (part1 != 0) {+    FillDigits32(part1, buffer, length);+    FillDigits32FixedLength(part2, 7, buffer, length);+  } else {+    FillDigits32(part2, buffer, length);+  }+}+++static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {+  // An empty buffer represents 0.+  if (*length == 0) {+    buffer[0] = '1';+    *decimal_point = 1;+    *length = 1;+    return;+  }+  // Round the last digit until we either have a digit that was not '9' or until+  // we reached the first digit.+  buffer[(*length) - 1]++;+  for (int i = (*length) - 1; i > 0; --i) {+    if (buffer[i] != '0' + 10) {+      return;+    }+    buffer[i] = '0';+    buffer[i - 1]++;+  }+  // If the first digit is now '0' + 10, we would need to set it to '0' and add+  // a '1' in front. However we reach the first digit only if all following+  // digits had been '9' before rounding up. Now all trailing digits are '0' and+  // we simply switch the first digit to '1' and update the decimal-point+  // (indicating that the point is now one digit to the right).+  if (buffer[0] == '0' + 10) {+    buffer[0] = '1';+    (*decimal_point)++;+  }+}+++// The given fractionals number represents a fixed-point number with binary+// point at bit (-exponent).+// Preconditions:+//   -128 <= exponent <= 0.+//   0 <= fractionals * 2^exponent < 1+//   The buffer holds the result.+// The function will round its result. During the rounding-process digits not+// generated by this function might be updated, and the decimal-point variable+// might be updated. If this function generates the digits 99 and the buffer+// already contained "199" (thus yielding a buffer of "19999") then a+// rounding-up will change the contents of the buffer to "20000".+static void FillFractionals(uint64_t fractionals, int exponent,+                            int fractional_count, Vector<char> buffer,+                            int* length, int* decimal_point) {+  ASSERT(-128 <= exponent && exponent <= 0);+  // 'fractionals' is a fixed-point number, with binary point at bit+  // (-exponent). Inside the function the non-converted remainder of fractionals+  // is a fixed-point number, with binary point at bit 'point'.+  if (-exponent <= 64) {+    // One 64 bit number is sufficient.+    ASSERT(fractionals >> 56 == 0);+    int point = -exponent;+    for (int i = 0; i < fractional_count; ++i) {+      if (fractionals == 0) break;+      // Instead of multiplying by 10 we multiply by 5 and adjust the point+      // location. This way the fractionals variable will not overflow.+      // Invariant at the beginning of the loop: fractionals < 2^point.+      // Initially we have: point <= 64 and fractionals < 2^56+      // After each iteration the point is decremented by one.+      // Note that 5^3 = 125 < 128 = 2^7.+      // Therefore three iterations of this loop will not overflow fractionals+      // (even without the subtraction at the end of the loop body). At this+      // time point will satisfy point <= 61 and therefore fractionals < 2^point+      // and any further multiplication of fractionals by 5 will not overflow.+      fractionals *= 5;+      point--;+      int digit = static_cast<int>(fractionals >> point);+      buffer[*length] = '0' + digit;+      (*length)++;+      fractionals -= static_cast<uint64_t>(digit) << point;+    }+    // If the first bit after the point is set we have to round up.+    if (((fractionals >> (point - 1)) & 1) == 1) {+      RoundUp(buffer, length, decimal_point);+    }+  } else {  // We need 128 bits.+    ASSERT(64 < -exponent && -exponent <= 128);+    UInt128 fractionals128 = UInt128(fractionals, 0);+    fractionals128.Shift(-exponent - 64);+    int point = 128;+    for (int i = 0; i < fractional_count; ++i) {+      if (fractionals128.IsZero()) break;+      // As before: instead of multiplying by 10 we multiply by 5 and adjust the+      // point location.+      // This multiplication will not overflow for the same reasons as before.+      fractionals128.Multiply(5);+      point--;+      int digit = fractionals128.DivModPowerOf2(point);+      buffer[*length] = '0' + digit;+      (*length)++;+    }+    if (fractionals128.BitAt(point - 1) == 1) {+      RoundUp(buffer, length, decimal_point);+    }+  }+}+++// Removes leading and trailing zeros.+// If leading zeros are removed then the decimal point position is adjusted.+static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {+  while (*length > 0 && buffer[(*length) - 1] == '0') {+    (*length)--;+  }+  int first_non_zero = 0;+  while (first_non_zero < *length && buffer[first_non_zero] == '0') {+    first_non_zero++;+  }+  if (first_non_zero != 0) {+    for (int i = first_non_zero; i < *length; ++i) {+      buffer[i - first_non_zero] = buffer[i];+    }+    *length -= first_non_zero;+    *decimal_point -= first_non_zero;+  }+}+++bool FastFixedDtoa(double v,+                   int fractional_count,+                   Vector<char> buffer,+                   int* length,+                   int* decimal_point) {+  const uint32_t kMaxUInt32 = 0xFFFFFFFF;+  uint64_t significand = Double(v).Significand();+  int exponent = Double(v).Exponent();+  // v = significand * 2^exponent (with significand a 53bit integer).+  // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we+  // don't know how to compute the representation. 2^73 ~= 9.5*10^21.+  // If necessary this limit could probably be increased, but we don't need+  // more.+  if (exponent > 20) return false;+  if (fractional_count > 20) return false;+  *length = 0;+  // At most kDoubleSignificandSize bits of the significand are non-zero.+  // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero+  // bits:  0..11*..0xxx..53*..xx+  if (exponent + kDoubleSignificandSize > 64) {+    // The exponent must be > 11.+    //+    // We know that v = significand * 2^exponent.+    // And the exponent > 11.+    // We simplify the task by dividing v by 10^17.+    // The quotient delivers the first digits, and the remainder fits into a 64+    // bit number.+    // Dividing by 10^17 is equivalent to dividing by 5^17*2^17.+    const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5);  // 5^17+    uint64_t divisor = kFive17;+    int divisor_power = 17;+    uint64_t dividend = significand;+    uint32_t quotient;+    uint64_t remainder;+    // Let v = f * 2^e with f == significand and e == exponent.+    // Then need q (quotient) and r (remainder) as follows:+    //   v            = q * 10^17       + r+    //   f * 2^e      = q * 10^17       + r+    //   f * 2^e      = q * 5^17 * 2^17 + r+    // If e > 17 then+    //   f * 2^(e-17) = q * 5^17        + r/2^17+    // else+    //   f  = q * 5^17 * 2^(17-e) + r/2^e+    if (exponent > divisor_power) {+      // We only allow exponents of up to 20 and therefore (17 - e) <= 3+      dividend <<= exponent - divisor_power;+      quotient = static_cast<uint32_t>(dividend / divisor);+      remainder = (dividend % divisor) << divisor_power;+    } else {+      divisor <<= divisor_power - exponent;+      quotient = static_cast<uint32_t>(dividend / divisor);+      remainder = (dividend % divisor) << exponent;+    }+    FillDigits32(quotient, buffer, length);+    FillDigits64FixedLength(remainder, divisor_power, buffer, length);+    *decimal_point = *length;+  } else if (exponent >= 0) {+    // 0 <= exponent <= 11+    significand <<= exponent;+    FillDigits64(significand, buffer, length);+    *decimal_point = *length;+  } else if (exponent > -kDoubleSignificandSize) {+    // We have to cut the number.+    uint64_t integrals = significand >> -exponent;+    uint64_t fractionals = significand - (integrals << -exponent);+    if (integrals > kMaxUInt32) {+      FillDigits64(integrals, buffer, length);+    } else {+      FillDigits32(static_cast<uint32_t>(integrals), buffer, length);+    }+    *decimal_point = *length;+    FillFractionals(fractionals, exponent, fractional_count,+                    buffer, length, decimal_point);+  } else if (exponent < -128) {+    // This configuration (with at most 20 digits) means that all digits must be+    // 0.+    ASSERT(fractional_count <= 20);+    buffer[0] = '\0';+    *length = 0;+    *decimal_point = -fractional_count;+  } else {+    *decimal_point = 0;+    FillFractionals(significand, exponent, fractional_count,+                    buffer, length, decimal_point);+  }+  TrimZeros(buffer, length, decimal_point);+  buffer[*length] = '\0';+  if ((*length) == 0) {+    // The string is empty and the decimal_point thus has no importance. Mimick+    // Gay's dtoa and and set it to -fractional_count.+    *decimal_point = -fractional_count;+  }+  return true;+}++}  // namespace double_conversion
+ double-conversion/src/fixed-dtoa.h view
@@ -0,0 +1,56 @@+// 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.++#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_+#define DOUBLE_CONVERSION_FIXED_DTOA_H_++#include "utils.h"++namespace double_conversion {++// Produces digits necessary to print a given number with+// 'fractional_count' digits after the decimal point.+// The buffer must be big enough to hold the result plus one terminating null+// character.+//+// The produced digits might be too short in which case the caller has to fill+// the gaps with '0's.+// Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and+// decimal_point = -2.+// Halfway cases are rounded towards +/-Infinity (away from 0). The call+// FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0.+// The returned buffer may contain digits that would be truncated from the+// shortest representation of the input.+//+// This method only works for some parameters. If it can't handle the input it+// returns false. The output is null-terminated when the function succeeds.+bool FastFixedDtoa(double v, int fractional_count,+                   Vector<char> buffer, int* length, int* decimal_point);++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_FIXED_DTOA_H_
+ double-conversion/src/strtod.cc view
@@ -0,0 +1,441 @@+// 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 <stdarg.h>+#include <limits.h>++#include "strtod.h"+#include "bignum.h"+#include "cached-powers.h"+#include "double.h"++namespace double_conversion {++// 2^53 = 9007199254740992.+// Any integer with at most 15 decimal digits will hence fit into a double+// (which has a 53bit significand) without loss of precision.+static const int kMaxExactDoubleIntegerDecimalDigits = 15;+// 2^64 = 18446744073709551616 > 10^19+static const int kMaxUint64DecimalDigits = 19;++// Max double: 1.7976931348623157 x 10^308+// Min non-zero double: 4.9406564584124654 x 10^-324+// Any x >= 10^309 is interpreted as +infinity.+// Any x <= 10^-324 is interpreted as 0.+// Note that 2.5e-324 (despite being smaller than the min double) will be read+// as non-zero (equal to the min non-zero double).+static const int kMaxDecimalPower = 309;+static const int kMinDecimalPower = -324;++// 2^64 = 18446744073709551616+static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);+++static const double exact_powers_of_ten[] = {+  1.0,  // 10^0+  10.0,+  100.0,+  1000.0,+  10000.0,+  100000.0,+  1000000.0,+  10000000.0,+  100000000.0,+  1000000000.0,+  10000000000.0,  // 10^10+  100000000000.0,+  1000000000000.0,+  10000000000000.0,+  100000000000000.0,+  1000000000000000.0,+  10000000000000000.0,+  100000000000000000.0,+  1000000000000000000.0,+  10000000000000000000.0,+  100000000000000000000.0,  // 10^20+  1000000000000000000000.0,+  // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22+  10000000000000000000000.0+};+static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);++// Maximum number of significant digits in the decimal representation.+// In fact the value is 772 (see conversions.cc), but to give us some margin+// we round up to 780.+static const int kMaxSignificantDecimalDigits = 780;++static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {+  for (int i = 0; i < buffer.length(); i++) {+    if (buffer[i] != '0') {+      return buffer.SubVector(i, buffer.length());+    }+  }+  return Vector<const char>(buffer.start(), 0);+}+++static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {+  for (int i = buffer.length() - 1; i >= 0; --i) {+    if (buffer[i] != '0') {+      return buffer.SubVector(0, i + 1);+    }+  }+  return Vector<const char>(buffer.start(), 0);+}+++static void TrimToMaxSignificantDigits(Vector<const char> buffer,+                                       int exponent,+                                       char* significant_buffer,+                                       int* significant_exponent) {+  for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {+    significant_buffer[i] = buffer[i];+  }+  // The input buffer has been trimmed. Therefore the last digit must be+  // different from '0'.+  ASSERT(buffer[buffer.length() - 1] != '0');+  // Set the last digit to be non-zero. This is sufficient to guarantee+  // correct rounding.+  significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';+  *significant_exponent =+      exponent + (buffer.length() - kMaxSignificantDecimalDigits);+}++// Reads digits from the buffer and converts them to a uint64.+// Reads in as many digits as fit into a uint64.+// When the string starts with "1844674407370955161" no further digit is read.+// Since 2^64 = 18446744073709551616 it would still be possible read another+// digit if it was less or equal than 6, but this would complicate the code.+static uint64_t ReadUint64(Vector<const char> buffer,+                           int* number_of_read_digits) {+  uint64_t result = 0;+  int i = 0;+  while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {+    int digit = buffer[i++] - '0';+    ASSERT(0 <= digit && digit <= 9);+    result = 10 * result + digit;+  }+  *number_of_read_digits = i;+  return result;+}+++// Reads a DiyFp from the buffer.+// The returned DiyFp is not necessarily normalized.+// If remaining_decimals is zero then the returned DiyFp is accurate.+// Otherwise it has been rounded and has error of at most 1/2 ulp.+static void ReadDiyFp(Vector<const char> buffer,+                      DiyFp* result,+                      int* remaining_decimals) {+  int read_digits;+  uint64_t significand = ReadUint64(buffer, &read_digits);+  if (buffer.length() == read_digits) {+    *result = DiyFp(significand, 0);+    *remaining_decimals = 0;+  } else {+    // Round the significand.+    if (buffer[read_digits] >= '5') {+      significand++;+    }+    // Compute the binary exponent.+    int exponent = 0;+    *result = DiyFp(significand, exponent);+    *remaining_decimals = buffer.length() - read_digits;+  }+}+++static bool DoubleStrtod(Vector<const char> trimmed,+                         int exponent,+                         double* result) {+#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)+  // On x86 the floating-point stack can be 64 or 80 bits wide. If it is+  // 80 bits wide (as is the case on Linux) then double-rounding occurs and the+  // result is not accurate.+  // We know that Windows32 uses 64 bits and is therefore accurate.+  // Note that the ARM simulator is compiled for 32bits. It therefore exhibits+  // the same problem.+  return false;+#endif+  if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {+    int read_digits;+    // The trimmed input fits into a double.+    // If the 10^exponent (resp. 10^-exponent) fits into a double too then we+    // can compute the result-double simply by multiplying (resp. dividing) the+    // two numbers.+    // This is possible because IEEE guarantees that floating-point operations+    // return the best possible approximation.+    if (exponent < 0 && -exponent < kExactPowersOfTenSize) {+      // 10^-exponent fits into a double.+      *result = static_cast<double>(ReadUint64(trimmed, &read_digits));+      ASSERT(read_digits == trimmed.length());+      *result /= exact_powers_of_ten[-exponent];+      return true;+    }+    if (0 <= exponent && exponent < kExactPowersOfTenSize) {+      // 10^exponent fits into a double.+      *result = static_cast<double>(ReadUint64(trimmed, &read_digits));+      ASSERT(read_digits == trimmed.length());+      *result *= exact_powers_of_ten[exponent];+      return true;+    }+    int remaining_digits =+        kMaxExactDoubleIntegerDecimalDigits - trimmed.length();+    if ((0 <= exponent) &&+        (exponent - remaining_digits < kExactPowersOfTenSize)) {+      // The trimmed string was short and we can multiply it with+      // 10^remaining_digits. As a result the remaining exponent now fits+      // into a double too.+      *result = static_cast<double>(ReadUint64(trimmed, &read_digits));+      ASSERT(read_digits == trimmed.length());+      *result *= exact_powers_of_ten[remaining_digits];+      *result *= exact_powers_of_ten[exponent - remaining_digits];+      return true;+    }+  }+  return false;+}+++// Returns 10^exponent as an exact DiyFp.+// The given exponent must be in the range [1; kDecimalExponentDistance[.+static DiyFp AdjustmentPowerOfTen(int exponent) {+  ASSERT(0 < exponent);+  ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);+  // Simply hardcode the remaining powers for the given decimal exponent+  // distance.+  ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);+  switch (exponent) {+    case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);+    case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);+    case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);+    case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);+    case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);+    case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);+    case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);+    default:+      UNREACHABLE();+      return DiyFp(0, 0);+  }+}+++// If the function returns true then the result is the correct double.+// Otherwise it is either the correct double or the double that is just below+// the correct double.+static bool DiyFpStrtod(Vector<const char> buffer,+                        int exponent,+                        double* result) {+  DiyFp input;+  int remaining_decimals;+  ReadDiyFp(buffer, &input, &remaining_decimals);+  // Since we may have dropped some digits the input is not accurate.+  // If remaining_decimals is different than 0 than the error is at most+  // .5 ulp (unit in the last place).+  // We don't want to deal with fractions and therefore keep a common+  // denominator.+  const int kDenominatorLog = 3;+  const int kDenominator = 1 << kDenominatorLog;+  // Move the remaining decimals into the exponent.+  exponent += remaining_decimals;+  int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);++  int old_e = input.e();+  input.Normalize();+  error <<= old_e - input.e();++  ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);+  if (exponent < PowersOfTenCache::kMinDecimalExponent) {+    *result = 0.0;+    return true;+  }+  DiyFp cached_power;+  int cached_decimal_exponent;+  PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,+                                                     &cached_power,+                                                     &cached_decimal_exponent);++  if (cached_decimal_exponent != exponent) {+    int adjustment_exponent = exponent - cached_decimal_exponent;+    DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);+    input.Multiply(adjustment_power);+    if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {+      // The product of input with the adjustment power fits into a 64 bit+      // integer.+      ASSERT(DiyFp::kSignificandSize == 64);+    } else {+      // The adjustment power is exact. There is hence only an error of 0.5.+      error += kDenominator / 2;+    }+  }++  input.Multiply(cached_power);+  // The error introduced by a multiplication of a*b equals+  //   error_a + error_b + error_a*error_b/2^64 + 0.5+  // Substituting a with 'input' and b with 'cached_power' we have+  //   error_b = 0.5  (all cached powers have an error of less than 0.5 ulp),+  //   error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64+  int error_b = kDenominator / 2;+  int error_ab = (error == 0 ? 0 : 1);  // We round up to 1.+  int fixed_error = kDenominator / 2;+  error += error_b + error_ab + fixed_error;++  old_e = input.e();+  input.Normalize();+  error <<= old_e - input.e();++  // See if the double's significand changes if we add/subtract the error.+  int order_of_magnitude = DiyFp::kSignificandSize + input.e();+  int effective_significand_size =+      Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);+  int precision_digits_count =+      DiyFp::kSignificandSize - effective_significand_size;+  if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {+    // This can only happen for very small denormals. In this case the+    // half-way multiplied by the denominator exceeds the range of an uint64.+    // Simply shift everything to the right.+    int shift_amount = (precision_digits_count + kDenominatorLog) -+        DiyFp::kSignificandSize + 1;+    input.set_f(input.f() >> shift_amount);+    input.set_e(input.e() + shift_amount);+    // We add 1 for the lost precision of error, and kDenominator for+    // the lost precision of input.f().+    error = (error >> shift_amount) + 1 + kDenominator;+    precision_digits_count -= shift_amount;+  }+  // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.+  ASSERT(DiyFp::kSignificandSize == 64);+  ASSERT(precision_digits_count < 64);+  uint64_t one64 = 1;+  uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;+  uint64_t precision_bits = input.f() & precision_bits_mask;+  uint64_t half_way = one64 << (precision_digits_count - 1);+  precision_bits *= kDenominator;+  half_way *= kDenominator;+  DiyFp rounded_input(input.f() >> precision_digits_count,+                      input.e() + precision_digits_count);+  if (precision_bits >= half_way + error) {+    rounded_input.set_f(rounded_input.f() + 1);+  }+  // If the last_bits are too close to the half-way case than we are too+  // inaccurate and round down. In this case we return false so that we can+  // fall back to a more precise algorithm.++  *result = Double(rounded_input).value();+  if (half_way - error < precision_bits && precision_bits < half_way + error) {+    // Too imprecise. The caller will have to fall back to a slower version.+    // However the returned number is guaranteed to be either the correct+    // double, or the next-lower double.+    return false;+  } else {+    return true;+  }+}+++// Returns the correct double for the buffer*10^exponent.+// The variable guess should be a close guess that is either the correct double+// or its lower neighbor (the nearest double less than the correct one).+// Preconditions:+//   buffer.length() + exponent <= kMaxDecimalPower + 1+//   buffer.length() + exponent > kMinDecimalPower+//   buffer.length() <= kMaxDecimalSignificantDigits+static double BignumStrtod(Vector<const char> buffer,+                           int exponent,+                           double guess) {+  if (guess == Double::Infinity()) {+    return guess;+  }++  DiyFp upper_boundary = Double(guess).UpperBoundary();++  ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);+  ASSERT(buffer.length() + exponent > kMinDecimalPower);+  ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);+  // Make sure that the Bignum will be able to hold all our numbers.+  // Our Bignum implementation has a separate field for exponents. Shifts will+  // consume at most one bigit (< 64 bits).+  // ln(10) == 3.3219...+  ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);+  Bignum input;+  Bignum boundary;+  input.AssignDecimalString(buffer);+  boundary.AssignUInt64(upper_boundary.f());+  if (exponent >= 0) {+    input.MultiplyByPowerOfTen(exponent);+  } else {+    boundary.MultiplyByPowerOfTen(-exponent);+  }+  if (upper_boundary.e() > 0) {+    boundary.ShiftLeft(upper_boundary.e());+  } else {+    input.ShiftLeft(-upper_boundary.e());+  }+  int comparison = Bignum::Compare(input, boundary);+  if (comparison < 0) {+    return guess;+  } else if (comparison > 0) {+    return Double(guess).NextDouble();+  } else if ((Double(guess).Significand() & 1) == 0) {+    // Round towards even.+    return guess;+  } else {+    return Double(guess).NextDouble();+  }+}+++double Strtod(Vector<const char> buffer, int exponent) {+  Vector<const char> left_trimmed = TrimLeadingZeros(buffer);+  Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);+  exponent += left_trimmed.length() - trimmed.length();+  if (trimmed.length() == 0) return 0.0;+  if (trimmed.length() > kMaxSignificantDecimalDigits) {+    char significant_buffer[kMaxSignificantDecimalDigits];+    int significant_exponent;+    TrimToMaxSignificantDigits(trimmed, exponent,+                               significant_buffer, &significant_exponent);+    return Strtod(Vector<const char>(significant_buffer,+                                     kMaxSignificantDecimalDigits),+                  significant_exponent);+  }+  if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {+    return Double::Infinity();+  }+  if (exponent + trimmed.length() <= kMinDecimalPower) {+    return 0.0;+  }++  double guess;+  if (DoubleStrtod(trimmed, exponent, &guess) ||+      DiyFpStrtod(trimmed, exponent, &guess)) {+    return guess;+  }+  return BignumStrtod(trimmed, exponent, guess);+}++}  // namespace double_conversion
+ double-conversion/src/strtod.h view
@@ -0,0 +1,41 @@+// 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.++#ifndef DOUBLE_CONVERSION_STRTOD_H_+#define DOUBLE_CONVERSION_STRTOD_H_++#include "utils.h"++namespace double_conversion {++// The buffer must only contain digits in the range [0-9]. It must not+// contain a dot or a sign. It must not start with '0', and must not be empty.+double Strtod(Vector<const char> buffer, int exponent);++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_STRTOD_H_
+ double-conversion/src/utils.h view
@@ -0,0 +1,297 @@+// 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.++#ifndef DOUBLE_CONVERSION_UTILS_H_+#define DOUBLE_CONVERSION_UTILS_H_++#include <stdlib.h>+#include <string.h>++#include <assert.h>+#define ASSERT(condition)      (assert(condition))+#define UNIMPLEMENTED() (abort())+#define UNREACHABLE()   (abort())++// Double operations detection based on target architecture.+// Linux uses a 80bit wide floating point stack on x86. This induces double+// rounding, which in turn leads to wrong results.+// An easy way to test if the floating-point operations are correct is to+// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then+// the result is equal to 89255e-22.+// The best way to test this, is to create a division-function and to compare+// the output of the division with the expected result. (Inlining must be+// disabled.)+// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)+#if defined(_M_X64) || defined(__x86_64__) || \+    defined(__ARMEL__) || \+    defined(_MIPS_ARCH_MIPS32R2)+#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1+#elif defined(_M_IX86) || defined(__i386__)+#if defined(_WIN32)+// Windows uses a 64bit wide floating point stack.+#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1+#else+#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS+#endif  // _WIN32+#else+#error Target architecture was not detected as supported by Double-Conversion.+#endif+++#if defined(_WIN32) && !defined(__MINGW32__)++typedef signed char int8_t;+typedef unsigned char uint8_t;+typedef short int16_t;  // NOLINT+typedef unsigned short uint16_t;  // NOLINT+typedef int int32_t;+typedef unsigned int uint32_t;+typedef __int64 int64_t;+typedef unsigned __int64 uint64_t;+// intptr_t and friends are defined in crtdefs.h through stdio.h.++#else++#include <stdint.h>++#endif++// The following macro works on both 32 and 64-bit platforms.+// Usage: instead of writing 0x1234567890123456+//      write UINT64_2PART_C(0x12345678,90123456);+#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))+++// The expression ARRAY_SIZE(a) is a compile-time constant of type+// size_t which represents the number of elements of the given+// array. You should only use ARRAY_SIZE on statically allocated+// arrays.+#define ARRAY_SIZE(a)                                   \+  ((sizeof(a) / sizeof(*(a))) /                         \+  static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))++// A macro to disallow the evil copy constructor and operator= functions+// This should be used in the private: declarations for a class+#define DISALLOW_COPY_AND_ASSIGN(TypeName)      \+  TypeName(const TypeName&);                    \+  void operator=(const TypeName&)++// A macro to disallow all the implicit constructors, namely the+// default constructor, copy constructor and operator= functions.+//+// This should be used in the private: declarations for a class+// that wants to prevent anyone from instantiating it. This is+// especially useful for classes containing only static methods.+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \+  TypeName();                                    \+  DISALLOW_COPY_AND_ASSIGN(TypeName)++namespace double_conversion {++static const int kCharSize = sizeof(char);++// Returns the maximum of the two parameters.+template <typename T>+static T Max(T a, T b) {+  return a < b ? b : a;+}+++// Returns the minimum of the two parameters.+template <typename T>+static T Min(T a, T b) {+  return a < b ? a : b;+}+++inline int StrLength(const char* string) {+  size_t length = strlen(string);+  ASSERT(length == static_cast<size_t>(static_cast<int>(length)));+  return static_cast<int>(length);+}++// This is a simplified version of V8's Vector class.+template <typename T>+class Vector {+ public:+  Vector() : start_(NULL), length_(0) {}+  Vector(T* data, int length) : start_(data), length_(length) {+    ASSERT(length == 0 || (length > 0 && data != NULL));+  }++  // Returns a vector using the same backing storage as this one,+  // spanning from and including 'from', to but not including 'to'.+  Vector<T> SubVector(int from, int to) {+    ASSERT(to <= length_);+    ASSERT(from < to);+    ASSERT(0 <= from);+    return Vector<T>(start() + from, to - from);+  }++  // Returns the length of the vector.+  int length() const { return length_; }++  // Returns whether or not the vector is empty.+  bool is_empty() const { return length_ == 0; }++  // Returns the pointer to the start of the data in the vector.+  T* start() const { return start_; }++  // Access individual vector elements - checks bounds in debug mode.+  T& operator[](int index) const {+    ASSERT(0 <= index && index < length_);+    return start_[index];+  }++  T& first() { return start_[0]; }++  T& last() { return start_[length_ - 1]; }++ private:+  T* start_;+  int length_;+};+++// Helper class for building result strings in a character buffer. The+// purpose of the class is to use safe operations that checks the+// buffer bounds on all operations in debug mode.+class StringBuilder {+ public:+  StringBuilder(char* buffer, int size)+      : buffer_(buffer, size), position_(0) { }++  ~StringBuilder() { if (!is_finalized()) Finalize(); }++  int size() const { return buffer_.length(); }++  // Get the current position in the builder.+  int position() const {+    ASSERT(!is_finalized());+    return position_;+  }++  // Reset the position.+  void Reset() { position_ = 0; }++  // Add a single character to the builder. It is not allowed to add+  // 0-characters; use the Finalize() method to terminate the string+  // instead.+  void AddCharacter(char c) {+    ASSERT(c != '\0');+    ASSERT(!is_finalized() && position_ < buffer_.length());+    buffer_[position_++] = c;+  }++  // Add an entire string to the builder. Uses strlen() internally to+  // compute the length of the input string.+  void AddString(const char* s) {+    AddSubstring(s, StrLength(s));+  }++  // Add the first 'n' characters of the given string 's' to the+  // builder. The input string must have enough characters.+  void AddSubstring(const char* s, int n) {+    ASSERT(!is_finalized() && position_ + n < buffer_.length());+    ASSERT(static_cast<size_t>(n) <= strlen(s));+    memcpy(&buffer_[position_], s, n * kCharSize);+    position_ += n;+  }+++  // Add character padding to the builder. If count is non-positive,+  // nothing is added to the builder.+  void AddPadding(char c, int count) {+    for (int i = 0; i < count; i++) {+      AddCharacter(c);+    }+  }++  // Finalize the string by 0-terminating it and returning the buffer.+  char* Finalize() {+    ASSERT(!is_finalized() && position_ < buffer_.length());+    buffer_[position_] = '\0';+    // Make sure nobody managed to add a 0-character to the+    // buffer while building the string.+    ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));+    position_ = -1;+    ASSERT(is_finalized());+    return buffer_.start();+  }++ private:+  Vector<char> buffer_;+  int position_;++  bool is_finalized() const { return position_ < 0; }++  DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);+};++// The type-based aliasing rule allows the compiler to assume that pointers of+// different types (for some definition of different) never alias each other.+// Thus the following code does not work:+//+// float f = foo();+// int fbits = *(int*)(&f);+//+// The compiler 'knows' that the int pointer can't refer to f since the types+// don't match, so the compiler may cache f in a register, leaving random data+// in fbits.  Using C++ style casts makes no difference, however a pointer to+// char data is assumed to alias any other pointer.  This is the 'memcpy+// exception'.+//+// Bit_cast uses the memcpy exception to move the bits from a variable of one+// type of a variable of another type.  Of course the end result is likely to+// be implementation dependent.  Most compilers (gcc-4.2 and MSVC 2005)+// will completely optimize BitCast away.+//+// There is an additional use for BitCast.+// Recent gccs will warn when they see casts that may result in breakage due to+// the type-based aliasing rule.  If you have checked that there is no breakage+// you can use BitCast to cast one pointer type to another.  This confuses gcc+// enough that it can no longer see that you have cast one pointer type to+// another thus avoiding the warning.+template <class Dest, class Source>+inline Dest BitCast(const Source& source) {+  // Compile time assertion: sizeof(Dest) == sizeof(Source)+  // A compile error here means your Dest and Source have different sizes.+  typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];++  Dest dest;+  memcpy(&dest, &source, sizeof(dest));+  return dest;+}++template <class Dest, class Source>+inline Dest BitCast(Source* source) {+  return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));+}++}  // namespace double_conversion++#endif  // DOUBLE_CONVERSION_UTILS_H_
+ double-conversion/test/cctest/SConscript view
@@ -0,0 +1,16 @@+double_conversion_test_sources = [+    'cctest.cc',+    'gay-fixed.cc',+    'gay-precision.cc',+    'gay-shortest.cc',+    'test-bignum.cc',+    'test-bignum-dtoa.cc',+    'test-conversions.cc',+    'test-diy-fp.cc',+    'test-double.cc',+    'test-dtoa.cc',+    'test-fast-dtoa.cc',+    'test-fixed-dtoa.cc',+    'test-strtod.cc',+  ]+Return('double_conversion_test_sources')
+ double-conversion/test/cctest/cctest.cc view
@@ -0,0 +1,122 @@+// Copyright 2008 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 "cctest.h"+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+++CcTest* CcTest::last_ = NULL;+++CcTest::CcTest(TestFunction* callback, const char* file, const char* name,+               const char* dependency, bool enabled)+    : callback_(callback), name_(name), dependency_(dependency), prev_(last_) {+  // Find the base name of this test (const_cast required on Windows).+  char *basename = strrchr(const_cast<char *>(file), '/');+  if (!basename) {+    basename = strrchr(const_cast<char *>(file), '\\');+  }+  if (!basename) {+    basename = strdup(file);+  } else {+    basename = strdup(basename + 1);+  }+  // Drop the extension, if there is one.+  char *extension = strrchr(basename, '.');+  if (extension) *extension = 0;+  // Install this test in the list of tests+  file_ = basename;+  enabled_ = enabled;+  prev_ = last_;+  last_ = this;+}+++static void PrintTestList(CcTest* current) {+  if (current == NULL) return;+  PrintTestList(current->prev());+  if (current->dependency() != NULL) {+    printf("%s/%s<%s\n",+           current->file(), current->name(), current->dependency());+  } else {+    printf("%s/%s<\n", current->file(), current->name());+  }+}+++int main(int argc, char* argv[]) {+  int tests_run = 0;+  bool print_run_count = true;+  for (int i = 1; i < argc; i++) {+    char* arg = argv[i];+    if (strcmp(arg, "--list") == 0) {+      PrintTestList(CcTest::last());+      print_run_count = false;++    } else {+      char* arg_copy = strdup(arg);+      char* testname = strchr(arg_copy, '/');+      if (testname) {+        // Split the string in two by nulling the slash and then run+        // exact matches.+        *testname = 0;+        char* file = arg_copy;+        char* name = testname + 1;+        CcTest* test = CcTest::last();+        while (test != NULL) {+          if (test->enabled()+              && strcmp(test->file(), file) == 0+              && strcmp(test->name(), name) == 0) {+            test->Run();+            tests_run++;+          }+          test = test->prev();+        }++      } else {+        // Run all tests with the specified file or test name.+        char* file_or_name = arg_copy;+        CcTest* test = CcTest::last();+        while (test != NULL) {+          if (test->enabled()+              && (strcmp(test->file(), file_or_name) == 0+                  || strcmp(test->name(), file_or_name) == 0)) {+            test->Run();+            tests_run++;+          }+          test = test->prev();+        }+      }+      delete[] arg_copy;+    }+  }+  if (print_run_count && tests_run != 1)+    printf("Ran %i tests.\n", tests_run);+  return 0;+}
+ double-conversion/test/cctest/cctest.h view
@@ -0,0 +1,141 @@+// Copyright 2008 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.++#ifndef CCTEST_H_+#define CCTEST_H_++#include <stdio.h>+#include <string.h>++#include "utils.h"++#ifndef TEST+#define TEST(Name)                                                       \+  static void Test##Name();                                              \+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true);  \+  static void Test##Name()+#endif++#ifndef DEPENDENT_TEST+#define DEPENDENT_TEST(Name, Dep)                                        \+  static void Test##Name();                                              \+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true);  \+  static void Test##Name()+#endif++#ifndef DISABLED_TEST+#define DISABLED_TEST(Name)                                              \+  static void Test##Name();                                              \+  CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false); \+  static void Test##Name()+#endif++#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)+#define CHECK_GE(a, b) CHECK((a) >= (b))++static inline void CheckHelper(const char* file,+                               int line,+                               const char* source,+                               bool condition) {+  if (!condition) {+    printf("%s:%d:\n CHECK(%s) failed\n", file, line, source);+    abort();+  }+}++#define CHECK_EQ(a, b) CheckEqualsHelper(__FILE__, __LINE__, #a, a, #b, b)++static inline void CheckEqualsHelper(const char* file, int line,+                                     const char* expected_source,+                                     const char* expected,+                                     const char* value_source,+                                     const char* value) {+  if ((expected == NULL && value != NULL) ||+      (expected != NULL && value == NULL) ||+      (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {+    printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"+           "#  Expected: %s\n"+           "#  Found:    %s\n",+           file, line, expected_source, value_source, expected, value);+    abort();+  }+}++static inline void CheckEqualsHelper(const char* file, int line,+                                     const char* expected_source,+                                     int expected,+                                     const char* value_source,+                                     int value) {+  if (expected != value) {+    printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"+           "#  Expected: %d\n"+           "#  Found:    %d\n",+           file, line, expected_source, value_source, expected, value);+    abort();+  }+}++static inline void CheckEqualsHelper(const char* file, int line,+                                     const char* expected_source,+                                     double expected,+                                     const char* value_source,+                                     double value) {+  // If expected and value are NaNs then expected != value.+  if (expected != value && (expected == expected || value == value)) {+    printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"+           "#  Expected: %.30e\n"+           "#  Found:    %.30e\n",+           file, line, expected_source, value_source, expected, value);+    abort();+  }+}+++class CcTest {+ public:+  typedef void (TestFunction)();+  CcTest(TestFunction* callback, const char* file, const char* name,+         const char* dependency, bool enabled);+  void Run() { callback_(); }+  static int test_count();+  static CcTest* last() { return last_; }+  CcTest* prev() { return prev_; }+  const char* file() { return file_; }+  const char* name() { return name_; }+  const char* dependency() { return dependency_; }+  bool enabled() { return enabled_; }+ private:+  TestFunction* callback_;+  const char* file_;+  const char* name_;+  const char* dependency_;+  bool enabled_;+  static CcTest* last_;+  CcTest* prev_;+};++#endif  // ifndef CCTEST_H_
+ double-conversion/test/cctest/checks.h view
@@ -0,0 +1,314 @@+// Copyright 2006-2008 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.++#ifndef V8_CHECKS_H_+#define V8_CHECKS_H_++#include <string.h>++#include "flags.h"++extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);+void API_Fatal(const char* location, const char* format, ...);++// The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during+// development, but they should not be relied on in the final product.+#ifdef DEBUG+#define FATAL(msg)                              \+  V8_Fatal(__FILE__, __LINE__, "%s", (msg))+#define UNIMPLEMENTED()                         \+  V8_Fatal(__FILE__, __LINE__, "unimplemented code")+#define UNREACHABLE()                           \+  V8_Fatal(__FILE__, __LINE__, "unreachable code")+#else+#define FATAL(msg)                              \+  V8_Fatal("", 0, "%s", (msg))+#define UNIMPLEMENTED()                         \+  V8_Fatal("", 0, "unimplemented code")+#define UNREACHABLE() ((void) 0)+#endif+++// Used by the CHECK macro -- should not be called directly.+static inline void CheckHelper(const char* file,+                               int line,+                               const char* source,+                               bool condition) {+  if (!condition)+    V8_Fatal(file, line, "CHECK(%s) failed", source);+}+++// The CHECK macro checks that the given condition is true; if not, it+// prints a message to stderr and aborts.+#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)+++// Helper function used by the CHECK_EQ function when given int+// arguments.  Should not be called directly.+static inline void CheckEqualsHelper(const char* file, int line,+                                     const char* expected_source, int expected,+                                     const char* value_source, int value) {+  if (expected != value) {+    V8_Fatal(file, line,+             "CHECK_EQ(%s, %s) failed\n#   Expected: %i\n#   Found: %i",+             expected_source, value_source, expected, value);+  }+}+++// Helper function used by the CHECK_EQ function when given int64_t+// arguments.  Should not be called directly.+static inline void CheckEqualsHelper(const char* file, int line,+                                     const char* expected_source,+                                     int64_t expected,+                                     const char* value_source,+                                     int64_t value) {+  if (expected != value) {+    // Print int64_t values in hex, as two int32s,+    // to avoid platform-dependencies.+    V8_Fatal(file, line,+             "CHECK_EQ(%s, %s) failed\n#"+             "   Expected: 0x%08x%08x\n#   Found: 0x%08x%08x",+             expected_source, value_source,+             static_cast<uint32_t>(expected >> 32),+             static_cast<uint32_t>(expected),+             static_cast<uint32_t>(value >> 32),+             static_cast<uint32_t>(value));+  }+}+++// Helper function used by the CHECK_NE function when given int+// arguments.  Should not be called directly.+static inline void CheckNonEqualsHelper(const char* file,+                                        int line,+                                        const char* unexpected_source,+                                        int unexpected,+                                        const char* value_source,+                                        int value) {+  if (unexpected == value) {+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",+             unexpected_source, value_source, value);+  }+}+++// Helper function used by the CHECK function when given string+// arguments.  Should not be called directly.+static inline void CheckEqualsHelper(const char* file,+                                     int line,+                                     const char* expected_source,+                                     const char* expected,+                                     const char* value_source,+                                     const char* value) {+  if ((expected == NULL && value != NULL) ||+      (expected != NULL && value == NULL) ||+      (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {+    V8_Fatal(file, line,+             "CHECK_EQ(%s, %s) failed\n#   Expected: %s\n#   Found: %s",+             expected_source, value_source, expected, value);+  }+}+++static inline void CheckNonEqualsHelper(const char* file,+                                        int line,+                                        const char* expected_source,+                                        const char* expected,+                                        const char* value_source,+                                        const char* value) {+  if (expected == value ||+      (expected != NULL && value != NULL && strcmp(expected, value) == 0)) {+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %s",+             expected_source, value_source, value);+  }+}+++// Helper function used by the CHECK function when given pointer+// arguments.  Should not be called directly.+static inline void CheckEqualsHelper(const char* file,+                                     int line,+                                     const char* expected_source,+                                     const void* expected,+                                     const char* value_source,+                                     const void* value) {+  if (expected != value) {+    V8_Fatal(file, line,+             "CHECK_EQ(%s, %s) failed\n#   Expected: %p\n#   Found: %p",+             expected_source, value_source,+             expected, value);+  }+}+++static inline void CheckNonEqualsHelper(const char* file,+                                        int line,+                                        const char* expected_source,+                                        const void* expected,+                                        const char* value_source,+                                        const void* value) {+  if (expected == value) {+    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",+             expected_source, value_source, value);+  }+}+++// Helper function used by the CHECK function when given floating+// point arguments.  Should not be called directly.+static inline void CheckEqualsHelper(const char* file,+                                     int line,+                                     const char* expected_source,+                                     double expected,+                                     const char* value_source,+                                     double value) {+  // Force values to 64 bit memory to truncate 80 bit precision on IA32.+  volatile double* exp = new double[1];+  *exp = expected;+  volatile double* val = new double[1];+  *val = value;+  if (*exp != *val) {+    V8_Fatal(file, line,+             "CHECK_EQ(%s, %s) failed\n#   Expected: %f\n#   Found: %f",+             expected_source, value_source, *exp, *val);+  }+  delete[] exp;+  delete[] val;+}+++static inline void CheckNonEqualsHelper(const char* file,+                                     int line,+                                     const char* expected_source,+                                     double expected,+                                     const char* value_source,+                                     double value) {+  // Force values to 64 bit memory to truncate 80 bit precision on IA32.+  volatile double* exp = new double[1];+  *exp = expected;+  volatile double* val = new double[1];+  *val = value;+  if (*exp == *val) {+    V8_Fatal(file, line,+             "CHECK_NE(%s, %s) failed\n#   Value: %f",+             expected_source, value_source, *val);+  }+  delete[] exp;+  delete[] val;+}+++namespace v8 {+  class Value;+  template <class T> class Handle;+}+++void CheckNonEqualsHelper(const char* file,+                          int line,+                          const char* unexpected_source,+                          v8::Handle<v8::Value> unexpected,+                          const char* value_source,+                          v8::Handle<v8::Value> value);+++void CheckEqualsHelper(const char* file,+                       int line,+                       const char* expected_source,+                       v8::Handle<v8::Value> expected,+                       const char* value_source,+                       v8::Handle<v8::Value> value);+++#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \+  #expected, expected, #value, value)+++#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \+  #unexpected, unexpected, #value, value)+++#define CHECK_GT(a, b) CHECK((a) > (b))+#define CHECK_GE(a, b) CHECK((a) >= (b))+++// This is inspired by the static assertion facility in boost.  This+// is pretty magical.  If it causes you trouble on a platform you may+// find a fix in the boost code.+template <bool> class StaticAssertion;+template <> class StaticAssertion<true> { };+// This macro joins two tokens.  If one of the tokens is a macro the+// helper call causes it to be resolved before joining.+#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)+#define SEMI_STATIC_JOIN_HELPER(a, b) a##b+// Causes an error during compilation of the condition is not+// statically known to be true.  It is formulated as a typedef so that+// it can be used wherever a typedef can be used.  Beware that this+// actually causes each use to introduce a new defined type with a+// name depending on the source line.+template <int> class StaticAssertionHelper { };+#define STATIC_CHECK(test)                                                  \+  typedef                                                                   \+    StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \+    SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)+++// The ASSERT macro is equivalent to CHECK except that it only+// generates code in debug builds.+#ifdef DEBUG+#define ASSERT_RESULT(expr)  CHECK(expr)+#define ASSERT(condition)    CHECK(condition)+#define ASSERT_EQ(v1, v2)    CHECK_EQ(v1, v2)+#define ASSERT_NE(v1, v2)    CHECK_NE(v1, v2)+#define ASSERT_GE(v1, v2)    CHECK_GE(v1, v2)+#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)+#else+#define ASSERT_RESULT(expr)     (expr)+#define ASSERT(condition)      ((void) 0)+#define ASSERT_EQ(v1, v2)      ((void) 0)+#define ASSERT_NE(v1, v2)      ((void) 0)+#define ASSERT_GE(v1, v2)      ((void) 0)+#define SLOW_ASSERT(condition) ((void) 0)+#endif+// Static asserts has no impact on runtime performance, so they can be+// safely enabled in release mode. Moreover, the ((void) 0) expression+// obeys different syntax rules than typedef's, e.g. it can't appear+// inside class declaration, this leads to inconsistency between debug+// and release compilation modes behaviour.+#define STATIC_ASSERT(test)  STATIC_CHECK(test)+++#define ASSERT_TAG_ALIGNED(address) \+  ASSERT((reinterpret_cast<intptr_t>(address) & kHeapObjectTagMask) == 0)++#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & kHeapObjectTagMask) == 0)++#define ASSERT_NOT_NULL(p)  ASSERT_NE(NULL, p)++#endif  // V8_CHECKS_H_
+ double-conversion/test/cctest/gay-fixed.cc view

file too large to diff

+ double-conversion/test/cctest/gay-fixed.h view
@@ -0,0 +1,46 @@+// Copyright 2006-2008 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.++#ifndef GAY_FIXED_H_+#define GAY_FIXED_H_++namespace double_conversion {++struct PrecomputedFixed {+  double v;+  int number_digits;+  const char* representation;+  int decimal_point;+};++// Returns precomputed values of dtoa. The strings have been generated using+// Gay's dtoa in mode "fixed".+Vector<const PrecomputedFixed> PrecomputedFixedRepresentations();++}  // namespace double_conversion++#endif  // GAY_FIXED_H_
+ double-conversion/test/cctest/gay-precision.cc view

file too large to diff

+ double-conversion/test/cctest/gay-precision.h view
@@ -0,0 +1,46 @@+// Copyright 2006-2008 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.++#ifndef GAY_PRECISION_H_+#define GAY_PRECISION_H_++namespace double_conversion {++struct PrecomputedPrecision {+  double v;+  int number_digits;+  const char* representation;+  int decimal_point;+};++// Returns precomputed values of dtoa. The strings have been generated using+// Gay's dtoa in mode "precision".+Vector<const PrecomputedPrecision> PrecomputedPrecisionRepresentations();++}  // namespace double_conversion++#endif  // GAY_PRECISION_H_
+ double-conversion/test/cctest/gay-shortest.cc view

file too large to diff

+ double-conversion/test/cctest/gay-shortest.h view
@@ -0,0 +1,43 @@+// Copyright 2006-2008 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.++#ifndef GAY_SHORTEST_H_+#define GAY_SHORTEST_H_++namespace double_conversion {++struct PrecomputedShortest {+  double v;+  const char* representation;+  int decimal_point;+};++Vector<const PrecomputedShortest> PrecomputedShortestRepresentations();++}  // namespace double_conversion++#endif  // GAY_SHORTEST_H_
+ double-conversion/test/cctest/test-bignum-dtoa.cc view
@@ -0,0 +1,313 @@+// 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 <stdlib.h>++#include "bignum-dtoa.h"++#include "cctest.h"+#include "double.h"+#include "gay-fixed.h"+#include "gay-precision.h"+#include "gay-shortest.h"+#include "utils.h"++using namespace double_conversion;+++// Removes trailing '0' digits.+// Can return the empty string if all digits are 0.+static void TrimRepresentation(Vector<char> representation) {+  int len = strlen(representation.start());+  int i;+  for (i = len - 1; i >= 0; --i) {+    if (representation[i] != '0') break;+  }+  representation[i + 1] = '\0';+}+++static const int kBufferSize = 100;+++TEST(BignumDtoaVariousDoubles) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;++  BignumDtoa(1.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  BignumDtoa(1.0, BIGNUM_DTOA_FIXED, 3, buffer, &length, &point);+  CHECK_GE(3, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  BignumDtoa(1.0, BIGNUM_DTOA_PRECISION, 3, buffer, &length, &point);+  CHECK_GE(3, length);+  TrimRepresentation(buffer);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  BignumDtoa(1.5, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  BignumDtoa(1.5, BIGNUM_DTOA_FIXED, 10, buffer, &length, &point);+  CHECK_GE(10, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  BignumDtoa(1.5, BIGNUM_DTOA_PRECISION, 10, buffer, &length, &point);+  CHECK_GE(10, length);+  TrimRepresentation(buffer);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  double min_double = 5e-324;+  BignumDtoa(min_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("5", buffer.start());+  CHECK_EQ(-323, point);++  BignumDtoa(min_double, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);+  CHECK_GE(5, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("", buffer.start());++  BignumDtoa(min_double, BIGNUM_DTOA_PRECISION, 5, buffer, &length, &point);+  CHECK_GE(5, length);+  TrimRepresentation(buffer);+  CHECK_EQ("49407", buffer.start());+  CHECK_EQ(-323, point);++  double max_double = 1.7976931348623157e308;+  BignumDtoa(max_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("17976931348623157", buffer.start());+  CHECK_EQ(309, point);++  BignumDtoa(max_double, BIGNUM_DTOA_PRECISION, 7, buffer, &length, &point);+  CHECK_GE(7, length);+  TrimRepresentation(buffer);+  CHECK_EQ("1797693", buffer.start());+  CHECK_EQ(309, point);++  BignumDtoa(4294967272.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);++  BignumDtoa(4294967272.0, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);+  CHECK_EQ("429496727200000", buffer.start());+  CHECK_EQ(10, point);+++  BignumDtoa(4294967272.0, BIGNUM_DTOA_PRECISION, 14, buffer, &length, &point);+  CHECK_GE(14, length);+  TrimRepresentation(buffer);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);++  BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_SHORTEST, 0,+             buffer, &length, &point);+  CHECK_EQ("4185580496821357", buffer.start());+  CHECK_EQ(299, point);++  BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_PRECISION, 20,+             buffer, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("41855804968213567225", buffer.start());+  CHECK_EQ(299, point);++  BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_SHORTEST, 0,+             buffer, &length, &point);+  CHECK_EQ("5562684646268003", buffer.start());+  CHECK_EQ(-308, point);++  BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_PRECISION, 1,+             buffer, &length, &point);+  CHECK_GE(1, length);+  TrimRepresentation(buffer);+  CHECK_EQ("6", buffer.start());+  CHECK_EQ(-308, point);++  BignumDtoa(2147483648.0, BIGNUM_DTOA_SHORTEST, 0,+             buffer, &length, &point);+  CHECK_EQ("2147483648", buffer.start());+  CHECK_EQ(10, point);+++  BignumDtoa(2147483648.0, BIGNUM_DTOA_FIXED, 2,+             buffer, &length, &point);+  CHECK_GE(2, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("2147483648", buffer.start());+  CHECK_EQ(10, point);++  BignumDtoa(2147483648.0, BIGNUM_DTOA_PRECISION, 5,+             buffer, &length, &point);+  CHECK_GE(5, length);+  TrimRepresentation(buffer);+  CHECK_EQ("21475", buffer.start());+  CHECK_EQ(10, point);++  BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_SHORTEST, 0,+             buffer, &length, &point);+  CHECK_EQ("35844466002796428", buffer.start());+  CHECK_EQ(299, point);++  BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_PRECISION, 10,+             buffer, &length, &point);+  CHECK_GE(10, length);+  TrimRepresentation(buffer);+  CHECK_EQ("35844466", buffer.start());+  CHECK_EQ(299, point);++  uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);+  double v = Double(smallest_normal64).value();+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("22250738585072014", buffer.start());+  CHECK_EQ(-307, point);++  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("22250738585072013831", buffer.start());+  CHECK_EQ(-307, point);++  uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  v = Double(largest_denormal64).value();+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("2225073858507201", buffer.start());+  CHECK_EQ(-307, point);++  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("2225073858507200889", buffer.start());+  CHECK_EQ(-307, point);++  BignumDtoa(4128420500802942e-24, BIGNUM_DTOA_SHORTEST, 0,+             buffer, &length, &point);+  CHECK_EQ("4128420500802942", buffer.start());+  CHECK_EQ(-8, point);++  v = 3.9292015898194142585311918e-10;+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+  CHECK_EQ("39292015898194143", buffer.start());++  v = 4194304.0;+  BignumDtoa(v, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);+  CHECK_GE(5, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("4194304", buffer.start());++  v = 3.3161339052167390562200598e-237;+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 19, buffer, &length, &point);+  CHECK_GE(19, length);+  TrimRepresentation(buffer);+  CHECK_EQ("3316133905216739056", buffer.start());+  CHECK_EQ(-236, point);++  v = 7.9885183916008099497815232e+191;+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 4, buffer, &length, &point);+  CHECK_GE(4, length);+  TrimRepresentation(buffer);+  CHECK_EQ("7989", buffer.start());+  CHECK_EQ(192, point);++  v = 1.0000000000000012800000000e+17;+  BignumDtoa(v, BIGNUM_DTOA_FIXED, 1, buffer, &length, &point);+  CHECK_GE(1, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("100000000000000128", buffer.start());+  CHECK_EQ(18, point);+}+++TEST(BignumDtoaGayShortest) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;++  Vector<const PrecomputedShortest> precomputed =+      PrecomputedShortestRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedShortest current_test = precomputed[i];+    double v = current_test.v;+    BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}+++TEST(BignumDtoaGayFixed) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;++  Vector<const PrecomputedFixed> precomputed =+      PrecomputedFixedRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedFixed current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    BignumDtoa(v, BIGNUM_DTOA_FIXED, number_digits, buffer, &length, &point);+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_GE(number_digits, length - point);+    TrimRepresentation(buffer);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}+++TEST(BignumDtoaGayPrecision) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;++  Vector<const PrecomputedPrecision> precomputed =+      PrecomputedPrecisionRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedPrecision current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    BignumDtoa(v, BIGNUM_DTOA_PRECISION, number_digits,+               buffer, &length, &point);+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_GE(number_digits, length);+    TrimRepresentation(buffer);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}
+ double-conversion/test/cctest/test-bignum.cc view
@@ -0,0 +1,1502 @@+// 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 <stdlib.h>+#include <string.h>+++#include "bignum.h"+#include "cctest.h"+#include "utils.h"++using namespace double_conversion;+++static const int kBufferSize = 1024;++static void AssignHexString(Bignum* bignum, const char* str) {+  bignum->AssignHexString(Vector<const char>(str, strlen(str)));+}+++static void AssignDecimalString(Bignum* bignum, const char* str) {+  bignum->AssignDecimalString(Vector<const char>(str, strlen(str)));+}+++TEST(Assign) {+  char buffer[kBufferSize];+  Bignum bignum;+  Bignum bignum2;+  bignum.AssignUInt16(0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);+  bignum.AssignUInt16(0xA);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);+  bignum.AssignUInt16(0x20);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("20", buffer);+++  bignum.AssignUInt64(0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);+  bignum.AssignUInt64(0xA);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);+  bignum.AssignUInt64(0x20);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("20", buffer);+  bignum.AssignUInt64(0x100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100", buffer);++  // The first real test, since this will not fit into one bigit.+  bignum.AssignUInt64(0x12345678);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("12345678", buffer);++  uint64_t big = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);+  bignum.AssignUInt64(big);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFF", buffer);++  big = UINT64_2PART_C(0x12345678, 9ABCDEF0);+  bignum.AssignUInt64(big);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("123456789ABCDEF0", buffer);++  bignum2.AssignBignum(bignum);+  CHECK(bignum2.ToHexString(buffer, kBufferSize));+  CHECK_EQ("123456789ABCDEF0", buffer);++  AssignDecimalString(&bignum, "0");+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  AssignDecimalString(&bignum, "1");+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  AssignDecimalString(&bignum, "1234567890");+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("499602D2", buffer);++  AssignHexString(&bignum, "0");+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  AssignHexString(&bignum, "123456789ABCDEF0");+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("123456789ABCDEF0", buffer);+}+++TEST(ShiftLeft) {+  char buffer[kBufferSize];+  Bignum bignum;+  AssignHexString(&bignum, "0");+  bignum.ShiftLeft(100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  AssignHexString(&bignum, "1");+  bignum.ShiftLeft(1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2", buffer);++  AssignHexString(&bignum, "1");+  bignum.ShiftLeft(4);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10", buffer);++  AssignHexString(&bignum, "1");+  bignum.ShiftLeft(32);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000000", buffer);++  AssignHexString(&bignum, "1");+  bignum.ShiftLeft(64);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000", buffer);++  AssignHexString(&bignum, "123456789ABCDEF");+  bignum.ShiftLeft(64);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("123456789ABCDEF0000000000000000", buffer);+  bignum.ShiftLeft(1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2468ACF13579BDE0000000000000000", buffer);+}+++TEST(AddUInt64) {+  char buffer[kBufferSize];+  Bignum bignum;+  AssignHexString(&bignum, "0");+  bignum.AddUInt64(0xA);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(0xA);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("B", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(0x100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("101", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.AddUInt64(0x1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.AddUInt64(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000000000000000000000FFFF", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");+  bignum.AddUInt64(0x1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000000000000000000000000000000000000000000", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddUInt64(1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000001", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddUInt64(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000FFFF", buffer);++  AssignHexString(&bignum, "0");+  bignum.AddUInt64(UINT64_2PART_C(0xA, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A00000000", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(UINT64_2PART_C(0xA, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A00000001", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(UINT64_2PART_C(0x100, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000001", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddUInt64(UINT64_2PART_C(0xFFFF, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFF00000001", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.AddUInt64(UINT64_2PART_C(0x1, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10FFFFFFF", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.AddUInt64(UINT64_2PART_C(0xFFFF, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000000000FFFF00000000", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");+  bignum.AddUInt64(UINT64_2PART_C(0x1, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000000000000000000FFFFFFFF", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddUInt64(UINT64_2PART_C(0x1, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000100000000", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddUInt64(UINT64_2PART_C(0xFFFF, 00000000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000FFFF00000000", buffer);+}+++TEST(AddBignum) {+  char buffer[kBufferSize];+  Bignum bignum;+  Bignum other;++  AssignHexString(&other, "1");+  AssignHexString(&bignum, "0");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  AssignHexString(&bignum, "1");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000000000000", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000000000000000000001", buffer);++  AssignHexString(&other, "1000000000000");++  AssignHexString(&bignum, "1");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000001", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000FFFFFFF", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000000001000000000000", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000000000000FFFFFFFFFFFF", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000001000000000000", buffer);++  other.ShiftLeft(64);+  // other == "10000000000000000000000000000"++  bignum.AssignUInt16(0x1);+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000001", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000FFFFFFF", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000010000000000000000000000000000", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  bignum.AddBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10010000000000000000000000000", buffer);+}+++TEST(SubtractBignum) {+  char buffer[kBufferSize];+  Bignum bignum;+  Bignum other;++  AssignHexString(&bignum, "1");+  AssignHexString(&other, "0");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  AssignHexString(&bignum, "2");+  AssignHexString(&other, "0");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2", buffer);++  AssignHexString(&bignum, "10000000");+  AssignHexString(&other, "1");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFF", buffer);++  AssignHexString(&bignum, "100000000000000");+  AssignHexString(&other, "1");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFF", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000001");+  AssignHexString(&other, "1");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000000000000000000000", buffer);++  AssignHexString(&bignum, "1000000000001");+  AssignHexString(&other, "1000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  AssignHexString(&bignum, "100000FFFFFFF");+  AssignHexString(&other, "1000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFF", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000001000000000000");+  AssignHexString(&other, "1000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000000000000000000000", buffer);++  AssignHexString(&bignum, "1000000000000000000000000000000FFFFFFFFFFFF");+  AssignHexString(&other, "1000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // "10 0000 0000 0000 0000 0000 0000"+  AssignHexString(&other, "1000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFF000000000000", buffer);++  AssignHexString(&other, "1000000000000");+  other.ShiftLeft(48);+  // other == "1000000000000000000000000"++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // bignum == "10000000000000000000000000"+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("F000000000000000000000000", buffer);++  other.AssignUInt16(0x1);+  other.ShiftLeft(35);+  // other == "800000000"+  AssignHexString(&bignum, "FFFFFFF");+  bignum.ShiftLeft(60);+  // bignum = FFFFFFF000000000000000+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFEFFFFFF800000000", buffer);++  AssignHexString(&bignum, "10000000000000000000000000000000000000000000");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000000", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");+  bignum.SubtractBignum(other);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFF", buffer);+}+++TEST(MultiplyUInt32) {+  char buffer[kBufferSize];+  Bignum bignum;++  AssignHexString(&bignum, "0");+  bignum.MultiplyByUInt32(0x25);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  AssignHexString(&bignum, "2");+  bignum.MultiplyByUInt32(0x5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);++  AssignHexString(&bignum, "10000000");+  bignum.MultiplyByUInt32(0x9);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("90000000", buffer);++  AssignHexString(&bignum, "100000000000000");+  bignum.MultiplyByUInt32(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFF00000000000000", buffer);++  AssignHexString(&bignum, "100000000000000");+  bignum.MultiplyByUInt32(0xFFFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFF00000000000000", buffer);++  AssignHexString(&bignum, "1234567ABCD");+  bignum.MultiplyByUInt32(0xFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("12333335552433", buffer);++  AssignHexString(&bignum, "1234567ABCD");+  bignum.MultiplyByUInt32(0xFFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("12345679998A985433", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt32(0x2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1FFFFFFFFFFFFFFFE", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt32(0x4);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3FFFFFFFFFFFFFFFC", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt32(0xF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("EFFFFFFFFFFFFFFF1", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt32(0xFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFEFFFFFFFFFF000001", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // "10 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt32(2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("20000000000000000000000000", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // "10 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt32(0xF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("F0000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt32(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFE00010000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt32(0xFFFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt32(0xFFFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);++  AssignDecimalString(&bignum, "15611230384529777");+  bignum.MultiplyByUInt32(10000000);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("210EDD6D4CDD2580EE80", buffer);+}+++TEST(MultiplyUInt64) {+  char buffer[kBufferSize];+  Bignum bignum;++  AssignHexString(&bignum, "0");+  bignum.MultiplyByUInt64(0x25);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  AssignHexString(&bignum, "2");+  bignum.MultiplyByUInt64(0x5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);++  AssignHexString(&bignum, "10000000");+  bignum.MultiplyByUInt64(0x9);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("90000000", buffer);++  AssignHexString(&bignum, "100000000000000");+  bignum.MultiplyByUInt64(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFF00000000000000", buffer);++  AssignHexString(&bignum, "100000000000000");+  bignum.MultiplyByUInt64(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFF00000000000000", buffer);++  AssignHexString(&bignum, "1234567ABCD");+  bignum.MultiplyByUInt64(0xFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("12333335552433", buffer);++  AssignHexString(&bignum, "1234567ABCD");+  bignum.MultiplyByUInt64(UINT64_2PART_C(0xFF, FFFFFFFF));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1234567ABCBDCBA985433", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt64(0x2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1FFFFFFFFFFFFFFFE", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt64(0x4);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3FFFFFFFFFFFFFFFC", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt64(0xF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("EFFFFFFFFFFFFFFF1", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFFFF");+  bignum.MultiplyByUInt64(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFFFE0000000000000001", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // "10 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt64(2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("20000000000000000000000000", buffer);++  bignum.AssignUInt16(0x1);+  bignum.ShiftLeft(100);+  // "10 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt64(0xF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("F0000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt64(0xFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFE00010000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt64(0xFFFFFFFF);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFEFFFF00010000000000000000000000000", buffer);++  bignum.AssignUInt16(0xFFFF);+  bignum.ShiftLeft(100);+  // "FFFF0 0000 0000 0000 0000 0000 0000"+  bignum.MultiplyByUInt64(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFEFFFFFFFFFFFF00010000000000000000000000000", buffer);++  AssignDecimalString(&bignum, "15611230384529777");+  bignum.MultiplyByUInt64(UINT64_2PART_C(0x8ac72304, 89e80000));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1E10EE4B11D15A7F3DE7F3C7680000", buffer);+}+++TEST(MultiplyPowerOfTen) {+  char buffer[kBufferSize];+  Bignum bignum;++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3034", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1E208", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(3);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("12D450", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(4);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("BC4B20", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("75AEF40", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(6);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("498D5880", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(7);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2DF857500", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(8);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1CBB369200", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(9);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("11F5021B400", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(10);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("B3921510800", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(11);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("703B4D2A5000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(12);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("4625103A72000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(13);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2BD72A24874000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(14);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1B667A56D488000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(15);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("11200C7644D50000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(16);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("AB407C9EB0520000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(17);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("6B084DE32E3340000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(18);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("42E530ADFCE0080000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(19);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("29CF3E6CBE0C0500000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(20);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1A218703F6C783200000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(21);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1054F4627A3CB1F400000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(22);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A3518BD8C65EF38800000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(23);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("6612F7677BFB5835000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(24);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3FCBDAA0AD7D17212000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(25);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("27DF68A46C6E2E74B4000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(26);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("18EBA166C3C4DD08F08000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(27);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("F9344E03A5B0A259650000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(28);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("9BC0B0C2478E6577DF20000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(29);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("61586E796CB8FF6AEB740000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(30);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3CD7450BE3F39FA2D32880000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(31);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("26068B276E7843C5C3F9500000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(50);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("149D1B4CFED03B23AB5F4E1196EF45C08000000000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("5827249F27165024FBC47DFCA9359BF316332D1B91ACEECF471FBAB06D9B2"+           "0000000000000000000000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(200);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("64C1F5C06C3816AFBF8DAFD5A3D756365BB0FD020E6F084E759C1F7C99E4F"+           "55B9ACC667CEC477EB958C2AEEB3C6C19BA35A1AD30B35C51EB72040920000"+           "0000000000000000000000000000000000000000000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(500);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("96741A625EB5D7C91039FEB5C5ACD6D9831EDA5B083D800E6019442C8C8223"+           "3EAFB3501FE2058062221E15121334928880827DEE1EC337A8B26489F3A40A"+           "CB440A2423734472D10BFCE886F41B3AF9F9503013D86D088929CA86EEB4D8"+           "B9C831D0BD53327B994A0326227CFD0ECBF2EB48B02387AAE2D4CCCDF1F1A1"+           "B8CC4F1FA2C56AD40D0E4DAA9C28CDBF0A549098EA13200000000000000000"+           "00000000000000000000000000000000000000000000000000000000000000"+           "0000000000000000000000000000000000000000000000", buffer);++  AssignDecimalString(&bignum, "1234");+  bignum.MultiplyByPowerOfTen(1000);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1258040F99B1CD1CC9819C676D413EA50E4A6A8F114BB0C65418C62D399B81"+           "6361466CA8E095193E1EE97173553597C96673AF67FAFE27A66E7EF2E5EF2E"+           "E3F5F5070CC17FE83BA53D40A66A666A02F9E00B0E11328D2224B8694C7372"+           "F3D536A0AD1985911BD361496F268E8B23112500EAF9B88A9BC67B2AB04D38"+           "7FEFACD00F5AF4F764F9ABC3ABCDE54612DE38CD90CB6647CA389EA0E86B16"+           "BF7A1F34086E05ADBE00BD1673BE00FAC4B34AF1091E8AD50BA675E0381440"+           "EA8E9D93E75D816BAB37C9844B1441C38FC65CF30ABB71B36433AF26DD97BD"+           "ABBA96C03B4919B8F3515B92826B85462833380DC193D79F69D20DD6038C99"+           "6114EF6C446F0BA28CC772ACBA58B81C04F8FFDE7B18C4E5A3ABC51E637FDF"+           "6E37FDFF04C940919390F4FF92000000000000000000000000000000000000"+           "00000000000000000000000000000000000000000000000000000000000000"+           "00000000000000000000000000000000000000000000000000000000000000"+           "00000000000000000000000000000000000000000000000000000000000000"+           "0000000000000000000000000000", buffer);++  Bignum bignum2;+  AssignHexString(&bignum2, "3DA774C07FB5DF54284D09C675A492165B830D5DAAEB2A7501"+                            "DA17CF9DFA1CA2282269F92A25A97314296B717E3DCBB9FE17"+                            "41A842FE2913F540F40796F2381155763502C58B15AF7A7F88"+                            "6F744C9164FF409A28F7FA0C41F89ED79C1BE9F322C8578B97"+                            "841F1CBAA17D901BE1230E3C00E1C643AF32638B5674E01FEA"+                            "96FC90864E621B856A9E1CE56E6EB545B9C2F8F0CC10DDA88D"+                            "CC6D282605F8DB67044F2DFD3695E7BA63877AE16701536AE6"+                            "567C794D0BFE338DFBB42D92D4215AF3BB22BF0A8B283FDDC2"+                            "C667A10958EA6D2");+  CHECK(bignum2.ToHexString(buffer, kBufferSize));+  CHECK_EQ("3DA774C07FB5DF54284D09C675A492165B830D5DAAEB2A7501"+           "DA17CF9DFA1CA2282269F92A25A97314296B717E3DCBB9FE17"+           "41A842FE2913F540F40796F2381155763502C58B15AF7A7F88"+           "6F744C9164FF409A28F7FA0C41F89ED79C1BE9F322C8578B97"+           "841F1CBAA17D901BE1230E3C00E1C643AF32638B5674E01FEA"+           "96FC90864E621B856A9E1CE56E6EB545B9C2F8F0CC10DDA88D"+           "CC6D282605F8DB67044F2DFD3695E7BA63877AE16701536AE6"+           "567C794D0BFE338DFBB42D92D4215AF3BB22BF0A8B283FDDC2"+           "C667A10958EA6D2", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2688A8F84FD1AB949930261C0986DB4DF931E85A8AD2FA8921284EE1C2BC51"+           "E55915823BBA5789E7EC99E326EEE69F543ECE890929DED9AC79489884BE57"+           "630AD569E121BB76ED8DAC8FB545A8AFDADF1F8860599AFC47A93B6346C191"+           "7237F5BD36B73EB29371F4A4EE7A116CB5E8E5808D1BEA4D7F7E3716090C13"+           "F29E5DDA53F0FD513362A2D20F6505314B9419DB967F8A8A89589FC43917C3"+           "BB892062B17CBE421DB0D47E34ACCCE060D422CFF60DCBD0277EE038BD509C"+           "7BC494D8D854F5B76696F927EA99BC00C4A5D7928434", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1815699B31E30B3CDFBE17D185F44910BBBF313896C3DC95B4B9314D19B5B32"+           "F57AD71655476B630F3E02DF855502394A74115A5BA2B480BCBCD5F52F6F69D"+           "E6C5622CB5152A54788BD9D14B896DE8CB73B53C3800DDACC9C51E0C38FAE76"+           "2F9964232872F9C2738E7150C4AE3F1B18F70583172706FAEE26DC5A78C77A2"+           "FAA874769E52C01DA5C3499F233ECF3C90293E0FB69695D763DAA3AEDA5535B"+           "43DAEEDF6E9528E84CEE0EC000C3C8495C1F9C89F6218AF4C23765261CD5ADD"+           "0787351992A01E5BB8F2A015807AE7A6BB92A08", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("5E13A4863ADEE3E5C9FE8D0A73423D695D62D8450CED15A8C9F368952C6DC3"+           "F0EE7D82F3D1EFB7AF38A3B3920D410AFCAD563C8F5F39116E141A3C5C14B3"+           "58CD73077EA35AAD59F6E24AD98F10D5555ABBFBF33AC361EAF429FD5FBE94"+           "17DA9EF2F2956011F9F93646AA38048A681D984ED88127073443247CCC167C"+           "B354A32206EF5A733E73CF82D795A1AD598493211A6D613C39515E0E0F6304"+           "DCD9C810F3518C7F6A7CB6C81E99E02FCC65E8FDB7B7AE97306CC16A8631CE"+           "0A2AEF6568276BE4C176964A73C153FDE018E34CB4C2F40", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(10);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("8F8CB8EB51945A7E815809F6121EF2F4E61EF3405CD9432CAD2709749EEAFD"+           "1B81E843F14A3667A7BDCCC9E0BB795F63CDFDB62844AC7438976C885A0116"+           "29607DA54F9C023CC366570B7637ED0F855D931752038A614922D0923E382C"+           "B8E5F6C975672DB76E0DE471937BB9EDB11E28874F1C122D5E1EF38CECE9D0"+           "0723056BCBD4F964192B76830634B1D322B7EB0062F3267E84F5C824343A77"+           "4B7DCEE6DD464F01EBDC8C671BB18BB4EF4300A42474A6C77243F2A12B03BF"+           "0443C38A1C0D2701EDB393135AE0DEC94211F9D4EB51F990800", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(50);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("107A8BE345E24407372FC1DE442CBA696BC23C4FFD5B4BDFD9E5C39559815"+           "86628CF8472D2D589F2FC2BAD6E0816EC72CBF85CCA663D8A1EC6C51076D8"+           "2D247E6C26811B7EC4D4300FB1F91028DCB7B2C4E7A60C151161AA7E65E79"+           "B40917B12B2B5FBE7745984D4E8EFA31F9AE6062427B068B144A9CB155873"+           "E7C0C9F0115E5AC72DC5A73C4796DB970BF9205AB8C77A6996EB1B417F9D1"+           "6232431E6313C392203601B9C22CC10DDA88DCC6D282605F8DB67044F2DFD"+           "3695E7BA63877AE16701536AE6567C794D0BFE338DFBB42D924CF964BD2C0"+           "F586E03A2FCD35A408000000000000", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("46784A90ACD0ED3E7759CC585FB32D36EB6034A6F78D92604E3BAA5ED3D8B"+           "6E60E854439BE448897FB4B7EA5A3D873AA0FCB3CFFD80D0530880E45F511"+           "722A50CE7E058B5A6F5464DB7500E34984EE3202A9441F44FA1554C0CEA96"+           "B438A36F25E7C9D56D71AE2CD313EC37534DA299AC0854FC48591A7CF3171"+           "31265AA4AE62DE32344CE7BEEEF894AE686A2DAAFE5D6D9A10971FFD9C064"+           "5079B209E1048F58B5192D41D84336AC4C8C489EEF00939CFC9D55C122036"+           "01B9C22CC10DDA88DCC6D282605F8DB67044F2DFD3695E7BA3F67B96D3A32"+           "E11FB5561B68744C4035B0800DC166D49D98E3FD1D5BB2000000000000000"+           "0000000000", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(200);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("508BD351221DF139D72D88CDC0416845A53EE2D0E6B98352509A9AC312F8C"+           "6CB1A144889416201E0B6CE66EA3EBE259B5FD79ECFC1FD77963CE516CC7E"+           "2FE73D4B5B710C19F6BCB092C7A2FD76286543B8DBD2C596DFF2C896720BA"+           "DFF7BC9C366ACEA3A880AEC287C5E6207DF2739B5326FC19D773BD830B109"+           "ED36C7086544BF8FDB9D4B73719C2B5BC2F571A5937EC46876CD428281F6B"+           "F287E1E07F25C1B1D46BC37324FF657A8B2E0071DB83B86123CA34004F406"+           "001082D7945E90C6E8C9A9FEC2B44BE0DDA46E9F52B152E4D1336D2FCFBC9"+           "96E30CA0082256737365158FE36482AA7EB9DAF2AB128F10E7551A3CD5BE6"+           "0A922F3A7D5EED38B634A7EC95BCF7021BA6820A292000000000000000000"+           "00000000000000000000000000000000", buffer);++  bignum.AssignBignum(bignum2);+  bignum.MultiplyByPowerOfTen(500);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("7845F900E475B5086885BAAAE67C8E85185ACFE4633727F82A4B06B5582AC"+           "BE933C53357DA0C98C20C5AC900C4D76A97247DF52B79F48F9E35840FB715"+           "D392CE303E22622B0CF82D9471B398457DD3196F639CEE8BBD2C146873841"+           "F0699E6C41F04FC7A54B48CEB995BEB6F50FE81DE9D87A8D7F849CC523553"+           "7B7BBBC1C7CAAFF6E9650BE03B308C6D31012AEF9580F70D3EE2083ADE126"+           "8940FA7D6308E239775DFD2F8C97FF7EBD525DAFA6512216F7047A62A93DC"+           "38A0165BDC67E250DCC96A0181DE935A70B38704DC71819F02FC5261FF7E1"+           "E5F11907678B0A3E519FF4C10A867B0C26CE02BE6960BA8621A87303C101C"+           "3F88798BB9F7739655946F8B5744E6B1EAF10B0C5621330F0079209033C69"+           "20DE2E2C8D324F0624463735D482BF291926C22A910F5B80FA25170B6B57D"+           "8D5928C7BCA3FE87461275F69BD5A1B83181DAAF43E05FC3C72C4E93111B6"+           "6205EBF49B28FEDFB7E7526CBDA658A332000000000000000000000000000"+           "0000000000000000000000000000000000000000000000000000000000000"+           "0000000000000000000000000000000000000", buffer);+}+++TEST(DivideModuloIntBignum) {+  char buffer[kBufferSize];+  Bignum bignum;+  Bignum other;+  Bignum third;++  bignum.AssignUInt16(10);+  other.AssignUInt16(2);+  CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("0", buffer);++  bignum.AssignUInt16(10);+  bignum.ShiftLeft(500);+  other.AssignUInt16(2);+  other.ShiftLeft(500);+  CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK_EQ("0", buffer);++  bignum.AssignUInt16(11);+  other.AssignUInt16(2);+  CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignUInt16(10);+  bignum.ShiftLeft(500);+  other.AssignUInt16(1);+  bignum.AddBignum(other);+  other.AssignUInt16(2);+  other.ShiftLeft(500);+  CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignUInt16(10);+  bignum.ShiftLeft(500);+  other.AssignBignum(bignum);+  bignum.MultiplyByUInt32(0x1234);+  third.AssignUInt16(0xFFF);+  bignum.AddBignum(third);+  CHECK_EQ(0x1234, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFF", buffer);++  bignum.AssignUInt16(10);+  AssignHexString(&other, "1234567890");+  CHECK_EQ(0, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);++  AssignHexString(&bignum, "12345678");+  AssignHexString(&other, "3789012");+  CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("D9861E", buffer);++  AssignHexString(&bignum, "70000001");+  AssignHexString(&other, "1FFFFFFF");+  CHECK_EQ(3, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000004", buffer);++  AssignHexString(&bignum, "28000000");+  AssignHexString(&other, "12A05F20");+  CHECK_EQ(2, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2BF41C0", buffer);++  bignum.AssignUInt16(10);+  bignum.ShiftLeft(500);+  other.AssignBignum(bignum);+  bignum.MultiplyByUInt32(0x1234);+  third.AssignUInt16(0xFFF);+  other.SubtractBignum(third);+  CHECK_EQ(0x1234, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1232DCC", buffer);+  CHECK_EQ(0, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1232DCC", buffer);+}+++TEST(Compare) {+  Bignum bignum1;+  Bignum bignum2;+  bignum1.AssignUInt16(1);+  bignum2.AssignUInt16(1);+  CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));+  CHECK(Bignum::Equal(bignum1, bignum2));+  CHECK(Bignum::LessEqual(bignum1, bignum2));+  CHECK(!Bignum::Less(bignum1, bignum2));++  bignum1.AssignUInt16(0);+  bignum2.AssignUInt16(1);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));+  CHECK(!Bignum::Equal(bignum1, bignum2));+  CHECK(!Bignum::Equal(bignum2, bignum1));+  CHECK(Bignum::LessEqual(bignum1, bignum2));+  CHECK(!Bignum::LessEqual(bignum2, bignum1));+  CHECK(Bignum::Less(bignum1, bignum2));+  CHECK(!Bignum::Less(bignum2, bignum1));++  AssignHexString(&bignum1, "1234567890ABCDEF12345");+  AssignHexString(&bignum2, "1234567890ABCDEF12345");+  CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));++  AssignHexString(&bignum1, "1234567890ABCDEF12345");+  AssignHexString(&bignum2, "1234567890ABCDEF12346");+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "1234567890ABCDEF12345");+  bignum1.ShiftLeft(500);+  AssignHexString(&bignum2, "1234567890ABCDEF12345");+  bignum2.ShiftLeft(500);+  CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));++  AssignHexString(&bignum1, "1234567890ABCDEF12345");+  bignum1.ShiftLeft(500);+  AssignHexString(&bignum2, "1234567890ABCDEF12346");+  bignum2.ShiftLeft(500);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  bignum1.AssignUInt16(1);+  bignum1.ShiftLeft(64);+  AssignHexString(&bignum2, "10000000000000000");+  CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(0, Bignum::Compare(bignum2, bignum1));++  bignum1.AssignUInt16(1);+  bignum1.ShiftLeft(64);+  AssignHexString(&bignum2, "10000000000000001");+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  bignum1.AssignUInt16(1);+  bignum1.ShiftLeft(96);+  AssignHexString(&bignum2, "10000000000000001");+  bignum2.ShiftLeft(32);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(64);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");+  bignum1.ShiftLeft(32);+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(96);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");+  bignum1.ShiftLeft(32);+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(95);+  CHECK_EQ(+1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(-1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "FFFFFFFFFFFFFFFF");+  bignum1.ShiftLeft(32);+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(100);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "100000000000000");+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(14*4);+  CHECK_EQ(0, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(0, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "100000000000001");+  bignum2.AssignUInt16(1);+  bignum2.ShiftLeft(14*4);+  CHECK_EQ(+1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(-1, Bignum::Compare(bignum2, bignum1));++  AssignHexString(&bignum1, "200000000000000");+  bignum2.AssignUInt16(3);+  bignum2.ShiftLeft(14*4);+  CHECK_EQ(-1, Bignum::Compare(bignum1, bignum2));+  CHECK_EQ(+1, Bignum::Compare(bignum2, bignum1));+}+++TEST(PlusCompare) {+  Bignum a;+  Bignum b;+  Bignum c;+  a.AssignUInt16(1);+  b.AssignUInt16(0);+  c.AssignUInt16(1);+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));+  CHECK(Bignum::PlusEqual(a, b, c));+  CHECK(Bignum::PlusLessEqual(a, b, c));+  CHECK(!Bignum::PlusLess(a, b, c));++  a.AssignUInt16(0);+  b.AssignUInt16(0);+  c.AssignUInt16(1);+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));+  CHECK_EQ(+1, Bignum::PlusCompare(c, b, a));+  CHECK(!Bignum::PlusEqual(a, b, c));+  CHECK(!Bignum::PlusEqual(c, b, a));+  CHECK(Bignum::PlusLessEqual(a, b, c));+  CHECK(!Bignum::PlusLessEqual(c, b, a));+  CHECK(Bignum::PlusLess(a, b, c));+  CHECK(!Bignum::PlusLess(c, b, a));++  AssignHexString(&a, "1234567890ABCDEF12345");+  b.AssignUInt16(1);+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(+1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890ABCDEF12344");+  b.AssignUInt16(1);+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4);+  AssignHexString(&b, "ABCDEF12345");+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4);+  AssignHexString(&b, "ABCDEF12344");+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4);+  AssignHexString(&b, "ABCDEF12346");+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567891");+  a.ShiftLeft(11*4);+  AssignHexString(&b, "ABCDEF12345");+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567889");+  a.ShiftLeft(11*4);+  AssignHexString(&b, "ABCDEF12345");+  AssignHexString(&c, "1234567890ABCDEF12345");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF12345");+  c.ShiftLeft(32);+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12344");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF12345");+  c.ShiftLeft(32);+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12346");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF12345");+  c.ShiftLeft(32);+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567891");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF12345");+  c.ShiftLeft(32);+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567889");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF12345");+  c.ShiftLeft(32);+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF1234500000000");+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12344");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF1234500000000");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12346");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF1234500000000");+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567891");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF1234500000000");+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567889");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(32);+  AssignHexString(&c, "1234567890ABCDEF1234500000000");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  AssignHexString(&c, "123456789000000000ABCDEF12345");+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12346");+  AssignHexString(&c, "123456789000000000ABCDEF12345");+  CHECK_EQ(1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12344");+  AssignHexString(&c, "123456789000000000ABCDEF12345");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(16);+  AssignHexString(&c, "12345678900000ABCDEF123450000");+  CHECK_EQ(0, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12344");+  b.ShiftLeft(16);+  AssignHexString(&c, "12345678900000ABCDEF123450000");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12345");+  b.ShiftLeft(16);+  AssignHexString(&c, "12345678900000ABCDEF123450001");+  CHECK_EQ(-1, Bignum::PlusCompare(a, b, c));++  AssignHexString(&a, "1234567890");+  a.ShiftLeft(11*4 + 32);+  AssignHexString(&b, "ABCDEF12346");+  b.ShiftLeft(16);+  AssignHexString(&c, "12345678900000ABCDEF123450000");+  CHECK_EQ(+1, Bignum::PlusCompare(a, b, c));+}+++TEST(Square) {+  Bignum bignum;+  char buffer[kBufferSize];++  bignum.AssignUInt16(1);+  bignum.Square();+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignUInt16(2);+  bignum.Square();+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("4", buffer);++  bignum.AssignUInt16(10);+  bignum.Square();+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("64", buffer);++  AssignHexString(&bignum, "FFFFFFF");+  bignum.Square();+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFE0000001", buffer);++  AssignHexString(&bignum, "FFFFFFFFFFFFFF");+  bignum.Square();+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FFFFFFFFFFFFFE00000000000001", buffer);+}+++TEST(AssignPowerUInt16) {+  Bignum bignum;+  char buffer[kBufferSize];++  bignum.AssignPowerUInt16(1, 0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(1, 1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(1, 2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(2, 0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(2, 1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2", buffer);++  bignum.AssignPowerUInt16(2, 2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("4", buffer);++  bignum.AssignPowerUInt16(16, 1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10", buffer);++  bignum.AssignPowerUInt16(16, 2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100", buffer);++  bignum.AssignPowerUInt16(16, 5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000", buffer);++  bignum.AssignPowerUInt16(16, 8);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("100000000", buffer);++  bignum.AssignPowerUInt16(16, 16);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000", buffer);++  bignum.AssignPowerUInt16(16, 30);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1000000000000000000000000000000", buffer);++  bignum.AssignPowerUInt16(10, 0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(10, 1);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("A", buffer);++  bignum.AssignPowerUInt16(10, 2);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("64", buffer);++  bignum.AssignPowerUInt16(10, 5);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("186A0", buffer);++  bignum.AssignPowerUInt16(10, 8);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("5F5E100", buffer);++  bignum.AssignPowerUInt16(10, 16);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("2386F26FC10000", buffer);++  bignum.AssignPowerUInt16(10, 30);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("C9F2C9CD04674EDEA40000000", buffer);++  bignum.AssignPowerUInt16(10, 31);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("7E37BE2022C0914B2680000000", buffer);++  bignum.AssignPowerUInt16(2, 0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(2, 100);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("10000000000000000000000000", buffer);++  bignum.AssignPowerUInt16(17, 0);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1", buffer);++  bignum.AssignPowerUInt16(17, 99);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("1942BB9853FAD924A3D4DD92B89B940E0207BEF05DB9C26BC1B757"+           "80BE0C5A2C2990E02A681224F34ED68558CE4C6E33760931",+           buffer);++  bignum.AssignPowerUInt16(0xFFFF, 99);+  CHECK(bignum.ToHexString(buffer, kBufferSize));+  CHECK_EQ("FF9D12F09B886C54E77E7439C7D2DED2D34F669654C0C2B6B8C288250"+           "5A2211D0E3DC9A61831349EAE674B11D56E3049D7BD79DAAD6C9FA2BA"+           "528E3A794299F2EE9146A324DAFE3E88967A0358233B543E233E575B9"+           "DD4E3AA7942146426C328FF55BFD5C45E0901B1629260AF9AE2F310C5"+           "50959FAF305C30116D537D80CF6EBDBC15C5694062AF1AC3D956D0A41"+           "B7E1B79FF11E21D83387A1CE1F5882B31E4B5D8DE415BDBE6854466DF"+           "343362267A7E8833119D31D02E18DB5B0E8F6A64B0ED0D0062FFFF",+           buffer);+}
+ double-conversion/test/cctest/test-conversions.cc view
@@ -0,0 +1,3039 @@+// Copyright 2010 the V8 project authors. All rights reserved.++#include <string.h>++#include "cctest.h"+#include "double.h"+#include "double-conversion.h"+#include "utils.h"++// DoubleToString is already tested in test-dtoa.cc.++using namespace double_conversion;+++TEST(DoubleToShortest) {+  const int kBufferSize = 128;+  char buffer[kBufferSize];+  StringBuilder builder(buffer, kBufferSize);+  int flags = DoubleToStringConverter::UNIQUE_ZERO |+      DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;+  DoubleToStringConverter dc(flags, NULL, NULL, 'e', -6, 21, 0, 0);++  CHECK(dc.ToShortest(0.0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(12345.0, &builder));+  CHECK_EQ("12345", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(12345e23, &builder));+  CHECK_EQ("1.2345e+27", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(1e21, &builder));+  CHECK_EQ("1e+21", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(1e20, &builder));+  CHECK_EQ("100000000000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(111111111111111111111.0, &builder));+  CHECK_EQ("111111111111111110000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(1111111111111111111111.0, &builder));+  CHECK_EQ("1.1111111111111111e+21", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(11111111111111111111111.0, &builder));+  CHECK_EQ("1.1111111111111111e+22", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.00001, &builder));+  CHECK_EQ("-0.00001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.000001, &builder));+  CHECK_EQ("-0.000001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0000001, &builder));+  CHECK_EQ("-1e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0, &builder));+  CHECK_EQ("0", builder.Finalize());++  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc2(flags, NULL, NULL, 'e', -1, 1, 0, 0);+  builder.Reset();+  CHECK(dc2.ToShortest(0.1, &builder));+  CHECK_EQ("0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToShortest(0.01, &builder));+  CHECK_EQ("1e-2", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToShortest(1.0, &builder));+  CHECK_EQ("1", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToShortest(10.0, &builder));+  CHECK_EQ("1e1", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToShortest(-0.0, &builder));+  CHECK_EQ("-0", builder.Finalize());++  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |+      DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;+  DoubleToStringConverter dc3(flags, NULL, NULL, 'E', -5, 5, 0, 0);++  builder.Reset();+  CHECK(dc3.ToShortest(0.1, &builder));+  CHECK_EQ("0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToShortest(1.0, &builder));+  CHECK_EQ("1.0", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToShortest(10000.0, &builder));+  CHECK_EQ("10000.0", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToShortest(100000.0, &builder));+  CHECK_EQ("1E5", builder.Finalize());++  // Test the examples in the comments of ToShortest.+  flags = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;+  DoubleToStringConverter dc4(flags, NULL, NULL, 'e', -6, 21, 0, 0);++  builder.Reset();+  CHECK(dc4.ToShortest(0.000001, &builder));+  CHECK_EQ("0.000001", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToShortest(0.0000001, &builder));+  CHECK_EQ("1e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToShortest(111111111111111111111.0, &builder));+  CHECK_EQ("111111111111111110000", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToShortest(100000000000000000000.0, &builder));+  CHECK_EQ("100000000000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToShortest(1111111111111111111111.0, &builder));+  CHECK_EQ("1.1111111111111111e+21", builder.Finalize());++  // Test special value handling.+  DoubleToStringConverter dc5(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(!dc5.ToShortest(Double::Infinity(), &builder));++  builder.Reset();+  CHECK(!dc5.ToShortest(-Double::Infinity(), &builder));++  builder.Reset();+  CHECK(!dc5.ToShortest(Double::NaN(), &builder));++  builder.Reset();+  CHECK(!dc5.ToShortest(-Double::NaN(), &builder));++  DoubleToStringConverter dc6(flags, "Infinity", "NaN", 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc6.ToShortest(Double::Infinity(), &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc6.ToShortest(-Double::Infinity(), &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc6.ToShortest(Double::NaN(), &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc6.ToShortest(-Double::NaN(), &builder));+  CHECK_EQ("NaN", builder.Finalize());+}+++TEST(DoubleToFixed) {+  const int kBufferSize = 128;+  char buffer[kBufferSize];+  StringBuilder builder(buffer, kBufferSize);+  int flags = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |+      DoubleToStringConverter::UNIQUE_ZERO;+  DoubleToStringConverter dc(flags, "Infinity", "NaN", 'e',+                             0, 0, 0, 0);  // Padding zeroes.++  CHECK(dc.ToFixed(0.0, 0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.0, 0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.0, 1, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.0, 1, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  ASSERT(DoubleToStringConverter::kMaxFixedDigitsBeforePoint == 60);+  ASSERT(DoubleToStringConverter::kMaxFixedDigitsAfterPoint == 60);+  builder.Reset();+  CHECK(dc.ToFixed(+      0.0, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));+  CHECK_EQ("0.000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(+      9e59, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));+  CHECK_EQ("899999999999999918767229449717619953810131273674690656206848."+           "000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(+      -9e59, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));+  CHECK_EQ("-899999999999999918767229449717619953810131273674690656206848."+           "000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  builder.Reset();+  CHECK(!dc.ToFixed(+      1e60, DoubleToStringConverter::kMaxFixedDigitsAfterPoint, &builder));+  CHECK_EQ(0, builder.position());++  builder.Reset();+  CHECK(!dc.ToFixed(+      9e59, DoubleToStringConverter::kMaxFixedDigitsAfterPoint + 1, &builder));+  CHECK_EQ(0, builder.position());++  builder.Reset();+  CHECK(dc.ToFixed(3.0, 0, &builder));+  CHECK_EQ("3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(3.23, 1, &builder));+  CHECK_EQ("3.2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(3.23, 3, &builder));+  CHECK_EQ("3.230", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.0323, 2, &builder));+  CHECK_EQ("0.03", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.0373, 2, &builder));+  CHECK_EQ("0.04", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.0000373, 2, &builder));+  CHECK_EQ("0.00", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1.5, 0, &builder));+  CHECK_EQ("2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(2.5, 0, &builder));+  CHECK_EQ("3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(3.5, 0, &builder));+  CHECK_EQ("4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.15, 1, &builder));+  CHECK_EQ("0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.25, 1, &builder));+  CHECK_EQ("0.3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.35, 1, &builder));+  CHECK_EQ("0.3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.45, 1, &builder));+  CHECK_EQ("0.5", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.55, 1, &builder));+  CHECK_EQ("0.6", builder.Finalize());++  // Test positive/negative zeroes.+  int flags2 = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;+  DoubleToStringConverter dc2(flags2, "Infinity", "NaN", 'e',+                              0, 0, 0, 0);  // Padding zeroes.+  builder.Reset();+  CHECK(dc2.ToFixed(0.0, 1, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToFixed(-0.0, 1, &builder));+  CHECK_EQ("-0.0", builder.Finalize());++  // Verify the trailing dot is emitted.+  int flags3 = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |+      DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT;+  DoubleToStringConverter dc3(flags3, "Infinity", "NaN", 'e',+                              0, 0, 0, 0);  // Padding zeroes.+  builder.Reset();+  CHECK(dc3.ToFixed(0.0, 0, &builder));+  CHECK_EQ("0.", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToFixed(-0.0, 0, &builder));+  CHECK_EQ("-0.", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToFixed(1.0, 0, &builder));+  CHECK_EQ("1.", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToFixed(-1.0, 0, &builder));+  CHECK_EQ("-1.", builder.Finalize());++  // Verify no trailing zero is emitted, even if the configuration is set.+  // The given parameter takes precedence.+  int flags4 = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |+      DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |+      DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;+  DoubleToStringConverter dc4(flags4, "Infinity", "NaN", 'e',+                              0, 0, 0, 0);  // Padding zeroes.+  builder.Reset();+  CHECK(dc4.ToFixed(0.0, 0, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToFixed(-0.0, 0, &builder));+  CHECK_EQ("-0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToFixed(1.0, 0, &builder));+  CHECK_EQ("1.0", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToFixed(-1.0, 0, &builder));+  CHECK_EQ("-1.0", builder.Finalize());++  // Test the examples in the comments of ToFixed.+  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc5(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc5.ToFixed(3.12, 1, &builder));+  CHECK_EQ("3.1", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(3.1415, 3, &builder));+  CHECK_EQ("3.142", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(1234.56789, 4, &builder));+  CHECK_EQ("1234.5679", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(1.23, 5, &builder));+  CHECK_EQ("1.23000", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(0.1, 4, &builder));+  CHECK_EQ("0.1000", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(1e30, 2, &builder));+  CHECK_EQ("1000000000000000019884624838656.00", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(0.1, 30, &builder));+  CHECK_EQ("0.100000000000000005551115123126", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(0.1, 17, &builder));+  CHECK_EQ("0.10000000000000001", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(123.45, 0, &builder));+  CHECK_EQ("123", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToFixed(0.678, 0, &builder));+  CHECK_EQ("1", builder.Finalize());++  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT;+  DoubleToStringConverter dc6(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc6.ToFixed(123.45, 0, &builder));+  CHECK_EQ("123.", builder.Finalize());++  builder.Reset();+  CHECK(dc6.ToFixed(0.678, 0, &builder));+  CHECK_EQ("1.", builder.Finalize());++  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |+      DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;+  DoubleToStringConverter dc7(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc7.ToFixed(123.45, 0, &builder));+  CHECK_EQ("123.0", builder.Finalize());++  builder.Reset();+  CHECK(dc7.ToFixed(0.678, 0, &builder));+  CHECK_EQ("1.0", builder.Finalize());++  // Test special value handling.+  DoubleToStringConverter dc8(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(!dc8.ToFixed(Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToFixed(-Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToFixed(Double::NaN(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToFixed(-Double::NaN(), 1, &builder));++  DoubleToStringConverter dc9(flags, "Infinity", "NaN", 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc9.ToFixed(Double::Infinity(), 1, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc9.ToFixed(-Double::Infinity(), 1, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc9.ToFixed(Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc9.ToFixed(-Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());+}+++TEST(DoubleToExponential) {+  const int kBufferSize = 256;+  char buffer[kBufferSize];+  int flags = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |+      DoubleToStringConverter::UNIQUE_ZERO;+  StringBuilder builder(buffer, kBufferSize);+  DoubleToStringConverter dc(flags, "Infinity", "NaN", 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc.ToExponential(0.0, 5, &builder));+  CHECK_EQ("0.00000e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0, 0, &builder));+  CHECK_EQ("0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0, 1, &builder));+  CHECK_EQ("0.0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.123456, 5, &builder));+  CHECK_EQ("1.23456e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.2, 1, &builder));+  CHECK_EQ("1.2e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.0, 1, &builder));+  CHECK_EQ("0.0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0, 2, &builder));+  CHECK_EQ("0.00e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.0, 2, &builder));+  CHECK_EQ("0.00e+0", builder.Finalize());++  ASSERT(DoubleToStringConverter::kMaxExponentialDigits == 120);+  builder.Reset();+  CHECK(dc.ToExponential(+      0.0, DoubleToStringConverter::kMaxExponentialDigits, &builder));+  CHECK_EQ("0.00000000000000000000000000000000000000000000000000000000000"+           "0000000000000000000000000000000000000000000000000000000000000e+0",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(+      9e59, DoubleToStringConverter::kMaxExponentialDigits, &builder));+  CHECK_EQ("8.99999999999999918767229449717619953810131273674690656206848"+           "0000000000000000000000000000000000000000000000000000000000000e+59",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(+      -9e59, DoubleToStringConverter::kMaxExponentialDigits, &builder));+  CHECK_EQ("-8.99999999999999918767229449717619953810131273674690656206848"+           "0000000000000000000000000000000000000000000000000000000000000e+59",+           builder.Finalize());++  const double max_double = 1.7976931348623157e308;+  builder.Reset();+  CHECK(dc.ToExponential(+      max_double, DoubleToStringConverter::kMaxExponentialDigits, &builder));+  CHECK_EQ("1.79769313486231570814527423731704356798070567525844996598917"+           "4768031572607800285387605895586327668781715404589535143824642e+308",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.000001, 2, &builder));+  CHECK_EQ("1.00e-6", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0000001, 2, &builder));+  CHECK_EQ("1.00e-7", builder.Finalize());++  // Test the examples in the comments of ToExponential.+  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc2(flags, "Infinity", "NaN", 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc2.ToExponential(3.12, 1, &builder));+  CHECK_EQ("3.1e0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(5.0, 3, &builder));+  CHECK_EQ("5.000e0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(0.001, 2, &builder));+  CHECK_EQ("1.00e-3", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(3.1415, -1, &builder));+  CHECK_EQ("3.1415e0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(3.1415, 4, &builder));+  CHECK_EQ("3.1415e0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(3.1415, 3, &builder));+  CHECK_EQ("3.142e0", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(123456789000000, 3, &builder));+  CHECK_EQ("1.235e14", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(1000000000000000019884624838656.0, -1, &builder));+  CHECK_EQ("1e30", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(1000000000000000019884624838656.0, 32, &builder));+  CHECK_EQ("1.00000000000000001988462483865600e30", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToExponential(1234, 0, &builder));+  CHECK_EQ("1e3", builder.Finalize());++  // Test special value handling.+  DoubleToStringConverter dc3(flags, NULL, NULL, 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(!dc3.ToExponential(Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc3.ToExponential(-Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc3.ToExponential(Double::NaN(), 1, &builder));++  builder.Reset();+  CHECK(!dc3.ToExponential(-Double::NaN(), 1, &builder));++  DoubleToStringConverter dc4(flags, "Infinity", "NaN", 'e', 0, 0, 0, 0);++  builder.Reset();+  CHECK(dc4.ToExponential(Double::Infinity(), 1, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToExponential(-Double::Infinity(), 1, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToExponential(Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToExponential(-Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());+}+++TEST(DoubleToPrecision) {+  const int kBufferSize = 256;+  char buffer[kBufferSize];+  int flags = DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |+      DoubleToStringConverter::UNIQUE_ZERO;+  StringBuilder builder(buffer, kBufferSize);+  DoubleToStringConverter dc(flags, "Infinity", "NaN", 'e',+                             0, 0,   // Padding zeroes for shortest mode.+                             6, 0);  // Padding zeroes for precision mode.++  ASSERT(DoubleToStringConverter::kMinPrecisionDigits == 1);+  CHECK(dc.ToPrecision(0.0, 1, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-0.0, 1, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(0.0, 2, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-0.0, 2, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  ASSERT(DoubleToStringConverter::kMaxPrecisionDigits == 120);+  builder.Reset();+  CHECK(dc.ToPrecision(+      0.0, DoubleToStringConverter::kMaxPrecisionDigits, &builder));+  CHECK_EQ("0.00000000000000000000000000000000000000000000000000000000000"+           "000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(+      9e59, DoubleToStringConverter::kMaxPrecisionDigits, &builder));+  CHECK_EQ("899999999999999918767229449717619953810131273674690656206848."+           "000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(+      -9e59, DoubleToStringConverter::kMaxPrecisionDigits, &builder));+  CHECK_EQ("-899999999999999918767229449717619953810131273674690656206848."+           "000000000000000000000000000000000000000000000000000000000000",+           builder.Finalize());++  const double max_double = 1.7976931348623157e308;+  builder.Reset();+  CHECK(dc.ToPrecision(+      max_double, DoubleToStringConverter::kMaxPrecisionDigits, &builder));+  CHECK_EQ("1.79769313486231570814527423731704356798070567525844996598917"+           "476803157260780028538760589558632766878171540458953514382464e+308",+           builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(0.000001, 2, &builder));+  CHECK_EQ("0.0000010", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(0.0000001, 2, &builder));+  CHECK_EQ("1.0e-7", builder.Finalize());++  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc2(flags, NULL, NULL, 'e', 0, 0, 0, 1);+  builder.Reset();+  CHECK(dc2.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("230", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToPrecision(23.0, 2, &builder));+  CHECK_EQ("23", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToPrecision(2.30, 2, &builder));+  CHECK_EQ("2.3", builder.Finalize());++  builder.Reset();+  CHECK(dc2.ToPrecision(2300.0, 2, &builder));+  CHECK_EQ("2.3e3", builder.Finalize());++  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT;+  DoubleToStringConverter dc3(flags, NULL, NULL, 'e', 0, 0, 0, 1);+  builder.Reset();+  CHECK(dc3.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("230.", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToPrecision(23.0, 2, &builder));+  CHECK_EQ("23.", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToPrecision(2.30, 2, &builder));+  CHECK_EQ("2.3", builder.Finalize());++  builder.Reset();+  CHECK(dc3.ToPrecision(2300.0, 2, &builder));+  CHECK_EQ("2.3e3", builder.Finalize());++  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |+      DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;+  DoubleToStringConverter dc4(flags, NULL, NULL, 'e', 0, 0, 0, 1);+  builder.Reset();+  CHECK(dc4.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("2.3e2", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToPrecision(23.0, 2, &builder));+  CHECK_EQ("23.0", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToPrecision(2.30, 2, &builder));+  CHECK_EQ("2.3", builder.Finalize());++  builder.Reset();+  CHECK(dc4.ToPrecision(2300.0, 2, &builder));+  CHECK_EQ("2.3e3", builder.Finalize());++  // Test the examples in the comments of ToPrecision.+  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc5(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);+  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT;+  DoubleToStringConverter dc6(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);+  flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |+      DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;+  DoubleToStringConverter dc7(flags, "Infinity", "NaN", 'e', 0, 0, 6, 1);++  builder.Reset();+  CHECK(dc5.ToPrecision(0.0000012345, 2, &builder));+  CHECK_EQ("0.0000012", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToPrecision(0.00000012345, 2, &builder));+  CHECK_EQ("1.2e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc5.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("230", builder.Finalize());++  builder.Reset();+  CHECK(dc6.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("230.", builder.Finalize());++  builder.Reset();+  CHECK(dc7.ToPrecision(230.0, 2, &builder));+  CHECK_EQ("2.3e2", builder.Finalize());++  flags = DoubleToStringConverter::NO_FLAGS;+  DoubleToStringConverter dc8(flags, NULL, NULL, 'e', 0, 0, 6, 3);++  builder.Reset();+  CHECK(dc8.ToPrecision(123450.0, 6, &builder));+  CHECK_EQ("123450", builder.Finalize());++  builder.Reset();+  CHECK(dc8.ToPrecision(123450.0, 5, &builder));+  CHECK_EQ("123450", builder.Finalize());++  builder.Reset();+  CHECK(dc8.ToPrecision(123450.0, 4, &builder));+  CHECK_EQ("123500", builder.Finalize());++  builder.Reset();+  CHECK(dc8.ToPrecision(123450.0, 3, &builder));+  CHECK_EQ("123000", builder.Finalize());++  builder.Reset();+  CHECK(dc8.ToPrecision(123450.0, 2, &builder));+  CHECK_EQ("1.2e5", builder.Finalize());++  // Test special value handling.+  builder.Reset();+  CHECK(!dc8.ToPrecision(Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToPrecision(-Double::Infinity(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToPrecision(Double::NaN(), 1, &builder));++  builder.Reset();+  CHECK(!dc8.ToPrecision(-Double::NaN(), 1, &builder));++  builder.Reset();+  CHECK(dc7.ToPrecision(Double::Infinity(), 1, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc7.ToPrecision(-Double::Infinity(), 1, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc7.ToPrecision(Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc7.ToPrecision(-Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());+}+++TEST(DoubleToStringJavaScript) {+  const int kBufferSize = 128;+  char buffer[kBufferSize];+  StringBuilder builder(buffer, kBufferSize);+  const DoubleToStringConverter& dc =+      DoubleToStringConverter::EcmaScriptConverter();++  builder.Reset();+  CHECK(dc.ToShortest(Double::NaN(), &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(Double::Infinity(), &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-Double::Infinity(), &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(9.0, &builder));+  CHECK_EQ("9", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(90.0, &builder));+  CHECK_EQ("90", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(90.12, &builder));+  CHECK_EQ("90.12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.1, &builder));+  CHECK_EQ("0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.01, &builder));+  CHECK_EQ("0.01", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.0123, &builder));+  CHECK_EQ("0.0123", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(111111111111111111111.0, &builder));+  CHECK_EQ("111111111111111110000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(100000000000000000000.0, &builder));+  CHECK_EQ("100000000000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(1111111111111111111111.0, &builder));+  CHECK_EQ("1.1111111111111111e+21", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(11111111111111111111111.0, &builder));+  CHECK_EQ("1.1111111111111111e+22", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.00001, &builder));+  CHECK_EQ("0.00001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.000001, &builder));+  CHECK_EQ("0.000001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.0000001, &builder));+  CHECK_EQ("1e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.00000012, &builder));+  CHECK_EQ("1.2e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.000000123, &builder));+  CHECK_EQ("1.23e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.00000001, &builder));+  CHECK_EQ("1e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.000000012, &builder));+  CHECK_EQ("1.2e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.000000012, &builder));+  CHECK_EQ("1.2e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(0.0000000123, &builder));+  CHECK_EQ("1.23e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-9.0, &builder));+  CHECK_EQ("-9", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-90.0, &builder));+  CHECK_EQ("-90", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-90.12, &builder));+  CHECK_EQ("-90.12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.1, &builder));+  CHECK_EQ("-0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.01, &builder));+  CHECK_EQ("-0.01", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0123, &builder));+  CHECK_EQ("-0.0123", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-111111111111111111111.0, &builder));+  CHECK_EQ("-111111111111111110000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-1111111111111111111111.0, &builder));+  CHECK_EQ("-1.1111111111111111e+21", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-11111111111111111111111.0, &builder));+  CHECK_EQ("-1.1111111111111111e+22", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.00001, &builder));+  CHECK_EQ("-0.00001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.000001, &builder));+  CHECK_EQ("-0.000001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0000001, &builder));+  CHECK_EQ("-1e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.00000012, &builder));+  CHECK_EQ("-1.2e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.000000123, &builder));+  CHECK_EQ("-1.23e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.00000001, &builder));+  CHECK_EQ("-1e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.000000012, &builder));+  CHECK_EQ("-1.2e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.000000012, &builder));+  CHECK_EQ("-1.2e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToShortest(-0.0000000123, &builder));+  CHECK_EQ("-1.23e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(Double::NaN(), 2, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(Double::Infinity(), 2, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-Double::Infinity(), 2, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.1, 1, &builder));+  CHECK_EQ("-0.1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.1, 2, &builder));+  CHECK_EQ("-0.10", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.1, 3, &builder));+  CHECK_EQ("-0.100", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.01, 2, &builder));+  CHECK_EQ("-0.01", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.01, 3, &builder));+  CHECK_EQ("-0.010", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.01, 4, &builder));+  CHECK_EQ("-0.0100", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.001, 2, &builder));+  CHECK_EQ("-0.00", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.001, 3, &builder));+  CHECK_EQ("-0.001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.001, 4, &builder));+  CHECK_EQ("-0.0010", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1.0, 4, &builder));+  CHECK_EQ("-1.0000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1.0, 1, &builder));+  CHECK_EQ("-1.0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1.0, 0, &builder));+  CHECK_EQ("-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-12.0, 0, &builder));+  CHECK_EQ("-12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1.1, 0, &builder));+  CHECK_EQ("-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-12.1, 0, &builder));+  CHECK_EQ("-12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1.12, 0, &builder));+  CHECK_EQ("-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-12.12, 0, &builder));+  CHECK_EQ("-12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.0000006, 7, &builder));+  CHECK_EQ("-0.0000006", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.00000006, 8, &builder));+  CHECK_EQ("-0.00000006", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.00000006, 9, &builder));+  CHECK_EQ("-0.000000060", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.00000006, 10, &builder));+  CHECK_EQ("-0.0000000600", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0, 0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0, 1, &builder));+  CHECK_EQ("0.0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0, 2, &builder));+  CHECK_EQ("0.00", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1000, 0, &builder));+  CHECK_EQ("1000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.00001, 0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.00001, 5, &builder));+  CHECK_EQ("0.00001", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.0000000000000000001, 20, &builder));+  CHECK_EQ("0.00000000000000000010", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.00001, 17, &builder));+  CHECK_EQ("0.00001000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1000000000000000128.0, 0, &builder));+  CHECK_EQ("1000000000000000128", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1000000000000000128.0, 1, &builder));+  CHECK_EQ("1000000000000000128.0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1000000000000000128.0, 2, &builder));+  CHECK_EQ("1000000000000000128.00", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1000000000000000128.0, 20, &builder));+  CHECK_EQ("1000000000000000128.00000000000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.0, 0, &builder));+  CHECK_EQ("0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-42.0, 3, &builder));+  CHECK_EQ("-42.000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-1000000000000000128.0, 0, &builder));+  CHECK_EQ("-1000000000000000128", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.0000000000000000001, 20, &builder));+  CHECK_EQ("-0.00000000000000000010", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.123123123123123, 20, &builder));+  CHECK_EQ("0.12312312312312299889", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(0.5, 0, &builder));+  CHECK_EQ("1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(-0.5, 0, &builder));+  CHECK_EQ("-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(1.25, 1, &builder));+  CHECK_EQ("1.3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(234.20405, 4, &builder));+  CHECK_EQ("234.2040", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToFixed(234.2040506, 4, &builder));+  CHECK_EQ("234.2041", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, -1, &builder));+  CHECK_EQ("1e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.0, -1, &builder));+  CHECK_EQ("1.1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(112.0, -1, &builder));+  CHECK_EQ("1.12e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, 0, &builder));+  CHECK_EQ("1e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.0, 0, &builder));+  CHECK_EQ("1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(112.0, 0, &builder));+  CHECK_EQ("1e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, 1, &builder));+  CHECK_EQ("1.0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.0, 1, &builder));+  CHECK_EQ("1.1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(112.0, 1, &builder));+  CHECK_EQ("1.1e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, 2, &builder));+  CHECK_EQ("1.00e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.0, 2, &builder));+  CHECK_EQ("1.10e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(112.0, 2, &builder));+  CHECK_EQ("1.12e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, 3, &builder));+  CHECK_EQ("1.000e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.0, 3, &builder));+  CHECK_EQ("1.100e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(112.0, 3, &builder));+  CHECK_EQ("1.120e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.1, -1, &builder));+  CHECK_EQ("1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.11, -1, &builder));+  CHECK_EQ("1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.112, -1, &builder));+  CHECK_EQ("1.12e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.1, 0, &builder));+  CHECK_EQ("1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.11, 0, &builder));+  CHECK_EQ("1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.112, 0, &builder));+  CHECK_EQ("1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.1, 1, &builder));+  CHECK_EQ("1.0e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.11, 1, &builder));+  CHECK_EQ("1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.112, 1, &builder));+  CHECK_EQ("1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.1, 2, &builder));+  CHECK_EQ("1.00e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.11, 2, &builder));+  CHECK_EQ("1.10e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.112, 2, &builder));+  CHECK_EQ("1.12e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.1, 3, &builder));+  CHECK_EQ("1.000e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.11, 3, &builder));+  CHECK_EQ("1.100e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.112, 3, &builder));+  CHECK_EQ("1.120e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-1.0, -1, &builder));+  CHECK_EQ("-1e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-11.0, -1, &builder));+  CHECK_EQ("-1.1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-112.0, -1, &builder));+  CHECK_EQ("-1.12e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-1.0, 0, &builder));+  CHECK_EQ("-1e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-11.0, 0, &builder));+  CHECK_EQ("-1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-112.0, 0, &builder));+  CHECK_EQ("-1e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-1.0, 1, &builder));+  CHECK_EQ("-1.0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-11.0, 1, &builder));+  CHECK_EQ("-1.1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-112.0, 1, &builder));+  CHECK_EQ("-1.1e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-1.0, 2, &builder));+  CHECK_EQ("-1.00e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-11.0, 2, &builder));+  CHECK_EQ("-1.10e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-112.0, 2, &builder));+  CHECK_EQ("-1.12e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-1.0, 3, &builder));+  CHECK_EQ("-1.000e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-11.0, 3, &builder));+  CHECK_EQ("-1.100e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-112.0, 3, &builder));+  CHECK_EQ("-1.120e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.1, -1, &builder));+  CHECK_EQ("-1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.11, -1, &builder));+  CHECK_EQ("-1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.112, -1, &builder));+  CHECK_EQ("-1.12e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.1, 0, &builder));+  CHECK_EQ("-1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.11, 0, &builder));+  CHECK_EQ("-1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.112, 0, &builder));+  CHECK_EQ("-1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.1, 1, &builder));+  CHECK_EQ("-1.0e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.11, 1, &builder));+  CHECK_EQ("-1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.112, 1, &builder));+  CHECK_EQ("-1.1e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.1, 2, &builder));+  CHECK_EQ("-1.00e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.11, 2, &builder));+  CHECK_EQ("-1.10e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.112, 2, &builder));+  CHECK_EQ("-1.12e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.1, 3, &builder));+  CHECK_EQ("-1.000e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.11, 3, &builder));+  CHECK_EQ("-1.100e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.112, 3, &builder));+  CHECK_EQ("-1.120e-1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(Double::NaN(), 2, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(Double::Infinity(), 2, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-Double::Infinity(), 2, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(1.0, 0, &builder));+  CHECK_EQ("1e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0, -1, &builder));+  CHECK_EQ("0e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.0, 2, &builder));+  CHECK_EQ("0.00e+0", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.2356, 0, &builder));+  CHECK_EQ("1e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(11.2356, 4, &builder));+  CHECK_EQ("1.1236e+1", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.000112356, 4, &builder));+  CHECK_EQ("1.1236e-4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.000112356, 4, &builder));+  CHECK_EQ("-1.1236e-4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(0.000112356, -1, &builder));+  CHECK_EQ("1.12356e-4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToExponential(-0.000112356, -1, &builder));+  CHECK_EQ("-1.12356e-4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(Double::NaN(), 1, &builder));+  CHECK_EQ("NaN", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(Double::Infinity(), 2, &builder));+  CHECK_EQ("Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-Double::Infinity(), 2, &builder));+  CHECK_EQ("-Infinity", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(0.000555, 15, &builder));+  CHECK_EQ("0.000555000000000000", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(0.000000555, 15, &builder));+  CHECK_EQ("5.55000000000000e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-0.000000555, 15, &builder));+  CHECK_EQ("-5.55000000000000e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(123456789.0, 1, &builder));+  CHECK_EQ("1e+8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(123456789.0, 9, &builder));+  CHECK_EQ("123456789", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(123456789.0, 8, &builder));+  CHECK_EQ("1.2345679e+8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(123456789.0, 7, &builder));+  CHECK_EQ("1.234568e+8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-123456789.0, 7, &builder));+  CHECK_EQ("-1.234568e+8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.0000000012345, 2, &builder));+  CHECK_EQ("-1.2e-9", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.000000012345, 2, &builder));+  CHECK_EQ("-1.2e-8", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.00000012345, 2, &builder));+  CHECK_EQ("-1.2e-7", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.0000012345, 2, &builder));+  CHECK_EQ("-0.0000012", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.000012345, 2, &builder));+  CHECK_EQ("-0.000012", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.00012345, 2, &builder));+  CHECK_EQ("-0.00012", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.0012345, 2, &builder));+  CHECK_EQ("-0.0012", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.012345, 2, &builder));+  CHECK_EQ("-0.012", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-.12345, 2, &builder));+  CHECK_EQ("-0.12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-1.2345, 2, &builder));+  CHECK_EQ("-1.2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-12.345, 2, &builder));+  CHECK_EQ("-12", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-123.45, 2, &builder));+  CHECK_EQ("-1.2e+2", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-1234.5, 2, &builder));+  CHECK_EQ("-1.2e+3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-12345.0, 2, &builder));+  CHECK_EQ("-1.2e+4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-12345.67, 4, &builder));+  CHECK_EQ("-1.235e+4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(-12344.67, 4, &builder));+  CHECK_EQ("-1.234e+4", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(1.25, 2, &builder));+  CHECK_EQ("1.3", builder.Finalize());++  builder.Reset();+  CHECK(dc.ToPrecision(1.35, 2, &builder));+  CHECK_EQ("1.4", builder.Finalize());+}+++static double StrToD(const char* str, int flags, double empty_string_value,+                     int* processed_characters_count, bool* processed_all) {+  StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),+                                    NULL, NULL);+  double result = converter.StringToDouble(str, strlen(str),+                                           processed_characters_count);+  *processed_all = ((strlen(str) == *processed_characters_count));+  return result;+}+++TEST(StringToDoubleVarious) {+  int flags;+  int processed;+  bool all_used;++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES;++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("  ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("  ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD("42", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD(" + 42 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-42.0, StrToD(" - 42 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("42x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" + 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" - 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("  ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("  ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD("42", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD(" + 42 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-42.0, StrToD(" - 42 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(42.0, StrToD("42x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(42.0, StrToD("42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(42.0, StrToD(" + 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(6, processed);++  CHECK_EQ(-42.0, StrToD(" - 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(6, processed);+++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("  ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("  ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD("42", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD(" + 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(5, processed);++  CHECK_EQ(-42.0, StrToD(" - 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(5, processed);++  CHECK_EQ(Double::NaN(), StrToD("x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(42.0, StrToD("42x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(42.0, StrToD("42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(42.0, StrToD(" + 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(5, processed);++  CHECK_EQ(-42.0, StrToD(" - 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(5, processed);++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;++  CHECK_EQ(42.0, StrToD(" +42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(4, processed);++  CHECK_EQ(-42.0, StrToD(" -42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(4, processed);++  CHECK_EQ(Double::NaN(), StrToD(" + 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" - 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::NO_FLAGS;++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("  ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("  ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(42.0, StrToD("42", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" + 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" - 42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" x", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("42x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" + 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" - 42 x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES;++  CHECK_EQ(0.0, StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD(" 42", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("42 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::ALLOW_TRAILING_SPACES;++  CHECK_EQ(0.0, StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(42.0, StrToD("42 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 42", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+}+++TEST(StringToDoubleEmptyString) {+  int flags;+  int processed;+  bool all_used;++  flags = StringToDoubleConverter::NO_FLAGS;+  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  flags = StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;+  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  flags = StringToDoubleConverter::ALLOW_LEADING_SPACES;+  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  flags = StringToDoubleConverter::ALLOW_TRAILING_SPACES;+  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK;+  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD("", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+}+++TEST(StringToDoubleHexString) {+  int flags;+  int processed;+  bool all_used;++  flags = StringToDoubleConverter::ALLOW_HEX |+      StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;++  CHECK_EQ(18.0, StrToD("0x12", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("0x0", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD("0x123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(18.0, StrToD(" 0x12 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" 0x0 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD(" 0x123456789 ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xabcdef", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xABCDEF", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD(" 0xabcdef ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD(" 0xABCDEF ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x ", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x 3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x3g", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x3.23", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("x3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x3 foo", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x3 foo", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ 0x3 foo", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("-", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(-5.0, StrToD("-0x5", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-5.0, StrToD(" - 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(5.0, StrToD(" + 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("- -0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("- +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  flags = StringToDoubleConverter::ALLOW_HEX;++  CHECK_EQ(18.0, StrToD("0x12", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("0x0", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD("0x123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 0x12 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x0 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x123456789 ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xabcdef", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xABCDEF", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xabcdef ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xABCDEF ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x ", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x 3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x3g", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x3.23", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("x3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ 0x3 foo", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("-", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(-5.0, StrToD("-0x5", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" - 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" + 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("- -0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("- +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |+      StringToDoubleConverter::ALLOW_HEX;++  CHECK_EQ(18.0, StrToD("0x12", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("0x0", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD("0x123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 0x12 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x0 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(18.0, StrToD("0x12 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(4, processed);++  CHECK_EQ(0.0, StrToD("0x0 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0x123456789 ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xabcdef", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xABCDEF", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xabcdef ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xABCDEF ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xabcdef ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xABCDEF ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xabcdef", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0xABCDEF", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x ", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x 3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(3.0, StrToD("0x3g", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(3.0, StrToD("0x3.234", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x3g", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0x3.234", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("x3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ 0x3 foo", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("-", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(-5.0, StrToD("-0x5", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" - 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" + 0x5 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("- -0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("- +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("+ +0x5", flags, 0.0,  &processed, &all_used));+  CHECK_EQ(0, processed);++  flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK |+      StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |+      StringToDoubleConverter::ALLOW_HEX;++  CHECK_EQ(18.0, StrToD("0x12", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("0x0", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD("0x123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(18.0, StrToD(" 0x12 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" 0x0 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD(" 0x123456789 ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xabcdef", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD("0xABCDEF", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD(" 0xabcdef ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabcdef),+           StrToD(" 0xABCDEF ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0xabc),+           StrToD(" 0xabc def ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(7, processed);++  CHECK_EQ(static_cast<double>(0xabc),+           StrToD(" 0xABC DEF ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(7, processed);++  CHECK_EQ(static_cast<double>(0x12),+           StrToD(" 0x12 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" 0x0 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(static_cast<double>(0x123456789),+           StrToD(" 0x123456789 ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, Double::NaN(),+                                 &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x ", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 0x 3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ((double)0x3, StrToD("0x3g", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ((double)0x3, StrToD("0x3.234", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(Double::NaN(), StrToD("x3", flags, 0.0,+                                 &processed, &all_used));+  CHECK_EQ(0, processed);+}+++TEST(StringToDoubleOctalString) {+  int flags;+  int processed;+  bool all_used;++  flags = StringToDoubleConverter::ALLOW_OCTALS |+      StringToDoubleConverter::ALLOW_LEADING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES |+      StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;++  CHECK_EQ(10.0, StrToD("012", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD(" 012", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" 00", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD(" 012", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD(" 0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD(" 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD(" + 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD(" - 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD(" 012 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" 00 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD(" 012 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD(" 0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD(" 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD(" + 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD(" - 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("01234567e0", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::ALLOW_OCTALS;+  CHECK_EQ(10.0, StrToD("012", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("012 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("00 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("012 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD("0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD("01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("01234567e0", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);+++  flags = StringToDoubleConverter::ALLOW_OCTALS |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;+  CHECK_EQ(10.0, StrToD("012", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(10.0, StrToD("012 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(0.0, StrToD("00 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(123456789.0,+           StrToD("0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(10, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012foo ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(0.0, StrToD("00foo ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(123456789.0,+           StrToD("0123456789foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(10, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567foo ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567foo", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(-342391.0,+           StrToD("-01234567foo", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(10.0, StrToD("012 foo ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(0.0, StrToD("00 foo ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(123456789.0,+           StrToD("0123456789 foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(10, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567 foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567 foo", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(-342391.0,+           StrToD("-01234567 foo", flags, Double::NaN(), &processed,+                  &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567e0", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567e", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(8, processed);++  flags = StringToDoubleConverter::ALLOW_OCTALS |+      StringToDoubleConverter::ALLOW_TRAILING_SPACES |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;+  CHECK_EQ(10.0, StrToD("012", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 00 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD(" 012 ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" + 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(),+           StrToD(" - 01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(10.0, StrToD("012 ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("00 ", flags, 1.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123456789.0,+           StrToD("0123456789 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("01234567 ", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(342391.0,+           StrToD("+01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(-342391.0,+           StrToD("-01234567", flags, Double::NaN(), &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(10.0, StrToD("012foo ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(0.0, StrToD("00foo ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(2, processed);++  CHECK_EQ(123456789.0,+           StrToD("0123456789foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(10, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567foo ", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(8, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567foo", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(-342391.0,+           StrToD("-01234567foo", flags, Double::NaN(), &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(10.0, StrToD("012 foo ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(4, processed);++  CHECK_EQ(0.0, StrToD("00 foo ", flags, 1.0, &processed, &all_used));+  CHECK_EQ(3, processed);++  CHECK_EQ(123456789.0,+           StrToD("0123456789 foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(11, processed);++  CHECK_EQ(342391.0,+           StrToD("01234567 foo ", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(9, processed);++  CHECK_EQ(342391.0,+           StrToD("+01234567 foo", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(10, processed);++  CHECK_EQ(-342391.0,+           StrToD("-01234567 foo", flags, Double::NaN(),+                  &processed, &all_used));+  CHECK_EQ(10, processed);+}+++TEST(StringToDoubleSpecialValues) {+  int processed;+  int flags = StringToDoubleConverter::NO_FLAGS;++  {+    // Use 1.0 as junk_string_value.+    StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "NaN");++    CHECK_EQ(Double::NaN(), converter.StringToDouble("+NaN", 4, &processed));+    CHECK_EQ(4, processed);++    CHECK_EQ(-Double::Infinity(),+             converter.StringToDouble("-infinity", 9, &processed));+    CHECK_EQ(9, processed);++    CHECK_EQ(1.0, converter.StringToDouble("Infinity", 8, &processed));+    CHECK_EQ(0, processed);++    CHECK_EQ(1.0, converter.StringToDouble("++NaN", 5, &processed));+    CHECK_EQ(0, processed);+  }++  {+    // Use 1.0 as junk_string_value.+    StringToDoubleConverter converter(flags, 0.0, 1.0, "+infinity", "1NaN");++    // The '+' is consumed before trying to match the infinity string.+    CHECK_EQ(1.0, converter.StringToDouble("+infinity", 9, &processed));+    CHECK_EQ(0, processed);++    // The match for "1NaN" triggers, and doesn't let the 1234.0 complete.+    CHECK_EQ(1.0, converter.StringToDouble("1234.0", 6, &processed));+    CHECK_EQ(0, processed);+  }+}+++TEST(StringToDoubleCommentExamples) {+  // Make sure the examples in the comments are correct.+  int flags;+  int processed;+  bool all_used;++  flags = StringToDoubleConverter::ALLOW_HEX;++  CHECK_EQ(4660.0, StrToD("0x1234", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("0x1234.56", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  flags |= StringToDoubleConverter::ALLOW_TRAILING_JUNK;+  CHECK_EQ(4660.0,+           StrToD("0x1234.56", flags, 0.0, &processed, &all_used));+  CHECK_EQ(6, processed);++  flags = StringToDoubleConverter::ALLOW_OCTALS;+  CHECK_EQ(668.0, StrToD("01234", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(12349.0, StrToD("012349", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("01234.56", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 0);++  flags |= StringToDoubleConverter::ALLOW_TRAILING_JUNK;+  CHECK_EQ(668.0,+           StrToD("01234.56", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 5);++  flags  = StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;+  CHECK_EQ(-123.2, StrToD("-   123.2", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  flags  = StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;+  CHECK_EQ(123.2, StrToD("+   123.2", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  flags = StringToDoubleConverter::ALLOW_HEX |+      StringToDoubleConverter::ALLOW_TRAILING_JUNK;++  CHECK_EQ(4660.0, StrToD("0x1234", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(4660.0, StrToD("0x1234K", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 6);++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 0);++  CHECK_EQ(Double::NaN(), StrToD(" 1", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 0);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 0);++  CHECK_EQ(-123.45, StrToD("-123.45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("--123.45", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 0);++  CHECK_EQ(123e45, StrToD("123e45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123e45, StrToD("123E45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123e45, StrToD("123e+45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123e-45, StrToD("123e-45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123.0, StrToD("123e", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(123.0, StrToD("123e-", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  {+    StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "NaN");+    CHECK_EQ(Double::NaN(), converter.StringToDouble("+NaN", 4, &processed));+    CHECK_EQ(4, processed);++    CHECK_EQ(-Double::Infinity(),+             converter.StringToDouble("-infinity", 9, &processed));+    CHECK_EQ(9, processed);++    CHECK_EQ(1.0, converter.StringToDouble("Infinity", 9, &processed));+    CHECK_EQ(0, processed);+  }++  flags = StringToDoubleConverter::ALLOW_OCTALS |+      StringToDoubleConverter::ALLOW_LEADING_SPACES;++  CHECK_EQ(Double::NaN(), StrToD("0x1234", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(668.0, StrToD("01234", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD("", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(0.0, StrToD(" ", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(1.0, StrToD(" 1", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(), StrToD("0x", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("0123e45", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(1239e45, StrToD("01239e45", flags, 0.0, &processed, &all_used));+  CHECK(all_used);++  CHECK_EQ(Double::NaN(),+           StrToD("-infinity", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);++  CHECK_EQ(Double::NaN(), StrToD("NaN", flags, 0.0, &processed, &all_used));+  CHECK_EQ(0, processed);+}
+ double-conversion/test/cctest/test-diy-fp.cc view
@@ -0,0 +1,65 @@+// Copyright 2006-2008 the V8 project authors. All rights reserved.++#include <stdlib.h>++#include "cctest.h"+#include "diy-fp.h"+#include "utils.h"+++using namespace double_conversion;+++TEST(Subtract) {+  DiyFp diy_fp1 = DiyFp(3, 0);+  DiyFp diy_fp2 = DiyFp(1, 0);+  DiyFp diff = DiyFp::Minus(diy_fp1, diy_fp2);++  CHECK(2 == diff.f());  // NOLINT+  CHECK_EQ(0, diff.e());+  diy_fp1.Subtract(diy_fp2);+  CHECK(2 == diy_fp1.f());  // NOLINT+  CHECK_EQ(0, diy_fp1.e());+}+++TEST(Multiply) {+  DiyFp diy_fp1 = DiyFp(3, 0);+  DiyFp diy_fp2 = DiyFp(2, 0);+  DiyFp product = DiyFp::Times(diy_fp1, diy_fp2);++  CHECK(0 == product.f());  // NOLINT+  CHECK_EQ(64, product.e());+  diy_fp1.Multiply(diy_fp2);+  CHECK(0 == diy_fp1.f());  // NOLINT+  CHECK_EQ(64, diy_fp1.e());++  diy_fp1 = DiyFp(UINT64_2PART_C(0x80000000, 00000000), 11);+  diy_fp2 = DiyFp(2, 13);+  product = DiyFp::Times(diy_fp1, diy_fp2);+  CHECK(1 == product.f());  // NOLINT+  CHECK_EQ(11 + 13 + 64, product.e());++  // Test rounding.+  diy_fp1 = DiyFp(UINT64_2PART_C(0x80000000, 00000001), 11);+  diy_fp2 = DiyFp(1, 13);+  product = DiyFp::Times(diy_fp1, diy_fp2);+  CHECK(1 == product.f());  // NOLINT+  CHECK_EQ(11 + 13 + 64, product.e());++  diy_fp1 = DiyFp(UINT64_2PART_C(0x7fffffff, ffffffff), 11);+  diy_fp2 = DiyFp(1, 13);+  product = DiyFp::Times(diy_fp1, diy_fp2);+  CHECK(0 == product.f());  // NOLINT+  CHECK_EQ(11 + 13 + 64, product.e());++  // Halfway cases are allowed to round either way. So don't check for it.++  // Big numbers.+  diy_fp1 = DiyFp(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF), 11);+  diy_fp2 = DiyFp(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF), 13);+  // 128bit result: 0xfffffffffffffffe0000000000000001+  product = DiyFp::Times(diy_fp1, diy_fp2);+  CHECK(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFe) == product.f());+  CHECK_EQ(11 + 13 + 64, product.e());+}
+ double-conversion/test/cctest/test-double.cc view
@@ -0,0 +1,218 @@+// Copyright 2006-2008 the V8 project authors. All rights reserved.++#include <stdlib.h>++#include "cctest.h"+#include "diy-fp.h"+#include "double.h"+#include "utils.h"+++using namespace double_conversion;+++TEST(Uint64Conversions) {+  // Start by checking the byte-order.+  uint64_t ordered = UINT64_2PART_C(0x01234567, 89ABCDEF);+  CHECK_EQ(3512700564088504e-318, Double(ordered).value());++  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  CHECK_EQ(5e-324, Double(min_double64).value());++  uint64_t max_double64 = UINT64_2PART_C(0x7fefffff, ffffffff);+  CHECK_EQ(1.7976931348623157e308, Double(max_double64).value());+}++TEST(AsDiyFp) {+  uint64_t ordered = UINT64_2PART_C(0x01234567, 89ABCDEF);+  DiyFp diy_fp = Double(ordered).AsDiyFp();+  CHECK_EQ(0x12 - 0x3FF - 52, diy_fp.e());+  // The 52 mantissa bits, plus the implicit 1 in bit 52 as a UINT64.+  CHECK(UINT64_2PART_C(0x00134567, 89ABCDEF) == diy_fp.f());  // NOLINT++  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  diy_fp = Double(min_double64).AsDiyFp();+  CHECK_EQ(-0x3FF - 52 + 1, diy_fp.e());+  // This is a denormal; so no hidden bit.+  CHECK(1 == diy_fp.f());  // NOLINT++  uint64_t max_double64 = UINT64_2PART_C(0x7fefffff, ffffffff);+  diy_fp = Double(max_double64).AsDiyFp();+  CHECK_EQ(0x7FE - 0x3FF - 52, diy_fp.e());+  CHECK(UINT64_2PART_C(0x001fffff, ffffffff) == diy_fp.f());  // NOLINT+}+++TEST(AsNormalizedDiyFp) {+  uint64_t ordered = UINT64_2PART_C(0x01234567, 89ABCDEF);+  DiyFp diy_fp = Double(ordered).AsNormalizedDiyFp();+  CHECK_EQ(0x12 - 0x3FF - 52 - 11, diy_fp.e());+  CHECK((UINT64_2PART_C(0x00134567, 89ABCDEF) << 11) ==+        diy_fp.f());  // NOLINT++  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  diy_fp = Double(min_double64).AsNormalizedDiyFp();+  CHECK_EQ(-0x3FF - 52 + 1 - 63, diy_fp.e());+  // This is a denormal; so no hidden bit.+  CHECK(UINT64_2PART_C(0x80000000, 00000000) == diy_fp.f());  // NOLINT++  uint64_t max_double64 = UINT64_2PART_C(0x7fefffff, ffffffff);+  diy_fp = Double(max_double64).AsNormalizedDiyFp();+  CHECK_EQ(0x7FE - 0x3FF - 52 - 11, diy_fp.e());+  CHECK((UINT64_2PART_C(0x001fffff, ffffffff) << 11) ==+        diy_fp.f());  // NOLINT+}+++TEST(IsDenormal) {+  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  CHECK(Double(min_double64).IsDenormal());+  uint64_t bits = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  CHECK(Double(bits).IsDenormal());+  bits = UINT64_2PART_C(0x00100000, 00000000);+  CHECK(!Double(bits).IsDenormal());+}+++TEST(IsSpecial) {+  CHECK(Double(Double::Infinity()).IsSpecial());+  CHECK(Double(-Double::Infinity()).IsSpecial());+  CHECK(Double(Double::NaN()).IsSpecial());+  uint64_t bits = UINT64_2PART_C(0xFFF12345, 00000000);+  CHECK(Double(bits).IsSpecial());+  // Denormals are not special:+  CHECK(!Double(5e-324).IsSpecial());+  CHECK(!Double(-5e-324).IsSpecial());+  // And some random numbers:+  CHECK(!Double(0.0).IsSpecial());+  CHECK(!Double(-0.0).IsSpecial());+  CHECK(!Double(1.0).IsSpecial());+  CHECK(!Double(-1.0).IsSpecial());+  CHECK(!Double(1000000.0).IsSpecial());+  CHECK(!Double(-1000000.0).IsSpecial());+  CHECK(!Double(1e23).IsSpecial());+  CHECK(!Double(-1e23).IsSpecial());+  CHECK(!Double(1.7976931348623157e308).IsSpecial());+  CHECK(!Double(-1.7976931348623157e308).IsSpecial());+}+++TEST(IsInfinite) {+  CHECK(Double(Double::Infinity()).IsInfinite());+  CHECK(Double(-Double::Infinity()).IsInfinite());+  CHECK(!Double(Double::NaN()).IsInfinite());+  CHECK(!Double(0.0).IsInfinite());+  CHECK(!Double(-0.0).IsInfinite());+  CHECK(!Double(1.0).IsInfinite());+  CHECK(!Double(-1.0).IsInfinite());+  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  CHECK(!Double(min_double64).IsInfinite());+}+++TEST(IsNan) {+  CHECK(Double(Double::NaN()).IsNan());+  uint64_t other_nan = UINT64_2PART_C(0xFFFFFFFF, 00000001);+  CHECK(Double(other_nan).IsNan());+  CHECK(!Double(Double::Infinity()).IsNan());+  CHECK(!Double(-Double::Infinity()).IsNan());+  CHECK(!Double(0.0).IsNan());+  CHECK(!Double(-0.0).IsNan());+  CHECK(!Double(1.0).IsNan());+  CHECK(!Double(-1.0).IsNan());+  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  CHECK(!Double(min_double64).IsNan());+}+++TEST(Sign) {+  CHECK_EQ(1, Double(1.0).Sign());+  CHECK_EQ(1, Double(Double::Infinity()).Sign());+  CHECK_EQ(-1, Double(-Double::Infinity()).Sign());+  CHECK_EQ(1, Double(0.0).Sign());+  CHECK_EQ(-1, Double(-0.0).Sign());+  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  CHECK_EQ(1, Double(min_double64).Sign());+}+++TEST(NormalizedBoundaries) {+  DiyFp boundary_plus;+  DiyFp boundary_minus;+  DiyFp diy_fp = Double(1.5).AsNormalizedDiyFp();+  Double(1.5).NormalizedBoundaries(&boundary_minus, &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  // 1.5 does not have a significand of the form 2^p (for some p).+  // Therefore its boundaries are at the same distance.+  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());+  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT++  diy_fp = Double(1.0).AsNormalizedDiyFp();+  Double(1.0).NormalizedBoundaries(&boundary_minus, &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  // 1.0 does have a significand of the form 2^p (for some p).+  // Therefore its lower boundary is twice as close as the upper boundary.+  CHECK(boundary_plus.f() - diy_fp.f() > diy_fp.f() - boundary_minus.f());+  CHECK((1 << 9) == diy_fp.f() - boundary_minus.f());  // NOLINT+  CHECK((1 << 10) == boundary_plus.f() - diy_fp.f());  // NOLINT++  uint64_t min_double64 = UINT64_2PART_C(0x00000000, 00000001);+  diy_fp = Double(min_double64).AsNormalizedDiyFp();+  Double(min_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  // min-value does not have a significand of the form 2^p (for some p).+  // Therefore its boundaries are at the same distance.+  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());+  // Denormals have their boundaries much closer.+  CHECK((static_cast<uint64_t>(1) << 62) ==+        diy_fp.f() - boundary_minus.f());  // NOLINT++  uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);+  diy_fp = Double(smallest_normal64).AsNormalizedDiyFp();+  Double(smallest_normal64).NormalizedBoundaries(&boundary_minus,+                                                 &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  // Even though the significand is of the form 2^p (for some p), its boundaries+  // are at the same distance. (This is the only exception).+  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());+  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT++  uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  diy_fp = Double(largest_denormal64).AsNormalizedDiyFp();+  Double(largest_denormal64).NormalizedBoundaries(&boundary_minus,+                                                  &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());+  CHECK((1 << 11) == diy_fp.f() - boundary_minus.f());  // NOLINT++  uint64_t max_double64 = UINT64_2PART_C(0x7fefffff, ffffffff);+  diy_fp = Double(max_double64).AsNormalizedDiyFp();+  Double(max_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);+  CHECK_EQ(diy_fp.e(), boundary_minus.e());+  CHECK_EQ(diy_fp.e(), boundary_plus.e());+  // max-value does not have a significand of the form 2^p (for some p).+  // Therefore its boundaries are at the same distance.+  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());+  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT+}+++TEST(NextDouble) {+  CHECK_EQ(4e-324, Double(0.0).NextDouble());+  CHECK_EQ(0.0, Double(-0.0).NextDouble());+  CHECK_EQ(-0.0, Double(-4e-324).NextDouble());+  Double d0(-4e-324);+  Double d1(d0.NextDouble());+  Double d2(d1.NextDouble());+  CHECK_EQ(-0.0, d1.value());+  CHECK_EQ(0.0, d2.value());+  CHECK_EQ(4e-324, d2.NextDouble());+  CHECK_EQ(-1.7976931348623157e308, Double(-Double::Infinity()).NextDouble());+  CHECK_EQ(Double::Infinity(),+           Double(UINT64_2PART_C(0x7fefffff, ffffffff)).NextDouble());+}
+ double-conversion/test/cctest/test-dtoa.cc view
@@ -0,0 +1,422 @@+// 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 <stdlib.h>++#include "double-conversion.h"++#include "cctest.h"+#include "double.h"+#include "gay-fixed.h"+#include "gay-precision.h"+#include "gay-shortest.h"+++using namespace double_conversion;+++enum DtoaMode {+  SHORTEST,+  FIXED,+  PRECISION+};++static void DoubleToAscii(double v, DtoaMode test_mode, int requested_digits,+                          Vector<char> buffer, bool* sign, int* length,+                          int* point) {+  DoubleToStringConverter::DtoaMode mode = DoubleToStringConverter::SHORTEST;+  switch (test_mode) {+    case SHORTEST: mode = DoubleToStringConverter::SHORTEST; break;+    case FIXED: mode = DoubleToStringConverter::FIXED; break;+    case PRECISION: mode = DoubleToStringConverter::PRECISION; break;+  }+  DoubleToStringConverter::DoubleToAscii(v, mode, requested_digits,+                                 buffer.start(), buffer.length(),+                                 sign, length, point);+}++// Removes trailing '0' digits.+static void TrimRepresentation(Vector<char> representation) {+  int len = strlen(representation.start());+  int i;+  for (i = len - 1; i >= 0; --i) {+    if (representation[i] != '0') break;+  }+  representation[i + 1] = '\0';+}+++static const int kBufferSize = 100;+++TEST(DtoaVariousDoubles) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;+  bool sign;++  DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("0", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(0.0, FIXED, 2, buffer, &sign, &length, &point);+  CHECK_EQ(1, length);+  CHECK_EQ("0", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(0.0, PRECISION, 3, buffer, &sign, &length, &point);+  CHECK_EQ(1, length);+  CHECK_EQ("0", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.0, FIXED, 3, buffer, &sign, &length, &point);+  CHECK_GE(3, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.0, PRECISION, 3, buffer, &sign, &length, &point);+  CHECK_GE(3, length);+  TrimRepresentation(buffer);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.5, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.5, FIXED, 10, buffer, &sign, &length, &point);+  CHECK_GE(10, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  DoubleToAscii(1.5, PRECISION, 10, buffer, &sign, &length, &point);+  CHECK_GE(10, length);+  TrimRepresentation(buffer);+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  double min_double = 5e-324;+  DoubleToAscii(min_double, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("5", buffer.start());+  CHECK_EQ(-323, point);++  DoubleToAscii(min_double, FIXED, 5, buffer, &sign, &length, &point);+  CHECK_GE(5, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("", buffer.start());+  CHECK_GE(-5, point);++  DoubleToAscii(min_double, PRECISION, 5, buffer, &sign, &length, &point);+  CHECK_GE(5, length);+  TrimRepresentation(buffer);+  CHECK_EQ("49407", buffer.start());+  CHECK_EQ(-323, point);++  double max_double = 1.7976931348623157e308;+  DoubleToAscii(max_double, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("17976931348623157", buffer.start());+  CHECK_EQ(309, point);++  DoubleToAscii(max_double, PRECISION, 7, buffer, &sign, &length, &point);+  CHECK_GE(7, length);+  TrimRepresentation(buffer);+  CHECK_EQ("1797693", buffer.start());+  CHECK_EQ(309, point);++  DoubleToAscii(4294967272.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);++  DoubleToAscii(4294967272.0, FIXED, 5, buffer, &sign, &length, &point);+  CHECK_GE(5, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);+++  DoubleToAscii(4294967272.0, PRECISION, 14,+                buffer, &sign, &length, &point);+  CHECK_GE(14, length);+  TrimRepresentation(buffer);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);++  DoubleToAscii(4.1855804968213567e298, SHORTEST, 0,+                buffer, &sign, &length, &point);+  CHECK_EQ("4185580496821357", buffer.start());+  CHECK_EQ(299, point);++  DoubleToAscii(4.1855804968213567e298, PRECISION, 20,+                buffer, &sign, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("41855804968213567225", buffer.start());+  CHECK_EQ(299, point);++  DoubleToAscii(5.5626846462680035e-309, SHORTEST, 0,+                buffer, &sign, &length, &point);+  CHECK_EQ("5562684646268003", buffer.start());+  CHECK_EQ(-308, point);++  DoubleToAscii(5.5626846462680035e-309, PRECISION, 1,+                buffer, &sign, &length, &point);+  CHECK_GE(1, length);+  TrimRepresentation(buffer);+  CHECK_EQ("6", buffer.start());+  CHECK_EQ(-308, point);++  DoubleToAscii(-2147483648.0, SHORTEST, 0,+                buffer, &sign, &length, &point);+  CHECK_EQ(1, sign);+  CHECK_EQ("2147483648", buffer.start());+  CHECK_EQ(10, point);+++  DoubleToAscii(-2147483648.0, FIXED, 2, buffer, &sign, &length, &point);+  CHECK_GE(2, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ(1, sign);+  CHECK_EQ("2147483648", buffer.start());+  CHECK_EQ(10, point);++  DoubleToAscii(-2147483648.0, PRECISION, 5,+                buffer, &sign, &length, &point);+  CHECK_GE(5, length);+  TrimRepresentation(buffer);+  CHECK_EQ(1, sign);+  CHECK_EQ("21475", buffer.start());+  CHECK_EQ(10, point);++  DoubleToAscii(-3.5844466002796428e+298, SHORTEST, 0,+                buffer, &sign, &length, &point);+  CHECK_EQ(1, sign);+  CHECK_EQ("35844466002796428", buffer.start());+  CHECK_EQ(299, point);++  DoubleToAscii(-3.5844466002796428e+298, PRECISION, 10,+                buffer, &sign, &length, &point);+  CHECK_EQ(1, sign);+  CHECK_GE(10, length);+  TrimRepresentation(buffer);+  CHECK_EQ("35844466", buffer.start());+  CHECK_EQ(299, point);++  uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);+  double v = Double(smallest_normal64).value();+  DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("22250738585072014", buffer.start());+  CHECK_EQ(-307, point);++  DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("22250738585072013831", buffer.start());+  CHECK_EQ(-307, point);++  uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  v = Double(largest_denormal64).value();+  DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("2225073858507201", buffer.start());+  CHECK_EQ(-307, point);++  DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);+  CHECK_GE(20, length);+  TrimRepresentation(buffer);+  CHECK_EQ("2225073858507200889", buffer.start());+  CHECK_EQ(-307, point);++  DoubleToAscii(4128420500802942e-24, SHORTEST, 0,+                buffer, &sign, &length, &point);+  CHECK_EQ(0, sign);+  CHECK_EQ("4128420500802942", buffer.start());+  CHECK_EQ(-8, point);++  v = -3.9292015898194142585311918e-10;+  DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK_EQ("39292015898194143", buffer.start());++  v = 4194304.0;+  DoubleToAscii(v, FIXED, 5, buffer, &sign, &length, &point);+  CHECK_GE(5, length - point);+  TrimRepresentation(buffer);+  CHECK_EQ("4194304", buffer.start());++  v = 3.3161339052167390562200598e-237;+  DoubleToAscii(v, PRECISION, 19, buffer, &sign, &length, &point);+  CHECK_GE(19, length);+  TrimRepresentation(buffer);+  CHECK_EQ("3316133905216739056", buffer.start());+  CHECK_EQ(-236, point);+}+++TEST(DtoaSign) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool sign;+  int length;+  int point;++  DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-0.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK(sign);++  DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-1.0, SHORTEST, 0, buffer, &sign, &length, &point);+  CHECK(sign);++  DoubleToAscii(0.0, PRECISION, 1, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-0.0, PRECISION, 1, buffer, &sign, &length, &point);+  CHECK(sign);++  DoubleToAscii(1.0, PRECISION, 1, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-1.0, PRECISION, 1, buffer, &sign, &length, &point);+  CHECK(sign);++  DoubleToAscii(0.0, FIXED, 1, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-0.0, FIXED, 1, buffer, &sign, &length, &point);+  CHECK(sign);++  DoubleToAscii(1.0, FIXED, 1, buffer, &sign, &length, &point);+  CHECK(!sign);++  DoubleToAscii(-1.0, FIXED, 1, buffer, &sign, &length, &point);+  CHECK(sign);+}+++TEST(DtoaCorners) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool sign;+  int length;+  int point;++  DoubleToAscii(0.0, PRECISION, 0, buffer, &sign, &length, &point);+  CHECK_EQ(0, length);+  CHECK_EQ("", buffer.start());+  CHECK(!sign);++  DoubleToAscii(1.0, PRECISION, 0, buffer, &sign, &length, &point);+  CHECK_EQ(0, length);+  CHECK_EQ("", buffer.start());+  CHECK(!sign);++  DoubleToAscii(0.0, FIXED, 0, buffer, &sign, &length, &point);+  CHECK_EQ(1, length);+  CHECK_EQ("0", buffer.start());+  CHECK(!sign);++  DoubleToAscii(1.0, FIXED, 0, buffer, &sign, &length, &point);+  CHECK_EQ(1, length);+  CHECK_EQ("1", buffer.start());+  CHECK(!sign);+}+++TEST(DtoaGayShortest) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool sign;+  int length;+  int point;++  Vector<const PrecomputedShortest> precomputed =+      PrecomputedShortestRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedShortest current_test = precomputed[i];+    double v = current_test.v;+    DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);+    CHECK(!sign);  // All precomputed numbers are positive.+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}+++TEST(DtoaGayFixed) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool sign;+  int length;+  int point;++  Vector<const PrecomputedFixed> precomputed =+      PrecomputedFixedRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedFixed current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    DoubleToAscii(v, FIXED, number_digits, buffer, &sign, &length, &point);+    CHECK(!sign);  // All precomputed numbers are positive.+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_GE(number_digits, length - point);+    TrimRepresentation(buffer);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}+++TEST(DtoaGayPrecision) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool sign;+  int length;+  int point;++  Vector<const PrecomputedPrecision> precomputed =+      PrecomputedPrecisionRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedPrecision current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    DoubleToAscii(v, PRECISION, number_digits,+                  buffer, &sign, &length, &point);+    CHECK(!sign);  // All precomputed numbers are positive.+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_GE(number_digits, length);+    TrimRepresentation(buffer);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}
+ double-conversion/test/cctest/test-fast-dtoa.cc view
@@ -0,0 +1,266 @@+// Copyright 2006-2008 the V8 project authors. All rights reserved.++#include <stdlib.h>++#include "cctest.h"+#include "diy-fp.h"+#include "double.h"+#include "fast-dtoa.h"+#include "gay-precision.h"+#include "gay-shortest.h"+#include "utils.h"++using namespace double_conversion;++static const int kBufferSize = 100;+++// Removes trailing '0' digits.+static void TrimRepresentation(Vector<char> representation) {+  int len = strlen(representation.start());+  int i;+  for (i = len - 1; i >= 0; --i) {+    if (representation[i] != '0') break;+  }+  representation[i + 1] = '\0';+}+++TEST(FastDtoaShortestVariousDoubles) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;+  int status;++  double min_double = 5e-324;+  status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("5", buffer.start());+  CHECK_EQ(-323, point);++  double max_double = 1.7976931348623157e308;+  status = FastDtoa(max_double, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("17976931348623157", buffer.start());+  CHECK_EQ(309, point);++  status = FastDtoa(4294967272.0, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("4294967272", buffer.start());+  CHECK_EQ(10, point);++  status = FastDtoa(4.1855804968213567e298, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("4185580496821357", buffer.start());+  CHECK_EQ(299, point);++  status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("5562684646268003", buffer.start());+  CHECK_EQ(-308, point);++  status = FastDtoa(2147483648.0, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("2147483648", buffer.start());+  CHECK_EQ(10, point);++  status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_SHORTEST, 0,+                    buffer, &length, &point);+  if (status) {  // Not all FastDtoa variants manage to compute this number.+    CHECK_EQ("35844466002796428", buffer.start());+    CHECK_EQ(299, point);+  }++  uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);+  double v = Double(smallest_normal64).value();+  status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);+  if (status) {+    CHECK_EQ("22250738585072014", buffer.start());+    CHECK_EQ(-307, point);+  }++  uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  v = Double(largest_denormal64).value();+  status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);+  if (status) {+    CHECK_EQ("2225073858507201", buffer.start());+    CHECK_EQ(-307, point);+  }+}+++TEST(FastDtoaPrecisionVariousDoubles) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;+  int status;++  status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point);+  CHECK(status);+  CHECK(3 >= length);+  TrimRepresentation(buffer);+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  status = FastDtoa(1.5, FAST_DTOA_PRECISION, 10, buffer, &length, &point);+  if (status) {+    CHECK(10 >= length);+    TrimRepresentation(buffer);+    CHECK_EQ("15", buffer.start());+    CHECK_EQ(1, point);+  }++  double min_double = 5e-324;+  status = FastDtoa(min_double, FAST_DTOA_PRECISION, 5,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("49407", buffer.start());+  CHECK_EQ(-323, point);++  double max_double = 1.7976931348623157e308;+  status = FastDtoa(max_double, FAST_DTOA_PRECISION, 7,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("1797693", buffer.start());+  CHECK_EQ(309, point);++  status = FastDtoa(4294967272.0, FAST_DTOA_PRECISION, 14,+                    buffer, &length, &point);+  if (status) {+    CHECK(14 >= length);+    TrimRepresentation(buffer);+    CHECK_EQ("4294967272", buffer.start());+    CHECK_EQ(10, point);+  }++  status = FastDtoa(4.1855804968213567e298, FAST_DTOA_PRECISION, 17,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("41855804968213567", buffer.start());+  CHECK_EQ(299, point);++  status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_PRECISION, 1,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("6", buffer.start());+  CHECK_EQ(-308, point);++  status = FastDtoa(2147483648.0, FAST_DTOA_PRECISION, 5,+                    buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("21475", buffer.start());+  CHECK_EQ(10, point);++  status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_PRECISION, 10,+                    buffer, &length, &point);+  CHECK(status);+  CHECK(10 >= length);+  TrimRepresentation(buffer);+  CHECK_EQ("35844466", buffer.start());+  CHECK_EQ(299, point);++  uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);+  double v = Double(smallest_normal64).value();+  status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("22250738585072014", buffer.start());+  CHECK_EQ(-307, point);++  uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);+  v = Double(largest_denormal64).value();+  status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);+  CHECK(status);+  CHECK(20 >= length);+  TrimRepresentation(buffer);+  CHECK_EQ("22250738585072009", buffer.start());+  CHECK_EQ(-307, point);++  v = 3.3161339052167390562200598e-237;+  status = FastDtoa(v, FAST_DTOA_PRECISION, 18, buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("331613390521673906", buffer.start());+  CHECK_EQ(-236, point);++  v = 7.9885183916008099497815232e+191;+  status = FastDtoa(v, FAST_DTOA_PRECISION, 4, buffer, &length, &point);+  CHECK(status);+  CHECK_EQ("7989", buffer.start());+  CHECK_EQ(192, point);+}+++TEST(FastDtoaGayShortest) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool status;+  int length;+  int point;+  int succeeded = 0;+  int total = 0;+  bool needed_max_length = false;++  Vector<const PrecomputedShortest> precomputed =+      PrecomputedShortestRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedShortest current_test = precomputed[i];+    total++;+    double v = current_test.v;+    status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);+    CHECK(kFastDtoaMaximalLength >= length);+    if (!status) continue;+    if (length == kFastDtoaMaximalLength) needed_max_length = true;+    succeeded++;+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_EQ(current_test.representation, buffer.start());+  }+  CHECK(succeeded*1.0/total > 0.99);+  CHECK(needed_max_length);+}+++TEST(FastDtoaGayPrecision) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool status;+  int length;+  int point;+  int succeeded = 0;+  int total = 0;+  // Count separately for entries with less than 15 requested digits.+  int succeeded_15 = 0;+  int total_15 = 0;++  Vector<const PrecomputedPrecision> precomputed =+      PrecomputedPrecisionRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedPrecision current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    total++;+    if (number_digits <= 15) total_15++;+    status = FastDtoa(v, FAST_DTOA_PRECISION, number_digits,+                      buffer, &length, &point);+    CHECK(number_digits >= length);+    if (!status) continue;+    succeeded++;+    if (number_digits <= 15) succeeded_15++;+    TrimRepresentation(buffer);+    CHECK_EQ(current_test.decimal_point, point);+    CHECK_EQ(current_test.representation, buffer.start());+  }+  // The precomputed numbers contain many entries with many requested+  // digits. These have a high failure rate and we therefore expect a lower+  // success rate than for the shortest representation.+  CHECK(succeeded*1.0/total > 0.85);+  // However with less than 15 digits almost the algorithm should almost always+  // succeed.+  CHECK(succeeded_15*1.0/total_15 > 0.9999);+}
+ double-conversion/test/cctest/test-fixed-dtoa.cc view
@@ -0,0 +1,511 @@+// 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 <stdlib.h>+++#include "cctest.h"+#include "double.h"+#include "fixed-dtoa.h"+#include "gay-fixed.h"+#include "utils.h"++using namespace double_conversion;++static const int kBufferSize = 500;++TEST(FastFixedVariousDoubles) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  int length;+  int point;++  CHECK(FastFixedDtoa(1.0, 1, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1.0, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1.0, 0, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0xFFFFFFFF, 5, buffer, &length, &point));+  CHECK_EQ("4294967295", buffer.start());+  CHECK_EQ(10, point);++  CHECK(FastFixedDtoa(4294967296.0, 5, buffer, &length, &point));+  CHECK_EQ("4294967296", buffer.start());+  CHECK_EQ(10, point);++  CHECK(FastFixedDtoa(1e21, 5, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  // CHECK_EQ(22, point);+  CHECK_EQ(22, point);++  CHECK(FastFixedDtoa(999999999999999868928.00, 2, buffer, &length, &point));+  CHECK_EQ("999999999999999868928", buffer.start());+  CHECK_EQ(21, point);++  CHECK(FastFixedDtoa(6.9999999999999989514240000e+21, 5, buffer,+                      &length, &point));+  CHECK_EQ("6999999999999998951424", buffer.start());+  CHECK_EQ(22, point);++  CHECK(FastFixedDtoa(1.5, 5, buffer, &length, &point));+  CHECK_EQ("15", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1.55, 5, buffer, &length, &point));+  CHECK_EQ("155", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1.55, 1, buffer, &length, &point));+  CHECK_EQ("16", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1.00000001, 15, buffer, &length, &point));+  CHECK_EQ("100000001", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.1, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(0, point);++  CHECK(FastFixedDtoa(0.01, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-1, point);++  CHECK(FastFixedDtoa(0.001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-2, point);++  CHECK(FastFixedDtoa(0.0001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-3, point);++  CHECK(FastFixedDtoa(0.00001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-4, point);++  CHECK(FastFixedDtoa(0.000001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-5, point);++  CHECK(FastFixedDtoa(0.0000001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-6, point);++  CHECK(FastFixedDtoa(0.00000001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-7, point);++  CHECK(FastFixedDtoa(0.000000001, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-8, point);++  CHECK(FastFixedDtoa(0.0000000001, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-9, point);++  CHECK(FastFixedDtoa(0.00000000001, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-10, point);++  CHECK(FastFixedDtoa(0.000000000001, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-11, point);++  CHECK(FastFixedDtoa(0.0000000000001, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-12, point);++  CHECK(FastFixedDtoa(0.00000000000001, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-13, point);++  CHECK(FastFixedDtoa(0.000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-14, point);++  CHECK(FastFixedDtoa(0.0000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-15, point);++  CHECK(FastFixedDtoa(0.00000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-16, point);++  CHECK(FastFixedDtoa(0.000000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-17, point);++  CHECK(FastFixedDtoa(0.0000000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-18, point);++  CHECK(FastFixedDtoa(0.00000000000000000001, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-19, point);++  CHECK(FastFixedDtoa(0.10000000004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(0, point);++  CHECK(FastFixedDtoa(0.01000000004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-1, point);++  CHECK(FastFixedDtoa(0.00100000004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-2, point);++  CHECK(FastFixedDtoa(0.00010000004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-3, point);++  CHECK(FastFixedDtoa(0.00001000004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-4, point);++  CHECK(FastFixedDtoa(0.00000100004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-5, point);++  CHECK(FastFixedDtoa(0.00000010004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-6, point);++  CHECK(FastFixedDtoa(0.00000001004, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-7, point);++  CHECK(FastFixedDtoa(0.00000000104, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-8, point);++  CHECK(FastFixedDtoa(0.0000000001000004, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-9, point);++  CHECK(FastFixedDtoa(0.0000000000100004, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-10, point);++  CHECK(FastFixedDtoa(0.0000000000010004, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-11, point);++  CHECK(FastFixedDtoa(0.0000000000001004, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-12, point);++  CHECK(FastFixedDtoa(0.0000000000000104, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-13, point);++  CHECK(FastFixedDtoa(0.000000000000001000004, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-14, point);++  CHECK(FastFixedDtoa(0.000000000000000100004, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-15, point);++  CHECK(FastFixedDtoa(0.000000000000000010004, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-16, point);++  CHECK(FastFixedDtoa(0.000000000000000001004, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-17, point);++  CHECK(FastFixedDtoa(0.000000000000000000104, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-18, point);++  CHECK(FastFixedDtoa(0.000000000000000000014, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-19, point);++  CHECK(FastFixedDtoa(0.10000000006, 10, buffer, &length, &point));+  CHECK_EQ("1000000001", buffer.start());+  CHECK_EQ(0, point);++  CHECK(FastFixedDtoa(0.01000000006, 10, buffer, &length, &point));+  CHECK_EQ("100000001", buffer.start());+  CHECK_EQ(-1, point);++  CHECK(FastFixedDtoa(0.00100000006, 10, buffer, &length, &point));+  CHECK_EQ("10000001", buffer.start());+  CHECK_EQ(-2, point);++  CHECK(FastFixedDtoa(0.00010000006, 10, buffer, &length, &point));+  CHECK_EQ("1000001", buffer.start());+  CHECK_EQ(-3, point);++  CHECK(FastFixedDtoa(0.00001000006, 10, buffer, &length, &point));+  CHECK_EQ("100001", buffer.start());+  CHECK_EQ(-4, point);++  CHECK(FastFixedDtoa(0.00000100006, 10, buffer, &length, &point));+  CHECK_EQ("10001", buffer.start());+  CHECK_EQ(-5, point);++  CHECK(FastFixedDtoa(0.00000010006, 10, buffer, &length, &point));+  CHECK_EQ("1001", buffer.start());+  CHECK_EQ(-6, point);++  CHECK(FastFixedDtoa(0.00000001006, 10, buffer, &length, &point));+  CHECK_EQ("101", buffer.start());+  CHECK_EQ(-7, point);++  CHECK(FastFixedDtoa(0.00000000106, 10, buffer, &length, &point));+  CHECK_EQ("11", buffer.start());+  CHECK_EQ(-8, point);++  CHECK(FastFixedDtoa(0.0000000001000006, 15, buffer, &length, &point));+  CHECK_EQ("100001", buffer.start());+  CHECK_EQ(-9, point);++  CHECK(FastFixedDtoa(0.0000000000100006, 15, buffer, &length, &point));+  CHECK_EQ("10001", buffer.start());+  CHECK_EQ(-10, point);++  CHECK(FastFixedDtoa(0.0000000000010006, 15, buffer, &length, &point));+  CHECK_EQ("1001", buffer.start());+  CHECK_EQ(-11, point);++  CHECK(FastFixedDtoa(0.0000000000001006, 15, buffer, &length, &point));+  CHECK_EQ("101", buffer.start());+  CHECK_EQ(-12, point);++  CHECK(FastFixedDtoa(0.0000000000000106, 15, buffer, &length, &point));+  CHECK_EQ("11", buffer.start());+  CHECK_EQ(-13, point);++  CHECK(FastFixedDtoa(0.000000000000001000006, 20, buffer, &length, &point));+  CHECK_EQ("100001", buffer.start());+  CHECK_EQ(-14, point);++  CHECK(FastFixedDtoa(0.000000000000000100006, 20, buffer, &length, &point));+  CHECK_EQ("10001", buffer.start());+  CHECK_EQ(-15, point);++  CHECK(FastFixedDtoa(0.000000000000000010006, 20, buffer, &length, &point));+  CHECK_EQ("1001", buffer.start());+  CHECK_EQ(-16, point);++  CHECK(FastFixedDtoa(0.000000000000000001006, 20, buffer, &length, &point));+  CHECK_EQ("101", buffer.start());+  CHECK_EQ(-17, point);++  CHECK(FastFixedDtoa(0.000000000000000000106, 20, buffer, &length, &point));+  CHECK_EQ("11", buffer.start());+  CHECK_EQ(-18, point);++  CHECK(FastFixedDtoa(0.000000000000000000016, 20, buffer, &length, &point));+  CHECK_EQ("2", buffer.start());+  CHECK_EQ(-19, point);++  CHECK(FastFixedDtoa(0.6, 0, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.96, 1, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.996, 2, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.9996, 3, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.99996, 4, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.999996, 5, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.9999996, 6, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.99999996, 7, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.999999996, 8, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.9999999996, 9, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.99999999996, 10, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.999999999996, 11, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.9999999999996, 12, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.99999999999996, 13, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.999999999999996, 14, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.9999999999999996, 15, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(0.00999999999999996, 16, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-1, point);++  CHECK(FastFixedDtoa(0.000999999999999996, 17, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-2, point);++  CHECK(FastFixedDtoa(0.0000999999999999996, 18, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-3, point);++  CHECK(FastFixedDtoa(0.00000999999999999996, 19, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-4, point);++  CHECK(FastFixedDtoa(0.000000999999999999996, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-5, point);++  CHECK(FastFixedDtoa(323423.234234, 10, buffer, &length, &point));+  CHECK_EQ("323423234234", buffer.start());+  CHECK_EQ(6, point);++  CHECK(FastFixedDtoa(12345678.901234, 4, buffer, &length, &point));+  CHECK_EQ("123456789012", buffer.start());+  CHECK_EQ(8, point);++  CHECK(FastFixedDtoa(98765.432109, 5, buffer, &length, &point));+  CHECK_EQ("9876543211", buffer.start());+  CHECK_EQ(5, point);++  CHECK(FastFixedDtoa(42, 20, buffer, &length, &point));+  CHECK_EQ("42", buffer.start());+  CHECK_EQ(2, point);++  CHECK(FastFixedDtoa(0.5, 0, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(1, point);++  CHECK(FastFixedDtoa(1e-23, 10, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-10, point);++  CHECK(FastFixedDtoa(1e-123, 2, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-2, point);++  CHECK(FastFixedDtoa(1e-123, 0, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(0, point);++  CHECK(FastFixedDtoa(1e-23, 20, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-20, point);++  CHECK(FastFixedDtoa(1e-21, 20, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-20, point);++  CHECK(FastFixedDtoa(1e-22, 20, buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-20, point);++  CHECK(FastFixedDtoa(6e-21, 20, buffer, &length, &point));+  CHECK_EQ("1", buffer.start());+  CHECK_EQ(-19, point);++  CHECK(FastFixedDtoa(9.1193616301674545152000000e+19, 0,+                      buffer, &length, &point));+  CHECK_EQ("91193616301674545152", buffer.start());+  CHECK_EQ(20, point);++  CHECK(FastFixedDtoa(4.8184662102767651659096515e-04, 19,+                      buffer, &length, &point));+  CHECK_EQ("4818466210276765", buffer.start());+  CHECK_EQ(-3, point);++  CHECK(FastFixedDtoa(1.9023164229540652612705182e-23, 8,+                      buffer, &length, &point));+  CHECK_EQ("", buffer.start());+  CHECK_EQ(-8, point);++  CHECK(FastFixedDtoa(1000000000000000128.0, 0,+                      buffer, &length, &point));+  CHECK_EQ("1000000000000000128", buffer.start());+  CHECK_EQ(19, point);+}+++TEST(FastFixedDtoaGayFixed) {+  char buffer_container[kBufferSize];+  Vector<char> buffer(buffer_container, kBufferSize);+  bool status;+  int length;+  int point;++  Vector<const PrecomputedFixed> precomputed =+      PrecomputedFixedRepresentations();+  for (int i = 0; i < precomputed.length(); ++i) {+    const PrecomputedFixed current_test = precomputed[i];+    double v = current_test.v;+    int number_digits = current_test.number_digits;+    status = FastFixedDtoa(v, number_digits,+                           buffer, &length, &point);+    CHECK(status);+    CHECK_EQ(current_test.decimal_point, point);+    CHECK(number_digits >= length - point);+    CHECK_EQ(current_test.representation, buffer.start());+  }+}
+ double-conversion/test/cctest/test-strtod.cc view
@@ -0,0 +1,452 @@+// Copyright 2006-2008 the V8 project authors. All rights reserved.++#include <stdlib.h>++#include "bignum.h"+#include "cctest.h"+#include "diy-fp.h"+#include "double.h"+#include "strtod.h"+#include "utils.h"++using namespace double_conversion;++static Vector<const char> StringToVector(const char* str) {+  return Vector<const char>(str, strlen(str));+}+++static double StrtodChar(const char* str, int exponent) {+  return Strtod(StringToVector(str), exponent);+}+++TEST(Strtod) {+  Vector<const char> vector;++  vector = StringToVector("0");+  CHECK_EQ(0.0, Strtod(vector, 1));+  CHECK_EQ(0.0, Strtod(vector, 2));+  CHECK_EQ(0.0, Strtod(vector, -2));+  CHECK_EQ(0.0, Strtod(vector, -999));+  CHECK_EQ(0.0, Strtod(vector, +999));++  vector = StringToVector("1");+  CHECK_EQ(1.0, Strtod(vector, 0));+  CHECK_EQ(10.0, Strtod(vector, 1));+  CHECK_EQ(100.0, Strtod(vector, 2));+  CHECK_EQ(1e20, Strtod(vector, 20));+  CHECK_EQ(1e22, Strtod(vector, 22));+  CHECK_EQ(1e23, Strtod(vector, 23));+  CHECK_EQ(1e35, Strtod(vector, 35));+  CHECK_EQ(1e36, Strtod(vector, 36));+  CHECK_EQ(1e37, Strtod(vector, 37));+  CHECK_EQ(1e-1, Strtod(vector, -1));+  CHECK_EQ(1e-2, Strtod(vector, -2));+  CHECK_EQ(1e-5, Strtod(vector, -5));+  CHECK_EQ(1e-20, Strtod(vector, -20));+  CHECK_EQ(1e-22, Strtod(vector, -22));+  CHECK_EQ(1e-23, Strtod(vector, -23));+  CHECK_EQ(1e-25, Strtod(vector, -25));+  CHECK_EQ(1e-39, Strtod(vector, -39));++  vector = StringToVector("2");+  CHECK_EQ(2.0, Strtod(vector, 0));+  CHECK_EQ(20.0, Strtod(vector, 1));+  CHECK_EQ(200.0, Strtod(vector, 2));+  CHECK_EQ(2e20, Strtod(vector, 20));+  CHECK_EQ(2e22, Strtod(vector, 22));+  CHECK_EQ(2e23, Strtod(vector, 23));+  CHECK_EQ(2e35, Strtod(vector, 35));+  CHECK_EQ(2e36, Strtod(vector, 36));+  CHECK_EQ(2e37, Strtod(vector, 37));+  CHECK_EQ(2e-1, Strtod(vector, -1));+  CHECK_EQ(2e-2, Strtod(vector, -2));+  CHECK_EQ(2e-5, Strtod(vector, -5));+  CHECK_EQ(2e-20, Strtod(vector, -20));+  CHECK_EQ(2e-22, Strtod(vector, -22));+  CHECK_EQ(2e-23, Strtod(vector, -23));+  CHECK_EQ(2e-25, Strtod(vector, -25));+  CHECK_EQ(2e-39, Strtod(vector, -39));++  vector = StringToVector("9");+  CHECK_EQ(9.0, Strtod(vector, 0));+  CHECK_EQ(90.0, Strtod(vector, 1));+  CHECK_EQ(900.0, Strtod(vector, 2));+  CHECK_EQ(9e20, Strtod(vector, 20));+  CHECK_EQ(9e22, Strtod(vector, 22));+  CHECK_EQ(9e23, Strtod(vector, 23));+  CHECK_EQ(9e35, Strtod(vector, 35));+  CHECK_EQ(9e36, Strtod(vector, 36));+  CHECK_EQ(9e37, Strtod(vector, 37));+  CHECK_EQ(9e-1, Strtod(vector, -1));+  CHECK_EQ(9e-2, Strtod(vector, -2));+  CHECK_EQ(9e-5, Strtod(vector, -5));+  CHECK_EQ(9e-20, Strtod(vector, -20));+  CHECK_EQ(9e-22, Strtod(vector, -22));+  CHECK_EQ(9e-23, Strtod(vector, -23));+  CHECK_EQ(9e-25, Strtod(vector, -25));+  CHECK_EQ(9e-39, Strtod(vector, -39));++  vector = StringToVector("12345");+  CHECK_EQ(12345.0, Strtod(vector, 0));+  CHECK_EQ(123450.0, Strtod(vector, 1));+  CHECK_EQ(1234500.0, Strtod(vector, 2));+  CHECK_EQ(12345e20, Strtod(vector, 20));+  CHECK_EQ(12345e22, Strtod(vector, 22));+  CHECK_EQ(12345e23, Strtod(vector, 23));+  CHECK_EQ(12345e30, Strtod(vector, 30));+  CHECK_EQ(12345e31, Strtod(vector, 31));+  CHECK_EQ(12345e32, Strtod(vector, 32));+  CHECK_EQ(12345e35, Strtod(vector, 35));+  CHECK_EQ(12345e36, Strtod(vector, 36));+  CHECK_EQ(12345e37, Strtod(vector, 37));+  CHECK_EQ(12345e-1, Strtod(vector, -1));+  CHECK_EQ(12345e-2, Strtod(vector, -2));+  CHECK_EQ(12345e-5, Strtod(vector, -5));+  CHECK_EQ(12345e-20, Strtod(vector, -20));+  CHECK_EQ(12345e-22, Strtod(vector, -22));+  CHECK_EQ(12345e-23, Strtod(vector, -23));+  CHECK_EQ(12345e-25, Strtod(vector, -25));+  CHECK_EQ(12345e-39, Strtod(vector, -39));++  vector = StringToVector("12345678901234");+  CHECK_EQ(12345678901234.0, Strtod(vector, 0));+  CHECK_EQ(123456789012340.0, Strtod(vector, 1));+  CHECK_EQ(1234567890123400.0, Strtod(vector, 2));+  CHECK_EQ(12345678901234e20, Strtod(vector, 20));+  CHECK_EQ(12345678901234e22, Strtod(vector, 22));+  CHECK_EQ(12345678901234e23, Strtod(vector, 23));+  CHECK_EQ(12345678901234e30, Strtod(vector, 30));+  CHECK_EQ(12345678901234e31, Strtod(vector, 31));+  CHECK_EQ(12345678901234e32, Strtod(vector, 32));+  CHECK_EQ(12345678901234e35, Strtod(vector, 35));+  CHECK_EQ(12345678901234e36, Strtod(vector, 36));+  CHECK_EQ(12345678901234e37, Strtod(vector, 37));+  CHECK_EQ(12345678901234e-1, Strtod(vector, -1));+  CHECK_EQ(12345678901234e-2, Strtod(vector, -2));+  CHECK_EQ(12345678901234e-5, Strtod(vector, -5));+  CHECK_EQ(12345678901234e-20, Strtod(vector, -20));+  CHECK_EQ(12345678901234e-22, Strtod(vector, -22));+  CHECK_EQ(12345678901234e-23, Strtod(vector, -23));+  CHECK_EQ(12345678901234e-25, Strtod(vector, -25));+  CHECK_EQ(12345678901234e-39, Strtod(vector, -39));++  vector = StringToVector("123456789012345");+  CHECK_EQ(123456789012345.0, Strtod(vector, 0));+  CHECK_EQ(1234567890123450.0, Strtod(vector, 1));+  CHECK_EQ(12345678901234500.0, Strtod(vector, 2));+  CHECK_EQ(123456789012345e20, Strtod(vector, 20));+  CHECK_EQ(123456789012345e22, Strtod(vector, 22));+  CHECK_EQ(123456789012345e23, Strtod(vector, 23));+  CHECK_EQ(123456789012345e35, Strtod(vector, 35));+  CHECK_EQ(123456789012345e36, Strtod(vector, 36));+  CHECK_EQ(123456789012345e37, Strtod(vector, 37));+  CHECK_EQ(123456789012345e39, Strtod(vector, 39));+  CHECK_EQ(123456789012345e-1, Strtod(vector, -1));+  CHECK_EQ(123456789012345e-2, Strtod(vector, -2));+  CHECK_EQ(123456789012345e-5, Strtod(vector, -5));+  CHECK_EQ(123456789012345e-20, Strtod(vector, -20));+  CHECK_EQ(123456789012345e-22, Strtod(vector, -22));+  CHECK_EQ(123456789012345e-23, Strtod(vector, -23));+  CHECK_EQ(123456789012345e-25, Strtod(vector, -25));+  CHECK_EQ(123456789012345e-39, Strtod(vector, -39));++  CHECK_EQ(0.0, StrtodChar("0", 12345));+  CHECK_EQ(0.0, StrtodChar("", 1324));+  CHECK_EQ(0.0, StrtodChar("000000000", 123));+  CHECK_EQ(0.0, StrtodChar("2", -324));+  CHECK_EQ(4e-324, StrtodChar("3", -324));+  // It would be more readable to put non-zero literals on the left side (i.e.+  //   CHECK_EQ(1e-325, StrtodChar("1", -325))), but then Gcc complains that+  // they are truncated to zero.+  CHECK_EQ(0.0, StrtodChar("1", -325));+  CHECK_EQ(0.0, StrtodChar("1", -325));+  CHECK_EQ(0.0, StrtodChar("20000", -328));+  CHECK_EQ(40000e-328, StrtodChar("30000", -328));+  CHECK_EQ(0.0, StrtodChar("10000", -329));+  CHECK_EQ(0.0, StrtodChar("90000", -329));+  CHECK_EQ(0.0, StrtodChar("000000001", -325));+  CHECK_EQ(0.0, StrtodChar("000000001", -325));+  CHECK_EQ(0.0, StrtodChar("0000000020000", -328));+  CHECK_EQ(40000e-328, StrtodChar("00000030000", -328));+  CHECK_EQ(0.0, StrtodChar("0000000010000", -329));+  CHECK_EQ(0.0, StrtodChar("0000000090000", -329));++  // It would be more readable to put the literals (and not Double::Infinity())+  // on the left side (i.e. CHECK_EQ(1e309, StrtodChar("1", 309))), but then Gcc+  // complains that the floating constant exceeds range of 'double'.+  CHECK_EQ(Double::Infinity(), StrtodChar("1", 309));+  CHECK_EQ(1e308, StrtodChar("1", 308));+  CHECK_EQ(1234e305, StrtodChar("1234", 305));+  CHECK_EQ(1234e304, StrtodChar("1234", 304));+  CHECK_EQ(Double::Infinity(), StrtodChar("18", 307));+  CHECK_EQ(17e307, StrtodChar("17", 307));+  CHECK_EQ(Double::Infinity(), StrtodChar("0000001", 309));+  CHECK_EQ(1e308, StrtodChar("00000001", 308));+  CHECK_EQ(1234e305, StrtodChar("00000001234", 305));+  CHECK_EQ(1234e304, StrtodChar("000000001234", 304));+  CHECK_EQ(Double::Infinity(), StrtodChar("0000000018", 307));+  CHECK_EQ(17e307, StrtodChar("0000000017", 307));+  CHECK_EQ(Double::Infinity(), StrtodChar("1000000", 303));+  CHECK_EQ(1e308, StrtodChar("100000", 303));+  CHECK_EQ(1234e305, StrtodChar("123400000", 300));+  CHECK_EQ(1234e304, StrtodChar("123400000", 299));+  CHECK_EQ(Double::Infinity(), StrtodChar("180000000", 300));+  CHECK_EQ(17e307, StrtodChar("170000000", 300));+  CHECK_EQ(Double::Infinity(), StrtodChar("00000001000000", 303));+  CHECK_EQ(1e308, StrtodChar("000000000000100000", 303));+  CHECK_EQ(1234e305, StrtodChar("00000000123400000", 300));+  CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299));+  CHECK_EQ(Double::Infinity(), StrtodChar("00000000180000000", 300));+  CHECK_EQ(17e307, StrtodChar("00000000170000000", 300));+  CHECK_EQ(1.7976931348623157E+308, StrtodChar("17976931348623157", 292));+  CHECK_EQ(1.7976931348623158E+308, StrtodChar("17976931348623158", 292));+  CHECK_EQ(Double::Infinity(), StrtodChar("17976931348623159", 292));++  // The following number is the result of 89255.0/1e-22. Both floating-point+  // numbers can be accurately represented with doubles. However on Linux,x86+  // the floating-point stack is set to 80bits and the double-rounding+  // introduces an error.+  CHECK_EQ(89255e-22, StrtodChar("89255", -22));++  // Some random values.+  CHECK_EQ(358416272e-33, StrtodChar("358416272", -33));+  CHECK_EQ(104110013277974872254e-225,+           StrtodChar("104110013277974872254", -225));++  CHECK_EQ(123456789e108, StrtodChar("123456789", 108));+  CHECK_EQ(123456789e109, StrtodChar("123456789", 109));+  CHECK_EQ(123456789e110, StrtodChar("123456789", 110));+  CHECK_EQ(123456789e111, StrtodChar("123456789", 111));+  CHECK_EQ(123456789e112, StrtodChar("123456789", 112));+  CHECK_EQ(123456789e113, StrtodChar("123456789", 113));+  CHECK_EQ(123456789e114, StrtodChar("123456789", 114));+  CHECK_EQ(123456789e115, StrtodChar("123456789", 115));++  CHECK_EQ(1234567890123456789012345e108,+           StrtodChar("1234567890123456789012345", 108));+  CHECK_EQ(1234567890123456789012345e109,+           StrtodChar("1234567890123456789012345", 109));+  CHECK_EQ(1234567890123456789012345e110,+           StrtodChar("1234567890123456789012345", 110));+  CHECK_EQ(1234567890123456789012345e111,+           StrtodChar("1234567890123456789012345", 111));+  CHECK_EQ(1234567890123456789012345e112,+           StrtodChar("1234567890123456789012345", 112));+  CHECK_EQ(1234567890123456789012345e113,+           StrtodChar("1234567890123456789012345", 113));+  CHECK_EQ(1234567890123456789012345e114,+           StrtodChar("1234567890123456789012345", 114));+  CHECK_EQ(1234567890123456789012345e115,+           StrtodChar("1234567890123456789012345", 115));++  CHECK_EQ(1234567890123456789052345e108,+           StrtodChar("1234567890123456789052345", 108));+  CHECK_EQ(1234567890123456789052345e109,+           StrtodChar("1234567890123456789052345", 109));+  CHECK_EQ(1234567890123456789052345e110,+           StrtodChar("1234567890123456789052345", 110));+  CHECK_EQ(1234567890123456789052345e111,+           StrtodChar("1234567890123456789052345", 111));+  CHECK_EQ(1234567890123456789052345e112,+           StrtodChar("1234567890123456789052345", 112));+  CHECK_EQ(1234567890123456789052345e113,+           StrtodChar("1234567890123456789052345", 113));+  CHECK_EQ(1234567890123456789052345e114,+           StrtodChar("1234567890123456789052345", 114));+  CHECK_EQ(1234567890123456789052345e115,+           StrtodChar("1234567890123456789052345", 115));++  CHECK_EQ(5.445618932859895e-255,+           StrtodChar("5445618932859895362967233318697132813618813095743952975"+                      "4392982234069699615600475529427176366709107287468930197"+                      "8628345413991790019316974825934906752493984055268219809"+                      "5012176093045431437495773903922425632551857520884625114"+                      "6241265881735209066709685420744388526014389929047617597"+                      "0302268848374508109029268898695825171158085457567481507"+                      "4162979705098246243690189880319928315307816832576838178"+                      "2563074014542859888710209237525873301724479666744537857"+                      "9026553346649664045621387124193095870305991178772256504"+                      "4368663670643970181259143319016472430928902201239474588"+                      "1392338901353291306607057623202353588698746085415097902"+                      "6640064319118728664842287477491068264828851624402189317"+                      "2769161449825765517353755844373640588822904791244190695"+                      "2998382932630754670573838138825217065450843010498555058"+                      "88186560731", -1035));++  // Boundary cases. Boundaries themselves should round to even.+  //+  // 0x1FFFFFFFFFFFF * 2^3 = 72057594037927928+  //                   next: 72057594037927936+  //               boundary: 72057594037927932  should round up.+  CHECK_EQ(72057594037927928.0, StrtodChar("72057594037927928", 0));+  CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927936", 0));+  CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927932", 0));+  CHECK_EQ(72057594037927928.0, StrtodChar("7205759403792793199999", -5));+  CHECK_EQ(72057594037927936.0, StrtodChar("7205759403792793200001", -5));++  // 0x1FFFFFFFFFFFF * 2^10 = 9223372036854774784+  //                    next: 9223372036854775808+  //                boundary: 9223372036854775296 should round up.+  CHECK_EQ(9223372036854774784.0, StrtodChar("9223372036854774784", 0));+  CHECK_EQ(9223372036854775808.0, StrtodChar("9223372036854775808", 0));+  CHECK_EQ(9223372036854775808.0, StrtodChar("9223372036854775296", 0));+  CHECK_EQ(9223372036854774784.0, StrtodChar("922337203685477529599999", -5));+  CHECK_EQ(9223372036854775808.0, StrtodChar("922337203685477529600001", -5));++  // 0x1FFFFFFFFFFFF * 2^50 = 10141204801825834086073718800384+  //                    next: 10141204801825835211973625643008+  //                boundary: 10141204801825834649023672221696 should round up.+  CHECK_EQ(10141204801825834086073718800384.0,+           StrtodChar("10141204801825834086073718800384", 0));+  CHECK_EQ(10141204801825835211973625643008.0,+           StrtodChar("10141204801825835211973625643008", 0));+  CHECK_EQ(10141204801825835211973625643008.0,+           StrtodChar("10141204801825834649023672221696", 0));+  CHECK_EQ(10141204801825834086073718800384.0,+           StrtodChar("1014120480182583464902367222169599999", -5));+  CHECK_EQ(10141204801825835211973625643008.0,+           StrtodChar("1014120480182583464902367222169600001", -5));++  // 0x1FFFFFFFFFFFF * 2^99 = 5708990770823838890407843763683279797179383808+  //                    next: 5708990770823839524233143877797980545530986496+  //                boundary: 5708990770823839207320493820740630171355185152+  // The boundary should round up.+  CHECK_EQ(5708990770823838890407843763683279797179383808.0,+           StrtodChar("5708990770823838890407843763683279797179383808", 0));+  CHECK_EQ(5708990770823839524233143877797980545530986496.0,+           StrtodChar("5708990770823839524233143877797980545530986496", 0));+  CHECK_EQ(5708990770823839524233143877797980545530986496.0,+           StrtodChar("5708990770823839207320493820740630171355185152", 0));+  CHECK_EQ(5708990770823838890407843763683279797179383808.0,+           StrtodChar("5708990770823839207320493820740630171355185151999", -3));+  CHECK_EQ(5708990770823839524233143877797980545530986496.0,+           StrtodChar("5708990770823839207320493820740630171355185152001", -3));++  // The following test-cases got some public attention in early 2011 when they+  // sent Java and PHP into an infinite loop.+  CHECK_EQ(2.225073858507201e-308, StrtodChar("22250738585072011", -324));+  CHECK_EQ(2.22507385850720138309e-308,+           StrtodChar("22250738585072011360574097967091319759348195463516456480"+                      "23426109724822222021076945516529523908135087914149158913"+                      "03962110687008643869459464552765720740782062174337998814"+                      "10632673292535522868813721490129811224514518898490572223"+                      "07285255133155755015914397476397983411801999323962548289"+                      "01710708185069063066665599493827577257201576306269066333"+                      "26475653000092458883164330377797918696120494973903778297"+                      "04905051080609940730262937128958950003583799967207254304"+                      "36028407889577179615094551674824347103070260914462157228"+                      "98802581825451803257070188608721131280795122334262883686"+                      "22321503775666622503982534335974568884423900265498198385"+                      "48794829220689472168983109969836584681402285424333066033"+                      "98508864458040010349339704275671864433837704860378616227"+                      "71738545623065874679014086723327636718751", -1076));+}+++static int CompareBignumToDiyFp(const Bignum& bignum_digits,+                                int bignum_exponent,+                                DiyFp diy_fp) {+  Bignum bignum;+  bignum.AssignBignum(bignum_digits);+  Bignum other;+  other.AssignUInt64(diy_fp.f());+  if (bignum_exponent >= 0) {+    bignum.MultiplyByPowerOfTen(bignum_exponent);+  } else {+    other.MultiplyByPowerOfTen(-bignum_exponent);+  }+  if (diy_fp.e() >= 0) {+    other.ShiftLeft(diy_fp.e());+  } else {+    bignum.ShiftLeft(-diy_fp.e());+  }+  return Bignum::Compare(bignum, other);+}+++static bool CheckDouble(Vector<const char> buffer,+                        int exponent,+                        double to_check) {+  DiyFp lower_boundary;+  DiyFp upper_boundary;+  Bignum input_digits;+  input_digits.AssignDecimalString(buffer);+  if (to_check == 0.0) {+    const double kMinDouble = 4e-324;+    // Check that the buffer*10^exponent < (0 + kMinDouble)/2.+    Double d(kMinDouble);+    d.NormalizedBoundaries(&lower_boundary, &upper_boundary);+    return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) <= 0;+  }+  if (to_check == Double::Infinity()) {+    const double kMaxDouble = 1.7976931348623157e308;+    // Check that the buffer*10^exponent >= boundary between kMaxDouble and inf.+    Double d(kMaxDouble);+    d.NormalizedBoundaries(&lower_boundary, &upper_boundary);+    return CompareBignumToDiyFp(input_digits, exponent, upper_boundary) >= 0;+  }+  Double d(to_check);+  d.NormalizedBoundaries(&lower_boundary, &upper_boundary);+  if ((d.Significand() & 1) == 0) {+    return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) >= 0 &&+        CompareBignumToDiyFp(input_digits, exponent, upper_boundary) <= 0;+  } else {+    return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) > 0 &&+        CompareBignumToDiyFp(input_digits, exponent, upper_boundary) < 0;+  }+}+++// Copied from v8.cc and adapted to make the function deterministic.+static uint32_t DeterministicRandom() {+  // Random number generator using George Marsaglia's MWC algorithm.+  static uint32_t hi = 0;+  static uint32_t lo = 0;++  // Initialization values don't have any special meaning. (They are the result+  // of two calls to random().)+  if (hi == 0) hi = 0xbfe166e7;+  if (lo == 0) lo = 0x64d1c3c9;++  // Mix the bits.+  hi = 36969 * (hi & 0xFFFF) + (hi >> 16);+  lo = 18273 * (lo & 0xFFFF) + (lo >> 16);+  return (hi << 16) + (lo & 0xFFFF);+}+++static const int kBufferSize = 1024;+static const int kShortStrtodRandomCount = 2;+static const int kLargeStrtodRandomCount = 2;++TEST(RandomStrtod) {+  char buffer[kBufferSize];+  for (int length = 1; length < 15; length++) {+    for (int i = 0; i < kShortStrtodRandomCount; ++i) {+      int pos = 0;+      for (int j = 0; j < length; ++j) {+        buffer[pos++] = random() % 10 + '0';+      }+      int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length;+      buffer[pos] = '\0';+      Vector<const char> vector(buffer, pos);+      double strtod_result = Strtod(vector, exponent);+      CHECK(CheckDouble(vector, exponent, strtod_result));+    }+  }+  for (int length = 15; length < 800; length += 2) {+    for (int i = 0; i < kLargeStrtodRandomCount; ++i) {+      int pos = 0;+      for (int j = 0; j < length; ++j) {+        buffer[pos++] = random() % 10 + '0';+      }+      int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length;+      buffer[pos] = '\0';+      Vector<const char> vector(buffer, pos);+      double strtod_result = Strtod(vector, exponent);+      CHECK(CheckDouble(vector, exponent, strtod_result));+    }+  }+}
+ include/hs-double-conversion.h view
@@ -0,0 +1,24 @@+#ifndef _hs_double_conversion_h+#define _hs_double_conversion_h++#ifdef __cplusplus+extern "C"+{+#endif++#include <stddef.h>++int _hs_ToShortestLength(void);+int _hs_ToShortest(double value, uint16_t *buf);+int _hs_ToFixedLength(void);+int _hs_ToFixed(double value, uint16_t *buf, int ndigits);+int _hs_ToExponentialLength(void);+int _hs_ToExponential(double value, uint16_t *buf, int ndigits);+int _hs_ToPrecisionLength(void);+int _hs_ToPrecision(double value, uint16_t *buf, int ndigits);++#ifdef __cplusplus+}+#endif++#endif /* _hs_double_conversion_h */
+ tests/Properties.hs view
@@ -0,0 +1,11 @@+import Data.Double.Conversion+import Test.QuickCheck+import Test.Framework (defaultMain, testGroup)+import Test.Framework.Providers.QuickCheck2 (testProperty)+import qualified Data.Text as T++shortest a = (read . T.unpack . toShortest) a == a++main = defaultMain [+        testProperty "shortest" shortest+       ]
+ tests/double-conversion-tests.cabal view
@@ -0,0 +1,15 @@+name:           double-conversion-tests+version:        0+cabal-version:  >= 1.8+build-type:     Simple++executable qc+  main-is: Properties.hs++  build-depends:+    QuickCheck,+    base,+    double-conversion,+    test-framework,+    test-framework-quickcheck2,+    text >= 0.11.0.8