You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2026/04/21 04:09:38 UTC

(couchdb-jiffy) 27/49: Switch to Ryu for float point encoding

This is an automated email from the ASF dual-hosted git repository.

nickva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-jiffy.git

commit b42c9a48c89e4a09d6e1090e99f971f099b5f7e6
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Fri Apr 3 10:14:49 2026 -0400

    Switch to Ryu for float point encoding
    
    [Ryu](https://github.com/ulfjack/ryu) is faster then `double-conversion`, is
    adopted by Erlang/OTP team (and other languages and frameworks), and is written
    in C instead of C++.
    
    Since we're an Erlang library we'll just use the Erlang/OTP version of
    [Ryu](https://github.com/erlang/otp/tree/master/erts/emulator/ryu). We'll
    accept its defaults and peculiariaties and go with it, even if it means not
    producing string-identical output as we did before (for instance, after this
    change we don't emit `+` signs in front of the exponent and we also switch to
    the scientific notation a lot sooner, but as they say "when in Rome ...").
---
 Makefile                                     |    4 +-
 README.ryu.md                                |   28 +
 c_src/double-conversion/AUTHORS              |   14 -
 c_src/double-conversion/COPYING              |   26 -
 c_src/double-conversion/LICENSE              |   26 -
 c_src/double-conversion/README.md            |   54 --
 c_src/double-conversion/VERSION              |    3 -
 c_src/double-conversion/bignum-dtoa.cc       |  641 ---------------
 c_src/double-conversion/bignum-dtoa.h        |   84 --
 c_src/double-conversion/bignum.cc            |  767 -----------------
 c_src/double-conversion/bignum.h             |  144 ----
 c_src/double-conversion/cached-powers.cc     |  175 ----
 c_src/double-conversion/cached-powers.h      |   64 --
 c_src/double-conversion/diy-fp.cc            |   57 --
 c_src/double-conversion/diy-fp.h             |  118 ---
 c_src/double-conversion/double-conversion.cc | 1144 --------------------------
 c_src/double-conversion/double-conversion.h  |  576 -------------
 c_src/double-conversion/fast-dtoa.cc         |  665 ---------------
 c_src/double-conversion/fast-dtoa.h          |   88 --
 c_src/double-conversion/fixed-dtoa.cc        |  405 ---------
 c_src/double-conversion/fixed-dtoa.h         |   56 --
 c_src/double-conversion/ieee.h               |  402 ---------
 c_src/double-conversion/strtod.cc            |  580 -------------
 c_src/double-conversion/strtod.h             |   45 -
 c_src/double-conversion/utils.h              |  367 ---------
 c_src/doubles.cc                             |   33 -
 c_src/encoder.c                              |   13 +-
 c_src/jiffy.h                                |    1 -
 c_src/ryu/LICENSE-Apache2                    |  201 +++++
 c_src/ryu/LICENSE-Boost                      |   23 +
 c_src/ryu/common.h                           |  116 +++
 c_src/ryu/d2s.c                              |  391 +++++++++
 c_src/ryu/d2s_full_table.h                   |  367 +++++++++
 c_src/ryu/d2s_intrinsics.h                   |  359 ++++++++
 c_src/ryu/digit_table.h                      |   35 +
 c_src/ryu/ryu.h                              |   37 +
 c_src/ryu/to_chars.h                         |  342 ++++++++
 rebar.config                                 |    2 +-
 test/jiffy_03_number_tests.erl               |   12 +-
 39 files changed, 1912 insertions(+), 6553 deletions(-)

diff --git a/Makefile b/Makefile
index 0a88ae6..71da10c 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ clean:
 	rm -f test/*.beam
 	rm -rf eqc
 	rm -rf _build
-	rm -f c_src/*.gcno c_src/*.gcda c_src/double-conversion/*.gcno c_src/double-conversion/*.gcda
+	rm -f c_src/*.gcno c_src/*.gcda c_src/ryu/*.gcno c_src/ryu/*.gcda
 	rm -f coverage.info coverage-jiffy.info
 	rm -rf coverage-html
 
@@ -44,7 +44,7 @@ coverage:
 	$(MAKE) clean
 	CFLAGS="--coverage -O0" CXXFLAGS="--coverage -O0" LDFLAGS="--coverage" $(MAKE) check-with-eqc
 	@lcov --capture --directory c_src -o coverage.info --ignore-errors inconsistent,unsupported
-	@lcov --extract coverage.info '*/c_src/*' --exclude '*/double-conversion/*' -o coverage-jiffy.info --ignore-errors inconsistent,unsupported
+	@lcov --extract coverage.info '*/c_src/*' --exclude '*/ryu/*' -o coverage-jiffy.info --ignore-errors inconsistent,unsupported
 	@genhtml coverage-jiffy.info -o coverage-html --title "jiffy lcov report"
 	@echo "For coverage report: open coverage-html/index.html"
 
diff --git a/README.ryu.md b/README.ryu.md
new file mode 100644
index 0000000..27ece6a
--- /dev/null
+++ b/README.ryu.md
@@ -0,0 +1,28 @@
+# Ryu
+
+Our version of Ryu cames as-is from Erlang/OTP, accepting its format. We're an
+Erlang library so we'll accept what Erlang/OTP team goes with.
+
+Erlang's Ryu in turn is a modified version of
+[Ryu](https://github.com/ulfjack/ryu), keeping only what's needed, and then
+modified to produce Erlang-like formatted floats. For example, original Ryu
+will produce `"1E1"` from `10.0`, while Erlang and Jiffy will write `"10.0"`.
+
+# How to update
+
+```sh
+OTP_SRC=/path/to/otp
+
+cp $OTP_SRC/erts/emulator/ryu/common.h         c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/d2s.c            c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/d2s_full_table.h c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/d2s_intrinsics.h c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/digit_table.h    c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/ryu.h            c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/to_chars.h       c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/LICENSE-Apache2   c_src/ryu/
+cp $OTP_SRC/erts/emulator/ryu/LICENSE-Boost     c_src/ryu/
+```
+
+Note: we don't modify the ryu files after this. But we do handle the `-0.0` ==
+`0.0` case in `c_src/double.c`.
diff --git a/c_src/double-conversion/AUTHORS b/c_src/double-conversion/AUTHORS
deleted file mode 100644
index 88b38ae..0000000
--- a/c_src/double-conversion/AUTHORS
+++ /dev/null
@@ -1,14 +0,0 @@
-# Below is a list of people and organizations that have contributed
-# to the double-conversion project.  Names should be added to the
-# list like so:
-#
-#   Name/Organization <email address>
-
-Google Inc.
-Mozilla Foundation
-
-Jeff Muizelaar <jm...@mozilla.com>
-Mike Hommey <mh...@mozilla.com>
-Martin Olsson <mn...@minimum.se>
-Kent Williams <ch...@gmail.com>
-Elan Ruusamäe <gl...@delfi.ee>
diff --git a/c_src/double-conversion/COPYING b/c_src/double-conversion/COPYING
deleted file mode 100644
index 933718a..0000000
--- a/c_src/double-conversion/COPYING
+++ /dev/null
@@ -1,26 +0,0 @@
-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/c_src/double-conversion/LICENSE b/c_src/double-conversion/LICENSE
deleted file mode 100644
index 933718a..0000000
--- a/c_src/double-conversion/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-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/c_src/double-conversion/README.md b/c_src/double-conversion/README.md
deleted file mode 100644
index 4ae9be5..0000000
--- a/c_src/double-conversion/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-https://github.com/google/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 `double-conversion/double-conversion.h`. Other 
-examples can be found in `test/cctest/test-conversions.cc`.
-
-
-Building
-========
-
-This library can be built with [scons][0] or [cmake][1].
-The checked-in Makefile simply forwards to scons, and provides a
-shortcut to run all tests:
-
-    make
-    make test
-
-Scons
------
-
-The easiest way to install this library is to use `scons`. It builds
-the static and shared library, and is set up to install those at the
-correct locations:
-
-    scons install
-
-Use the `DESTDIR` option to change the target directory:
-
-    scons DESTDIR=alternative_directory install
-
-Cmake
------
-
-To use cmake run `cmake .` in the root directory. This overwrites the
-existing Makefile.
-
-Use `-DBUILD_SHARED_LIBS=ON` to enable the compilation of shared libraries.
-Note that this disables static libraries. There is currently no way to
-build both libraries at the same time with cmake.
-
-Use `-DBUILD_TESTING=ON` to build the test executable.
-
-    cmake . -DBUILD_TESTING=ON
-    make
-    test/cctest/cctest --list | tr -d '<' | xargs test/cctest/cctest
-
-[0]: http://www.scons.org/
-[1]: https://cmake.org/
diff --git a/c_src/double-conversion/VERSION b/c_src/double-conversion/VERSION
deleted file mode 100644
index 89e9751..0000000
--- a/c_src/double-conversion/VERSION
+++ /dev/null
@@ -1,3 +0,0 @@
-Clone from: https://github.com/google/double-conversion
-Version: v3.1.4
-Commit: 8fcee05fae7f2d6962deb9093891c47993c3d6a2
diff --git a/c_src/double-conversion/bignum-dtoa.cc b/c_src/double-conversion/bignum-dtoa.cc
deleted file mode 100644
index d99ac2a..0000000
--- a/c_src/double-conversion/bignum-dtoa.cc
+++ /dev/null
@@ -1,641 +0,0 @@
-// 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 <cmath>
-
-#include "bignum-dtoa.h"
-
-#include "bignum.h"
-#include "ieee.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(uint64_t significand,
-                                     int exponent,
-                                     bool lower_boundary_is_closer,
-                                     int estimated_power,
-                                     bool need_boundary_deltas,
-                                     Bignum* numerator,
-                                     Bignum* denominator,
-                                     Bignum* delta_minus,
-                                     Bignum* delta_plus);
-// 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;
-  int exponent;
-  bool lower_boundary_is_closer;
-  if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
-    float f = static_cast<float>(v);
-    ASSERT(f == v);
-    significand = Single(f).Significand();
-    exponent = Single(f).Exponent();
-    lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
-  } else {
-    significand = Double(v).Significand();
-    exponent = Double(v).Exponent();
-    lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
-  }
-  bool need_boundary_deltas =
-      (mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
-
-  bool is_even = (significand & 1) == 0;
-  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);
-  InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
-                           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:
-    case BIGNUM_DTOA_SHORTEST_SINGLE:
-      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;
-  for (;;) {
-    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)++] = static_cast<char>(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] = static_cast<char>(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++;
-  }
-  ASSERT(digit <= 10);
-  buffer[count - 1] = static_cast<char>(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 = Double::kSignificandSize;
-  double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
-  return static_cast<int>(estimate);
-}
-
-
-// See comments for InitialScaledStartValues.
-static void InitialScaledStartValuesPositiveExponent(
-    uint64_t significand, int exponent,
-    int estimated_power, bool need_boundary_deltas,
-    Bignum* numerator, Bignum* denominator,
-    Bignum* delta_minus, Bignum* delta_plus) {
-  // 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(significand);
-  numerator->ShiftLeft(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(exponent);
-    // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
-    delta_minus->AssignUInt16(1);
-    delta_minus->ShiftLeft(exponent);
-  }
-}
-
-
-// See comments for InitialScaledStartValues
-static void InitialScaledStartValuesNegativeExponentPositivePower(
-    uint64_t significand, int exponent,
-    int estimated_power, bool need_boundary_deltas,
-    Bignum* numerator, Bignum* denominator,
-    Bignum* delta_minus, Bignum* delta_plus) {
-  // 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. The adjustments if f == 2^p-1 are done later.
-    delta_minus->AssignUInt16(1);
-  }
-}
-
-
-// See comments for InitialScaledStartValues
-static void InitialScaledStartValuesNegativeExponentNegativePower(
-    uint64_t significand, int exponent,
-    int estimated_power, bool need_boundary_deltas,
-    Bignum* numerator, Bignum* denominator,
-    Bignum* delta_minus, Bignum* delta_plus) {
-  // 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 adjustments if f == 2^p-1 (lower boundary is closer) are done later.
-  }
-}
-
-
-// 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 the mode equals BIGNUM_DTOA_SHORTEST
-// or BIGNUM_DTOA_SHORTEST_SINGLE.
-
-static void InitialScaledStartValues(uint64_t significand,
-                                     int exponent,
-                                     bool lower_boundary_is_closer,
-                                     int estimated_power,
-                                     bool need_boundary_deltas,
-                                     Bignum* numerator,
-                                     Bignum* denominator,
-                                     Bignum* delta_minus,
-                                     Bignum* delta_plus) {
-  if (exponent >= 0) {
-    InitialScaledStartValuesPositiveExponent(
-        significand, exponent, estimated_power, need_boundary_deltas,
-        numerator, denominator, delta_minus, delta_plus);
-  } else if (estimated_power >= 0) {
-    InitialScaledStartValuesNegativeExponentPositivePower(
-        significand, exponent, estimated_power, need_boundary_deltas,
-        numerator, denominator, delta_minus, delta_plus);
-  } else {
-    InitialScaledStartValuesNegativeExponentNegativePower(
-        significand, exponent, estimated_power, need_boundary_deltas,
-        numerator, denominator, delta_minus, delta_plus);
-  }
-
-  if (need_boundary_deltas && lower_boundary_is_closer) {
-    // 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
-  }
-}
-
-
-// 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/c_src/double-conversion/bignum-dtoa.h b/c_src/double-conversion/bignum-dtoa.h
deleted file mode 100644
index 34b9619..0000000
--- a/c_src/double-conversion/bignum-dtoa.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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,
-  // Same as BIGNUM_DTOA_SHORTEST but for single-precision floats.
-  BIGNUM_DTOA_SHORTEST_SINGLE,
-  // 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/c_src/double-conversion/bignum.cc b/c_src/double-conversion/bignum.cc
deleted file mode 100644
index d077eef..0000000
--- a/c_src/double-conversion/bignum.cc
+++ /dev/null
@@ -1,767 +0,0 @@
-// 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_buffer_(), 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) {
-  (void) value;  // Mark variable as used.
-  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();
-  unsigned 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';
-  ASSERT('A' <= c && c <= 'F');
-  return 10 + c - 'A';
-}
-
-
-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_multiplication = 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) {
-      ASSERT(bit_size > 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_multiplication = true;
-      }
-    }
-    mask >>= 1;
-  }
-  AssignUInt64(this_value);
-  if (delayed_multiplication) {
-    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 `this` divided by other
-    // is 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));
-    ASSERT(bigits_[used_digits_ - 1] < 0x10000);
-    // Remove the multiples of the first digit.
-    // Example this = 23 and other equals 9. -> Remove 2 multiples.
-    result += static_cast<uint16_t>(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;
-    ASSERT(quotient < 0x10000);
-    result += static_cast<uint16_t>(quotient);
-    Clamp();
-    return result;
-  }
-
-  int division_estimate = this_bigit / (other_bigit + 1);
-  ASSERT(division_estimate < 0x10000);
-  result += static_cast<uint16_t>(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 static_cast<char>(value + '0');
-  return static_cast<char>(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);
-  }
-  Clamp();
-}
-
-
-}  // namespace double_conversion
diff --git a/c_src/double-conversion/bignum.h b/c_src/double-conversion/bignum.h
deleted file mode 100644
index 7c289fa..0000000
--- a/c_src/double-conversion/bignum.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// 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 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;
-
-  // Returns
-  //  -1 if a < b,
-  //   0 if a == b, and
-  //  +1 if a > b.
-  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_;
-
-  DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
-};
-
-}  // namespace double_conversion
-
-#endif  // DOUBLE_CONVERSION_BIGNUM_H_
diff --git a/c_src/double-conversion/cached-powers.cc b/c_src/double-conversion/cached-powers.cc
deleted file mode 100644
index 8ab281a..0000000
--- a/c_src/double-conversion/cached-powers.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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 <climits>
-#include <cmath>
-#include <cstdarg>
-
-#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 kCachedPowersOffset = 348;  // -1 * the first decimal_exponent.
-static const double kD_1_LOG2_10 = 0.30102999566398114;  //  1 / lg(10)
-// Difference between the decimal exponents in the table above.
-const int PowersOfTenCache::kDecimalExponentDistance = 8;
-const int PowersOfTenCache::kMinDecimalExponent = -348;
-const int PowersOfTenCache::kMaxDecimalExponent = 340;
-
-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 < static_cast<int>(ARRAY_SIZE(kCachedPowers)));
-  CachedPower cached_power = kCachedPowers[index];
-  ASSERT(min_exponent <= cached_power.binary_exponent);
-  (void) max_exponent;  // Mark variable as used.
-  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/c_src/double-conversion/cached-powers.h b/c_src/double-conversion/cached-powers.h
deleted file mode 100644
index 61a5061..0000000
--- a/c_src/double-conversion/cached-powers.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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/c_src/double-conversion/diy-fp.cc b/c_src/double-conversion/diy-fp.cc
deleted file mode 100644
index ddd1891..0000000
--- a/c_src/double-conversion/diy-fp.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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/c_src/double-conversion/diy-fp.h b/c_src/double-conversion/diy-fp.h
deleted file mode 100644
index 2edf346..0000000
--- a/c_src/double-conversion/diy-fp.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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 significand, int exponent) : f_(significand), e_(exponent) {}
-
-  // 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 significand = f_;
-    int exponent = 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 ((significand & k10MSBits) == 0) {
-      significand <<= 10;
-      exponent -= 10;
-    }
-    while ((significand & kUint64MSB) == 0) {
-      significand <<= 1;
-      exponent--;
-    }
-    f_ = significand;
-    e_ = exponent;
-  }
-
-  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/c_src/double-conversion/double-conversion.cc b/c_src/double-conversion/double-conversion.cc
deleted file mode 100644
index 163d41b..0000000
--- a/c_src/double-conversion/double-conversion.cc
+++ /dev/null
@@ -1,1144 +0,0 @@
-// 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 <climits>
-#include <locale>
-#include <cmath>
-
-#include "double-conversion.h"
-
-#include "bignum-dtoa.h"
-#include "fast-dtoa.h"
-#include "fixed-dtoa.h"
-#include "ieee.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 + 1];
-  buffer[kMaxExponentLength] = '\0';
-  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" or "0.000decimal_rep00".
-    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::ToShortestIeeeNumber(
-    double value,
-    StringBuilder* result_builder,
-    DoubleToStringConverter::DtoaMode mode) const {
-  ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
-  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, mode, 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];
-#ifndef NDEBUG
-  // Problem: there is an assert in StringBuilder::AddSubstring() that
-  // will pass this buffer to strlen(), and this buffer is not generally
-  // null-terminated.
-  memset(decimal_rep, 0, sizeof(decimal_rep));
-#endif
-  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::SHORTEST_SINGLE:
-        return BIGNUM_DTOA_SHORTEST_SINGLE;
-    case DoubleToStringConverter::FIXED:     return BIGNUM_DTOA_FIXED;
-    case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-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 || mode == SHORTEST_SINGLE || 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 SHORTEST_SINGLE:
-      fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 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:
-      fast_worked = false;
-      UNREACHABLE();
-  }
-  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';
-}
-
-
-namespace {
-
-inline char ToLower(char ch) {
-  static const std::ctype<char>& cType =
-      std::use_facet<std::ctype<char> >(std::locale::classic());
-  return cType.tolower(ch);
-}
-
-inline char Pass(char ch) {
-  return ch;
-}
-
-template <class Iterator, class Converter>
-static inline bool ConsumeSubStringImpl(Iterator* current,
-                                        Iterator end,
-                                        const char* substring,
-                                        Converter converter) {
-  ASSERT(converter(**current) == *substring);
-  for (substring++; *substring != '\0'; substring++) {
-    ++*current;
-    if (*current == end || converter(**current) != *substring) {
-      return false;
-    }
-  }
-  ++*current;
-  return true;
-}
-
-// Consumes the given substring from the iterator.
-// Returns false, if the substring does not match.
-template <class Iterator>
-static bool ConsumeSubString(Iterator* current,
-                             Iterator end,
-                             const char* substring,
-                             bool allow_case_insensibility) {
-  if (allow_case_insensibility) {
-    return ConsumeSubStringImpl(current, end, substring, ToLower);
-  } else {
-    return ConsumeSubStringImpl(current, end, substring, Pass);
-  }
-}
-
-// Consumes first character of the str is equal to ch
-inline bool ConsumeFirstCharacter(char ch,
-                                         const char* str,
-                                         bool case_insensibility) {
-  return case_insensibility ? ToLower(ch) == str[0] : ch == str[0];
-}
-}  // namespace
-
-// 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;
-
-
-static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
-static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
-
-
-static const uc16 kWhitespaceTable16[] = {
-  160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
-  8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
-};
-static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
-
-
-static bool isWhitespace(int x) {
-  if (x < 128) {
-    for (int i = 0; i < kWhitespaceTable7Length; i++) {
-      if (kWhitespaceTable7[i] == x) return true;
-    }
-  } else {
-    for (int i = 0; i < kWhitespaceTable16Length; i++) {
-      if (kWhitespaceTable16[i] == x) return true;
-    }
-  }
-  return false;
-}
-
-
-// Returns true if a nonspace found and false if the end has reached.
-template <class Iterator>
-static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
-  while (*current != end) {
-    if (!isWhitespace(**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;
-}
-
-
-// Returns true if 'c' is a decimal digit that is valid for the given radix.
-//
-// The function is small and could be inlined, but VS2012 emitted a warning
-// because it constant-propagated the radix and concluded that the last
-// condition was always true. By moving it into a separate function the
-// compiler wouldn't warn anymore.
-#ifdef _MSC_VER
-#pragma optimize("",off)
-static bool IsDecimalDigitForRadix(int c, int radix) {
-  return '0' <= c && c <= '9' && (c - '0') < radix;
-}
-#pragma optimize("",on)
-#else
-static bool inline IsDecimalDigitForRadix(int c, int radix) {
-  return '0' <= c && c <= '9' && (c - '0') < radix;
-}
-#endif
-// Returns true if 'c' is a character digit that is valid for the given radix.
-// The 'a_character' should be 'a' or 'A'.
-//
-// The function is small and could be inlined, but VS2012 emitted a warning
-// because it constant-propagated the radix and concluded that the first
-// condition was always false. By moving it into a separate function the
-// compiler wouldn't warn anymore.
-static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
-  return radix > 10 && c >= a_character && c < a_character + radix - 10;
-}
-
-// Returns true, when the iterator is equal to end.
-template<class Iterator>
-static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) {
-  if (separator == StringToDoubleConverter::kNoSeparator) {
-    ++(*it);
-    return *it == end;
-  }
-  if (!isDigit(**it, base)) {
-    ++(*it);
-    return *it == end;
-  }
-  ++(*it);
-  if (*it == end) return true;
-  if (*it + 1 == end) return false;
-  if (**it == separator && isDigit(*(*it + 1), base)) {
-    ++(*it);
-  }
-  return *it == end;
-}
-
-// Checks whether the string in the range start-end is a hex-float string.
-// This function assumes that the leading '0x'/'0X' is already consumed.
-//
-// Hex float strings are of one of the following forms:
-//   - hex_digits+ 'p' ('+'|'-')? exponent_digits+
-//   - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
-//   - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
-template<class Iterator>
-static bool IsHexFloatString(Iterator start,
-                             Iterator end,
-                             uc16 separator,
-                             bool allow_trailing_junk) {
-  ASSERT(start != end);
-
-  Iterator current = start;
-
-  bool saw_digit = false;
-  while (isDigit(*current, 16)) {
-    saw_digit = true;
-    if (Advance(&current, separator, 16, end)) return false;
-  }
-  if (*current == '.') {
-    if (Advance(&current, separator, 16, end)) return false;
-    while (isDigit(*current, 16)) {
-      saw_digit = true;
-      if (Advance(&current, separator, 16, end)) return false;
-    }
-    if (!saw_digit) return false;  // Only the '.', but no digits.
-  }
-  if (*current != 'p' && *current != 'P') return false;
-  if (Advance(&current, separator, 16, end)) return false;
-  if (*current == '+' || *current == '-') {
-    if (Advance(&current, separator, 16, end)) return false;
-  }
-  if (!isDigit(*current, 10)) return false;
-  if (Advance(&current, separator, 16, end)) return true;
-  while (isDigit(*current, 10)) {
-    if (Advance(&current, separator, 16, end)) return true;
-  }
-  return allow_trailing_junk || !AdvanceToNonspace(&current, end);
-}
-
-
-// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
-//
-// If parse_as_hex_float is true, then the string must be a valid
-// hex-float.
-template <int radix_log_2, class Iterator>
-static double RadixStringToIeee(Iterator* current,
-                                Iterator end,
-                                bool sign,
-                                uc16 separator,
-                                bool parse_as_hex_float,
-                                bool allow_trailing_junk,
-                                double junk_string_value,
-                                bool read_as_double,
-                                bool* result_is_junk) {
-  ASSERT(*current != end);
-  ASSERT(!parse_as_hex_float ||
-      IsHexFloatString(*current, end, separator, allow_trailing_junk));
-
-  const int kDoubleSize = Double::kSignificandSize;
-  const int kSingleSize = Single::kSignificandSize;
-  const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
-
-  *result_is_junk = true;
-
-  int64_t number = 0;
-  int exponent = 0;
-  const int radix = (1 << radix_log_2);
-  // Whether we have encountered a '.' and are parsing the decimal digits.
-  // Only relevant if parse_as_hex_float is true.
-  bool post_decimal = false;
-
-  // Skip leading 0s.
-  while (**current == '0') {
-    if (Advance(current, separator, radix, end)) {
-      *result_is_junk = false;
-      return SignedZero(sign);
-    }
-  }
-
-  while (true) {
-    int digit;
-    if (IsDecimalDigitForRadix(**current, radix)) {
-      digit = static_cast<char>(**current) - '0';
-      if (post_decimal) exponent -= radix_log_2;
-    } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
-      digit = static_cast<char>(**current) - 'a' + 10;
-      if (post_decimal) exponent -= radix_log_2;
-    } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
-      digit = static_cast<char>(**current) - 'A' + 10;
-      if (post_decimal) exponent -= radix_log_2;
-    } else if (parse_as_hex_float && **current == '.') {
-      post_decimal = true;
-      Advance(current, separator, radix, end);
-      ASSERT(*current != end);
-      continue;
-    } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
-      break;
-    } else {
-      if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
-        break;
-      } else {
-        return junk_string_value;
-      }
-    }
-
-    number = number * radix + digit;
-    int overflow = static_cast<int>(number >> kSignificandSize);
-    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;
-      for (;;) {
-        if (Advance(current, separator, radix, end)) break;
-        if (parse_as_hex_float && **current == '.') {
-          // Just run over the '.'. We are just trying to see whether there is
-          // a non-zero digit somewhere.
-          Advance(current, separator, radix, end);
-          ASSERT(*current != end);
-          post_decimal = true;
-        }
-        if (!isDigit(**current, radix)) break;
-        zero_tail = zero_tail && **current == '0';
-        if (!post_decimal) exponent += radix_log_2;
-      }
-
-      if (!parse_as_hex_float &&
-          !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 << kSignificandSize)) != 0) {
-        exponent++;
-        number >>= 1;
-      }
-      break;
-    }
-    if (Advance(current, separator, radix, end)) break;
-  }
-
-  ASSERT(number < ((int64_t)1 << kSignificandSize));
-  ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
-
-  *result_is_junk = false;
-
-  if (parse_as_hex_float) {
-    ASSERT(**current == 'p' || **current == 'P');
-    Advance(current, separator, radix, end);
-    ASSERT(*current != end);
-    bool is_negative = false;
-    if (**current == '+') {
-      Advance(current, separator, radix, end);
-      ASSERT(*current != end);
-    } else if (**current == '-') {
-      is_negative = true;
-      Advance(current, separator, radix, end);
-      ASSERT(*current != end);
-    }
-    int written_exponent = 0;
-    while (IsDecimalDigitForRadix(**current, 10)) {
-      written_exponent = 10 * written_exponent + **current - '0';
-      if (Advance(current, separator, radix, end)) break;
-    }
-    if (is_negative) written_exponent = -written_exponent;
-    exponent += written_exponent;
-  }
-
-  if (exponent == 0 || number == 0) {
-    if (sign) {
-      if (number == 0) return -0.0;
-      number = -number;
-    }
-    return static_cast<double>(number);
-  }
-
-  ASSERT(number != 0);
-  double result = Double(DiyFp(number, exponent)).value();
-  return sign ? -result : result;
-}
-
-template <class Iterator>
-double StringToDoubleConverter::StringToIeee(
-    Iterator input,
-    int length,
-    bool read_as_double,
-    int* processed_characters_count) const {
-  Iterator current = input;
-  Iterator 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;
-  const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 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 = static_cast<int>(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 sign = false;
-
-  if (*current == '+' || *current == '-') {
-    sign = (*current == '-');
-    ++current;
-    Iterator 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 (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) {
-      if (!ConsumeSubString(&current, end, infinity_symbol_, allow_case_insensibility)) {
-        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 = static_cast<int>(current - input);
-      return sign ? -Double::Infinity() : Double::Infinity();
-    }
-  }
-
-  if (nan_symbol_ != NULL) {
-    if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) {
-      if (!ConsumeSubString(&current, end, nan_symbol_, allow_case_insensibility)) {
-        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 = static_cast<int>(current - input);
-      return sign ? -Double::NaN() : Double::NaN();
-    }
-  }
-
-  bool leading_zero = false;
-  if (*current == '0') {
-    if (Advance(&current, separator_, 10, end)) {
-      *processed_characters_count = static_cast<int>(current - input);
-      return SignedZero(sign);
-    }
-
-    leading_zero = true;
-
-    // It could be hexadecimal value.
-    if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
-        (*current == 'x' || *current == 'X')) {
-      ++current;
-
-      bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
-                IsHexFloatString(current, end, separator_, allow_trailing_junk);
-
-      if (current == end) return junk_string_value_;  // "0x"
-      if (!parse_as_hex_float && !isDigit(*current, 16)) {
-        return junk_string_value_;
-      }
-
-      bool result_is_junk;
-      double result = RadixStringToIeee<4>(&current,
-                                           end,
-                                           sign,
-                                           separator_,
-                                           parse_as_hex_float,
-                                           allow_trailing_junk,
-                                           junk_string_value_,
-                                           read_as_double,
-                                           &result_is_junk);
-      if (!result_is_junk) {
-        if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
-        *processed_characters_count = static_cast<int>(current - input);
-      }
-      return result;
-    }
-
-    // Ignore leading zeros in the integer part.
-    while (*current == '0') {
-      if (Advance(&current, separator_, 10, end)) {
-        *processed_characters_count = static_cast<int>(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';
-    if (Advance(&current, separator_, 10, 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;
-
-    if (Advance(&current, separator_, 10, 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') {
-        if (Advance(&current, separator_, 10, end)) {
-          *processed_characters_count = static_cast<int>(current - input);
-          return SignedZero(sign);
-        }
-        exponent--;  // Move this 0 into the exponent.
-      }
-    }
-
-    // There is a fractional part.
-    // We don't emit a '.', but adjust the exponent instead.
-    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';
-      }
-      if (Advance(&current, separator_, 10, 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;
-    Iterator junk_begin = current;
-    ++current;
-    if (current == end) {
-      if (allow_trailing_junk) {
-        current = junk_begin;
-        goto parsing_done;
-      } else {
-        return junk_string_value_;
-      }
-    }
-    char exponen_sign = '+';
-    if (*current == '+' || *current == '-') {
-      exponen_sign = static_cast<char>(*current);
-      ++current;
-      if (current == end) {
-        if (allow_trailing_junk) {
-          current = junk_begin;
-          goto parsing_done;
-        } else {
-          return junk_string_value_;
-        }
-      }
-    }
-
-    if (current == end || *current < '0' || *current > '9') {
-      if (allow_trailing_junk) {
-        current = junk_begin;
-        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 += (exponen_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;
-    bool result_is_junk;
-    char* start = buffer;
-    result = RadixStringToIeee<3>(&start,
-                                  buffer + buffer_pos,
-                                  sign,
-                                  separator_,
-                                  false, // Don't parse as hex_float.
-                                  allow_trailing_junk,
-                                  junk_string_value_,
-                                  read_as_double,
-                                  &result_is_junk);
-    ASSERT(!result_is_junk);
-    *processed_characters_count = static_cast<int>(current - input);
-    return result;
-  }
-
-  if (nonzero_digit_dropped) {
-    buffer[buffer_pos++] = '1';
-    exponent--;
-  }
-
-  ASSERT(buffer_pos < kBufferSize);
-  buffer[buffer_pos] = '\0';
-
-  double converted;
-  if (read_as_double) {
-    converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
-  } else {
-    converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
-  }
-  *processed_characters_count = static_cast<int>(current - input);
-  return sign? -converted: converted;
-}
-
-
-double StringToDoubleConverter::StringToDouble(
-    const char* buffer,
-    int length,
-    int* processed_characters_count) const {
-  return StringToIeee(buffer, length, true, processed_characters_count);
-}
-
-
-double StringToDoubleConverter::StringToDouble(
-    const uc16* buffer,
-    int length,
-    int* processed_characters_count) const {
-  return StringToIeee(buffer, length, true, processed_characters_count);
-}
-
-
-float StringToDoubleConverter::StringToFloat(
-    const char* buffer,
-    int length,
-    int* processed_characters_count) const {
-  return static_cast<float>(StringToIeee(buffer, length, false,
-                                         processed_characters_count));
-}
-
-
-float StringToDoubleConverter::StringToFloat(
-    const uc16* buffer,
-    int length,
-    int* processed_characters_count) const {
-  return static_cast<float>(StringToIeee(buffer, length, false,
-                                         processed_characters_count));
-}
-
-}  // namespace double_conversion
diff --git a/c_src/double-conversion/double-conversion.h b/c_src/double-conversion/double-conversion.h
deleted file mode 100644
index 6dbc099..0000000
--- a/c_src/double-conversion/double-conversion.h
+++ /dev/null
@@ -1,576 +0,0 @@
-// Copyright 2012 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 {
-    return ToShortestIeeeNumber(value, result_builder, SHORTEST);
-  }
-
-  // Same as ToShortest, but for single-precision floats.
-  bool ToShortestSingle(float value, StringBuilder* result_builder) const {
-    return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
-  }
-
-
-  // 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,
-    // Same as SHORTEST, but for single-precision floats.
-    SHORTEST_SINGLE,
-    // 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 digit characters. 'v' must not be NaN,
-  // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
-  // applies to 'v' after it has been casted to a single-precision float. That
-  // is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
-  // -Infinity.
-  //
-  // The result should be interpreted as buffer * 10^(point-length).
-  //
-  // The digits are written to the buffer in the platform's charset, which is
-  // often UTF-8 (with ASCII-range digits) but may be another charset, such
-  // as EBCDIC.
-  //
-  // 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.
-  //  - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
-  //  - 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 and the padding-zeroes limit the size of the
-  // output. Don't forget the decimal point, the exponent character and the
-  // terminating null-character when computing the maximal output size.
-  // 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:
-  // Implementation for ToShortest and ToShortestSingle.
-  bool ToShortestIeeeNumber(double value,
-                            StringBuilder* result_builder,
-                            DtoaMode mode) const;
-
-  // 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_;
-
-  DC_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,
-    ALLOW_CASE_INSENSIBILITY = 64,
-    ALLOW_HEX_FLOATS = 128,
-  };
-
-  static const uc16 kNoSeparator = '\0';
-
-  // 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 whitespace, including spaces,
-  //                          new-lines, and tabs.
-  //  - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
-  //  - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
-  //       Ex: StringToDouble("-   123.2") -> -123.2.
-  //           StringToDouble("+   123.2") -> 123.2
-  //  - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
-  //      infinity and nan.
-  //  - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
-  //      This *must* start with "0x" and separate the exponent with "p".
-  //      Examples: 0x1.2p3 == 9.0
-  //                0x10.1p0 == 16.0625
-  //      ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
-  //
-  // 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.
-  //
-  // If the separator character is not kNoSeparator, then that specific
-  // character is ignored when in between two valid digits of the significant.
-  // It is not allowed to appear in the exponent.
-  // It is not allowed to lead or trail the number.
-  // It is not allowed to appear twice next to each other.
-  //
-  // 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.
-  //
-  //  flags = NO_FLAGS,
-  //  separator = ' ':
-  //    StringToDouble("1 2 3 4") -> 1234.0
-  //    StringToDouble("1  2") -> NaN // junk_string_value
-  //    StringToDouble("1 000 000.0") -> 1000000.0
-  //    StringToDouble("1.000 000") -> 1.0
-  //    StringToDouble("1.0e1 000") -> NaN // junk_string_value
-  StringToDoubleConverter(int flags,
-                          double empty_string_value,
-                          double junk_string_value,
-                          const char* infinity_symbol,
-                          const char* nan_symbol,
-                          uc16 separator = kNoSeparator)
-      : flags_(flags),
-        empty_string_value_(empty_string_value),
-        junk_string_value_(junk_string_value),
-        infinity_symbol_(infinity_symbol),
-        nan_symbol_(nan_symbol),
-        separator_(separator) {
-  }
-
-  // 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) const;
-
-  // Same as StringToDouble above but for 16 bit characters.
-  double StringToDouble(const uc16* buffer,
-                        int length,
-                        int* processed_characters_count) const;
-
-  // Same as StringToDouble but reads a float.
-  // Note that this is not equivalent to static_cast<float>(StringToDouble(...))
-  // due to potential double-rounding.
-  float StringToFloat(const char* buffer,
-                      int length,
-                      int* processed_characters_count) const;
-
-  // Same as StringToFloat above but for 16 bit characters.
-  float StringToFloat(const uc16* buffer,
-                      int length,
-                      int* processed_characters_count) const;
-
- private:
-  const int flags_;
-  const double empty_string_value_;
-  const double junk_string_value_;
-  const char* const infinity_symbol_;
-  const char* const nan_symbol_;
-  const uc16 separator_;
-
-  template <class Iterator>
-  double StringToIeee(Iterator start_pointer,
-                      int length,
-                      bool read_as_double,
-                      int* processed_characters_count) const;
-
-  DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
-};
-
-}  // namespace double_conversion
-
-#endif  // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
diff --git a/c_src/double-conversion/fast-dtoa.cc b/c_src/double-conversion/fast-dtoa.cc
deleted file mode 100644
index 6135038..0000000
--- a/c_src/double-conversion/fast-dtoa.cc
+++ /dev/null
@@ -1,665 +0,0 @@
-// Copyright 2012 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 "ieee.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;
-}
-
-// 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.
-//
-// Returns power == 10^(exponent_plus_one-1) such that
-//    power <= number < power * 10.
-// If number_bits == 0 then 0^(0-1) is returned.
-// The number of bits must be <= 32.
-// Precondition: number < (1 << (number_bits + 1)).
-
-// Inspired by the method for finding an integer log base 10 from here:
-// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
-static unsigned int const kSmallPowersOfTen[] =
-    {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
-     1000000000};
-
-static void BiggestPowerTen(uint32_t number,
-                            int number_bits,
-                            uint32_t* power,
-                            int* exponent_plus_one) {
-  ASSERT(number < (1u << (number_bits + 1)));
-  // 1233/4096 is approximately 1/lg(10).
-  int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
-  // We increment to skip over the first entry in the kPowersOf10 table.
-  // Note: kPowersOf10[i] == 10^(i-1).
-  exponent_plus_one_guess++;
-  // We don't have any guarantees that 2^number_bits <= number.
-  if (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
-    exponent_plus_one_guess--;
-  }
-  *power = kSmallPowersOfTen[exponent_plus_one_guess];
-  *exponent_plus_one = exponent_plus_one_guess;
-}
-
-// 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_plus_one;
-  BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
-                  &divisor, &divisor_exponent_plus_one);
-  *kappa = divisor_exponent_plus_one;
-  *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;
-    ASSERT(digit <= 9);
-    buffer[*length] = static_cast<char>('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());
-  for (;;) {
-    fractionals *= 10;
-    unit *= 10;
-    unsafe_interval.set_f(unsafe_interval.f() * 10);
-    // Integer division by one.
-    int digit = static_cast<int>(fractionals >> -one.e());
-    ASSERT(digit <= 9);
-    buffer[*length] = static_cast<char>('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_plus_one;
-  BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
-                  &divisor, &divisor_exponent_plus_one);
-  *kappa = divisor_exponent_plus_one;
-  *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;
-    ASSERT(digit <= 9);
-    buffer[*length] = static_cast<char>('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());
-    ASSERT(digit <= 9);
-    buffer[*length] = static_cast<char>('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,
-                   FastDtoaMode mode,
-                   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;
-  if (mode == FAST_DTOA_SHORTEST) {
-    Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
-  } else {
-    ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
-    float single_v = static_cast<float>(v);
-    Single(single_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:
-    case FAST_DTOA_SHORTEST_SINGLE:
-      result = Grisu3(v, mode, 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/c_src/double-conversion/fast-dtoa.h b/c_src/double-conversion/fast-dtoa.h
deleted file mode 100644
index 5f1e8ee..0000000
--- a/c_src/double-conversion/fast-dtoa.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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,
-  // Same as FAST_DTOA_SHORTEST but for single-precision floats.
-  FAST_DTOA_SHORTEST_SINGLE,
-  // 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;
-// Same for single-precision numbers.
-static const int kFastDtoaMaximalSingleLength = 9;
-
-// 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/c_src/double-conversion/fixed-dtoa.cc b/c_src/double-conversion/fixed-dtoa.cc
deleted file mode 100644
index 0f989bc..0000000
--- a/c_src/double-conversion/fixed-dtoa.cc
+++ /dev/null
@@ -1,405 +0,0 @@
-// 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 <cmath>
-
-#include "fixed-dtoa.h"
-#include "ieee.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) const {
-    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] = static_cast<char>('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,
-                                    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);
-      ASSERT(digit <= 9);
-      buffer[*length] = static_cast<char>('0' + digit);
-      (*length)++;
-      fractionals -= static_cast<uint64_t>(digit) << point;
-    }
-    // If the first bit after the point is set we have to round up.
-    ASSERT(fractionals == 0 || point - 1 >= 0);
-    if ((fractionals != 0) && ((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);
-      ASSERT(digit <= 9);
-      buffer[*length] = static_cast<char>('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, 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/c_src/double-conversion/fixed-dtoa.h b/c_src/double-conversion/fixed-dtoa.h
deleted file mode 100644
index 3bdd08e..0000000
--- a/c_src/double-conversion/fixed-dtoa.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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/c_src/double-conversion/ieee.h b/c_src/double-conversion/ieee.h
deleted file mode 100644
index 4a5fe8f..0000000
--- a/c_src/double-conversion/ieee.h
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright 2012 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); }
-static uint32_t float_to_uint32(float f) { return BitCast<uint32_t>(f); }
-static float uint32_to_float(uint32_t d32) { return BitCast<float>(d32); }
-
-// 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();
-    }
-  }
-
-  double PreviousDouble() const {
-    if (d64_ == (kInfinity | kSignMask)) return -Infinity();
-    if (Sign() < 0) {
-      return Double(d64_ + 1).value();
-    } else {
-      if (Significand() == 0) return -0.0;
-      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();
-    DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
-    DiyFp m_minus;
-    if (LowerBoundaryIsCloser()) {
-      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;
-  }
-
-  bool LowerBoundaryIsCloser() const {
-    // The boundary is closer if the significand is of the form f == 2^p-1 then
-    // the lower 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.
-    bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
-    return physical_significand_is_zero && (Exponent() != kDenormalExponent);
-  }
-
-  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);
-  }
-
-  DC_DISALLOW_COPY_AND_ASSIGN(Double);
-};
-
-class Single {
- public:
-  static const uint32_t kSignMask = 0x80000000;
-  static const uint32_t kExponentMask = 0x7F800000;
-  static const uint32_t kSignificandMask = 0x007FFFFF;
-  static const uint32_t kHiddenBit = 0x00800000;
-  static const int kPhysicalSignificandSize = 23;  // Excludes the hidden bit.
-  static const int kSignificandSize = 24;
-
-  Single() : d32_(0) {}
-  explicit Single(float f) : d32_(float_to_uint32(f)) {}
-  explicit Single(uint32_t d32) : d32_(d32) {}
-
-  // The value encoded by this Single 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());
-  }
-
-  // Returns the single's bit as uint64.
-  uint32_t AsUint32() const {
-    return d32_;
-  }
-
-  int Exponent() const {
-    if (IsDenormal()) return kDenormalExponent;
-
-    uint32_t d32 = AsUint32();
-    int biased_e =
-        static_cast<int>((d32 & kExponentMask) >> kPhysicalSignificandSize);
-    return biased_e - kExponentBias;
-  }
-
-  uint32_t Significand() const {
-    uint32_t d32 = AsUint32();
-    uint32_t significand = d32 & kSignificandMask;
-    if (!IsDenormal()) {
-      return significand + kHiddenBit;
-    } else {
-      return significand;
-    }
-  }
-
-  // Returns true if the single is a denormal.
-  bool IsDenormal() const {
-    uint32_t d32 = AsUint32();
-    return (d32 & kExponentMask) == 0;
-  }
-
-  // We consider denormals not to be special.
-  // Hence only Infinity and NaN are special.
-  bool IsSpecial() const {
-    uint32_t d32 = AsUint32();
-    return (d32 & kExponentMask) == kExponentMask;
-  }
-
-  bool IsNan() const {
-    uint32_t d32 = AsUint32();
-    return ((d32 & kExponentMask) == kExponentMask) &&
-        ((d32 & kSignificandMask) != 0);
-  }
-
-  bool IsInfinite() const {
-    uint32_t d32 = AsUint32();
-    return ((d32 & kExponentMask) == kExponentMask) &&
-        ((d32 & kSignificandMask) == 0);
-  }
-
-  int Sign() const {
-    uint32_t d32 = AsUint32();
-    return (d32 & kSignMask) == 0? 1: -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 Single must be greater than 0.
-  void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
-    ASSERT(value() > 0.0);
-    DiyFp v = this->AsDiyFp();
-    DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
-    DiyFp m_minus;
-    if (LowerBoundaryIsCloser()) {
-      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;
-  }
-
-  // Precondition: the value encoded by this Single must be greater or equal
-  // than +0.0.
-  DiyFp UpperBoundary() const {
-    ASSERT(Sign() > 0);
-    return DiyFp(Significand() * 2 + 1, Exponent() - 1);
-  }
-
-  bool LowerBoundaryIsCloser() const {
-    // The boundary is closer if the significand is of the form f == 2^p-1 then
-    // the lower 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.
-    bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0);
-    return physical_significand_is_zero && (Exponent() != kDenormalExponent);
-  }
-
-  float value() const { return uint32_to_float(d32_); }
-
-  static float Infinity() {
-    return Single(kInfinity).value();
-  }
-
-  static float NaN() {
-    return Single(kNaN).value();
-  }
-
- private:
-  static const int kExponentBias = 0x7F + kPhysicalSignificandSize;
-  static const int kDenormalExponent = -kExponentBias + 1;
-  static const int kMaxExponent = 0xFF - kExponentBias;
-  static const uint32_t kInfinity = 0x7F800000;
-  static const uint32_t kNaN = 0x7FC00000;
-
-  const uint32_t d32_;
-
-  DC_DISALLOW_COPY_AND_ASSIGN(Single);
-};
-
-}  // namespace double_conversion
-
-#endif  // DOUBLE_CONVERSION_DOUBLE_H_
diff --git a/c_src/double-conversion/strtod.cc b/c_src/double-conversion/strtod.cc
deleted file mode 100644
index a75cf5d..0000000
--- a/c_src/double-conversion/strtod.cc
+++ /dev/null
@@ -1,580 +0,0 @@
-// 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 <climits>
-#include <cstdarg>
-
-#include "bignum.h"
-#include "cached-powers.h"
-#include "ieee.h"
-#include "strtod.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 CutToMaxSignificantDigits(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);
-}
-
-
-// Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits.
-// If possible the input-buffer is reused, but if the buffer needs to be
-// modified (due to cutting), then the input needs to be copied into the
-// buffer_copy_space.
-static void TrimAndCut(Vector<const char> buffer, int exponent,
-                       char* buffer_copy_space, int space_size,
-                       Vector<const char>* trimmed, int* updated_exponent) {
-  Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
-  Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
-  exponent += left_trimmed.length() - right_trimmed.length();
-  if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
-    (void) space_size;  // Mark variable as used.
-    ASSERT(space_size >= kMaxSignificantDecimalDigits);
-    CutToMaxSignificantDigits(right_trimmed, exponent,
-                              buffer_copy_space, updated_exponent);
-    *trimmed = Vector<const char>(buffer_copy_space,
-                                 kMaxSignificantDecimalDigits);
-  } else {
-    *trimmed = right_trimmed;
-    *updated_exponent = exponent;
-  }
-}
-
-
-// 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;
-#else
-  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;
-#endif
-}
-
-
-// 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();
-  }
-}
-
-
-// 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;
-  uint64_t 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
-//   - -1 if buffer*10^exponent < diy_fp.
-//   -  0 if buffer*10^exponent == diy_fp.
-//   - +1 if buffer*10^exponent > diy_fp.
-// Preconditions:
-//   buffer.length() + exponent <= kMaxDecimalPower + 1
-//   buffer.length() + exponent > kMinDecimalPower
-//   buffer.length() <= kMaxDecimalSignificantDigits
-static int CompareBufferWithDiyFp(Vector<const char> buffer,
-                                  int exponent,
-                                  DiyFp diy_fp) {
-  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 buffer_bignum;
-  Bignum diy_fp_bignum;
-  buffer_bignum.AssignDecimalString(buffer);
-  diy_fp_bignum.AssignUInt64(diy_fp.f());
-  if (exponent >= 0) {
-    buffer_bignum.MultiplyByPowerOfTen(exponent);
-  } else {
-    diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
-  }
-  if (diy_fp.e() > 0) {
-    diy_fp_bignum.ShiftLeft(diy_fp.e());
-  } else {
-    buffer_bignum.ShiftLeft(-diy_fp.e());
-  }
-  return Bignum::Compare(buffer_bignum, diy_fp_bignum);
-}
-
-
-// Returns true if the guess is the correct double.
-// Returns false, when guess is either correct or the next-lower double.
-static bool ComputeGuess(Vector<const char> trimmed, int exponent,
-                         double* guess) {
-  if (trimmed.length() == 0) {
-    *guess = 0.0;
-    return true;
-  }
-  if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
-    *guess = Double::Infinity();
-    return true;
-  }
-  if (exponent + trimmed.length() <= kMinDecimalPower) {
-    *guess = 0.0;
-    return true;
-  }
-
-  if (DoubleStrtod(trimmed, exponent, guess) ||
-      DiyFpStrtod(trimmed, exponent, guess)) {
-    return true;
-  }
-  if (*guess == Double::Infinity()) {
-    return true;
-  }
-  return false;
-}
-
-double Strtod(Vector<const char> buffer, int exponent) {
-  char copy_buffer[kMaxSignificantDecimalDigits];
-  Vector<const char> trimmed;
-  int updated_exponent;
-  TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
-             &trimmed, &updated_exponent);
-  exponent = updated_exponent;
-
-  double guess;
-  bool is_correct = ComputeGuess(trimmed, exponent, &guess);
-  if (is_correct) return guess;
-
-  DiyFp upper_boundary = Double(guess).UpperBoundary();
-  int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_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();
-  }
-}
-
-static float SanitizedDoubletof(double d) {
-  ASSERT(d >= 0.0);
-  // ASAN has a sanitize check that disallows casting doubles to floats if
-  // they are too big.
-  // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
-  // The behavior should be covered by IEEE 754, but some projects use this
-  // flag, so work around it.
-  float max_finite = 3.4028234663852885981170418348451692544e+38;
-  // The half-way point between the max-finite and infinity value.
-  // Since infinity has an even significand everything equal or greater than
-  // this value should become infinity.
-  double half_max_finite_infinity =
-      3.40282356779733661637539395458142568448e+38;
-  if (d >= max_finite) {
-    if (d >= half_max_finite_infinity) {
-      return Single::Infinity();
-    } else {
-      return max_finite;
-    }
-  } else {
-    return static_cast<float>(d);
-  }
-}
-
-float Strtof(Vector<const char> buffer, int exponent) {
-  char copy_buffer[kMaxSignificantDecimalDigits];
-  Vector<const char> trimmed;
-  int updated_exponent;
-  TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
-             &trimmed, &updated_exponent);
-  exponent = updated_exponent;
-
-  double double_guess;
-  bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
-
-  float float_guess = SanitizedDoubletof(double_guess);
-  if (float_guess == double_guess) {
-    // This shortcut triggers for integer values.
-    return float_guess;
-  }
-
-  // We must catch double-rounding. Say the double has been rounded up, and is
-  // now a boundary of a float, and rounds up again. This is why we have to
-  // look at previous too.
-  // Example (in decimal numbers):
-  //    input: 12349
-  //    high-precision (4 digits): 1235
-  //    low-precision (3 digits):
-  //       when read from input: 123
-  //       when rounded from high precision: 124.
-  // To do this we simply look at the neigbors of the correct result and see
-  // if they would round to the same float. If the guess is not correct we have
-  // to look at four values (since two different doubles could be the correct
-  // double).
-
-  double double_next = Double(double_guess).NextDouble();
-  double double_previous = Double(double_guess).PreviousDouble();
-
-  float f1 = SanitizedDoubletof(double_previous);
-  float f2 = float_guess;
-  float f3 = SanitizedDoubletof(double_next);
-  float f4;
-  if (is_correct) {
-    f4 = f3;
-  } else {
-    double double_next2 = Double(double_next).NextDouble();
-    f4 = SanitizedDoubletof(double_next2);
-  }
-  (void) f2;  // Mark variable as used.
-  ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
-
-  // If the guess doesn't lie near a single-precision boundary we can simply
-  // return its float-value.
-  if (f1 == f4) {
-    return float_guess;
-  }
-
-  ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
-         (f1 == f2 && f2 != f3 && f3 == f4) ||
-         (f1 == f2 && f2 == f3 && f3 != f4));
-
-  // guess and next are the two possible candidates (in the same way that
-  // double_guess was the lower candidate for a double-precision guess).
-  float guess = f1;
-  float next = f4;
-  DiyFp upper_boundary;
-  if (guess == 0.0f) {
-    float min_float = 1e-45f;
-    upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp();
-  } else {
-    upper_boundary = Single(guess).UpperBoundary();
-  }
-  int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
-  if (comparison < 0) {
-    return guess;
-  } else if (comparison > 0) {
-    return next;
-  } else if ((Single(guess).Significand() & 1) == 0) {
-    // Round towards even.
-    return guess;
-  } else {
-    return next;
-  }
-}
-
-}  // namespace double_conversion
diff --git a/c_src/double-conversion/strtod.h b/c_src/double-conversion/strtod.h
deleted file mode 100644
index ed0293b..0000000
--- a/c_src/double-conversion/strtod.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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);
-
-// 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.
-float Strtof(Vector<const char> buffer, int exponent);
-
-}  // namespace double_conversion
-
-#endif  // DOUBLE_CONVERSION_STRTOD_H_
diff --git a/c_src/double-conversion/utils.h b/c_src/double-conversion/utils.h
deleted file mode 100644
index 4328344..0000000
--- a/c_src/double-conversion/utils.h
+++ /dev/null
@@ -1,367 +0,0 @@
-// 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 <cstdlib>
-#include <cstring>
-
-#include <cassert>
-#ifndef ASSERT
-#define ASSERT(condition)         \
-    assert(condition);
-#endif
-#ifndef UNIMPLEMENTED
-#define UNIMPLEMENTED() (abort())
-#endif
-#ifndef DOUBLE_CONVERSION_NO_RETURN
-#ifdef _MSC_VER
-#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
-#else
-#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
-#endif
-#endif
-#ifndef UNREACHABLE
-#ifdef _MSC_VER
-void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
-inline void abort_noreturn() { abort(); }
-#define UNREACHABLE()   (abort_noreturn())
-#else
-#define UNREACHABLE()   (abort())
-#endif
-#endif
-
-#ifndef DOUBLE_CONVERSION_UNUSED
-#ifdef __GNUC__
-#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
-#else
-#define DOUBLE_CONVERSION_UNUSED
-#endif
-#endif
-
-// 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)
-//
-// For example:
-/*
-// -- in div.c
-double Div_double(double x, double y) { return x / y; }
-
-// -- in main.c
-double Div_double(double x, double y);  // Forward declaration.
-
-int main(int argc, char** argv) {
-  return Div_double(89255.0, 1e22) == 89255e-22;
-}
-*/
-// Run as follows ./main || echo "correct"
-//
-// If it prints "correct" then the architecture should be here, in the "correct" section.
-#if defined(_M_X64) || defined(__x86_64__) || \
-    defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
-    defined(__hppa__) || defined(__ia64__) || \
-    defined(__mips__) || \
-    defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
-    defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
-    defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
-    defined(__SH4__) || defined(__alpha__) || \
-    defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
-    defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
-    defined(__riscv) || \
-    defined(__or1k__) || defined(__arc__) || \
-    defined(__EMSCRIPTEN__)
-#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#elif defined(__mc68000__) || \
-    defined(__pnacl__) || defined(__native_client__)
-#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
-#elif defined(_M_IX86) || defined(__i386__) || 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
-
-typedef uint16_t uc16;
-
-// 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.
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a)                                   \
-  ((sizeof(a) / sizeof(*(a))) /                         \
-  static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-#endif
-
-// A macro to disallow the evil copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#ifndef DC_DISALLOW_COPY_AND_ASSIGN
-#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName)      \
-  TypeName(const TypeName&);                    \
-  void operator=(const TypeName&)
-#endif
-
-// 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.
-#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
-#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                    \
-  DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
-#endif
-
-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 len) : start_(data), length_(len) {
-    ASSERT(len == 0 || (len > 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 buffer_size)
-      : buffer_(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));
-    memmove(&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; }
-
-  DC_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.
-#if __cplusplus >= 201103L
-  static_assert(sizeof(Dest) == sizeof(Source),
-                "source and destination size mismatch");
-#else
-  DOUBLE_CONVERSION_UNUSED
-  typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
-#endif
-
-  Dest dest;
-  memmove(&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/c_src/doubles.cc b/c_src/doubles.cc
deleted file mode 100644
index 05c6443..0000000
--- a/c_src/doubles.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "double-conversion/double-conversion.h"
-
-#define BEGIN_C extern "C" {
-#define END_C }
-
-
-namespace dc = double_conversion;
-
-
-BEGIN_C
-
-int
-double_to_shortest(unsigned char* buf, size_t size, size_t* len, double val)
-{
-    int flags = dc::DoubleToStringConverter::UNIQUE_ZERO |
-                dc::DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN |
-                dc::DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |
-                dc::DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT;
-
-    dc::StringBuilder builder(reinterpret_cast<char*>(buf), size);
-    dc::DoubleToStringConverter conv(flags, NULL, NULL, 'e', -6, 21, 6, 0);
-
-    if(!conv.ToShortest(val, &builder)) {
-        return 0;
-    }
-
-    *len = (size_t) builder.position();
-    builder.Finalize();
-
-    return 1;
-}
-
-END_C
diff --git a/c_src/encoder.c b/c_src/encoder.c
index f331290..d952652 100644
--- a/c_src/encoder.c
+++ b/c_src/encoder.c
@@ -6,6 +6,7 @@
 #include <string.h>
 
 #include "jiffy.h"
+#include "ryu/ryu.h"
 
 #define BIN_INC_SIZE 2048
 
@@ -624,20 +625,14 @@ enc_long(Encoder* e, ErlNifSInt64 val)
 static inline int
 enc_double(Encoder* e, double val)
 {
-    unsigned char* start;
-    size_t len;
-
     if(!enc_ensure(e, 32)) {
         return 0;
     }
 
-    start = &(e->p[e->i]);
+    // Normalize -0.0 to 0.0 for JSON output
+    if(val == 0.0) val = 0.0;
 
-    if(!double_to_shortest(start, e->buffer.size, &len, val)) {
-        return 0;
-    }
-
-    e->i += len;
+    e->i += d2s_buffered_n(val, (char*)&(e->p[e->i]));
     e->count++;
     return 1;
 }
diff --git a/c_src/jiffy.h b/c_src/jiffy.h
index 19f8365..daf4bd2 100644
--- a/c_src/jiffy.h
+++ b/c_src/jiffy.h
@@ -85,6 +85,5 @@ int utf8_to_unicode(unsigned char* buf, size_t size);
 int unicode_to_utf8(int c, unsigned char* buf);
 int unicode_from_pair(int hi, int lo);
 int unicode_uescape(int c, unsigned char* buf);
-int double_to_shortest(unsigned char *buf, size_t size, size_t* len, double val);
 
 #endif // Included JIFFY_H
diff --git a/c_src/ryu/LICENSE-Apache2 b/c_src/ryu/LICENSE-Apache2
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/c_src/ryu/LICENSE-Apache2
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/c_src/ryu/LICENSE-Boost b/c_src/ryu/LICENSE-Boost
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/c_src/ryu/LICENSE-Boost
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/c_src/ryu/common.h b/c_src/ryu/common.h
new file mode 100644
index 0000000..9bec061
--- /dev/null
+++ b/c_src/ryu/common.h
@@ -0,0 +1,116 @@
+// Copyright 2018 Ulf Adams
+// Copyright 2021 Thomas Depierre
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_COMMON_H
+#define RYU_COMMON_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_M_IX86) || defined(_M_ARM)
+#define RYU_32_BIT_PLATFORM
+#endif
+
+// Returns the number of decimal digits in v, which must not contain more than 9 digits.
+static inline uint32_t decimalLength9(const uint32_t v) {
+  // Function precondition: v is not a 10-digit number.
+  // (f2s: 9 digits are sufficient for round-tripping.)
+  // (d2fixed: We print 9-digit blocks.)
+  assert(v < 1000000000);
+  if (v >= 100000000) { return 9; }
+  if (v >= 10000000) { return 8; }
+  if (v >= 1000000) { return 7; }
+  if (v >= 100000) { return 6; }
+  if (v >= 10000) { return 5; }
+  if (v >= 1000) { return 4; }
+  if (v >= 100) { return 3; }
+  if (v >= 10) { return 2; }
+  return 1;
+}
+
+// Returns e == 0 ? 1 : [log_2(5^e)]; requires 0 <= e <= 3528.
+static inline int32_t log2pow5(const int32_t e) {
+  // This approximation works up to the point that the multiplication overflows at e = 3529.
+  // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
+  // than 2^9297.
+  assert(e >= 0);
+  assert(e <= 3528);
+  return (int32_t) ((((uint32_t) e) * 1217359) >> 19);
+}
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528.
+static inline int32_t pow5bits(const int32_t e) {
+  // This approximation works up to the point that the multiplication overflows at e = 3529.
+  // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
+  // than 2^9297.
+  assert(e >= 0);
+  assert(e <= 3528);
+  return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
+}
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528.
+static inline int32_t ceil_log2pow5(const int32_t e) {
+  return log2pow5(e) + 1;
+}
+
+// Returns floor(log_10(2^e)); requires 0 <= e <= 1650.
+static inline uint32_t log10Pow2(const int32_t e) {
+  // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
+  assert(e >= 0);
+  assert(e <= 1650);
+  return (((uint32_t) e) * 78913) >> 18;
+}
+
+// Returns floor(log_10(5^e)); requires 0 <= e <= 2620.
+static inline uint32_t log10Pow5(const int32_t e) {
+  // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
+  assert(e >= 0);
+  assert(e <= 2620);
+  return (((uint32_t) e) * 732923) >> 20;
+}
+
+static inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
+  if (mantissa) {
+    memcpy(result, "NaN", 3);
+    return 3;
+  }
+  if (sign) {
+    result[0] = '-';
+  }
+  if (exponent) {
+    memcpy(result + sign, "Infinity", 8);
+    return sign + 8;
+  }
+  // CHANGE_FOR_ERLANG we use "0.0" as the 0 and not "0E0"
+  memcpy(result + sign, "0.0", 3);
+  return sign + 3;
+}
+
+static inline uint32_t float_to_bits(const float f) {
+  uint32_t bits = 0;
+  memcpy(&bits, &f, sizeof(float));
+  return bits;
+}
+
+static inline uint64_t double_to_bits(const double d) {
+  uint64_t bits = 0;
+  memcpy(&bits, &d, sizeof(double));
+  return bits;
+}
+
+#endif // RYU_COMMON_H
diff --git a/c_src/ryu/d2s.c b/c_src/ryu/d2s.c
new file mode 100644
index 0000000..ef15e60
--- /dev/null
+++ b/c_src/ryu/d2s.c
@@ -0,0 +1,391 @@
+// Copyright 2018 Ulf Adams
+// Copyright 2021 Thomas Depierre
+// Copyright 2025 Copyright Ericsson AB 2025. All Rights Reserved.
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+// Runtime compiler options:
+// -DRYU_DEBUG Generate verbose debugging output to stdout.
+//
+// -DRYU_ONLY_64_BIT_OPS Avoid using uint128_t or 64-bit intrinsics. Slower,
+//     depending on your compiler.
+//
+
+// CHANGE_FOR_ERLANG: "ryu/ryu.h" -> "ryu.h"
+#include "ryu.h"
+// END CHANGE_FOR_ERLANG
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef RYU_DEBUG
+#include <inttypes.h>
+#include <stdio.h>
+#endif
+
+// CHANGE_FOR_ERLANG: "ryu/*.h" -> "*.h"
+#include "common.h"
+#include "digit_table.h"
+#include "d2s_intrinsics.h"
+// END CHANGE_FOR_ERLANG
+
+// CHANGE_FOR_ERLANG we got rid of the small_table. Also namespace as above
+#include "d2s_full_table.h"
+// END CHANGE_FOR_ERLANG
+
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_BIAS 1023
+
+static inline uint32_t decimalLength17(const uint64_t v) {
+  // This is slightly faster than a loop.
+  // The average output length is 16.38 digits, so we check high-to-low.
+  // Function precondition: v is not an 18, 19, or 20-digit number.
+  // (17 digits are sufficient for round-tripping.)
+  assert(v < 100000000000000000L);
+  if (v >= 10000000000000000L) { return 17; }
+  if (v >= 1000000000000000L) { return 16; }
+  if (v >= 100000000000000L) { return 15; }
+  if (v >= 10000000000000L) { return 14; }
+  if (v >= 1000000000000L) { return 13; }
+  if (v >= 100000000000L) { return 12; }
+  if (v >= 10000000000L) { return 11; }
+  if (v >= 1000000000L) { return 10; }
+  if (v >= 100000000L) { return 9; }
+  if (v >= 10000000L) { return 8; }
+  if (v >= 1000000L) { return 7; }
+  if (v >= 100000L) { return 6; }
+  if (v >= 10000L) { return 5; }
+  if (v >= 1000L) { return 4; }
+  if (v >= 100L) { return 3; }
+  if (v >= 10L) { return 2; }
+  return 1;
+}
+
+// A floating decimal representing m * 10^e.
+typedef struct floating_decimal_64 {
+  uint64_t mantissa;
+  // Decimal exponent's range is -324 to 308
+  // inclusive, and can fit in a short if needed.
+  int32_t exponent;
+} floating_decimal_64;
+
+// CHANGE_FOR_ERLANG include STL to_chars function
+#include "to_chars.h"
+// END CHANGE_FOR_ERLANG
+
+static inline floating_decimal_64 d2d(const uint64_t ieeeMantissa, const uint32_t ieeeExponent) {
+  int32_t e2;
+  uint64_t m2;
+  if (ieeeExponent == 0) {
+    // We subtract 2 so that the bounds computation has 2 additional bits.
+    e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+    m2 = ieeeMantissa;
+  } else {
+    e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+    m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+  }
+  const bool even = (m2 & 1) == 0;
+  const bool acceptBounds = even;
+
+#ifdef RYU_DEBUG
+  printf("-> %" PRIu64 " * 2^%d\n", m2, e2 + 2);
+#endif
+
+  // Step 2: Determine the interval of valid decimal representations.
+  const uint64_t mv = 4 * m2;
+  // Implicit bool -> int conversion. True is 1, false is 0.
+  const uint32_t mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+  // We would compute mp and mm like this:
+  // uint64_t mp = 4 * m2 + 2;
+  // uint64_t mm = mv - 1 - mmShift;
+
+  // Step 3: Convert to a decimal power base using 128-bit arithmetic.
+  uint64_t vr, vp, vm;
+  int32_t e10;
+  bool vmIsTrailingZeros = false;
+  bool vrIsTrailingZeros = false;
+  if (e2 >= 0) {
+    // I tried special-casing q == 0, but there was no effect on performance.
+    // This expression is slightly faster than max(0, log10Pow2(e2) - 1).
+    const uint32_t q = log10Pow2(e2) - (e2 > 3);
+    e10 = (int32_t) q;
+    const int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t) q) - 1;
+    const int32_t i = -e2 + (int32_t) q + k;
+    vr = mulShiftAll64(m2, DOUBLE_POW5_INV_SPLIT[q], i, &vp, &vm, mmShift);
+#ifdef RYU_DEBUG
+    printf("%" PRIu64 " * 2^%d / 10^%u\n", mv, e2, q);
+    printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+#endif
+    if (q <= 21) {
+      // This should use q <= 22, but I think 21 is also safe. Smaller values
+      // may still be safe, but it's more difficult to reason about them.
+      // Only one of mp, mv, and mm can be a multiple of 5, if any.
+      const uint32_t mvMod5 = ((uint32_t) mv) - 5 * ((uint32_t) div5(mv));
+      if (mvMod5 == 0) {
+        vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+      } else if (acceptBounds) {
+        // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
+        // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
+        // <=> true && pow5Factor(mm) >= q, since e2 >= q.
+        vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
+      } else {
+        // Same as min(e2 + 1, pow5Factor(mp)) >= q.
+        vp -= multipleOfPowerOf5(mv + 2, q);
+      }
+    }
+  } else {
+    // This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
+    const uint32_t q = log10Pow5(-e2) - (-e2 > 1);
+    e10 = (int32_t) q + e2;
+    const int32_t i = -e2 - (int32_t) q;
+    const int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
+    const int32_t j = (int32_t) q - k;
+    vr = mulShiftAll64(m2, DOUBLE_POW5_SPLIT[i], j, &vp, &vm, mmShift);
+#ifdef RYU_DEBUG
+    printf("%" PRIu64 " * 5^%d / 10^%u\n", mv, -e2, q);
+    printf("%u %d %d %d\n", q, i, k, j);
+    printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+#endif
+    if (q <= 1) {
+      // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
+      // mv = 4 * m2, so it always has at least two trailing 0 bits.
+      vrIsTrailingZeros = true;
+      if (acceptBounds) {
+        // mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1.
+        vmIsTrailingZeros = mmShift == 1;
+      } else {
+        // mp = mv + 2, so it always has at least one trailing 0 bit.
+        --vp;
+      }
+    } else if (q < 63) { // TODO(ulfjack): Use a tighter bound here.
+      // We want to know if the full product has at least q trailing zeros.
+      // We need to compute min(p2(mv), p5(mv) - e2) >= q
+      // <=> p2(mv) >= q && p5(mv) - e2 >= q
+      // <=> p2(mv) >= q (because -e2 >= q)
+      vrIsTrailingZeros = multipleOfPowerOf2(mv, q);
+#ifdef RYU_DEBUG
+      printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+    }
+  }
+#ifdef RYU_DEBUG
+  printf("e10=%d\n", e10);
+  printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+  printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
+  printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+
+  // Step 4: Find the shortest decimal representation in the interval of valid representations.
+  int32_t removed = 0;
+  uint8_t lastRemovedDigit = 0;
+  uint64_t output;
+  // On average, we remove ~2 digits.
+  if (vmIsTrailingZeros || vrIsTrailingZeros) {
+    // General case, which happens rarely (~0.7%).
+    for (;;) {
+      const uint64_t vpDiv10 = div10(vp);
+      const uint64_t vmDiv10 = div10(vm);
+      if (vpDiv10 <= vmDiv10) {
+        break;
+      }
+      const uint32_t vmMod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmDiv10);
+      const uint64_t vrDiv10 = div10(vr);
+      const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+      vmIsTrailingZeros &= vmMod10 == 0;
+      vrIsTrailingZeros &= lastRemovedDigit == 0;
+      lastRemovedDigit = (uint8_t) vrMod10;
+      vr = vrDiv10;
+      vp = vpDiv10;
+      vm = vmDiv10;
+      ++removed;
+    }
+#ifdef RYU_DEBUG
+    printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+    printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
+#endif
+    if (vmIsTrailingZeros) {
+      for (;;) {
+        const uint64_t vmDiv10 = div10(vm);
+        const uint32_t vmMod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmDiv10);
+        if (vmMod10 != 0) {
+          break;
+        }
+        const uint64_t vpDiv10 = div10(vp);
+        const uint64_t vrDiv10 = div10(vr);
+        const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+        vrIsTrailingZeros &= lastRemovedDigit == 0;
+        lastRemovedDigit = (uint8_t) vrMod10;
+        vr = vrDiv10;
+        vp = vpDiv10;
+        vm = vmDiv10;
+        ++removed;
+      }
+    }
+#ifdef RYU_DEBUG
+    printf("%" PRIu64 " %d\n", vr, lastRemovedDigit);
+    printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+    if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0) {
+      // Round even if the exact number is .....50..0.
+      lastRemovedDigit = 4;
+    }
+    // We need to take vr + 1 if vr is outside bounds or we need to round up.
+    output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+  } else {
+    // Specialized for the common case (~99.3%). Percentages below are relative to this.
+    bool roundUp = false;
+    const uint64_t vpDiv100 = div100(vp);
+    const uint64_t vmDiv100 = div100(vm);
+    if (vpDiv100 > vmDiv100) { // Optimization: remove two digits at a time (~86.2%).
+      const uint64_t vrDiv100 = div100(vr);
+      const uint32_t vrMod100 = ((uint32_t) vr) - 100 * ((uint32_t) vrDiv100);
+      roundUp = vrMod100 >= 50;
+      vr = vrDiv100;
+      vp = vpDiv100;
+      vm = vmDiv100;
+      removed += 2;
+    }
+    // Loop iterations below (approximately), without optimization above:
+    // 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
+    // Loop iterations below (approximately), with optimization above:
+    // 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
+    for (;;) {
+      const uint64_t vpDiv10 = div10(vp);
+      const uint64_t vmDiv10 = div10(vm);
+      if (vpDiv10 <= vmDiv10) {
+        break;
+      }
+      const uint64_t vrDiv10 = div10(vr);
+      const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+      roundUp = vrMod10 >= 5;
+      vr = vrDiv10;
+      vp = vpDiv10;
+      vm = vmDiv10;
+      ++removed;
+    }
+#ifdef RYU_DEBUG
+    printf("%" PRIu64 " roundUp=%s\n", vr, roundUp ? "true" : "false");
+    printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+    // We need to take vr + 1 if vr is outside bounds or we need to round up.
+    output = vr + (vr == vm || roundUp);
+  }
+  const int32_t exp = e10 + removed;
+
+#ifdef RYU_DEBUG
+  printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+  printf("O=%" PRIu64 "\n", output);
+  printf("EXP=%d\n", exp);
+#endif
+
+  floating_decimal_64 fd;
+  fd.exponent = exp;
+  fd.mantissa = output;
+  return fd;
+}
+
+static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t ieeeExponent,
+  floating_decimal_64* const v) {
+  const uint64_t m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+  const int32_t e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
+
+  if (e2 > 0) {
+    // f = m2 * 2^e2 >= 2^53 is an integer.
+    // Ignore this case for now.
+    return false;
+  }
+
+  if (e2 < -52) {
+    // f < 1.
+    return false;
+  }
+
+  // Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52: 1 <= f = m2 / 2^-e2 < 2^53.
+  // Test if the lower -e2 bits of the significand are 0, i.e. whether the fraction is 0.
+  const uint64_t mask = (1ull << -e2) - 1;
+  const uint64_t fraction = m2 & mask;
+  if (fraction != 0) {
+    return false;
+  }
+
+  // f is an integer in the range [1, 2^53).
+  // Note: mantissa might contain trailing (decimal) 0's.
+  // Note: since 2^53 < 10^16, there is no need to adjust decimalLength17().
+  v->mantissa = m2 >> -e2;
+  v->exponent = 0;
+  return true;
+}
+
+int d2s_buffered_n(double f, char* result) {
+  // Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
+  const uint64_t bits = double_to_bits(f);
+
+#ifdef RYU_DEBUG
+  printf("IN=");
+  for (int32_t bit = 63; bit >= 0; --bit) {
+    printf("%d", (int) ((bits >> bit) & 1));
+  }
+  printf("\n");
+#endif
+
+  // Decode bits into sign, mantissa, and exponent.
+  const bool ieeeSign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
+  const uint64_t ieeeMantissa = bits & ((1ull << DOUBLE_MANTISSA_BITS) - 1);
+  const uint32_t ieeeExponent = (uint32_t) ((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
+  // Case distinction; exit early for the easy cases.
+  if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0)) {
+    return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+  }
+
+  floating_decimal_64 v;
+  const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
+  if (isSmallInt) {
+    // For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros.
+    // For scientific notation we need to move these zeros into the exponent.
+    // (This is not needed for fixed-point notation, so it might be beneficial to trim
+    // trailing zeros in to_chars only if needed - once fixed-point notation output is implemented.)
+    for (;;) {
+      const uint64_t q = div10(v.mantissa);
+      const uint32_t r = ((uint32_t) v.mantissa) - 10 * ((uint32_t) q);
+      if (r != 0) {
+        break;
+      }
+      v.mantissa = q;
+      ++v.exponent;
+    }
+  } else {
+    v = d2d(ieeeMantissa, ieeeExponent);
+  }
+
+  return to_chars(v, ieeeSign, result);
+}
+
+void d2s_buffered(double f, char* result) {
+  const int index = d2s_buffered_n(f, result);
+
+  // Terminate the string.
+  result[index] = '\0';
+}
+
+char* d2s(double f) {
+  char* const result = (char*) malloc(25);
+  d2s_buffered(f, result);
+  return result;
+}
diff --git a/c_src/ryu/d2s_full_table.h b/c_src/ryu/d2s_full_table.h
new file mode 100644
index 0000000..c8629ee
--- /dev/null
+++ b/c_src/ryu/d2s_full_table.h
@@ -0,0 +1,367 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_D2S_FULL_TABLE_H
+#define RYU_D2S_FULL_TABLE_H
+
+// These tables are generated by PrintDoubleLookupTable.
+#define DOUBLE_POW5_INV_BITCOUNT 125
+#define DOUBLE_POW5_BITCOUNT 125
+
+#define DOUBLE_POW5_INV_TABLE_SIZE 342
+#define DOUBLE_POW5_TABLE_SIZE 326
+
+static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = {
+  {                    1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u },
+  {  5165088340638674453u, 1475739525896764129u }, {  7821419487252849886u, 1180591620717411303u },
+  {  8824922364862649494u, 1888946593147858085u }, {  7059937891890119595u, 1511157274518286468u },
+  { 13026647942995916322u, 1208925819614629174u }, {  9774590264567735146u, 1934281311383406679u },
+  { 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u },
+  { 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u },
+  {  9162556910162266299u, 1267650600228229401u }, {  7281393426775805432u, 2028240960365167042u },
+  { 16893161185646375315u, 1622592768292133633u }, {  2446482504291369283u, 1298074214633706907u },
+  {  7603720821608101175u, 2076918743413931051u }, {  2393627842544570617u, 1661534994731144841u },
+  { 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u },
+  {  5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u },
+  {  3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u },
+  {  6382248639981364905u, 1393796574908163946u }, {  2832900194486363201u, 2230074519853062314u },
+  {  5955668970331000884u, 1784059615882449851u }, {  1075186361522890384u, 1427247692705959881u },
+  { 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u },
+  {  3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u },
+  {  5547241898389809503u, 1870722095783555735u }, {  4437793518711847602u, 1496577676626844588u },
+  { 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u },
+  {  6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u },
+  { 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u },
+  { 14151565162110759939u, 1255420347077336152u }, {  7885109000409574610u, 2008672555323737844u },
+  {  9997436015069570011u, 1606938044258990275u }, {  7997948812055656009u, 1285550435407192220u },
+  { 12796718099289049614u, 2056880696651507552u }, {  2858676849947419045u, 1645504557321206042u },
+  { 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u },
+  {  3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u },
+  { 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u },
+  {  8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u },
+  { 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u },
+  { 15986332124095098083u, 2261564242916331941u }, {  9099716884534168143u, 1809251394333065553u },
+  { 14658471137111155161u, 1447401115466452442u }, {  4348079280205103483u, 1157920892373161954u },
+  { 14335624477811986218u, 1852673427797059126u }, {  7779150767507678651u, 1482138742237647301u },
+  {  2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u },
+  { 12097921058438802501u, 1517710072051350836u }, {  5988988032009131678u, 1214168057641080669u },
+  { 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u },
+  {  7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u },
+  { 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u },
+  {  4951948911778577463u, 2037035976334486086u }, {   272210314680951647u, 1629628781067588869u },
+  {  3907117066486671641u, 1303703024854071095u }, {  6251387306378674625u, 2085924839766513752u },
+  { 16069156289328670670u, 1668739871813211001u }, {  9165976216721026213u, 1334991897450568801u },
+  {  7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u },
+  { 13518030318433270404u, 1367031702989382452u }, {  6871453250525591353u, 2187250724783011924u },
+  {  9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u },
+  { 10282995085511086630u, 2239744742177804210u }, {  8226396068408869304u, 1791795793742243368u },
+  { 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u },
+  {  5324776569667477496u, 1834798892792057209u }, {  7949170070475892320u, 1467839114233645767u },
+  { 17427382500606444826u, 1174271291386916613u }, {  5747719112518849781u, 1878834066219066582u },
+  { 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u },
+  {  5295368560860596524u, 1923926083808324180u }, {  4236294848688477220u, 1539140867046659344u },
+  {  7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u },
+  {  9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u },
+  { 12335095245094488799u, 2017382717255397335u }, {  9868076196075591040u, 1613906173804317868u },
+  { 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u },
+  {  7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u },
+  { 11918976037903224966u, 2115379100128795516u }, {  5845832015580669650u, 1692303280103036413u },
+  { 12055363241948356366u, 1353842624082429130u }, {   841837113407818570u, 2166148198531886609u },
+  {  4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u },
+  { 12225235553534690011u, 2218135755296651887u }, {  2401490813343931363u, 1774508604237321510u },
+  {  1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u },
+  {  6886345170554478103u, 1817096810739017226u }, {  1819727321701672159u, 1453677448591213781u },
+  { 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u },
+  { 15587778368262418694u, 1488565707357402911u }, {  8780873879868024632u, 1190852565885922329u },
+  {  2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u },
+  {  7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u },
+  { 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u },
+  {  1553625868034358140u, 1997919072202235028u }, {  8621598323911307159u, 1598335257761788022u },
+  { 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u },
+  {   121653480894270168u, 1636695303948070935u }, {    97322784715416134u, 1309356243158456748u },
+  { 14913111714512307107u, 2094969989053530796u }, {  8241140556867935363u, 1675975991242824637u },
+  { 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u },
+  { 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u },
+  { 14650556434236701088u, 2196735251241795108u }, {   652398703163629901u, 1757388200993436087u },
+  { 11589965406756634890u, 1405910560794748869u }, {  7475898206584884855u, 2249456897271598191u },
+  {  2291369750525997561u, 1799565517817278553u }, {  9211793429904618695u, 1439652414253822842u },
+  { 18428218302589300235u, 2303443862806116547u }, {  7363877012587619542u, 1842755090244893238u },
+  { 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u },
+  {  2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u },
+  { 13231802778477390823u, 1207667975942893232u }, {  6413489186596184024u, 1932268761508629172u },
+  { 16198837793502678189u, 1545815009206903337u }, {  5580372605318321905u, 1236652007365522670u },
+  {  8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u },
+  {  7190041073742725760u, 1266331655542295214u }, {   436019273762630246u, 2026130648867672343u },
+  {  7727513048493924843u, 1620904519094137874u }, {  9871359253537050198u, 1296723615275310299u },
+  {  4726128361433549347u, 2074757784440496479u }, {  7470251503888749801u, 1659806227552397183u },
+  { 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u },
+  { 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u },
+  {  4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u },
+  {  3483374466074094362u, 1392346379889585943u }, {  1884050330976640656u, 2227754207823337509u },
+  {  5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u },
+  {  5913764258841343181u, 2281220308811097609u }, {  8420360221814984868u, 1824976247048878087u },
+  { 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u },
+  { 10245762345624985047u, 1868775676978051161u }, {  4507261061758077715u, 1495020541582440929u },
+  {  7295157664148372495u, 1196016433265952743u }, {  7982903447895485668u, 1913626293225524389u },
+  { 10075671573058298858u, 1530901034580419511u }, {  4371188443704728763u, 1224720827664335609u },
+  { 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u },
+  { 15839291315758726049u, 1254114127528279663u }, {  3206773216762499739u, 2006582604045247462u },
+  { 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u },
+  {  4907049252451240275u, 2054740586542333401u }, {   236290587219081897u, 1643792469233866721u },
+  { 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u },
+  {  5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u },
+  { 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u },
+  { 12584037722297574282u, 1378913065775496824u }, {  9066413911450387881u, 2206260905240794919u },
+  { 10942479943902220628u, 1765008724192635935u }, {  8753983955121776503u, 1412006979354108748u },
+  { 10317025513452932081u, 2259211166966573997u }, {   874922781278525018u, 1807368933573259198u },
+  {  8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u },
+  { 14767872471458792434u, 1850745787979017418u }, {   746251532941302978u, 1480596630383213935u },
+  {   597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u },
+  {  8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u },
+  { 17270291175157100626u, 1940647615375886168u }, {  2748186495899949531u, 1552518092300708935u },
+  {  2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u },
+  { 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u },
+  {  8826220925580526867u, 2034916513940385215u }, {  7060976740464421494u, 1627933211152308172u },
+  { 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u },
+  {  9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u },
+  { 13015147745246481542u, 2133764618521553367u }, {  3033420566713364587u, 1707011694817242694u },
+  {  6116085268112601993u, 1365609355853794155u }, {  9785736428980163188u, 2184974969366070648u },
+  { 15207286772667951197u, 1747979975492856518u }, {  1097782973908629988u, 1398383980394285215u },
+  {  1756452758253807981u, 2237414368630856344u }, {  5094511021344956708u, 1789931494904685075u },
+  {  4075608817075965366u, 1431945195923748060u }, {  6520974107321544586u, 2291112313477996896u },
+  {  1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u },
+  { 17210690286378213644u, 1173049504500734410u }, {  9090360384495590213u, 1876879207201175057u },
+  { 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u },
+  { 16096930852848599373u, 1921924308174003258u }, {  1809498238053148529u, 1537539446539202607u },
+  { 12515645034668249793u, 1230031557231362085u }, {  1578287981759648052u, 1968050491570179337u },
+  { 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u },
+  {  3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u },
+  {  6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u },
+  { 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u },
+  {  7551343283653851484u, 2113178124542660985u }, {  6041074626923081187u, 1690542499634128788u },
+  { 12211557331022285596u, 1352433999707303030u }, {  1091747655926105338u, 2163894399531684849u },
+  {  4562746939482794594u, 1731115519625347879u }, {  7339546366328145998u, 1384892415700278303u },
+  {  8053925371383123274u, 2215827865120445285u }, {  6443140297106498619u, 1772662292096356228u },
+  { 12533209867169019542u, 1418129833677084982u }, {  5295740528502789974u, 2269007733883335972u },
+  { 15304638867027962949u, 1815206187106668777u }, {  4865013464138549713u, 1452164949685335022u },
+  { 14960057215536570740u, 1161731959748268017u }, {  9178696285890871890u, 1858771135597228828u },
+  { 14721654658196518159u, 1487016908477783062u }, {  4398626097073393881u, 1189613526782226450u },
+  {  7037801755317430209u, 1903381642851562320u }, {  5630241404253944167u, 1522705314281249856u },
+  {   814844308661245011u, 1218164251424999885u }, {  1303750893857992017u, 1949062802279999816u },
+  { 15800395974054034906u, 1559250241823999852u }, {  5261619149759407279u, 1247400193459199882u },
+  { 12107939454356961969u, 1995840309534719811u }, {  5997002748743659252u, 1596672247627775849u },
+  {  8486951013736837725u, 1277337798102220679u }, {  2511075177753209390u, 2043740476963553087u },
+  { 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u },
+  {  4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u },
+  {  3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u },
+  {  9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u },
+  {  5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u },
+  { 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u },
+  { 13453306206113055875u, 1797693134862315907u }, {  3383947335406624054u, 1438154507889852726u },
+  { 16482362180876329456u, 2301047212623764361u }, {  9496540929959153242u, 1840837770099011489u },
+  { 11286581558709232917u, 1472670216079209191u }, {  5339916432225476010u, 1178136172863367353u },
+  {  4854517476818851293u, 1885017876581387765u }, {  3883613981455081034u, 1508014301265110212u },
+  { 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u },
+  {  5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u },
+  {  6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u },
+  { 12969830440044306787u, 1265014083170691364u }, {  9683682259845159889u, 2024022533073106183u },
+  { 15125643437359948558u, 1619218026458484946u }, {  8411165935146048523u, 1295374421166787957u },
+  { 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u },
+  {  8022738107230848036u, 1326463407274790868u }, {  9147032156827446534u, 2122341451639665389u },
+  { 11006974540203867551u, 1697873161311732311u }, {  5116230817421183718u, 1358298529049385849u },
+  { 15564666937357714594u, 2173277646479017358u }, {  1383687105660440706u, 1738622117183213887u },
+  { 12174996128754083534u, 1390897693746571109u }, {  8411947361780802685u, 2225436309994513775u },
+  {  6729557889424642148u, 1780349047995611020u }, {  5383646311539713719u, 1424279238396488816u },
+  {  1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u },
+  { 16285752362063044992u, 1458461940118004547u }, {  5649904260166615347u, 1166769552094403638u },
+  {  5350498001524674232u, 1866831283351045821u }, {   591049586477829062u, 1493465026680836657u },
+  { 11540886113407994219u, 1194772021344669325u }, {    18673707743239135u, 1911635234151470921u },
+  { 14772334225162232601u, 1529308187321176736u }, {  8128518565387875758u, 1223446549856941389u },
+  {  1937583260394870242u, 1957514479771106223u }, {  8928764237799716840u, 1566011583816884978u },
+  { 14521709019723594119u, 1252809267053507982u }, {  8477339172590109297u, 2004494827285612772u },
+  { 17849917782297818407u, 1603595861828490217u }, {  6901236596354434079u, 1282876689462792174u },
+  { 18420676183650915173u, 2052602703140467478u }, {  3668494502695001169u, 1642082162512373983u },
+  { 10313493231639821582u, 1313665730009899186u }, {  9122891541139893884u, 2101865168015838698u },
+  { 14677010862395735754u, 1681492134412670958u }, {   673562245690857633u, 1345193707530136767u }
+};
+
+static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = {
+  {                    0u, 1152921504606846976u }, {                    0u, 1441151880758558720u },
+  {                    0u, 1801439850948198400u }, {                    0u, 2251799813685248000u },
+  {                    0u, 1407374883553280000u }, {                    0u, 1759218604441600000u },
+  {                    0u, 2199023255552000000u }, {                    0u, 1374389534720000000u },
+  {                    0u, 1717986918400000000u }, {                    0u, 2147483648000000000u },
+  {                    0u, 1342177280000000000u }, {                    0u, 1677721600000000000u },
+  {                    0u, 2097152000000000000u }, {                    0u, 1310720000000000000u },
+  {                    0u, 1638400000000000000u }, {                    0u, 2048000000000000000u },
+  {                    0u, 1280000000000000000u }, {                    0u, 1600000000000000000u },
+  {                    0u, 2000000000000000000u }, {                    0u, 1250000000000000000u },
+  {                    0u, 1562500000000000000u }, {                    0u, 1953125000000000000u },
+  {                    0u, 1220703125000000000u }, {                    0u, 1525878906250000000u },
+  {                    0u, 1907348632812500000u }, {                    0u, 1192092895507812500u },
+  {                    0u, 1490116119384765625u }, {  4611686018427387904u, 1862645149230957031u },
+  {  9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u },
+  { 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u },
+  { 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u },
+  { 15629249925580062720u, 2220446049250313080u }, {  9768281203487539200u, 1387778780781445675u },
+  {  7598665485932036096u, 1734723475976807094u }, {   274959820560269312u, 2168404344971008868u },
+  {  9395221924704944128u, 1355252715606880542u }, {  2520655369026404352u, 1694065894508600678u },
+  { 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u },
+  { 13702562178731606016u, 1654361225106055349u }, {  3293144668132343808u, 2067951531382569187u },
+  { 18199116482078572544u, 1292469707114105741u }, {  8913837547316051968u, 1615587133892632177u },
+  { 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u },
+  { 15190102943214346240u, 1577721810442023610u }, {  9764256642163156992u, 1972152263052529513u },
+  { 17631875447420442880u, 1232595164407830945u }, {  8204786253993389888u, 1540743955509788682u },
+  {  1032610780636961552u, 1925929944387235853u }, {  2951224747111794922u, 1203706215242022408u },
+  {  3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u },
+  { 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u },
+  {  3710578054803671186u, 1836709923159824231u }, {    26536550077201078u, 2295887403949780289u },
+  { 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u },
+  {  8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u },
+  { 12076381983474541759u, 1751623080406021338u }, {  5872105442488401391u, 2189528850507526673u },
+  { 15199280947623720629u, 1368455531567204170u }, {  9775729147674874978u, 1710569414459005213u },
+  { 16831347453020981627u, 2138211768073756516u }, {  1296220121283337709u, 1336382355046097823u },
+  { 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u },
+  {  6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u },
+  { 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u },
+  {   532749306367912313u, 1593091911132452277u }, {  5277622651387278295u, 1991364888915565346u },
+  {  7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u },
+  {  8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u },
+  { 10989071563364309441u, 1519290839321567799u }, {  9124653435777998898u, 1899113549151959749u },
+  {  8008751406574943263u, 1186945968219974843u }, {  5399253239791291175u, 1483682460274968554u },
+  { 15972438586593889776u, 1854603075343710692u }, {   759402079766405302u, 1159126922089819183u },
+  { 14784310654990170340u, 1448908652612273978u }, {  9257016281882937117u, 1811135815765342473u },
+  { 16182956370781059300u, 2263919769706678091u }, {  7808504722524468110u, 1414949856066673807u },
+  {  5148944884728197234u, 1768687320083342259u }, {  1824495087482858639u, 2210859150104177824u },
+  {  1140309429676786649u, 1381786968815111140u }, {  1425386787095983311u, 1727233711018888925u },
+  {  6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u },
+  { 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u },
+  {   803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u },
+  {  4714634887749086344u, 2059023035787211567u }, {  9864175832484260821u, 1286889397367007229u },
+  { 16941905809032713930u, 1608611746708759036u }, {  2730638187581340797u, 2010764683385948796u },
+  { 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u },
+  {  4396021111970173586u, 1963637386119090621u }, {  5053356204195052443u, 1227273366324431638u },
+  { 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u },
+  { 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u },
+  { 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u },
+  {  4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u },
+  {  7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u },
+  { 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u },
+  { 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u },
+  { 10956397575869330579u, 2180075438084173168u }, {  6847748484918331612u, 1362547148802608230u },
+  { 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u },
+  { 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u },
+  { 13024893955298202172u, 2079081953128979843u }, {  5834715712847682405u, 1299426220705612402u },
+  { 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u },
+  { 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u },
+  { 12596021324643517422u, 1982767060402850955u }, {  5566670318688504437u, 1239229412751781847u },
+  {  2346651879933242642u, 1549036765939727309u }, {  7545000868343941206u, 1936295957424659136u },
+  {  4715625542714963254u, 1210184973390411960u }, {  5894531928393704067u, 1512731216738014950u },
+  { 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u },
+  { 16997363506238734644u, 1477276578845717724u }, {  2799960309088866689u, 1846595723557147156u },
+  { 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u },
+  { 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u },
+  { 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u },
+  {  3447025083132431277u, 2201313642927583642u }, {  6766076695385157452u, 1375821026829739776u },
+  {  8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u },
+  {  6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u },
+  { 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u },
+  {  5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u },
+  { 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u },
+  {  7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u },
+  {  3885132398186337741u, 1564127418111797597u }, {  9468101516160310080u, 1955159272639746996u },
+  { 15140935484454969608u, 1221974545399841872u }, {   479425281859160394u, 1527468181749802341u },
+  {  5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u },
+  { 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u },
+  { 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u },
+  {  8047776328842869663u, 1820883967578175474u }, {   836348374198811271u, 2276104959472719343u },
+  {  7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u },
+  {  8166621051047176104u, 2222758749485077483u }, {  2798295147690791113u, 1389224218428173427u },
+  { 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u },
+  {  8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u },
+  {  3828506775840797949u, 2119787930951192363u }, {    86973725686804766u, 1324867456844495227u },
+  { 13943775212390669669u, 1656084321055619033u }, {  3594660960206173375u, 2070105401319523792u },
+  {  2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u },
+  {  5816254103165035138u, 2021587305976097453u }, {  5941001823691840913u, 1263492066235060908u },
+  {  7426252279614801142u, 1579365082793826135u }, {  4671129331091113523u, 1974206353492282669u },
+  {  5225298841145639904u, 1233878970932676668u }, {  6531623551432049880u, 1542348713665845835u },
+  {  3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u },
+  { 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u },
+  { 11355826773077190286u, 1176718684132267635u }, {  9583097447919099954u, 1470898355165334544u },
+  { 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u },
+  {  2440964573842414192u, 1436424174966147016u }, {  3051205717303017741u, 1795530218707683770u },
+  { 13037379183483547984u, 2244412773384604712u }, {  8148361989677217490u, 1402757983365377945u },
+  { 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u },
+  { 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u },
+  {  9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u },
+  {  3292878744173340370u, 1672217826086733276u }, {  4116098430216675462u, 2090272282608416595u },
+  {   266718509671728212u, 1306420176630260372u }, {   333398137089660265u, 1633025220787825465u },
+  {  5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u },
+  { 12575375104699370472u, 1594751192175610805u }, {  1884160825592049379u, 1993438990219513507u },
+  { 17318501580490888525u, 1245899368887195941u }, {  7813068920331446945u, 1557374211108994927u },
+  {  5154650131986920777u, 1946717763886243659u }, {   915813323278131534u, 1216698602428902287u },
+  { 14979824709379828129u, 1520873253036127858u }, {  9501408849870009354u, 1901091566295159823u },
+  { 12855909558809837702u, 1188182228934474889u }, {  2234828893230133415u, 1485227786168093612u },
+  {  2793536116537666769u, 1856534732710117015u }, {  8663489100477123587u, 1160334207943823134u },
+  {  1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u },
+  {  9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u },
+  { 16011667041914537212u, 1770529492101780905u }, {  6179525747111007803u, 2213161865127226132u },
+  { 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u },
+  { 15834525901571292854u, 2161290883913306769u }, {  2979049660840976177u, 1350806802445816731u },
+  { 17558870131333383934u, 1688508503057270913u }, {  8113529608884566205u, 2110635628821588642u },
+  {  9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u },
+  { 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u },
+  {  1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u },
+  {  4853210475701136017u, 1258036869061940099u }, {  1454827076199032118u, 1572546086327425124u },
+  {  1818533845248790147u, 1965682607909281405u }, {  3442426662494187794u, 1228551629943300878u },
+  { 13526405364972510550u, 1535689537429126097u }, {  3072948650933474476u, 1919611921786407622u },
+  { 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u },
+  {  9630225068416591280u, 1874621017369538693u }, {  8324733676974063502u, 1171638135855961683u },
+  {  5794231077790191473u, 1464547669819952104u }, {  7242788847237739342u, 1830684587274940130u },
+  { 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u },
+  {  1596658836748081690u, 1787777917260683721u }, {  6607509564362490017u, 2234722396575854651u },
+  {  1823850468512862308u, 1396701497859909157u }, {  6891499104068465790u, 1745876872324886446u },
+  { 17837745916940358045u, 2182346090406108057u }, {  4231062170446641922u, 1363966306503817536u },
+  {  5288827713058302403u, 1704957883129771920u }, {  6611034641322878003u, 2131197353912214900u },
+  { 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u },
+  { 11644235287647684442u, 2081247415929897363u }, {  4971804045566108824u, 1300779634956185852u },
+  {  6214755056957636030u, 1625974543695232315u }, {  3156757802769657134u, 2032468179619040394u },
+  {  6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u },
+  { 17206059723201118751u, 1984832206659219134u }, {  6142101308573311315u, 1240520129162011959u },
+  {  3065940617289251240u, 1550650161452514949u }, {  8444111790038951954u, 1938312701815643686u },
+  {   665883850346957067u, 1211445438634777304u }, {   832354812933696334u, 1514306798293471630u },
+  { 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u },
+  { 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u },
+  { 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u },
+  {  1277659885424598868u, 1805194375864829576u }, {  1597074856780748586u, 2256492969831036970u },
+  {  5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u },
+  {  1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u },
+  { 11243484188358716120u, 1721567512383298469u }, {   219297180166231438u, 2151959390479123087u },
+  {  7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u },
+  { 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u },
+  { 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u },
+  { 16925056528170176201u, 1282667750405742577u }, {  7321262604930556539u, 1603334688007178222u },
+  { 18374950293017971482u, 2004168360008972777u }, {  4566814905495150320u, 1252605225005607986u },
+  { 14931890668723713708u, 1565756531257009982u }, {  9441491299049866327u, 1957195664071262478u },
+  {  1289246043478778550u, 1223247290044539049u }, {  6223243572775861092u, 1529059112555673811u },
+  {  3167368447542438461u, 1911323890694592264u }, {  1979605279714024038u, 1194577431684120165u },
+  {  7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u },
+  { 13606538515115052232u, 1166579523129023598u }, {  7784801107039039482u, 1458224403911279498u },
+  {   507629346944023544u, 1822780504889099373u }, {  5246222702107417334u, 2278475631111374216u },
+  {  3278889188817135834u, 1424047269444608885u }, {  8710297504448807696u, 1780059086805761106u }
+};
+
+#endif // RYU_D2S_FULL_TABLE_H
diff --git a/c_src/ryu/d2s_intrinsics.h b/c_src/ryu/d2s_intrinsics.h
new file mode 100644
index 0000000..4529e6b
--- /dev/null
+++ b/c_src/ryu/d2s_intrinsics.h
@@ -0,0 +1,359 @@
+// Copyright 2018 Ulf Adams
+// Copyright 2021 Thomas Depierre
+// Copyright 2025 Copyright Ericsson AB 2025. All Rights Reserved.
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_D2S_INTRINSICS_H
+#define RYU_D2S_INTRINSICS_H
+
+#include <assert.h>
+#include <stdint.h>
+
+// Defines RYU_32_BIT_PLATFORM if applicable.
+#include "common.h"
+
+// ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined.
+// Let's do the same for now.
+#if defined(__SIZEOF_INT128__) && !defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS)
+#define HAS_UINT128
+#elif defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
+#define HAS_64_BIT_INTRINSICS
+#endif
+
+#if defined(HAS_UINT128)
+typedef __uint128_t uint128_t;
+#endif
+
+#if defined(HAS_64_BIT_INTRINSICS)
+
+#include <intrin.h>
+
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+  return _umul128(a, b, productHi);
+}
+
+// Returns the lower 64 bits of (hi*2^64 + lo) >> dist, with 0 < dist < 64.
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+  // For the __shiftright128 intrinsic, the shift value is always
+  // modulo 64.
+  // In the current implementation of the double-precision version
+  // of Ryu, the shift value is always < 64. (In the case
+  // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [49, 58].
+  // Otherwise in the range [2, 59].)
+  // However, this function is now also called by s2d, which requires supporting
+  // the larger shift range (TODO: what is the actual range?).
+  // Check this here in case a future change requires larger shift
+  // values. In this case this function needs to be adjusted.
+  assert(dist < 64);
+  return __shiftright128(lo, hi, (unsigned char) dist);
+}
+
+#else // defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+  // The casts here help MSVC to avoid calls to the __allmul library function.
+  const uint32_t aLo = (uint32_t)a;
+  const uint32_t aHi = (uint32_t)(a >> 32);
+  const uint32_t bLo = (uint32_t)b;
+  const uint32_t bHi = (uint32_t)(b >> 32);
+
+  const uint64_t b00 = (uint64_t)aLo * bLo;
+  const uint64_t b01 = (uint64_t)aLo * bHi;
+  const uint64_t b10 = (uint64_t)aHi * bLo;
+  const uint64_t b11 = (uint64_t)aHi * bHi;
+
+  const uint32_t b00Lo = (uint32_t)b00;
+  const uint32_t b00Hi = (uint32_t)(b00 >> 32);
+
+  const uint64_t mid1 = b10 + b00Hi;
+  const uint32_t mid1Lo = (uint32_t)(mid1);
+  const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
+
+  const uint64_t mid2 = b01 + mid1Lo;
+  const uint32_t mid2Lo = (uint32_t)(mid2);
+  const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
+
+  const uint64_t pHi = b11 + mid1Hi + mid2Hi;
+  const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
+
+  *productHi = pHi;
+  return pLo;
+}
+
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+  // We don't need to handle the case dist >= 64 here (see above).
+  assert(dist < 64);
+  assert(dist > 0);
+  return (hi << (64 - dist)) | (lo >> dist);
+}
+
+#endif // defined(HAS_64_BIT_INTRINSICS)
+
+#if defined(RYU_32_BIT_PLATFORM)
+
+// Returns the high 64 bits of the 128-bit product of a and b.
+static inline uint64_t umulh(const uint64_t a, const uint64_t b) {
+  // Reuse the umul128 implementation.
+  // Optimizers will likely eliminate the instructions used to compute the
+  // low part of the product.
+  uint64_t hi;
+  umul128(a, b, &hi);
+  return hi;
+}
+
+// On 32-bit platforms, compilers typically generate calls to library
+// functions for 64-bit divisions, even if the divisor is a constant.
+//
+// E.g.:
+// https://bugs.llvm.org/show_bug.cgi?id=37932
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
+//
+// The functions here perform division-by-constant using multiplications
+// in the same way as 64-bit compilers would do.
+//
+// NB:
+// The multipliers and shift values are the ones generated by clang x64
+// for expressions like x/5, x/10, etc.
+
+static inline uint64_t div5(const uint64_t x) {
+  return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
+}
+
+static inline uint64_t div10(const uint64_t x) {
+  return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
+}
+
+static inline uint64_t div100(const uint64_t x) {
+  return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
+}
+
+static inline uint64_t div1e8(const uint64_t x) {
+  return umulh(x, 0xABCC77118461CEFDu) >> 26;
+}
+
+static inline uint64_t div1e9(const uint64_t x) {
+  return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
+}
+
+static inline uint32_t mod1e9(const uint64_t x) {
+  // Avoid 64-bit math as much as possible.
+  // Returning (uint32_t) (x - 1000000000 * div1e9(x)) would
+  // perform 32x64-bit multiplication and 64-bit subtraction.
+  // x and 1000000000 * div1e9(x) are guaranteed to differ by
+  // less than 10^9, so their highest 32 bits must be identical,
+  // so we can truncate both sides to uint32_t before subtracting.
+  // We can also simplify (uint32_t) (1000000000 * div1e9(x)).
+  // We can truncate before multiplying instead of after, as multiplying
+  // the highest 32 bits of div1e9(x) can't affect the lowest 32 bits.
+  return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
+}
+
+#else // defined(RYU_32_BIT_PLATFORM)
+
+static inline uint64_t div5(const uint64_t x) {
+  return x / 5;
+}
+
+static inline uint64_t div10(const uint64_t x) {
+  return x / 10;
+}
+
+static inline uint64_t div100(const uint64_t x) {
+  return x / 100;
+}
+
+static inline uint64_t div1e8(const uint64_t x) {
+  return x / 100000000;
+}
+
+static inline uint64_t div1e9(const uint64_t x) {
+  return x / 1000000000;
+}
+
+static inline uint32_t mod1e9(const uint64_t x) {
+  return (uint32_t) (x - 1000000000 * div1e9(x));
+}
+
+#endif // defined(RYU_32_BIT_PLATFORM)
+
+static inline uint32_t pow5Factor(uint64_t value) {
+  const uint64_t m_inv_5 = 14757395258967641293u; // 5 * m_inv_5 = 1 (mod 2^64)
+  const uint64_t n_div_5 = 3689348814741910323u;  // #{ n | n = 0 (mod 2^64) } = 2^64 / 5
+  uint32_t count = 0;
+  for (;;) {
+    assert(value != 0);
+    value *= m_inv_5;
+    if (value > n_div_5)
+      break;
+    ++count;
+  }
+  return count;
+}
+
+// Returns true if value is divisible by 5^p.
+static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
+  // I tried a case distinction on p, but there was no performance difference.
+  return pow5Factor(value) >= p;
+}
+
+// Returns true if value is divisible by 2^p.
+static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
+  assert(value != 0);
+  assert(p < 64);
+  // __builtin_ctzll doesn't appear to be faster here.
+  return (value & ((1ull << p) - 1)) == 0;
+}
+
+// We need a 64x128-bit multiplication and a subsequent 128-bit shift.
+// Multiplication:
+//   The 64-bit factor is variable and passed in, the 128-bit factor comes
+//   from a lookup table. We know that the 64-bit factor only has 55
+//   significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
+//   factor only has 124 significant bits (i.e., the 4 topmost bits are
+//   zeros).
+// Shift:
+//   In principle, the multiplication result requires 55 + 124 = 179 bits to
+//   represent. However, we then shift this value to the right by j, which is
+//   at least j >= 115, so the result is guaranteed to fit into 179 - 115 = 64
+//   bits. This means that we only need the topmost 64 significant bits of
+//   the 64x128-bit multiplication.
+//
+// There are several ways to do this:
+// 1. Best case: the compiler exposes a 128-bit type.
+//    We perform two 64x64-bit multiplications, add the higher 64 bits of the
+//    lower result to the higher result, and shift by j - 64 bits.
+//
+//    We explicitly cast from 64-bit to 128-bit, so the compiler can tell
+//    that these are only 64-bit inputs, and can map these to the best
+//    possible sequence of assembly instructions.
+//    x64 machines happen to have matching assembly instructions for
+//    64x64-bit multiplications and 128-bit shifts.
+//
+// 2. Second best case: the compiler exposes intrinsics for the x64 assembly
+//    instructions mentioned in 1.
+//
+// 3. We only have 64x64 bit instructions that return the lower 64 bits of
+//    the result, i.e., we have to use plain C.
+//    Our inputs are less than the full width, so we have three options:
+//    a. Ignore this fact and just implement the intrinsics manually.
+//    b. Split both into 31-bit pieces, which guarantees no internal overflow,
+//       but requires extra work upfront (unless we change the lookup table).
+//    c. Split only the first factor into 31-bit pieces, which also guarantees
+//       no internal overflow, but requires extra work since the intermediate
+//       results are not perfectly aligned.
+#if defined(HAS_UINT128)
+
+// Best case: use 128-bit type.
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+  const uint128_t b0 = ((uint128_t) m) * mul[0];
+  const uint128_t b2 = ((uint128_t) m) * mul[1];
+  return (uint64_t) (((b0 >> 64) + b2) >> (j - 64));
+}
+
+static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
+  uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+//  m <<= 2;
+//  uint128_t b0 = ((uint128_t) m) * mul[0]; // 0
+//  uint128_t b2 = ((uint128_t) m) * mul[1]; // 64
+//
+//  uint128_t hi = (b0 >> 64) + b2;
+//  uint128_t lo = b0 & 0xffffffffffffffffull;
+//  uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0];
+//  uint128_t vpLo = lo + (factor << 1);
+//  *vp = (uint64_t) ((hi + (vpLo >> 64)) >> (j - 64));
+//  uint128_t vmLo = lo - (factor << mmShift);
+//  *vm = (uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64));
+//  return (uint64_t) (hi >> (j - 64));
+  *vp = mulShift64(4 * m + 2, mul, j);
+  *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
+  return mulShift64(4 * m, mul, j);
+}
+
+#elif defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+  // m is maximum 55 bits
+  uint64_t high1;                                   // 128
+  const uint64_t low1 = umul128(m, mul[1], &high1); // 64
+  uint64_t high0;                                   // 64
+  umul128(m, mul[0], &high0);                       // 0
+  const uint64_t sum = high0 + low1;
+  if (sum < high0) {
+    ++high1; // overflow into high1
+  }
+  return shiftright128(sum, high1, j - 64);
+}
+
+static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
+  uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+  *vp = mulShift64(4 * m + 2, mul, j);
+  *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
+  return mulShift64(4 * m, mul, j);
+}
+
+#else // !defined(HAS_UINT128) && !defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+  // m is maximum 55 bits
+  uint64_t high1;                                   // 128
+  const uint64_t low1 = umul128(m, mul[1], &high1); // 64
+  uint64_t high0;                                   // 64
+  umul128(m, mul[0], &high0);                       // 0
+  const uint64_t sum = high0 + low1;
+  if (sum < high0) {
+    ++high1; // overflow into high1
+  }
+  return shiftright128(sum, high1, j - 64);
+}
+
+// This is faster if we don't have a 64x64->128-bit multiplication.
+static inline uint64_t mulShiftAll64(uint64_t m, const uint64_t* const mul, const int32_t j,
+  uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+  m <<= 1;
+  // m is maximum 55 bits
+  uint64_t tmp;
+  const uint64_t lo = umul128(m, mul[0], &tmp);
+  uint64_t hi;
+  const uint64_t mid = tmp + umul128(m, mul[1], &hi);
+  hi += mid < tmp; // overflow into hi
+
+  const uint64_t lo2 = lo + mul[0];
+  const uint64_t mid2 = mid + mul[1] + (lo2 < lo);
+  const uint64_t hi2 = hi + (mid2 < mid);
+  *vp = shiftright128(mid2, hi2, (uint32_t) (j - 64 - 1));
+
+  if (mmShift == 1) {
+    const uint64_t lo3 = lo - mul[0];
+    const uint64_t mid3 = mid - mul[1] - (lo3 > lo);
+    const uint64_t hi3 = hi - (mid3 > mid);
+    *vm = shiftright128(mid3, hi3, (uint32_t) (j - 64 - 1));
+  } else {
+    const uint64_t lo3 = lo + lo;
+    const uint64_t mid3 = mid + mid + (lo3 < lo);
+    const uint64_t hi3 = hi + hi + (mid3 < mid);
+    const uint64_t lo4 = lo3 - mul[0];
+    const uint64_t mid4 = mid3 - mul[1] - (lo4 > lo3);
+    const uint64_t hi4 = hi3 - (mid4 > mid3);
+    *vm = shiftright128(mid4, hi4, (uint32_t) (j - 64));
+  }
+
+  return shiftright128(mid, hi, (uint32_t) (j - 64 - 1));
+}
+
+#endif // HAS_64_BIT_INTRINSICS
+
+#endif // RYU_D2S_INTRINSICS_H
diff --git a/c_src/ryu/digit_table.h b/c_src/ryu/digit_table.h
new file mode 100644
index 0000000..02219bc
--- /dev/null
+++ b/c_src/ryu/digit_table.h
@@ -0,0 +1,35 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_DIGIT_TABLE_H
+#define RYU_DIGIT_TABLE_H
+
+// A table of all two-digit numbers. This is used to speed up decimal digit
+// generation by copying pairs of digits into the final output.
+static const char DIGIT_TABLE[200] = {
+  '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+  '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+  '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+  '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+  '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+  '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+  '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+  '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+  '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+  '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+};
+
+#endif // RYU_DIGIT_TABLE_H
diff --git a/c_src/ryu/ryu.h b/c_src/ryu/ryu.h
new file mode 100644
index 0000000..e6cb809
--- /dev/null
+++ b/c_src/ryu/ryu.h
@@ -0,0 +1,37 @@
+// Copyright 2018 Ulf Adams
+// Copyright 2021 Thomas Depierre
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+//    (See accompanying file LICENSE-Apache or copy at
+//     http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE-Boost or copy at
+//     https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_H
+#define RYU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+int d2s_buffered_n(double f, char* result);
+void d2s_buffered(double f, char* result);
+char* d2s(double f);
+
+//CHANGE_FOR_ERLANG we dropped all the other functions as not used by us
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RYU_H
diff --git a/c_src/ryu/to_chars.h b/c_src/ryu/to_chars.h
new file mode 100644
index 0000000..a4ff145
--- /dev/null
+++ b/c_src/ryu/to_chars.h
@@ -0,0 +1,342 @@
+// SPDX-CopyrightText: Copyright (c) Microsoft Corporation.
+// SPDX-CopyrightText: Copyright 2018 Ulf Adams
+// SPDX-CopyrightText: Copyright 2021 Thomas Depierre
+// SPDX-CopyrightText: Copyright 2025 Copyright Ericsson AB 2025. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception AND BSL-1.0
+//h
+// The license information in the original file is not super clear.
+// Microsoft seems to have changed it from Apache-2.0 to Apache-2.0 WITH LLVM-exception
+// which they most likely are not allowed to do as the LLVM exception is less
+// restrictive than Apache-2.0 plain. There is not much we can do about that
+// though so we use their license.
+//
+// Library: STL
+// Git repository: https://github.com/microsoft/STL
+// Commit: e745bad3b1d05b5b19ec652d68abb37865ffa454
+// Original function: https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/inc/xcharconv_ryu.h#L1926
+
+//CHANGE_FOR_ERLANG: This format is new, it is here to handle the different format switch used in the STL code
+enum chars_format {
+    FMT_SCIENTIFIC,
+    FMT_FIXED,
+    FMT_GENERAL
+};  
+
+// This is inspired from the MS STL Charconv, under Apache with LLVM exception licence
+// see https://github.com/microsoft/STL/blob/main/LICENSE.txt
+// The inspiration is at https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/inc/xcharconv_ryu.h#L1926
+// CHANGE_FOR_ERLANG all the types and typecast have been adapted to C types from Cpp.
+// I have also kept the Ryu original function head as it allows to not impact the rest of the code
+// __v and __mantissa and __exponent have lost their double underscore over the whole function
+// all the test on the lenght of the buffer have been dropped too. This could need change, but
+// we always pass a 256 bytes buffer when we only need 26 bytes maximum.
+static inline int to_chars(const floating_decimal_64 v, const bool sign, char* const result) {
+  // Step 5: Print the decimal representation.
+  uint64_t __output = v.mantissa;
+  const int32_t _Ryu_exponent = v.exponent;
+  const uint32_t __olength = decimalLength17(__output);
+  int32_t _Scientific_exponent = _Ryu_exponent + ((int32_t) __olength) - 1;
+
+  // CHANGE_FOR_ERLANG: we use our chars_format instead of the STL one
+  enum chars_format _Fmt;
+
+  int32_t _Lower;
+  int32_t _Upper;
+
+  if (__olength == 1) {
+    // CHANGE_FOR_ERLANG the format and examples have been adapted to the erlang format
+    // as the original would have not shown a change in format
+    // (erlang always add ".0" to scientific format) and omit the + in the exponent
+    // Value | Fixed    | Scientific
+    // 1e-4  | "0.0001" | "1.0e-4"
+    // 1e2   | "100.0"  | "1.0e2"
+    // CHANGE_FOR_ERLANG the values for a switch, as seen in the example above, for erlang
+    // are different than for STL format.
+    _Lower = -4;
+    _Upper = 2;
+  } else if (_Scientific_exponent >= 10) {
+    // CHANGE_FOR_ERLANG This case does not exist for the STL and is due to the 
+    // negative sign in the exponent.
+    // Value        | Fixed           | Scientific
+    // 123456789e1  | "1234567890.0"  | "1.23456789e9"
+    // 123456789e2  | "12345678900.0" | "1.23456789e10"
+
+    _Lower = - (int32_t) (__olength + 2);
+    _Upper = 2;
+  } else {
+    // CHANGE_FOR_ERLANG the format and examples have been adapted to the erlang format
+    // as the original would have not shown a change in format
+    // (erlang always add ".0" to scientific format) and omit the + in the exponent
+    // Value   | Fixed      | Scientific
+    // 1234e-6 | "0.001234" | "1.234e-4"
+    // 1234e1  | "12340.0"  | "1.234e4"
+    // CHANGE_FOR_ERLANG the values for a switch, as seen in the example above, for erlang
+    // are different than for STL format.
+    _Lower = - (int32_t) (__olength + 2);
+    _Upper = 1;
+  }
+
+  if (_Lower <= _Ryu_exponent && _Ryu_exponent <= _Upper) {
+    // CHANGE_FOR_ERLANG this is added to handle the -2**53, 2**53 range special case
+    // These are edge cases not captured above, all the other are naturally handled
+    // by _Lower nad _Upper
+    if ((__output >= (1ull << 53) && _Ryu_exponent == 0) 
+          || (__output > ((1ull << 52) / 5) && _Ryu_exponent == 1)
+          || (__output > ((1ull << 51) / 25) && _Ryu_exponent == 2)) {
+      _Fmt = FMT_SCIENTIFIC;
+    } else {
+      _Fmt = FMT_FIXED;
+    }
+  } else {
+    // CHANGE_FOR_ERLANG we do not need to handle the %g case here.
+    _Fmt = FMT_SCIENTIFIC;
+  }
+
+  // CHANGE_FOR_ERLANG we handle the sign here as it is handled outside of this in the STL case
+  // and we need it to compute the start of the buffer for the characters after
+  if (sign) {
+    result[0] = '-';
+  }
+
+  // CHANGE_FOR_ERLANG we compute the start of the usable buffer. It is done here
+  // in order to be fixed for both branches of formatting.
+  char* const __result = result + sign;
+
+  if (_Fmt == FMT_FIXED) {
+    // CHANGE_FOR_ERLANG this whole table has been adapted to erlang examples to help
+    // debug and evolve the edge cases
+    // Example: __output == 1729, __olength == 4
+
+    // _Ryu_exponent | Printed  | _Whole_digits | _Total_fixed_length  | Notes
+    // --------------|----------|---------------|----------------------|---------------------------------------
+    //             1 | 17290.0  |  5            |  _Whole_digits + 2   | Unified length cases.
+    //             0 | 1729.0   |  4            |                      |
+    // --------------|----------|---------------|----------------------|---------------------------------------
+    //            -1 | 172.9    |  3            | __olength + 1        | This case can't happen for
+    //            -2 | 17.29    |  2            |                      | __olength == 1, but no additional
+    //            -3 | 1.729    |  1            |                      | code is needed to avoid it.
+    // --------------|----------|---------------|----------------------|---------------------------------------
+    //            -4 | 0.1729   |  0            | 2 - _Ryu_exponent    | If the decimal point appears, we need
+    //            -5 | 0.01729  | -1            |                      | to put the "0" in front
+    //            -6 | 0.001729 | -2            |                      |
+
+    const int32_t _Whole_digits = (int32_t) (__olength) + _Ryu_exponent;
+
+    uint32_t _Total_fixed_length;
+    if (_Ryu_exponent >= 0) { 
+      // CHANGE_FOR_ERLANG the examples and values have been adapted to erlang format one
+      // CHANGE_FOR_ERLANG we also dropped the whole adjustement, as it is only of value
+      // for %f which we do not handle
+      // cases "17290.0" and "1729.0"
+      _Total_fixed_length = (uint32_t) (_Whole_digits) + 2;
+    } else if (_Whole_digits > 0) { // case "17.29"
+      _Total_fixed_length = __olength + 1;
+    } else { // case "0.001729"
+      _Total_fixed_length = (uint32_t) (2 - _Ryu_exponent);
+    }
+
+    char* _Mid;
+    if (_Ryu_exponent >= 0) { // case "172900.0"
+      // CHANGE_FOR_ERLANG we do not need the can_use_ryu, as we are not doing %f
+      // but always shortest round_trip. The whole complexity here is dropped
+      // Print the decimal digits, left-aligned within [result, result + _Total_fixed_length).
+      _Mid = __result + __olength;
+    } else { // cases "1729.0", "17.29", and "0.001729"
+      // Print the decimal digits, right-aligned within [result, result + _Total_fixed_length).
+      _Mid = __result + _Total_fixed_length;
+    }
+
+    // We prefer 32-bit operations, even on 64-bit platforms.
+    // We have at most 17 digits, and uint32_t can store 9 digits.
+    // If __output doesn't fit into uint32_t, we cut off 8 digits,
+    // so the rest will fit into uint32_t.
+    // CHANGE_FOR_ERLANG we consider in this whole thing that memcopy use the same
+    // char has defined in the DIGIT_TABLE
+    // CHANGE_FOR_ERLANG __DIGIT_TABLE became DIGIT_TABLE
+    if ((__output >> 32) != 0) {
+      // Expensive 64-bit division.
+      const uint64_t __q = div1e8(__output);
+      uint32_t __output2 = (uint32_t) (__output - 100000000 * __q);
+      __output = __q;
+
+      const uint32_t __c = __output2 % 10000;
+      __output2 /= 10000;
+      const uint32_t __d = __output2 % 10000;
+      const uint32_t __c0 = (__c % 100) << 1;
+      const uint32_t __c1 = (__c / 100) << 1;
+      const uint32_t __d0 = (__d % 100) << 1;
+      const uint32_t __d1 = (__d / 100) << 1;
+
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c0, 2);
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c1, 2);
+      memcpy(_Mid -= 2, DIGIT_TABLE + __d0, 2);
+      memcpy(_Mid -= 2, DIGIT_TABLE + __d1, 2);
+    }
+    uint32_t __output2 = (uint32_t) __output;
+    while (__output2 >= 10000) {
+#ifdef __clang__ // TRANSITION, LLVM-38217
+      const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
+#else
+      const uint32_t __c = __output2 % 10000;
+#endif
+      __output2 /= 10000;
+      const uint32_t __c0 = (__c % 100) << 1;
+      const uint32_t __c1 = (__c / 100) << 1;
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c0, 2);
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c1, 2);
+    }
+    if (__output2 >= 100) {
+      const uint32_t __c = (__output2 % 100) << 1;
+      __output2 /= 100;
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c, 2);
+    }
+    if (__output2 >= 10) {
+      const uint32_t __c = __output2 << 1;
+      memcpy(_Mid -= 2, DIGIT_TABLE + __c, 2);
+    } else {
+      *--_Mid = (char) ('0' + __output2);
+    }
+
+    if (_Ryu_exponent > 0) { // case "172900.0"
+      // Performance note: it might be more efficient to do this immediately after setting _Mid.
+      // CHANGE_FOR_ERLANG we have different case here, so we have to add the ".0" here
+      // we use memset as we do not have access to fill_n
+      memset(__result + __olength, '0', (size_t) _Ryu_exponent);
+      __result[__olength + (size_t) _Ryu_exponent] = '.';
+      __result[__olength + (size_t) _Ryu_exponent + 1] = '0';
+    } else if (_Ryu_exponent == 0) { // case "1729.0"
+      // CHANGE_FOR_ERLANG we have different case here, so we have to add the ".0" here
+      __result[__olength] = '.';
+      __result[__olength + 1] = '0';
+    } else if (_Whole_digits > 0) { // case "17.29"
+      // Performance note: moving digits might not be optimal.
+      memmove(__result, __result + 1, (size_t) _Whole_digits);
+      __result[_Whole_digits] = '.';
+    } else { // case "0.001729"
+      // CHANGE_FOR_ERLANG we use the memset here as we do not have access to fill_n
+      // Performance note: a larger memset() followed by overwriting '.' might be more efficient.
+      __result[0] = '0';
+      __result[1] = '.';
+      memset(__result + 2, '0', (size_t) (-_Whole_digits));
+    }
+
+    // CHANGE_FOR_ERLANG we do not need the errc and we are only interested in
+    // returning the length, as it is what Ryu and erlang expect. We do add the
+    // sign as we did it here instead of adding it by default as in the STL
+    return _Total_fixed_length + sign;
+  }
+
+  uint32_t _Scientific_exponent_length;
+  // CHANGE_FOR_ERLANG we have to do a little bit more complex logic here because we do not always
+  // print the exponent sign, only if it is negative
+  if (_Scientific_exponent <= -100) { // "e-100"
+    _Scientific_exponent_length = 5;
+  } else if (_Scientific_exponent <= -10 || _Scientific_exponent >= 100) { // "e-10" or "e100"
+    _Scientific_exponent_length = 4;
+  } else if ((_Scientific_exponent > -10 && _Scientific_exponent < 0) || _Scientific_exponent >= 10) { // "e-9" or "e10"
+    _Scientific_exponent_length = 3;
+  } else { // "e1"
+    _Scientific_exponent_length = 2;
+  }
+
+  // CHANGE_FOR_ERLANG we do not need the ternary as we did all the logic above
+  const uint32_t _Total_scientific_length = __olength + 1 +(__olength == 1) // digits + decimal point + possible 0 after decimal point
+    + _Scientific_exponent_length; // + scientific exponent
+
+  // Print the decimal digits.
+  uint32_t __i = 0;
+  // We prefer 32-bit operations, even on 64-bit platforms.
+  // We have at most 17 digits, and uint32_t can store 9 digits.
+  // If __output doesn't fit into uint32_t, we cut off 8 digits,
+  // so the rest will fit into uint32_t.
+    // CHANGE_FOR_ERLANG we consider in this whole thing that memcopy use the same
+    // char has defined in the DIGIT_TABLE
+    // CHANGE_FOR_ERLANG __DIGIT_TABLE became DIGIT_TABLE
+  if ((__output >> 32) != 0) {
+    // Expensive 64-bit division.
+    const uint64_t __q = div1e8(__output);
+    uint32_t __output2 = (uint32_t) (__output) - 100000000 * (uint32_t) (__q);
+    __output = __q;
+
+    const uint32_t __c = __output2 % 10000;
+    __output2 /= 10000;
+    const uint32_t __d = __output2 % 10000;
+    const uint32_t __c0 = (__c % 100) << 1;
+    const uint32_t __c1 = (__c / 100) << 1;
+    const uint32_t __d0 = (__d % 100) << 1;
+    const uint32_t __d1 = (__d / 100) << 1;
+    memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c0, 2);
+    memcpy(__result + __olength - __i - 3, DIGIT_TABLE + __c1, 2);
+    memcpy(__result + __olength - __i - 5, DIGIT_TABLE + __d0, 2);
+    memcpy(__result + __olength - __i - 7, DIGIT_TABLE + __d1, 2);
+    __i += 8;
+  }
+  uint32_t __output2 = (uint32_t) (__output);
+  while (__output2 >= 10000) {
+#ifdef __clang__ // TRANSITION, LLVM-38217
+    const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
+#else
+    const uint32_t __c = __output2 % 10000;
+#endif
+    __output2 /= 10000;
+    const uint32_t __c0 = (__c % 100) << 1;
+    const uint32_t __c1 = (__c / 100) << 1;
+    memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c0, 2);
+    memcpy(__result + __olength - __i - 3, DIGIT_TABLE + __c1, 2);
+    __i += 4;
+  }
+  if (__output2 >= 100) {
+    const uint32_t __c = (__output2 % 100) << 1;
+    __output2 /= 100;
+    memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c, 2);
+    __i += 2;
+  }
+  if (__output2 >= 10) {
+    const uint32_t __c = __output2 << 1;
+    // We can't use memcpy here: the decimal dot goes between these two digits.
+    __result[2] = DIGIT_TABLE[__c + 1];
+    __result[0] = DIGIT_TABLE[__c];
+  } else {
+    __result[0] = (char) ('0' + __output2);
+  }
+
+  // Print decimal point if needed.
+  uint32_t __index;
+  if (__olength > 1) {
+    __result[1] = '.';
+    __index = __olength + 1;
+  } else {
+    // In erlang we _have_ to print the ".0" in the case this is an integer
+    __result[1] = '.';
+    __result[2] = '0';
+    __index = __olength + 2;
+  }
+
+  // Print the exponent.
+  __result[__index++] = 'e';
+  if (_Scientific_exponent < 0) {
+    __result[__index++] = '-';
+    _Scientific_exponent = -_Scientific_exponent;
+  }
+  // CHANGE_FOR_ERLANG no else, as we do not print the positive sign on the exponent
+
+  if (_Scientific_exponent >= 100) {
+    const int32_t __c = _Scientific_exponent % 10;
+    memcpy(__result + __index, DIGIT_TABLE + 2 * (_Scientific_exponent / 10), 2);
+    __result[__index + 2] = (char) ('0' + __c);
+    __index += 3;
+  } else if (_Scientific_exponent >= 10) {
+    // CHANGE_FOR_ERLANG we have to do this only if the exponent is larger than 10
+    memcpy(__result + __index, DIGIT_TABLE + 2 * _Scientific_exponent, 2);
+    __index += 2;
+  } else { 
+  // CHANGE_FOR_ERLANG we can have an exponent under 10, which is not handled by the table
+  // so we handle it here
+    __result[__index++] = (char) ('0' + _Scientific_exponent);
+  }
+
+    // CHANGE_FOR_ERLANG we do not need the errc and we are only interested in
+    // returning the length, as it is what Ryu and erlang expect. We do add the
+    // sign as we did it here instead of adding it by default as in the STL
+  return _Total_scientific_length + sign;
+}
diff --git a/rebar.config b/rebar.config
index 2cd6b3b..e86c145 100644
--- a/rebar.config
+++ b/rebar.config
@@ -4,7 +4,7 @@
     {"priv/jiffy.so", [
         "c_src/*.c",
         "c_src/*.cc",
-        "c_src/double-conversion/*.cc"
+        "c_src/ryu/*.c"
     ]}
 ]}.
 
