Bryan O'Sullivan avatar Bryan O'Sullivan committed 070bbc2

Sync with upstream git repo

commit e5b34421b763f7bf7e4f9081403db417d5a55a36

Comments (0)

Files changed (28)

double-conversion/AUTHORS

+# 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 <jmuizelaar@mozilla.com>
+Mike Hommey <mhommey@mozilla.com>
+Martin Olsson <mnemo@minimum.se>

double-conversion/Changelog

+2012-06-10:
+  Tagged v1.1.1.
+  Null terminate exponent buffer (only an issue when asserts are enabled).
+  Support more architectures.
+
+2012-02-05:
+  Merged in Single-branch with single-precision support.
+  Tagged v1.1 (based on b28450f33e1db493948a535d8f84e88fa211bd10).
+
+2012-02-05:
+  Tagged v1.0 (based on eda0196e9ac8fcdf59e92cb62885ee0af5391969).

double-conversion/SConstruct

 double_conversion_test_sources = ['test/cctest/' + x for x in SConscript('test/cctest/SConscript')]
 test = double_conversion_sources + double_conversion_test_sources
 print(test)
-env = Environment(CPPPATH='#/src')
+env = Environment(CPPPATH='#/src', LIBS=['m', 'stdc++'])
 debug = ARGUMENTS.get('debug', 0)
+optimize = ARGUMENTS.get('optimize', 0)
 if int(debug):
-  env.Append(CCFLAGS = '-g')
+  env.Append(CCFLAGS = '-g -Wall -Werror')
+if int(optimize):
+  env.Append(CCFLAGS = '-O3')
 print double_conversion_sources
 print double_conversion_test_sources
 env.Program('run_tests', double_conversion_sources + double_conversion_test_sources)

double-conversion/src/bignum-dtoa.cc

 #include "bignum-dtoa.h"
 
 #include "bignum.h"
