diff --git a/Data/Double/Conversion.hs b/Data/Double/Conversion.hs
new file mode 100644
--- /dev/null
+++ b/Data/Double/Conversion.hs
@@ -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
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -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>.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Benchmarks.hs
@@ -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 -> ()
diff --git a/benchmarks/double-conversion-benchmarks.cabal b/benchmarks/double-conversion-benchmarks.cabal
new file mode 100644
--- /dev/null
+++ b/benchmarks/double-conversion-benchmarks.cabal
@@ -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
diff --git a/cbits/hs-double-conversion.cc b/cbits/hs-double-conversion.cc
new file mode 100644
--- /dev/null
+++ b/cbits/hs-double-conversion.cc
@@ -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);
+}
diff --git a/double-conversion.cabal b/double-conversion.cabal
new file mode 100644
--- /dev/null
+++ b/double-conversion.cabal
@@ -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
diff --git a/double-conversion/COPYING b/double-conversion/COPYING
new file mode 100644
--- /dev/null
+++ b/double-conversion/COPYING
@@ -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.
diff --git a/double-conversion/LICENSE b/double-conversion/LICENSE
new file mode 100644
--- /dev/null
+++ b/double-conversion/LICENSE
@@ -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.
diff --git a/double-conversion/Makefile b/double-conversion/Makefile
new file mode 100644
--- /dev/null
+++ b/double-conversion/Makefile
@@ -0,0 +1,7 @@
+all:
+	scons debug=1
+
+test:
+	./run_tests --list | tr -d '<' | xargs ./run_tests
+
+.PHONY: test all
diff --git a/double-conversion/README b/double-conversion/README
new file mode 100644
--- /dev/null
+++ b/double-conversion/README
@@ -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.
diff --git a/double-conversion/SConstruct b/double-conversion/SConstruct
new file mode 100644
--- /dev/null
+++ b/double-conversion/SConstruct
@@ -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)
diff --git a/double-conversion/src/SConscript b/double-conversion/src/SConscript
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/SConscript
@@ -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')
diff --git a/double-conversion/src/bignum-dtoa.cc b/double-conversion/src/bignum-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/bignum-dtoa.cc
@@ -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
diff --git a/double-conversion/src/bignum-dtoa.h b/double-conversion/src/bignum-dtoa.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/bignum-dtoa.h
@@ -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_
diff --git a/double-conversion/src/bignum.cc b/double-conversion/src/bignum.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/bignum.cc
@@ -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
diff --git a/double-conversion/src/bignum.h b/double-conversion/src/bignum.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/bignum.h
@@ -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_
diff --git a/double-conversion/src/cached-powers.cc b/double-conversion/src/cached-powers.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/cached-powers.cc
@@ -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
diff --git a/double-conversion/src/cached-powers.h b/double-conversion/src/cached-powers.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/cached-powers.h
@@ -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_
diff --git a/double-conversion/src/diy-fp.cc b/double-conversion/src/diy-fp.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/diy-fp.cc
@@ -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
diff --git a/double-conversion/src/diy-fp.h b/double-conversion/src/diy-fp.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/diy-fp.h
@@ -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_
diff --git a/double-conversion/src/double-conversion.cc b/double-conversion/src/double-conversion.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/double-conversion.cc
@@ -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
diff --git a/double-conversion/src/double-conversion.h b/double-conversion/src/double-conversion.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/double-conversion.h
@@ -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_
diff --git a/double-conversion/src/double.h b/double-conversion/src/double.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/double.h
@@ -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_
diff --git a/double-conversion/src/fast-dtoa.cc b/double-conversion/src/fast-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/fast-dtoa.cc
@@ -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
diff --git a/double-conversion/src/fast-dtoa.h b/double-conversion/src/fast-dtoa.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/fast-dtoa.h
@@ -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_
diff --git a/double-conversion/src/fixed-dtoa.cc b/double-conversion/src/fixed-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/fixed-dtoa.cc
@@ -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
diff --git a/double-conversion/src/fixed-dtoa.h b/double-conversion/src/fixed-dtoa.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/fixed-dtoa.h
@@ -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_
diff --git a/double-conversion/src/strtod.cc b/double-conversion/src/strtod.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/strtod.cc
@@ -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
diff --git a/double-conversion/src/strtod.h b/double-conversion/src/strtod.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/strtod.h
@@ -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_
diff --git a/double-conversion/src/utils.h b/double-conversion/src/utils.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/src/utils.h
@@ -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_
diff --git a/double-conversion/test/cctest/SConscript b/double-conversion/test/cctest/SConscript
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/SConscript
@@ -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')
diff --git a/double-conversion/test/cctest/cctest.cc b/double-conversion/test/cctest/cctest.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/cctest.cc
@@ -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;
+}
diff --git a/double-conversion/test/cctest/cctest.h b/double-conversion/test/cctest/cctest.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/cctest.h
@@ -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_
diff --git a/double-conversion/test/cctest/checks.h b/double-conversion/test/cctest/checks.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/checks.h
@@ -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_
diff --git a/double-conversion/test/cctest/gay-fixed.cc b/double-conversion/test/cctest/gay-fixed.cc
new file mode 100644
# file too large to diff: double-conversion/test/cctest/gay-fixed.cc
diff --git a/double-conversion/test/cctest/gay-fixed.h b/double-conversion/test/cctest/gay-fixed.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/gay-fixed.h
@@ -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_
diff --git a/double-conversion/test/cctest/gay-precision.cc b/double-conversion/test/cctest/gay-precision.cc
new file mode 100644
# file too large to diff: double-conversion/test/cctest/gay-precision.cc
diff --git a/double-conversion/test/cctest/gay-precision.h b/double-conversion/test/cctest/gay-precision.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/gay-precision.h
@@ -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_
diff --git a/double-conversion/test/cctest/gay-shortest.cc b/double-conversion/test/cctest/gay-shortest.cc
new file mode 100644
# file too large to diff: double-conversion/test/cctest/gay-shortest.cc
diff --git a/double-conversion/test/cctest/gay-shortest.h b/double-conversion/test/cctest/gay-shortest.h
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/gay-shortest.h
@@ -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_
diff --git a/double-conversion/test/cctest/test-bignum-dtoa.cc b/double-conversion/test/cctest/test-bignum-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-bignum-dtoa.cc
@@ -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());
+  }
+}
diff --git a/double-conversion/test/cctest/test-bignum.cc b/double-conversion/test/cctest/test-bignum.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-bignum.cc
@@ -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);
+}
diff --git a/double-conversion/test/cctest/test-conversions.cc b/double-conversion/test/cctest/test-conversions.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-conversions.cc
@@ -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);
+}
diff --git a/double-conversion/test/cctest/test-diy-fp.cc b/double-conversion/test/cctest/test-diy-fp.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-diy-fp.cc
@@ -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());
+}
diff --git a/double-conversion/test/cctest/test-double.cc b/double-conversion/test/cctest/test-double.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-double.cc
@@ -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());
+}
diff --git a/double-conversion/test/cctest/test-dtoa.cc b/double-conversion/test/cctest/test-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-dtoa.cc
@@ -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());
+  }
+}
diff --git a/double-conversion/test/cctest/test-fast-dtoa.cc b/double-conversion/test/cctest/test-fast-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-fast-dtoa.cc
@@ -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);
+}
diff --git a/double-conversion/test/cctest/test-fixed-dtoa.cc b/double-conversion/test/cctest/test-fixed-dtoa.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-fixed-dtoa.cc
@@ -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());
+  }
+}
diff --git a/double-conversion/test/cctest/test-strtod.cc b/double-conversion/test/cctest/test-strtod.cc
new file mode 100644
--- /dev/null
+++ b/double-conversion/test/cctest/test-strtod.cc
@@ -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));
+    }
+  }
+}
diff --git a/include/hs-double-conversion.h b/include/hs-double-conversion.h
new file mode 100644
--- /dev/null
+++ b/include/hs-double-conversion.h
@@ -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 */
diff --git a/tests/Properties.hs b/tests/Properties.hs
new file mode 100644
--- /dev/null
+++ b/tests/Properties.hs
@@ -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
+       ]
diff --git a/tests/double-conversion-tests.cabal b/tests/double-conversion-tests.cabal
new file mode 100644
--- /dev/null
+++ b/tests/double-conversion-tests.cabal
@@ -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