diff --git a/test/jiffy_03_number_tests.erl b/test/jiffy_03_number_tests.erl
index b19dffd..56759ff 100644
--- a/test/jiffy_03_number_tests.erl
+++ b/test/jiffy_03_number_tests.erl
@@ -55,12 +55,12 @@ cases(ok) ->
         {
             <<"1234567890123456789012345.0">>,
             1.23456789012345678e24,
-            <<"1.2345678901234568e+24">>
+            <<"1.2345678901234568e24">>
         },
         {
             <<"1234567890123456789012345.0E3">>,
             1.2345678901234569e27,
-            <<"1.2345678901234569e+27">>
+            <<"1.2345678901234569e27">>
         },
         {
             <<"1234567890123456789012345012">>,
@@ -71,18 +71,18 @@ cases(ok) ->
         {
             <<"0.000000000000000000000000000000000001">>,
             1.0E-36,
-            <<"1e-36">>
+            <<"1.0e-36">>
         },
         {<<"0.75">>, 0.75},
         {<<"2.0123456789">>, 2.0123456789, <<"2.0123456789">>},
-        {<<"2.4234324E24">>, 2.4234324E24, <<"2.4234324e+24">>},
+        {<<"2.4234324E24">>, 2.4234324E24, <<"2.4234324e24">>},
         {<<"-3.1416">>, -3.1416, <<"-3.1416">>},
-        {<<"1E4">>, 10000.0, <<"10000.0">>},
+        {<<"1E4">>, 10000.0, <<"1.0e4">>},
         {<<"1.0E+01">>, 10.0, <<"10.0">>},
         {<<"1e1">>, 10.0, <<"10.0">>},
         {<<"3.0E2">>, 300.0, <<"300.0">>},
         {<<"0E3">>, 0.0, <<"0.0">>},
-        {<<"1.5E3">>, 1500.0, <<"1500.0">>},
+        {<<"1.5E3">>, 1500.0, <<"1.5e3">>},
         {<<"2.5E-1">>, 0.25, <<"0.25">>},
         {<<"-0.325E+2">>, -32.5, <<"-32.5">>},
         %% Large integers to exercise digits10 (11-12+ digit path)