-#include "double.h"
+#include "ieee.h"
 
 namespace double_conversion {
 
 static int EstimatePower(int exponent);
 // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
 // and denominator.
-static void InitialScaledStartValues(double v,
+static void InitialScaledStartValues(uint64_t significand,
+                                     int exponent,
+                                     bool lower_boundary_is_closer,
                                      int estimated_power,
                                      bool need_boundary_deltas,
                                      Bignum* numerator,
                 Vector<char> buffer, int* length, int* decimal_point) {
   ASSERT(v > 0);
   ASSERT(!Double(v).IsSpecial());
-  uint64_t significand = Double(v).Significand();
+  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 exponent = Double(v).Exponent();
   int normalized_exponent = NormalizedExponent(significand, exponent);
   // estimated_power might be too low by 1.
   int estimated_power = EstimatePower(normalized_exponent);
   // The maximum double is 1.7976931348623157e308 which needs fewer than
   // 308*4 binary digits.
   ASSERT(Bignum::kMaxSignificantBits >= 324*4);
-  bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);
-  InitialScaledStartValues(v, estimated_power, need_boundary_deltas,
+  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.
   //  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);
   const double k1Log10 = 0.30102999566398114;  // 1/lg(10)
 
   // For doubles len(f) == 53 (don't forget the hidden bit).
-  const int kSignificandSize = 53;
+  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(
-    double v, int estimated_power, bool need_boundary_deltas,
+    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.
   // by 10^estimated_power.
 
   // numerator = v.
-  numerator->AssignUInt64(Double(v).Significand());
-  numerator->ShiftLeft(Double(v).Exponent());
+  numerator->AssignUInt64(significand);
+  numerator->ShiftLeft(exponent);
   // denominator = 10^estimated_power.
   denominator->AssignPowerUInt16(10, estimated_power);
 
     // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
     // denominator (of 2) delta_plus equals 2^e.
     delta_plus->AssignUInt16(1);
-    delta_plus->ShiftLeft(Double(v).Exponent());
-    // Same for delta_minus (with adjustments below if f == 2^p-1).
+    delta_plus->ShiftLeft(exponent);
+    // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
     delta_minus->AssignUInt16(1);
-    delta_minus->ShiftLeft(Double(v).Exponent());
-
-    // If the significand (without the hidden bit) is 0, then the lower
-    // boundary is closer than just half a ulp (unit in the last place).
-    // There is only one exception: if the next lower number is a denormal then
-    // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we
-    // have to test it in the other function where exponent < 0).
-    uint64_t v_bits = Double(v).AsUint64();
-    if ((v_bits & Double::kSignificandMask) == 0) {
-      // The lower boundary is closer at half the distance of "normal" numbers.
-      // Increase the common denominator and adapt all but the delta_minus.
-      denominator->ShiftLeft(1);  // *2
-      numerator->ShiftLeft(1);    // *2
-      delta_plus->ShiftLeft(1);   // *2
-    }
+    delta_minus->ShiftLeft(exponent);
   }
 }
 
 
 // See comments for InitialScaledStartValues
 static void InitialScaledStartValuesNegativeExponentPositivePower(
-    double v, int estimated_power, bool need_boundary_deltas,
+    uint64_t significand, int exponent,
+    int estimated_power, bool need_boundary_deltas,
     Bignum* numerator, Bignum* denominator,
     Bignum* delta_minus, Bignum* delta_plus) {
-  uint64_t significand = Double(v).Significand();
-  int exponent = Double(v).Exponent();
   // v = f * 2^e with e < 0, and with estimated_power >= 0.
   // This means that e is close to 0 (have a look at how estimated_power is
   // computed).
     // Given that the denominator already includes v's exponent the distance
     // to the boundaries is simply 1.
     delta_plus->AssignUInt16(1);
-    // Same for delta_minus (with adjustments below if f == 2^p-1).
+    // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
     delta_minus->AssignUInt16(1);
-
-    // If the significand (without the hidden bit) is 0, then the lower
-    // boundary is closer than just one ulp (unit in the last place).
-    // There is only one exception: if the next lower number is a denormal
-    // then the distance is 1 ulp. Since the exponent is close to zero
-    // (otherwise estimated_power would have been negative) this cannot happen
-    // here either.
-    uint64_t v_bits = Double(v).AsUint64();
-    if ((v_bits & Double::kSignificandMask) == 0) {
-      // The lower boundary is closer at half the distance of "normal" numbers.
-      // Increase the denominator and adapt all but the delta_minus.
-      denominator->ShiftLeft(1);  // *2
-      numerator->ShiftLeft(1);    // *2
-      delta_plus->ShiftLeft(1);   // *2
-    }
   }
 }
 
 
 // See comments for InitialScaledStartValues
 static void InitialScaledStartValuesNegativeExponentNegativePower(
-    double v, int estimated_power, bool need_boundary_deltas,
+    uint64_t significand, int exponent,
+    int estimated_power, bool need_boundary_deltas,
     Bignum* numerator, Bignum* denominator,
     Bignum* delta_minus, Bignum* delta_plus) {
-  const uint64_t kMinimalNormalizedExponent =
-      UINT64_2PART_C(0x00100000, 00000000);
-  uint64_t significand = Double(v).Significand();
-  int exponent = Double(v).Exponent();
   // Instead of multiplying the denominator with 10^estimated_power we
   // multiply all values (numerator and deltas) by 10^-estimated_power.
 
     // delta_plus = 10^-estimated_power, and
     // delta_minus = 10^-estimated_power.
     // These assignments have been done earlier.
-
-    // The special case where the lower boundary is twice as close.
-    // This time we have to look out for the exception too.
-    uint64_t v_bits = Double(v).AsUint64();
-    if ((v_bits & Double::kSignificandMask) == 0 &&
-        // The only exception where a significand == 0 has its boundaries at
-        // "normal" distances:
-        (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
-      numerator->ShiftLeft(1);    // *2
-      denominator->ShiftLeft(1);  // *2
-      delta_plus->ShiftLeft(1);   // *2
-    }
+    // The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
   }
 }
 
 //
 // It is then easy to kickstart the digit-generation routine.
 //
-// The boundary-deltas are only filled if need_boundary_deltas is set.
-static void InitialScaledStartValues(double v,
+// 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 (Double(v).Exponent() >= 0) {
+  if (exponent >= 0) {
     InitialScaledStartValuesPositiveExponent(
-        v, estimated_power, need_boundary_deltas,
+        significand, exponent, estimated_power, need_boundary_deltas,
         numerator, denominator, delta_minus, delta_plus);
   } else if (estimated_power >= 0) {
     InitialScaledStartValuesNegativeExponentPositivePower(
-        v, estimated_power, need_boundary_deltas,
+        significand, exponent, estimated_power, need_boundary_deltas,
         numerator, denominator, delta_minus, delta_plus);
   } else {
     InitialScaledStartValuesNegativeExponentNegativePower(
-        v, estimated_power, need_boundary_deltas,
+        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
+  }
 }
 
 

double-conversion/src/bignum-dtoa.h

   // 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.

double-conversion/src/bignum.h

 
   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;

double-conversion/src/cached-powers.cc

 };
 
 static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
-static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent;
+static const int kCachedPowersOffset = 348;  // -1 * the first decimal_exponent.
 static const double kD_1_LOG2_10 = 0.30102999566398114;  //  1 / lg(10)
-const int PowersOfTenCache::kDecimalExponentDistance =
-    kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent;
-const int PowersOfTenCache::kMinDecimalExponent =
-    kCachedPowers[0].decimal_exponent;
-const int PowersOfTenCache::kMaxDecimalExponent =
-    kCachedPowers[kCachedPowersLength - 1].decimal_exponent;
+// 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,

double-conversion/src/double-conversion.cc

 #include "double-conversion.h"
 
 #include "bignum-dtoa.h"
-#include "double.h"
 #include "fast-dtoa.h"
 #include "fixed-dtoa.h"
+#include "ieee.h"
 #include "strtod.h"
 #include "utils.h"
 
   }
   ASSERT(exponent < 1e4);
   const int kMaxExponentLength = 5;
