double-conversion 0.2.0.6 → 2.0.1.0
raw patch · 28 files changed
+774/−151 lines, 28 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- double-conversion.cabal +9/−2
- double-conversion/AUTHORS +14/−0
- double-conversion/CMakeLists.txt +93/−0
- double-conversion/Changelog +34/−0
- double-conversion/README +43/−0
- double-conversion/SConstruct +40/−8
- double-conversion/double-conversionBuildTreeSettings.cmake.in +2/−0
- double-conversion/double-conversionConfig.cmake.in +17/−0
- double-conversion/double-conversionConfigVersion.cmake.in +11/−0
- double-conversion/src/CMakeLists.txt +48/−0
- double-conversion/src/bignum-dtoa.cc +6/−5
- double-conversion/src/bignum.cc +13/−11
- double-conversion/src/cached-powers.cc +1/−0
- double-conversion/src/diy-fp.h +11/−11
- double-conversion/src/double-conversion.cc +143/−57
- double-conversion/src/double-conversion.h +20/−13
- double-conversion/src/fast-dtoa.cc +10/−9
- double-conversion/src/fixed-dtoa.cc +7/−5
- double-conversion/src/ieee.h +4/−0
- double-conversion/src/strtod.cc +3/−2
- double-conversion/src/utils.h +21/−8
- double-conversion/test/CMakeLists.txt +1/−0
- double-conversion/test/cctest/CMakeLists.txt +50/−0
- double-conversion/test/cctest/cctest.cc +9/−7
- double-conversion/test/cctest/test-bignum-dtoa.cc +1/−1
- double-conversion/test/cctest/test-conversions.cc +143/−2
- double-conversion/test/cctest/test-fast-dtoa.cc +4/−4
- double-conversion/test/cctest/test-strtod.cc +16/−6
double-conversion.cabal view
@@ -1,5 +1,5 @@ name: double-conversion-version: 0.2.0.6+version: 2.0.1.0 license: BSD3 license-file: LICENSE homepage: https://github.com/bos/double-conversion@@ -8,7 +8,6 @@ author: Bryan O'Sullivan <bos@serpentine.com> maintainer: Bryan O'Sullivan <bos@serpentine.com> stability: experimental-tested-with: GHC == 7.0.3 synopsis: Fast conversion between double precision floating point and text cabal-version: >= 1.8 build-type: Simple@@ -34,16 +33,23 @@ README.markdown benchmarks/*.cabal benchmarks/*.hs+ double-conversion/*.cmake.in+ double-conversion/AUTHORS+ double-conversion/CMakeLists.txt double-conversion/COPYING+ double-conversion/Changelog double-conversion/LICENSE double-conversion/Makefile double-conversion/README double-conversion/SConstruct double-conversion/src/*.cc double-conversion/src/*.h+ double-conversion/src/CMakeLists.txt double-conversion/src/SConscript+ double-conversion/test/CMakeLists.txt double-conversion/test/cctest/*.cc double-conversion/test/cctest/*.h+ double-conversion/test/cctest/CMakeLists.txt double-conversion/test/cctest/SConscript include/*.h tests/*.hs@@ -51,6 +57,7 @@ flag developer description: operate in developer mode default: False+ manual: True library c-sources:
+ double-conversion/AUTHORS view
@@ -0,0 +1,14 @@+# 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>+Kent Williams <chaircrusher@gmail.com>+Elan Ruusamäe <glen@delfi.ee>
+ double-conversion/CMakeLists.txt view
@@ -0,0 +1,93 @@+cmake_minimum_required(VERSION 2.8)+project(double-conversion)++# pick a version #+set(double-conversion_VERSION 2.0.1)+set(double-conversion_SOVERSION_MAJOR 1)+set(double-conversion_SOVERSION_MINOR 0)+set(double-conversion_SOVERSION_PATCH 0)+set(double-conversion_SOVERSION+ ${double-conversion_SOVERSION_MAJOR}.${double-conversion_SOVERSION_MINOR}.${double-conversion_SOVERSION_PATCH})++# set paths for install -- empty initially+# Offer the user the choice of overriding the installation directories+set(INSTALL_BIN_DIR CACHE PATH "Installation directory for libraries")+set(INSTALL_LIB_DIR CACHE PATH "Installation directory for libraries")+set(INSTALL_INCLUDE_DIR CACHE PATH "Installation directory for include")+# set suffix for CMake files used for packaging+if(WIN32 AND NOT CYGWIN)+ set(INSTALL_CMAKE_DIR CMake)+else()+ set(INSTALL_CMAKE_DIR lib/CMake/double-conversion)+endif()++# Make relative paths absolute (needed later)+foreach(p LIB BIN INCLUDE CMAKE)+ set(var INSTALL_${p}_DIR)+ if(NOT IS_ABSOLUTE "${${var}}")+ set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")+ endif()+endforeach()++#+# set up include dirs+include_directories("${PROJECT_SOURCE_DIR}/src"+ "${PROJECT_BINARY_DIR}"+ )++# Add src subdirectory+add_subdirectory(src)++#+# set up testing if requested+option(BUILD_TESTING "Build test programs" OFF)+if(BUILD_TESTING)+ enable_testing()+ include(CTest)+ add_subdirectory(test)+endif()++#+# mention the library target as export library+export(TARGETS double-conversion+ FILE "${PROJECT_BINARY_DIR}/double-conversionLibraryDepends.cmake")++#+# set this build as an importable package+export(PACKAGE double-conversion)++#+# make a cmake file -- in this case, all that needs defining+# is double-conversion_INCLUDE_DIRS+configure_file(double-conversionBuildTreeSettings.cmake.in+ "${PROJECT_BINARY_DIR}/double-conversionBuildTreeSettings.cmake"+ @ONLY)++#+# determine where include is relative to the CMake dir in+# in installed tree+file(RELATIVE_PATH CONF_REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"+ "${INSTALL_INCLUDE_DIR}")++#+# sets up config to be used by CMake find_package+configure_file(double-conversionConfig.cmake.in+ "${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"+ @ONLY)+#+# Export version # checked by find_package+configure_file(double-conversionConfigVersion.cmake.in+ "${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"+ @ONLY)+#+# install config files for find_package+install(FILES+ "${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"+ "${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"+ DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)+++#+# generates install cmake files to find libraries in installation.+install(EXPORT double-conversionLibraryDepends DESTINATION+ "${INSTALL_CMAKE_DIR}" COMPONENT dev)
+ double-conversion/Changelog view
@@ -0,0 +1,34 @@+2014-03-08:+ Update version number for cmake.+ Support shared libraries with cmake.+ Add build instructions to the README.++2014-01-12:+ Tagged v2.0.1.+ Fix compilation for ARMv8 64bit (used wrong define).+ Improved SConstruct file. Thanks to Milan Bouchet-Valat and Elan Ruusamäe.+ Fixed lots of warnings (especially on Windows). Thanks to Greg Smith.++2013-11-09:+ Tagged v2.0.0.+ String-to-Double|Float: ALLOW_LEADING_SPACES and similar flags now include+ new-lines, tabs and all Unicode whitespace characters.++2013-11-09:+ Tagged v1.1.2.+ Add support for ARM 64 and OsX ppc.+ Rewrite tests so they pass under Visual Studio.+ Add CMake build system support.+ Fix warnings.++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/README view
@@ -9,3 +9,46 @@ There is extensive documentation in src/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]: http://www.cmake.org
double-conversion/SConstruct view
@@ -1,14 +1,46 @@+# vim:ft=python+import os+ double_conversion_sources = ['src/' + x for x in SConscript('src/SConscript')] double_conversion_test_sources = ['test/cctest/' + x for x in SConscript('test/cctest/SConscript')]-test = double_conversion_sources + double_conversion_test_sources-print(test)-env = Environment(CPPPATH='#/src', LIBS=['m', 'stdc++'])++DESTDIR = ARGUMENTS.get('DESTDIR', '')+prefix = ARGUMENTS.get('prefix', '/usr/local')+lib = ARGUMENTS.get('libsuffix', 'lib')+libdir = os.path.join(DESTDIR + prefix, lib)++env = Environment(CPPPATH='#/src', LIBS=['m', 'stdc++'],+ CXXFLAGS=ARGUMENTS.get('CXXFLAGS', '')) debug = ARGUMENTS.get('debug', 0) optimize = ARGUMENTS.get('optimize', 0)+env.Replace(CXX = ARGUMENTS.get('CXX', 'g++'))++# for shared lib, requires scons 2.3.0+env['SHLIBVERSION'] = '1.0.0'++CCFLAGS = [] if int(debug):- env.Append(CCFLAGS = '-g -Wall -Werror')+ CCFLAGS.append(ARGUMENTS.get('CXXFLAGS', '-g -Wall -Wshadow -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)+ CCFLAGS.append(ARGUMENTS.get('CXXFLAGS', '-O3'))++env.Append(CCFLAGS = " ".join(CCFLAGS))++double_conversion_shared_objects = [+ env.SharedObject(src) for src in double_conversion_sources]+double_conversion_static_objects = [+ env.StaticObject(src) for src in double_conversion_sources]++library_name = 'double-conversion'++static_lib = env.StaticLibrary(library_name, double_conversion_static_objects)+static_lib_pic = env.StaticLibrary(library_name + '_pic', double_conversion_shared_objects)+shared_lib = env.SharedLibrary(library_name, double_conversion_shared_objects)++env.Program('run_tests', double_conversion_test_sources, LIBS=[static_lib])++env.InstallVersionedLib(libdir, shared_lib)+env.Install(libdir, static_lib)+env.Install(libdir, static_lib_pic)++env.Alias('install', libdir)
+ double-conversion/double-conversionBuildTreeSettings.cmake.in view
@@ -0,0 +1,2 @@+set(double-conversion_INCLUDE_DIRS+ "@PROJECT_SOURCE_DIR@/src")
+ double-conversion/double-conversionConfig.cmake.in view
@@ -0,0 +1,17 @@+# - Config file for the double-conversion package+# It defines the following variables+# double-conversion_INCLUDE_DIRS+# double-conversion_LIBRARIES++get_filename_component(double-conversion_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)++if(EXISTS "${double-conversion_CMAKE_DIR}/CMakeCache.txt")+ include("${double-conversion_CMAKE_DIR}/double-conversionBuildTreeSettings.cmake")+else()+ set(double-conversion_INCLUDE_DIRS+ "${double-conversion_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@/include/double-conversion")+endif()++include("${double-conversion_CMAKE_DIR}/double-conversionLibraryDepends.cmake")++set(double-conversion_LIBRARIES double-conversion)
+ double-conversion/double-conversionConfigVersion.cmake.in view
@@ -0,0 +1,11 @@+set(PACKAGE_VERSION "@double-conversion_VERSION@")+ +# Check whether the requested PACKAGE_FIND_VERSION is compatible+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")+ set(PACKAGE_VERSION_COMPATIBLE FALSE)+else()+ set(PACKAGE_VERSION_COMPATIBLE TRUE)+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")+ set(PACKAGE_VERSION_EXACT TRUE)+ endif()+endif()
+ double-conversion/src/CMakeLists.txt view
@@ -0,0 +1,48 @@++set(headers+ bignum.h+ cached-powers.h+ diy-fp.h+ double-conversion.h+ fast-dtoa.h+ fixed-dtoa.h+ ieee.h+ strtod.h+ utils.h+ )++add_library(double-conversion+bignum.cc+bignum-dtoa.cc+cached-powers.cc+diy-fp.cc+double-conversion.cc+fast-dtoa.cc+fixed-dtoa.cc+strtod.cc+${headers}+)++#+# associates the list of headers with the library+# for the purposes of installation/import into other projects+set_target_properties(double-conversion+ PROPERTIES PUBLIC_HEADER "${headers}")++if (BUILD_SHARED_LIBS)+ set_target_properties(double-conversion+ PROPERTIES VERSION ${double-conversion_SOVERSION}+ SOVERSION ${double-conversion_SOVERSION_MAJOR})+endif()++#+# install command to set up library install+# given the above PUBLIC_HEADER property set, this+# pulls along all the header files with the library.+install(TARGETS double-conversion+ EXPORT double-conversionLibraryDepends+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}/lib" COMPONENT shlib+ ARCHIVE DESTINATION "${INSTALL_LIB_DIR}/lib" COMPONENT lib+ PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/include/double-conversion"+ COMPONENT dev)
double-conversion/src/bignum-dtoa.cc view
@@ -192,13 +192,13 @@ delta_plus = delta_minus; } *length = 0;- while (true) {+ 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)++] = digit + '0';+ 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@@ -282,7 +282,7 @@ // exponent (decimal_point), when rounding upwards. static void GenerateCountedDigits(int count, int* decimal_point, Bignum* numerator, Bignum* denominator,- Vector<char>(buffer), int* length) {+ Vector<char> buffer, int* length) { ASSERT(count >= 0); for (int i = 0; i < count - 1; ++i) { uint16_t digit;@@ -290,7 +290,7 @@ ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. // digit = numerator / denominator (integer division). // numerator = numerator % denominator.- buffer[i] = digit + '0';+ buffer[i] = static_cast<char>(digit + '0'); // Prepare for next iteration. numerator->Times10(); }@@ -300,7 +300,8 @@ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { digit++; }- buffer[count - 1] = digit + '0';+ 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) {
double-conversion/src/bignum.cc view
@@ -40,6 +40,7 @@ template<typename S> static int BitSize(S value) {+ (void) value; // Mark variable as used. return 8 * sizeof(value); } @@ -122,9 +123,8 @@ static int HexCharValue(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('a' <= c && c <= 'f') return 10 + c - 'a';- if ('A' <= c && c <= 'F') return 10 + c - 'A';- UNREACHABLE();- return 0; // To make compiler happy.+ ASSERT('A' <= c && c <= 'F');+ return 10 + c - 'A'; } @@ -501,13 +501,14 @@ // Start by removing multiples of 'other' until both numbers have the same // number of digits. while (BigitLength() > other.BigitLength()) {- // This naive approach is extremely inefficient if the this divided other- // might be big. This function is implemented for doubleToString where+ // 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 += bigits_[used_digits_ - 1];+ result += static_cast<uint16_t>(bigits_[used_digits_ - 1]); SubtractTimes(other, bigits_[used_digits_ - 1]); } @@ -523,13 +524,15 @@ // Shortcut for easy (and common) case. int quotient = this_bigit / other_bigit; bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;- result += quotient;+ ASSERT(quotient < 0x10000);+ result += static_cast<uint16_t>(quotient); Clamp(); return result; } int division_estimate = this_bigit / (other_bigit + 1);- result += division_estimate;+ ASSERT(division_estimate < 0x10000);+ result += static_cast<uint16_t>(division_estimate); SubtractTimes(other, division_estimate); if (other_bigit * (division_estimate + 1) > this_bigit) {@@ -560,8 +563,8 @@ static char HexCharOfValue(int value) { ASSERT(0 <= value && value <= 16);- if (value < 10) return value + '0';- return value - 10 + 'A';+ if (value < 10) return static_cast<char>(value + '0');+ return static_cast<char>(value - 10 + 'A'); } @@ -755,7 +758,6 @@ Chunk difference = bigits_[i] - borrow; bigits_[i] = difference & kBigitMask; borrow = difference >> (kChunkSize - 1);- ++i; } Clamp(); }
double-conversion/src/cached-powers.cc view
@@ -152,6 +152,7 @@ ASSERT(0 <= index && index < kCachedPowersLength); 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);
double-conversion/src/diy-fp.h view
@@ -42,7 +42,7 @@ static const int kSignificandSize = 64; DiyFp() : f_(0), e_(0) {}- DiyFp(uint64_t f, int e) : f_(f), e_(e) {}+ 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@@ -76,22 +76,22 @@ void Normalize() { ASSERT(f_ != 0);- uint64_t f = f_;- int e = e_;+ 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 ((f & k10MSBits) == 0) {- f <<= 10;- e -= 10;+ while ((significand & k10MSBits) == 0) {+ significand <<= 10;+ exponent -= 10; }- while ((f & kUint64MSB) == 0) {- f <<= 1;- e--;+ while ((significand & kUint64MSB) == 0) {+ significand <<= 1;+ exponent--; }- f_ = f;- e_ = e;+ f_ = significand;+ e_ = exponent; } static DiyFp Normalize(const DiyFp& a) {
double-conversion/src/double-conversion.cc view
@@ -348,7 +348,6 @@ case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; default: UNREACHABLE();- return BIGNUM_DTOA_SHORTEST; // To silence compiler. } } @@ -403,8 +402,8 @@ vector, length, point); break; default:- UNREACHABLE(); fast_worked = false;+ UNREACHABLE(); } if (fast_worked) return; @@ -417,8 +416,9 @@ // Consumes the given substring from the iterator. // Returns false, if the substring does not match.-static bool ConsumeSubString(const char** current,- const char* end,+template <class Iterator>+static bool ConsumeSubString(Iterator* current,+ Iterator end, const char* substring) { ASSERT(**current == *substring); for (substring++; *substring != '\0'; substring++) {@@ -440,10 +440,36 @@ 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.-static inline bool AdvanceToNonspace(const char** current, const char* end) {+template <class Iterator>+static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { while (*current != end) {- if (**current != ' ') return true;+ if (!isWhitespace(**current)) return true; ++*current; } return false;@@ -462,26 +488,50 @@ } +// 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.+static bool IsDecimalDigitForRadix(int c, int radix) {+ return '0' <= c && c <= '9' && (c - '0') < radix;+}++// 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;+}++ // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.-template <int radix_log_2>-static double RadixStringToIeee(const char* current,- const char* end,+template <int radix_log_2, class Iterator>+static double RadixStringToIeee(Iterator* current,+ Iterator end, bool sign, bool allow_trailing_junk, double junk_string_value, bool read_as_double,- const char** trailing_pointer) {- ASSERT(current != end);+ bool* result_is_junk) {+ ASSERT(*current != end); const int kDoubleSize = Double::kSignificandSize; const int kSingleSize = Single::kSignificandSize; const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; + *result_is_junk = true;+ // Skip leading 0s.- while (*current == '0') {- ++current;- if (current == end) {- *trailing_pointer = end;+ while (**current == '0') {+ ++(*current);+ if (*current == end) {+ *result_is_junk = false; return SignedZero(sign); } }@@ -492,14 +542,14 @@ do { int digit;- if (*current >= '0' && *current <= '9' && *current < '0' + radix) {- digit = static_cast<char>(*current) - '0';- } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {- digit = static_cast<char>(*current) - 'a' + 10;- } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {- digit = static_cast<char>(*current) - 'A' + 10;+ if (IsDecimalDigitForRadix(**current, radix)) {+ digit = static_cast<char>(**current) - '0';+ } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {+ digit = static_cast<char>(**current) - 'a' + 10;+ } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {+ digit = static_cast<char>(**current) - 'A' + 10; } else {- if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) {+ if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { break; } else { return junk_string_value;@@ -523,14 +573,14 @@ exponent = overflow_bits_count; bool zero_tail = true;- while (true) {- ++current;- if (current == end || !isDigit(*current, radix)) break;- zero_tail = zero_tail && *current == '0';+ for (;;) {+ ++(*current);+ if (*current == end || !isDigit(**current, radix)) break;+ zero_tail = zero_tail && **current == '0'; exponent += radix_log_2; } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {+ if (!allow_trailing_junk && AdvanceToNonspace(current, end)) { return junk_string_value; } @@ -552,13 +602,13 @@ } break; }- ++current;- } while (current != end);+ ++(*current);+ } while (*current != end); ASSERT(number < ((int64_t)1 << kSignificandSize)); ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); - *trailing_pointer = current;+ *result_is_junk = false; if (exponent == 0) { if (sign) {@@ -573,13 +623,14 @@ } +template <class Iterator> double StringToDoubleConverter::StringToIeee(- const char* input,+ Iterator input, int length,- int* processed_characters_count,- bool read_as_double) {- const char* current = input;- const char* end = input + length;+ bool read_as_double,+ int* processed_characters_count) const {+ Iterator current = input;+ Iterator end = input + length; *processed_characters_count = 0; @@ -600,7 +651,7 @@ if (allow_leading_spaces || allow_trailing_spaces) { if (!AdvanceToNonspace(¤t, end)) {- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return empty_string_value_; } if (!allow_leading_spaces && (input != current)) {@@ -626,7 +677,7 @@ if (*current == '+' || *current == '-') { sign = (*current == '-'); ++current;- const char* next_non_space = 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)) {@@ -649,7 +700,7 @@ } ASSERT(buffer_pos == 0);- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return sign ? -Double::Infinity() : Double::Infinity(); } }@@ -668,7 +719,7 @@ } ASSERT(buffer_pos == 0);- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return sign ? -Double::NaN() : Double::NaN(); } }@@ -677,7 +728,7 @@ if (*current == '0') { ++current; if (current == end) {- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return SignedZero(sign); } @@ -690,17 +741,17 @@ return junk_string_value_; // "0x". } - const char* tail_pointer = NULL;- double result = RadixStringToIeee<4>(current,+ bool result_is_junk;+ double result = RadixStringToIeee<4>(¤t, 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;+ &result_is_junk);+ if (!result_is_junk) {+ if (allow_trailing_spaces) AdvanceToNonspace(¤t, end);+ *processed_characters_count = static_cast<int>(current - input); } return result; }@@ -709,7 +760,7 @@ while (*current == '0') { ++current; if (current == end) {- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return SignedZero(sign); } }@@ -757,7 +808,7 @@ while (*current == '0') { ++current; if (current == end) {- *processed_characters_count = current - input;+ *processed_characters_count = static_cast<int>(current - input); return SignedZero(sign); } exponent--; // Move this 0 into the exponent.@@ -801,9 +852,9 @@ return junk_string_value_; } }- char sign = '+';+ char exponen_sign = '+'; if (*current == '+' || *current == '-') {- sign = static_cast<char>(*current);+ exponen_sign = static_cast<char>(*current); ++current; if (current == end) { if (allow_trailing_junk) {@@ -837,7 +888,7 @@ ++current; } while (current != end && *current >= '0' && *current <= '9'); - exponent += (sign == '-' ? -num : num);+ exponent += (exponen_sign == '-' ? -num : num); } if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {@@ -855,16 +906,17 @@ if (octal) { double result;- const char* tail_pointer = NULL;- result = RadixStringToIeee<3>(buffer,+ bool result_is_junk;+ char* start = buffer;+ result = RadixStringToIeee<3>(&start, buffer + buffer_pos, sign, allow_trailing_junk, junk_string_value_, read_as_double,- &tail_pointer);- ASSERT(tail_pointer != NULL);- *processed_characters_count = current - input;+ &result_is_junk);+ ASSERT(!result_is_junk);+ *processed_characters_count = static_cast<int>(current - input); return result; } @@ -882,8 +934,42 @@ } else { converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent); }- *processed_characters_count = current - input;+ *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
double-conversion/src/double-conversion.h view
@@ -415,9 +415,10 @@ // junk, too. // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of // a double literal.- // - ALLOW_LEADING_SPACES: skip over leading spaces.- // - ALLOW_TRAILING_SPACES: ignore trailing spaces.- // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.+ // - 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 //@@ -502,20 +503,25 @@ // in the 'processed_characters_count'. Trailing junk is never included. double StringToDouble(const char* buffer, int length,- int* processed_characters_count) {- return StringToIeee(buffer, length, processed_characters_count, true);- }+ 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) {- return static_cast<float>(StringToIeee(buffer, length,- processed_characters_count, false));- }+ 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_;@@ -523,10 +529,11 @@ const char* const infinity_symbol_; const char* const nan_symbol_; - double StringToIeee(const char* buffer,+ template <class Iterator>+ double StringToIeee(Iterator start_pointer, int length,- int* processed_characters_count,- bool read_as_double);+ bool read_as_double,+ int* processed_characters_count) const; DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); };
double-conversion/src/fast-dtoa.cc view
@@ -248,10 +248,7 @@ // Note: kPowersOf10[i] == 10^(i-1). exponent_plus_one_guess++; // We don't have any guarantees that 2^number_bits <= number.- // TODO(floitsch): can we change the 'while' into an 'if'? We definitely see- // number < (2^number_bits - 1), but I haven't encountered- // number < (2^number_bits - 2) yet.- while (number < kSmallPowersOfTen[exponent_plus_one_guess]) {+ if (number < kSmallPowersOfTen[exponent_plus_one_guess]) { exponent_plus_one_guess--; } *power = kSmallPowersOfTen[exponent_plus_one_guess];@@ -350,7 +347,8 @@ // that is smaller than integrals. while (*kappa > 0) { int digit = integrals / divisor;- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; integrals %= divisor; (*kappa)--;@@ -379,13 +377,14 @@ ASSERT(one.e() >= -60); ASSERT(fractionals < one.f()); ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());- while (true) {+ 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());- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; fractionals &= one.f() - 1; // Modulo by one. (*kappa)--;@@ -459,7 +458,8 @@ // that is smaller than 'integrals'. while (*kappa > 0) { int digit = integrals / divisor;- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; requested_digits--; integrals %= divisor;@@ -492,7 +492,8 @@ w_error *= 10; // Integer division by one. int digit = static_cast<int>(fractionals >> -one.e());- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; requested_digits--; fractionals &= one.f() - 1; // Modulo by one.
double-conversion/src/fixed-dtoa.cc view
@@ -133,7 +133,7 @@ while (number != 0) { int digit = number % 10; number /= 10;- buffer[(*length) + number_length] = '0' + digit;+ buffer[(*length) + number_length] = static_cast<char>('0' + digit); number_length++; } // Exchange the digits.@@ -150,7 +150,7 @@ } -static void FillDigits64FixedLength(uint64_t number, int requested_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.@@ -253,7 +253,8 @@ fractionals *= 5; point--; int digit = static_cast<int>(fractionals >> point);- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; fractionals -= static_cast<uint64_t>(digit) << point; }@@ -274,7 +275,8 @@ fractionals128.Multiply(5); point--; int digit = fractionals128.DivModPowerOf2(point);- buffer[*length] = '0' + digit;+ ASSERT(digit <= 9);+ buffer[*length] = static_cast<char>('0' + digit); (*length)++; } if (fractionals128.BitAt(point - 1) == 1) {@@ -358,7 +360,7 @@ remainder = (dividend % divisor) << exponent; } FillDigits32(quotient, buffer, length);- FillDigits64FixedLength(remainder, divisor_power, buffer, length);+ FillDigits64FixedLength(remainder, buffer, length); *decimal_point = *length; } else if (exponent >= 0) { // 0 <= exponent <= 11
double-conversion/src/ieee.h view
@@ -256,6 +256,8 @@ return (significand & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize); }++ DISALLOW_COPY_AND_ASSIGN(Double); }; class Single {@@ -391,6 +393,8 @@ static const uint32_t kNaN = 0x7FC00000; const uint32_t d32_;++ DISALLOW_COPY_AND_ASSIGN(Single); }; } // namespace double_conversion
double-conversion/src/strtod.cc view
@@ -137,6 +137,7 @@ 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);@@ -263,7 +264,6 @@ case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); default: UNREACHABLE();- return DiyFp(0, 0); } } @@ -286,7 +286,7 @@ const int kDenominator = 1 << kDenominatorLog; // Move the remaining decimals into the exponent. exponent += remaining_decimals;- int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);+ uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2); int old_e = input.e(); input.Normalize();@@ -515,6 +515,7 @@ double double_next2 = Double(double_next).NextDouble(); f4 = static_cast<float>(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
double-conversion/src/utils.h view
@@ -33,7 +33,8 @@ #include <assert.h> #ifndef ASSERT-#define ASSERT(condition) (assert(condition))+#define ASSERT(condition) \+ assert(condition); #endif #ifndef UNIMPLEMENTED #define UNIMPLEMENTED() (abort())@@ -55,11 +56,15 @@ #if defined(_M_X64) || defined(__x86_64__) || \ defined(__ARMEL__) || defined(__avr32__) || \ defined(__hppa__) || defined(__ia64__) || \- defined(__mips__) || defined(__powerpc__) || \+ defined(__mips__) || \+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ defined(__SH4__) || defined(__alpha__) || \- defined(_MIPS_ARCH_MIPS32R2)+ defined(_MIPS_ARCH_MIPS32R2) || \+ defined(__AARCH64EL__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1+#elif defined(__mc68000__)+#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.@@ -71,6 +76,11 @@ #error Target architecture was not detected as supported by Double-Conversion. #endif +#if defined(__GNUC__)+#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))+#else+#define DOUBLE_CONVERSION_UNUSED+#endif #if defined(_WIN32) && !defined(__MINGW32__) @@ -90,6 +100,8 @@ #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);@@ -155,8 +167,8 @@ class Vector { public: Vector() : start_(NULL), length_(0) {}- Vector(T* data, int length) : start_(data), length_(length) {- ASSERT(length == 0 || (length > 0 && data != NULL));+ 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,@@ -198,8 +210,8 @@ // buffer bounds on all operations in debug mode. class StringBuilder { public:- StringBuilder(char* buffer, int size)- : buffer_(buffer, size), position_(0) { }+ StringBuilder(char* buffer, int buffer_size)+ : buffer_(buffer, buffer_size), position_(0) { } ~StringBuilder() { if (!is_finalized()) Finalize(); } @@ -296,7 +308,8 @@ inline Dest BitCast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes.- typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];+ DOUBLE_CONVERSION_UNUSED+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; Dest dest; memmove(&dest, &source, sizeof(dest));
+ double-conversion/test/CMakeLists.txt view
@@ -0,0 +1,1 @@+add_subdirectory(cctest)
+ double-conversion/test/cctest/CMakeLists.txt view
@@ -0,0 +1,50 @@++set(CCTEST_SRC+ cctest.cc+ 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-dtoa.cc+ test-fast-dtoa.cc+ test-fixed-dtoa.cc+ test-ieee.cc+ test-strtod.cc+)++add_executable(cctest ${CCTEST_SRC})+target_link_libraries(cctest double-conversion)++add_test(NAME test_bignum+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-bignum)++add_test(NAME test_bignum_dtoa+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-bignum-dtoa)++add_test(NAME test_conversions+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-conversions)+add_test(NAME test_diy_fp+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-diy-fp)+add_test(NAME test_dtoa+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-dtoa)+add_test(NAME test_fast_dtoa+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-fast-dtoa)+add_test(NAME test_fixed_dtoa+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-fixed-dtoa)+add_test(NAME test_ieee+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-ieee)+add_test(NAME test_strtod+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}+ COMMAND $<TARGET_FILE:cctest> test-strtod)
double-conversion/test/cctest/cctest.cc view
@@ -34,16 +34,18 @@ CcTest* CcTest::last_ = NULL; -CcTest::CcTest(TestFunction* callback, const char* file, const char* name,- const char* dependency, bool enabled)- : callback_(callback), name_(name), dependency_(dependency), prev_(last_) {+CcTest::CcTest(TestFunction* callback, const char* test_file,+ const char* test_name, const char* test_dependency,+ bool test_is_enabled)+ : callback_(callback), name_(test_name), dependency_(test_dependency),+ prev_(last_) { // Find the base name of this test (const_cast required on Windows).- char *basename = strrchr(const_cast<char *>(file), '/');+ char *basename = strrchr(const_cast<char *>(test_file), '/'); if (!basename) {- basename = strrchr(const_cast<char *>(file), '\\');+ basename = strrchr(const_cast<char *>(test_file), '\\'); } if (!basename) {- basename = strdup(file);+ basename = strdup(test_file); } else { basename = strdup(basename + 1); }@@ -52,7 +54,7 @@ if (extension) *extension = 0; // Install this test in the list of tests file_ = basename;- enabled_ = enabled;+ enabled_ = test_is_enabled; prev_ = last_; last_ = this; }
double-conversion/test/cctest/test-bignum-dtoa.cc view
@@ -282,7 +282,7 @@ CHECK_EQ("332307", buffer.start()); CHECK_EQ(36, point); - BignumDtoa(1.23405349260765015351e-41f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,+ BignumDtoa(1.2341e-41f, BIGNUM_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point); CHECK_EQ("12341", buffer.start()); CHECK_EQ(-40, point);
double-conversion/test/cctest/test-conversions.cc view
@@ -1718,6 +1718,18 @@ } +static double StrToD16(const uc16* str16, int length, int flags,+ double empty_string_value,+ int* processed_characters_count, bool* processed_all) {+ StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),+ NULL, NULL);+ double result =+ converter.StringToDouble(str16, length, processed_characters_count);+ *processed_all = (length == *processed_characters_count);+ return result;+}++ static double StrToD(const char* str, int flags, double empty_string_value, int* processed_characters_count, bool* processed_all) { StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),@@ -1726,6 +1738,19 @@ processed_characters_count); *processed_all = ((strlen(str) == static_cast<unsigned>(*processed_characters_count)));++ uc16 buffer16[256];+ ASSERT(strlen(str) < ARRAY_SIZE(buffer16));+ int len = strlen(str);+ for (int i = 0; i < len; i++) {+ buffer16[i] = str[i];+ }+ int processed_characters_count16;+ bool processed_all16;+ double result16 = StrToD16(buffer16, len, flags, empty_string_value,+ &processed_characters_count16, &processed_all16);+ CHECK_EQ(result, result16);+ CHECK_EQ(*processed_characters_count, processed_characters_count16); return result; } @@ -2530,12 +2555,21 @@ CHECK_EQ(10.0, StrToD(" 012", flags, 0.0, &processed, &all_used)); CHECK(all_used); + CHECK_EQ(10.0, StrToD("\n012", flags, 0.0, &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(0.0, StrToD(" 00", flags, 1.0, &processed, &all_used)); CHECK(all_used); + CHECK_EQ(0.0, StrToD("\t00", flags, 1.0, &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(10.0, StrToD(" 012", flags, 1.0, &processed, &all_used)); CHECK(all_used); + CHECK_EQ(10.0, StrToD("\n012", flags, 1.0, &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(123456789.0, StrToD(" 0123456789", flags, Double::NaN(), &processed, &all_used)); CHECK(all_used);@@ -2545,6 +2579,10 @@ CHECK(all_used); CHECK_EQ(342391.0,+ StrToD("\n01234567", flags, Double::NaN(), &processed, &all_used));+ CHECK(all_used);++ CHECK_EQ(342391.0, StrToD(" + 01234567", flags, Double::NaN(), &processed, &all_used)); CHECK(all_used); @@ -2552,6 +2590,10 @@ StrToD(" - 01234567", flags, Double::NaN(), &processed, &all_used)); CHECK(all_used); + CHECK_EQ(-342391.0,+ StrToD("\n-\t01234567", flags, Double::NaN(), &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(10.0, StrToD(" 012 ", flags, 0.0, &processed, &all_used)); CHECK(all_used); @@ -3196,14 +3238,41 @@ } -static float StrToF(const char* str, int flags, float empty_string_value,- int* processed_characters_count, bool* processed_all) {+static float StrToF16(const uc16* str16, int length, int flags,+ double empty_string_value,+ int* processed_characters_count,+ bool* processed_all) {+ StringToDoubleConverter converter(flags, empty_string_value, Double::NaN(),+ NULL, NULL);+ double result =+ converter.StringToFloat(str16, length, processed_characters_count);+ *processed_all = (length == *processed_characters_count);+ return result;+}+++static double StrToF(const char* str, int flags, double empty_string_value,+ int* processed_characters_count, bool* processed_all) { StringToDoubleConverter converter(flags, empty_string_value, Single::NaN(), NULL, NULL); float result = converter.StringToFloat(str, strlen(str), processed_characters_count); *processed_all = ((strlen(str) == static_cast<unsigned>(*processed_characters_count)));++ uc16 buffer16[256];+ ASSERT(strlen(str) < ARRAY_SIZE(buffer16));+ int len = strlen(str);+ for (int i = 0; i < len; i++) {+ buffer16[i] = str[i];+ }+ int processed_characters_count16;+ bool processed_all16;+ float result16 = StrToF16(buffer16, len, flags, empty_string_value,+ &processed_characters_count16,+ &processed_all16);+ CHECK_EQ(result, result16);+ CHECK_EQ(*processed_characters_count, processed_characters_count16); return result; } @@ -4568,4 +4637,76 @@ CHECK_EQ(1.0f, converter.StringToDouble("1234.0", 6, &processed)); CHECK_EQ(0, processed); }+}+++TEST(StringToDoubleFloatWhitespace) {+ int flags;+ int processed;+ bool all_used;++ flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |+ StringToDoubleConverter::ALLOW_TRAILING_SPACES |+ StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN;++ const char kWhitespaceAscii[] = {+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20,+ '-',+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20,+ '1', '.', '2',+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20,+ 0x00+ };+ CHECK_EQ(-1.2, StrToD(kWhitespaceAscii, flags, Double::NaN(),+ &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(-1.2f, StrToF(kWhitespaceAscii, flags, Double::NaN(),+ &processed, &all_used));+ CHECK(all_used);++ const uc16 kOghamSpaceMark = 0x1680;+ const uc16 kMongolianVowelSeparator = 0x180E;+ const uc16 kEnQuad = 0x2000;+ const uc16 kEmQuad = 0x2001;+ const uc16 kEnSpace = 0x2002;+ const uc16 kEmSpace = 0x2003;+ const uc16 kThreePerEmSpace = 0x2004;+ const uc16 kFourPerEmSpace = 0x2005;+ const uc16 kSixPerEmSpace = 0x2006;+ const uc16 kFigureSpace = 0x2007;+ const uc16 kPunctuationSpace = 0x2008;+ const uc16 kThinSpace = 0x2009;+ const uc16 kHairSpace = 0x200A;+ const uc16 kNarrowNoBreakSpace = 0x202F;+ const uc16 kMediumMathematicalSpace = 0x205F;+ const uc16 kIdeographicSpace = 0x3000;++ const uc16 kWhitespace16[] = {+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20, 0xA0, 0xFEFF,+ kOghamSpaceMark, kMongolianVowelSeparator, kEnQuad, kEmQuad,+ kEnSpace, kEmSpace, kThreePerEmSpace, kFourPerEmSpace, kSixPerEmSpace,+ kFigureSpace, kPunctuationSpace, kThinSpace, kHairSpace,+ kNarrowNoBreakSpace, kMediumMathematicalSpace, kIdeographicSpace,+ '-',+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20, 0xA0, 0xFEFF,+ kOghamSpaceMark, kMongolianVowelSeparator, kEnQuad, kEmQuad,+ kEnSpace, kEmSpace, kThreePerEmSpace, kFourPerEmSpace, kSixPerEmSpace,+ kFigureSpace, kPunctuationSpace, kThinSpace, kHairSpace,+ kNarrowNoBreakSpace, kMediumMathematicalSpace, kIdeographicSpace,+ '1', '.', '2',+ 0x0A, 0x0D, 0x09, 0x0B, 0x0C, 0x20, 0xA0, 0xFEFF,+ kOghamSpaceMark, kMongolianVowelSeparator, kEnQuad, kEmQuad,+ kEnSpace, kEmSpace, kThreePerEmSpace, kFourPerEmSpace, kSixPerEmSpace,+ kFigureSpace, kPunctuationSpace, kThinSpace, kHairSpace,+ kNarrowNoBreakSpace, kMediumMathematicalSpace, kIdeographicSpace,+ };+ const int kWhitespace16Length = ARRAY_SIZE(kWhitespace16);+ CHECK_EQ(-1.2, StrToD16(kWhitespace16, kWhitespace16Length, flags,+ Double::NaN(),+ &processed, &all_used));+ CHECK(all_used);+ CHECK_EQ(-1.2f, StrToF16(kWhitespace16, kWhitespace16Length, flags,+ Single::NaN(),+ &processed, &all_used));+ CHECK(all_used); }
double-conversion/test/cctest/test-fast-dtoa.cc view
@@ -32,7 +32,7 @@ Vector<char> buffer(buffer_container, kBufferSize); int length; int point;- int status;+ bool status; double min_double = 5e-324; status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0,@@ -102,7 +102,7 @@ Vector<char> buffer(buffer_container, kBufferSize); int length; int point;- int status;+ bool status; float min_float = 1e-45f; status = FastDtoa(min_float, FAST_DTOA_SHORTEST_SINGLE, 0,@@ -131,7 +131,7 @@ CHECK_EQ("332307", buffer.start()); CHECK_EQ(36, point); - status = FastDtoa(1.23405349260765015351e-41f, FAST_DTOA_SHORTEST_SINGLE, 0,+ status = FastDtoa(1.2341e-41f, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point); CHECK(status); CHECK_EQ("12341", buffer.start());@@ -178,7 +178,7 @@ Vector<char> buffer(buffer_container, kBufferSize); int length; int point;- int status;+ bool status; status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point); CHECK(status);
double-conversion/test/cctest/test-strtod.cc view
@@ -515,8 +515,8 @@ CHECK_EQ(3401e34f, StrtofChar("00000340100000", 29)); CHECK_EQ(Single::Infinity(), StrtofChar("00000341000000", 30)); CHECK_EQ(34e37f, StrtofChar("000003400000", 32));- CHECK_EQ(3.4028235676e+38f, StrtofChar("34028235676", 28));- CHECK_EQ(3.4028235677e+38f, StrtofChar("34028235677", 28));+ CHECK_EQ(3.4028234e+38f, StrtofChar("34028235676", 28));+ CHECK_EQ(3.4028234e+38f, StrtofChar("34028235677", 28)); CHECK_EQ(Single::Infinity(), StrtofChar("34028235678", 28)); // The following number is the result of 89255.0/1e-22. Both floating-point@@ -538,7 +538,12 @@ // Verify that we don't double round. // Get the boundary of the boundary. CHECK_EQ(2.1665680640000002384185791015625e9, 2166568064.0);+ // Visual Studio gets this wrong and believes that these two numbers are the+ // same doubles. We want to test our conversion and not the compiler. We+ // therefore disable the check.+#ifndef _MSC_VER CHECK(2.16656806400000023841857910156251e9 != 2166568064.0);+#endif CHECK_EQ(2166568192.0f, StrtofChar("21665680640000002384185791015625", -22)); // 0x4fffffff = 8589934080@@ -551,8 +556,13 @@ CHECK_EQ(8589934592.0f, StrtofChar("858993433600001", -5)); // Verify that we don't double round. // Get the boundary of the boundary.+ // Visual Studio gets this wrong. To avoid failing tests because of a broken+ // compiler we disable the following two tests. They were only testing the+ // compiler. The real test is still active.+#ifndef _MSC_VER CHECK_EQ(8.589934335999999523162841796875e+09, 8589934336.0); CHECK(8.5899343359999995231628417968749e+09 != 8589934336.0);+#endif CHECK_EQ(8589934080.0f, StrtofChar("8589934335999999523162841796875", -21)); // 0x4f000000 = 2147483648@@ -649,7 +659,7 @@ for (int i = 0; i < kShortStrtodRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) {- buffer[pos++] = random() % 10 + '0';+ buffer[pos++] = DeterministicRandom() % 10 + '0'; } int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length; buffer[pos] = '\0';@@ -662,7 +672,7 @@ for (int i = 0; i < kLargeStrtodRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) {- buffer[pos++] = random() % 10 + '0';+ buffer[pos++] = DeterministicRandom() % 10 + '0'; } int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length; buffer[pos] = '\0';@@ -716,7 +726,7 @@ for (int i = 0; i < kShortStrtofRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) {- buffer[pos++] = random() % 10 + '0';+ buffer[pos++] = DeterministicRandom() % 10 + '0'; } int exponent = DeterministicRandom() % (5*2 + 1) - 5 - length; buffer[pos] = '\0';@@ -729,7 +739,7 @@ for (int i = 0; i < kLargeStrtofRandomCount; ++i) { int pos = 0; for (int j = 0; j < length; ++j) {- buffer[pos++] = random() % 10 + '0';+ buffer[pos++] = DeterministicRandom() % 10 + '0'; } int exponent = DeterministicRandom() % (38*2 + 1) - 38 - length; buffer[pos] = '\0';