-  char buffer[kMaxExponentLength];
+  char buffer[kMaxExponentLength + 1];
+  buffer[kMaxExponentLength] = '\0';
   int first_char_pos = kMaxExponentLength;
   while (exponent > 0) {
     buffer[--first_char_pos] = '0' + (exponent % 10);
 }
 
 
-bool DoubleToStringConverter::ToShortest(double value,
-                                         StringBuilder* result_builder) const {
+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);
   }
   char decimal_rep[kDecimalRepCapacity];
   int decimal_rep_length;
 
-  DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity,
+  DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
                 &sign, &decimal_rep_length, &decimal_point);
 
   bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
     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:
                                             int* point) {
   Vector<char> vector(buffer, buffer_length);
   ASSERT(!Double(v).IsSpecial());
-  ASSERT(mode == SHORTEST || requested_digits >= 0);
+  ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
 
   if (Double(v).Sign() < 0) {
     *sign = true;
     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;
 
 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
 template <int radix_log_2>
-static double RadixStringToDouble(const char* current,
-                                  const char* end,
-                                  bool sign,
-                                  bool allow_trailing_junk,
-                                  double junk_string_value,
-                                  const char** trailing_pointer) {
+static double RadixStringToIeee(const char* current,
+                                const char* end,
+                                bool sign,
+                                bool allow_trailing_junk,
+                                double junk_string_value,
+                                bool read_as_double,
+                                const char** trailing_pointer) {
   ASSERT(current != end);
 
+  const int kDoubleSize = Double::kSignificandSize;
+  const int kSingleSize = Single::kSignificandSize;
+  const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
+
   // Skip leading 0s.
   while (*current == '0') {
     ++current;
     }
 
     number = number * radix + digit;
-    int overflow = static_cast<int>(number >> 53);
+    int overflow = static_cast<int>(number >> kSignificandSize);
     if (overflow != 0) {
       // Overflow occurred. Need to determine which direction to round the
       // result.
       }
 
       // Rounding up may cause overflow.
-      if ((number & ((int64_t)1 << 53)) != 0) {
+      if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
         exponent++;
         number >>= 1;
       }
     ++current;
   } while (current != end);
 
-  ASSERT(number < ((int64_t)1 << 53));
+  ASSERT(number < ((int64_t)1 << kSignificandSize));
   ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
 
   *trailing_pointer = current;
 }
 
 
-double StringToDoubleConverter::StringToDouble(
+double StringToDoubleConverter::StringToIeee(
     const char* input,
     int length,
-    int* processed_characters_count) {
+    int* processed_characters_count,
+    bool read_as_double) {
   const char* current = input;
   const char* end = input + length;
 
   int significant_digits = 0;
   int insignificant_digits = 0;
   bool nonzero_digit_dropped = false;
-  bool fractional_part = false;
 
   bool sign = false;
 
       }
 
       const char* tail_pointer = NULL;
-      double result = RadixStringToDouble<4>(current,
-                                             end,
-                                             sign,
-                                             allow_trailing_junk,
-                                             junk_string_value_,
-                                             &tail_pointer);
+      double result = RadixStringToIeee<4>(current,
+                                           end,
+                                           sign,
+                                           allow_trailing_junk,
+                                           junk_string_value_,
+                                           read_as_double,
+                                           &tail_pointer);
       if (tail_pointer != NULL) {
         if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
         *processed_characters_count = tail_pointer - input;
       }
     }
 
+    // There is a fractional part.
     // We don't emit a '.', but adjust the exponent instead.
-    fractional_part = true;
-
-    // There is a fractional part.
     while (*current >= '0' && *current <= '9') {
       if (significant_digits < kMaxSignificantDigits) {
         ASSERT(buffer_pos < kBufferSize);
   if (octal) {
     double result;
     const char* tail_pointer = NULL;
-    result = RadixStringToDouble<3>(buffer,
-                                    buffer + buffer_pos,
-                                    sign,
-                                    allow_trailing_junk,
-                                    junk_string_value_,
-                                    &tail_pointer);
+    result = RadixStringToIeee<3>(buffer,
+                                  buffer + buffer_pos,
+                                  sign,
+                                  allow_trailing_junk,
+                                  junk_string_value_,
+                                  read_as_double,
+                                  &tail_pointer);
     ASSERT(tail_pointer != NULL);
     *processed_characters_count = current - input;
     return result;
   ASSERT(buffer_pos < kBufferSize);
   buffer[buffer_pos] = '\0';
 
-  double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+  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 = current - input;
   return sign? -converted: converted;
 }

double-conversion/src/double-conversion.h

-// Copyright 2010 the V8 project authors. All rights reserved.
+// 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:
   // 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;
+  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
     // 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.
   // should be at least kBase10MaximalLength + 1 characters long.
   static const int kBase10MaximalLength = 17;
 
-  // Converts the given double 'v' to ascii.
+  // Converts the given double 'v' to ascii. '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 output depends on the given mode:
   //   '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
   // DoubleToAscii expects the given buffer to be big enough to hold all
   // digits and a terminating null-character. In SHORTEST-mode it expects a
   // buffer of at least kBase10MaximalLength + 1. In all other modes the
-  // requested_digits parameter (+ 1 for the null-character) limits the size of
-  // the output. The given length is only used in debug mode to ensure the
-  // buffer is big enough.
+  // 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,
                             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
   // in the 'processed_characters_count'. Trailing junk is never included.
   double StringToDouble(const char* buffer,
                         int length,
-                        int* processed_characters_count);
+                        int* processed_characters_count) {
+    return StringToIeee(buffer, length, processed_characters_count, true);
+  }
+
+  // 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) {
+    return static_cast<float>(StringToIeee(buffer, length,
+                                           processed_characters_count, false));
+  }
 
  private:
   const int flags_;
   const char* const infinity_symbol_;
   const char* const nan_symbol_;
 
+  double StringToIeee(const char* buffer,
+                      int length,
+                      int* processed_characters_count,
+                      bool read_as_double);
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
 };
 

double-conversion/src/double.h

-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef DOUBLE_CONVERSION_DOUBLE_H_
-#define DOUBLE_CONVERSION_DOUBLE_H_
-
-#include "diy-fp.h"
-
-namespace double_conversion {
-
-// We assume that doubles and uint64_t have the same endianness.
-static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
-static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
-
-// Helper functions for doubles.
-class Double {
- public:
-  static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
-  static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
-  static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
-  static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
-  static const int kPhysicalSignificandSize = 52;  // Excludes the hidden bit.
-  static const int kSignificandSize = 53;
-
-  Double() : d64_(0) {}
-  explicit Double(double d) : d64_(double_to_uint64(d)) {}
-  explicit Double(uint64_t d64) : d64_(d64) {}
-  explicit Double(DiyFp diy_fp)
-    : d64_(DiyFpToUint64(diy_fp)) {}
-
-  // The value encoded by this Double must be greater or equal to +0.0.
-  // It must not be special (infinity, or NaN).
-  DiyFp AsDiyFp() const {
-    ASSERT(Sign() > 0);
-    ASSERT(!IsSpecial());
-    return DiyFp(Significand(), Exponent());
-  }
-
-  // The value encoded by this Double must be strictly greater than 0.
-  DiyFp AsNormalizedDiyFp() const {
-    ASSERT(value() > 0.0);
-    uint64_t f = Significand();
-    int e = Exponent();
-
-    // The current double could be a denormal.
-    while ((f & kHiddenBit) == 0) {
-      f <<= 1;
-      e--;
-    }
-    // Do the final shifts in one go.
-    f <<= DiyFp::kSignificandSize - kSignificandSize;
-    e -= DiyFp::kSignificandSize - kSignificandSize;
-    return DiyFp(f, e);
-  }
-
-  // Returns the double's bit as uint64.
-  uint64_t AsUint64() const {
-    return d64_;
-  }
-
-  // Returns the next greater double. Returns +infinity on input +infinity.
-  double NextDouble() const {
-    if (d64_ == kInfinity) return Double(kInfinity).value();
-    if (Sign() < 0 && Significand() == 0) {
-      // -0.0
-      return 0.0;
-    }
-    if (Sign() < 0) {
-      return Double(d64_ - 1).value();
-    } else {
-      return Double(d64_ + 1).value();
-    }
-  }
-
-  int Exponent() const {
-    if (IsDenormal()) return kDenormalExponent;
-
-    uint64_t d64 = AsUint64();
-    int biased_e =
-        static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
-    return biased_e - kExponentBias;
-  }
-
-  uint64_t Significand() const {
-    uint64_t d64 = AsUint64();
-    uint64_t significand = d64 & kSignificandMask;
-    if (!IsDenormal()) {
-      return significand + kHiddenBit;
-    } else {
-      return significand;
-    }
-  }
-
-  // Returns true if the double is a denormal.
-  bool IsDenormal() const {
-    uint64_t d64 = AsUint64();
-    return (d64 & kExponentMask) == 0;
-  }
-
-  // We consider denormals not to be special.
-  // Hence only Infinity and NaN are special.
-  bool IsSpecial() const {
-    uint64_t d64 = AsUint64();
-    return (d64 & kExponentMask) == kExponentMask;
-  }
-
-  bool IsNan() const {
-    uint64_t d64 = AsUint64();
-    return ((d64 & kExponentMask) == kExponentMask) &&
-        ((d64 & kSignificandMask) != 0);
-  }
-
-  bool IsInfinite() const {
-    uint64_t d64 = AsUint64();
-    return ((d64 & kExponentMask) == kExponentMask) &&
-        ((d64 & kSignificandMask) == 0);
-  }
-
-  int Sign() const {
-    uint64_t d64 = AsUint64();
-    return (d64 & kSignMask) == 0? 1: -1;
-  }
-
-  // Precondition: the value encoded by this Double must be greater or equal
-  // than +0.0.
-  DiyFp UpperBoundary() const {
-    ASSERT(Sign() > 0);
-    return DiyFp(Significand() * 2 + 1, Exponent() - 1);
-  }
-
-  // Computes the two boundaries of this.
-  // The bigger boundary (m_plus) is normalized. The lower boundary has the same
-  // exponent as m_plus.
-  // Precondition: the value encoded by this Double must be greater than 0.
-  void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
-    ASSERT(value() > 0.0);
-    DiyFp v = this->AsDiyFp();
-    bool significand_is_zero = (v.f() == kHiddenBit);
-    DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
-    DiyFp m_minus;
-    if (significand_is_zero && v.e() != kDenormalExponent) {
-      // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
-      // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
-      // at a distance of 1e8.
-      // The only exception is for the smallest normal: the largest denormal is
-      // at the same distance as its successor.
-      // Note: denormals have the same exponent as the smallest normals.
-      m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
-    } else {
-      m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
-    }
-    m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
-    m_minus.set_e(m_plus.e());
-    *out_m_plus = m_plus;
-    *out_m_minus = m_minus;
-  }
-
-  double value() const { return uint64_to_double(d64_); }
-
-  // Returns the significand size for a given order of magnitude.
-  // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
-  // This function returns the number of significant binary digits v will have
-  // once it's encoded into a double. In almost all cases this is equal to
-  // kSignificandSize. The only exceptions are denormals. They start with
-  // leading zeroes and their effective significand-size is hence smaller.
-  static int SignificandSizeForOrderOfMagnitude(int order) {
-    if (order >= (kDenormalExponent + kSignificandSize)) {
-      return kSignificandSize;
-    }
-    if (order <= kDenormalExponent) return 0;
-    return order - kDenormalExponent;
-  }
-
-  static double Infinity() {
-    return Double(kInfinity).value();
-  }
-
-  static double NaN() {
-    return Double(kNaN).value();
-  }
-
- private:
-  static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
-  static const int kDenormalExponent = -kExponentBias + 1;
-  static const int kMaxExponent = 0x7FF - kExponentBias;
-  static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
-  static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
-
-  const uint64_t d64_;
-
-  static uint64_t DiyFpToUint64(DiyFp diy_fp) {
-    uint64_t significand = diy_fp.f();
-    int exponent = diy_fp.e();
-    while (significand > kHiddenBit + kSignificandMask) {
-      significand >>= 1;
-      exponent++;
-    }
-    if (exponent >= kMaxExponent) {
-      return kInfinity;
-    }
-    if (exponent < kDenormalExponent) {
-      return 0;
-    }
-    while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
-      significand <<= 1;
-      exponent--;
-    }
-    uint64_t biased_exponent;
-    if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
-      biased_exponent = 0;
-    } else {
-      biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
-    }
-    return (significand & kSignificandMask) |
-        (biased_exponent << kPhysicalSignificandSize);
-  }
-};
-
-}  // namespace double_conversion
-
-#endif  // DOUBLE_CONVERSION_DOUBLE_H_

double-conversion/src/fast-dtoa.cc

-// Copyright 2010 the V8 project authors. All rights reserved.
+// 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:
 
 #include "cached-powers.h"
 #include "diy-fp.h"
-#include "double.h"
-
-#include <stdio.h>
+#include "ieee.h"
 
 namespace double_conversion {
 
                             int number_bits,
                             uint32_t* power,
                             int* exponent_plus_one) {
-  ASSERT(number < (1 << (number_bits + 1)));
+  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.
 // 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) {
   // boundary_minus and boundary_plus will round to v when convert to a double.
   // Grisu3 will never output representations that lie exactly on a boundary.
   DiyFp boundary_minus, boundary_plus;
-  Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
+  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 decimal_exponent = 0;
   switch (mode) {
     case FAST_DTOA_SHORTEST:
-      result = Grisu3(v, buffer, length, &decimal_exponent);
+    case FAST_DTOA_SHORTEST_SINGLE:
+      result = Grisu3(v, mode, buffer, length, &decimal_exponent);
       break;
     case FAST_DTOA_PRECISION:
       result = Grisu3Counted(v, requested_digits,

double-conversion/src/fast-dtoa.h

   // 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).

double-conversion/src/fixed-dtoa.cc

 #include <math.h>
 
 #include "fixed-dtoa.h"
-#include "double.h"
+#include "ieee.h"
 
 namespace double_conversion {
 

double-conversion/src/ieee.h

+// 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 -Double::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);
+  }
+};
+
+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_;
+};
+
+}  // namespace double_conversion
+
+#endif  // DOUBLE_CONVERSION_DOUBLE_H_

double-conversion/src/strtod.cc

 #include "strtod.h"
 #include "bignum.h"
 #include "cached-powers.h"
-#include "double.h"
+#include "ieee.h"
 
 namespace double_conversion {
 
 }
 
 
-static void TrimToMaxSignificantDigits(Vector<const char> buffer,
+static void CutToMaxSignificantDigits(Vector<const char> buffer,
                                        int exponent,
                                        char* significant_buffer,
                                        int* 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) {
+    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.
 }
 
 
-// Returns the correct double for the buffer*10^exponent.
-// The variable guess should be a close guess that is either the correct double
-// or its lower neighbor (the nearest double less than the correct one).
+// 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 double BignumStrtod(Vector<const char> buffer,
-                           int exponent,
-                           double guess) {
-  if (guess == Double::Infinity()) {
-    return guess;
-  }
-
-  DiyFp upper_boundary = Double(guess).UpperBoundary();
-
+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);
   // consume at most one bigit (< 64 bits).
   // ln(10) == 3.3219...
   ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
-  Bignum input;
-  Bignum boundary;
-  input.AssignDecimalString(buffer);
-  boundary.AssignUInt64(upper_boundary.f());
+  Bignum buffer_bignum;
+  Bignum diy_fp_bignum;
+  buffer_bignum.AssignDecimalString(buffer);
+  diy_fp_bignum.AssignUInt64(diy_fp.f());
   if (exponent >= 0) {
-    input.MultiplyByPowerOfTen(exponent);
+    buffer_bignum.MultiplyByPowerOfTen(exponent);
   } else {
-    boundary.MultiplyByPowerOfTen(-exponent);
+    diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
   }
-  if (upper_boundary.e() > 0) {
-    boundary.ShiftLeft(upper_boundary.e());
+  if (diy_fp.e() > 0) {
+    diy_fp_bignum.ShiftLeft(diy_fp.e());
   } else {
-    input.ShiftLeft(-upper_boundary.e());
+    buffer_bignum.ShiftLeft(-diy_fp.e());
   }
-  int comparison = Bignum::Compare(input, boundary);
+  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) {
   }
 }
 
+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 Strtod(Vector<const char> buffer, int exponent) {
-  Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
-  Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
-  exponent += left_trimmed.length() - trimmed.length();
-  if (trimmed.length() == 0) return 0.0;
-  if (trimmed.length() > kMaxSignificantDecimalDigits) {
-    char significant_buffer[kMaxSignificantDecimalDigits];
-    int significant_exponent;
-    TrimToMaxSignificantDigits(trimmed, exponent,
-                               significant_buffer, &significant_exponent);
-    return Strtod(Vector<const char>(significant_buffer,
-                                     kMaxSignificantDecimalDigits),
-                  significant_exponent);
-  }
-  if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
-    return Double::Infinity();
-  }
-  if (exponent + trimmed.length() <= kMinDecimalPower) {
-    return 0.0;
+  double double_guess;
+  bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
+
+  float float_guess = static_cast<float>(double_guess);
+  if (float_guess == double_guess) {
+    // This shortcut triggers for integer values.
+    return float_guess;
   }
 
-  double guess;
-  if (DoubleStrtod(trimmed, exponent, &guess) ||
-      DiyFpStrtod(trimmed, exponent, &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 = static_cast<float>(double_previous);
+  float f2 = float_guess;
+  float f3 = static_cast<float>(double_next);
+  float f4;
+  if (is_correct) {
+    f4 = f3;
+  } else {
+    double double_next2 = Double(double_next).NextDouble();
+    f4 = static_cast<float>(double_next2);
+  }
+  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 canditates (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;
   }
-  return BignumStrtod(trimmed, exponent, guess);
 }
 
 }  // namespace double_conversion

double-conversion/src/strtod.h

 // 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_

double-conversion/src/utils.h

 #include <string.h>
 
 #include <assert.h>
+#ifndef ASSERT
 #define ASSERT(condition)      (assert(condition))
+#endif
+#ifndef UNIMPLEMENTED
 #define UNIMPLEMENTED() (abort())
+#endif
+#ifndef UNREACHABLE
 #define UNREACHABLE()   (abort())
+#endif
 
 // Double operations detection based on target architecture.
 // Linux uses a 80bit wide floating point stack on x86. This induces double
 // disabled.)
 // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
 #if defined(_M_X64) || defined(__x86_64__) || \
-    defined(__ARMEL__) || \
+    defined(__ARMEL__) || defined(__avr32__) || \
+    defined(__hppa__) || defined(__ia64__) || \
+    defined(__mips__) || defined(__powerpc__) || \
+    defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
+    defined(__SH4__) || defined(__alpha__) || \
     defined(_MIPS_ARCH_MIPS32R2)
 #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#elif defined(_M_IX86) || defined(__i386__)
+#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
 // 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 DISALLOW_COPY_AND_ASSIGN
 #define 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 DISALLOW_IMPLICIT_CONSTRUCTORS
 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
   TypeName();                                    \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
+#endif
 
 namespace double_conversion {
 
   void AddSubstring(const char* s, int n) {
     ASSERT(!is_finalized() && position_ + n < buffer_.length());
     ASSERT(static_cast<size_t>(n) <= strlen(s));
-    memcpy(&buffer_[position_], s, n * kCharSize);
+    memmove(&buffer_[position_], s, n * kCharSize);
     position_ += n;
   }
 
   typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
 
   Dest dest;
-  memcpy(&dest, &source, sizeof(dest));
+  memmove(&dest, &source, sizeof(dest));
   return dest;
 }
 
 
 }  // namespace double_conversion
 
-#endif  // DOUBLE_CONVERSION_UTILS_H_
+#endif  // DOUBLE_CONVERSION_UTILS_H_

double-conversion/test/cctest/SConscript

     'gay-fixed.cc',
     'gay-precision.cc',
     'gay-shortest.cc',
+    'gay-shortest-single.cc',
     'test-bignum.cc',
     'test-bignum-dtoa.cc',
     'test-conversions.cc',
     'test-diy-fp.cc',
-    'test-double.cc',
     'test-dtoa.cc',
     'test-fast-dtoa.cc',
     'test-fixed-dtoa.cc',
+    'test-ieee.cc',
     'test-strtod.cc',
   ]
 Return('double_conversion_test_sources')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.