├── .gitignore ├── BenchmarkFloatConv ├── BenchmarkFloatConv.sln └── BenchmarkFloatConv │ ├── BenchmarkFloatConv.cpp │ ├── BenchmarkFloatConv.vcxproj │ ├── BenchmarkFloatConv.vcxproj.user │ ├── Makefile │ └── google_double_conversion │ ├── CMakeLists.txt │ ├── SConscript │ ├── bignum-dtoa.cc │ ├── bignum-dtoa.h │ ├── bignum.cc │ ├── bignum.h │ ├── cached-powers.cc │ ├── cached-powers.h │ ├── diy-fp.cc │ ├── diy-fp.h │ ├── double-conversion.cc │ ├── double-conversion.h │ ├── fast-dtoa.cc │ ├── fast-dtoa.h │ ├── fixed-dtoa.cc │ ├── fixed-dtoa.h │ ├── ieee.h │ ├── strtod.cc │ ├── strtod.h │ └── utils.h ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | *.sdf 32 | *.pdb 33 | *.ipdb 34 | *.iobj 35 | *.ilk 36 | *.db 37 | *.suo 38 | *.VC 39 | README.txt 40 | 41 | .vs 42 | */[dD]ebug/ 43 | */[rR]elease/ 44 | */*/[dD]ebug/ 45 | */*/[rR]elease/ 46 | */*/*/[dD]ebug/ 47 | */*/*/[rR]elease/ 48 | */ipch/ 49 | */*/ipch/ 50 | */*/bin/ 51 | */*/obj/ 52 | 53 | *.ipch 54 | *.db-wal 55 | *.db-shm 56 | *.ide 57 | 58 | *.tlog 59 | *.filters -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2046 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BenchmarkFloatConv", "BenchmarkFloatConv\BenchmarkFloatConv.vcxproj", "{3C355360-BE86-48B0-B3D0-192BE91E770B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Debug|Win32.Build.0 = Debug|Win32 18 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Debug|x64.ActiveCfg = Debug|x64 19 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Debug|x64.Build.0 = Debug|x64 20 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Release|Win32.ActiveCfg = Release|Win32 21 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Release|Win32.Build.0 = Release|Win32 22 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Release|x64.ActiveCfg = Release|x64 23 | {3C355360-BE86-48B0-B3D0-192BE91E770B}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {66C8C2A3-8D6B-4889-ABEE-A54F25571405} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/BenchmarkFloatConv.cpp: -------------------------------------------------------------------------------- 1 | // BenchmarkFloatConv.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "google_double_conversion/double-conversion.h" 17 | #include 18 | 19 | typedef std::pair pair_type; 20 | typedef std::vector< pair_type > vector_type; 21 | 22 | #ifdef WIN32 23 | 24 | #pragma optimize("", off) 25 | template 26 | void do_not_optimize_away(T&& datum) { 27 | datum = datum; 28 | } 29 | #pragma optimize("", on) 30 | 31 | #else 32 | static void do_not_optimize_away(void* p) { 33 | asm volatile("" : : "g"(p) : "memory"); 34 | } 35 | #endif 36 | 37 | void init(vector_type& vec); 38 | 39 | #define MYASSERT(value, expected) 40 | 41 | //#define MYASSERT(value, expected) if(value != expected) { std::cerr << value << " and expected:" << expected << " are different" << std::endl; } 42 | 43 | class timer 44 | { 45 | public: 46 | timer() = default; 47 | void start(const std::string& text_) 48 | { 49 | text = text_; 50 | begin = std::chrono::high_resolution_clock::now(); 51 | } 52 | void stop() 53 | { 54 | auto end = std::chrono::high_resolution_clock::now(); 55 | auto dur = end - begin; 56 | auto ms = std::chrono::duration_cast(dur).count(); 57 | std::cout << std::setw(19) << text << ":" << std::setw(5) << ms << "ms" << std::endl; 58 | } 59 | 60 | private: 61 | std::string text; 62 | std::chrono::high_resolution_clock::time_point begin; 63 | }; 64 | 65 | // Original crack_atof version is at http://crackprogramming.blogspot.sg/2012/10/implement-atof.html 66 | // But it cannot convert floating point with high +/- exponent. 67 | // The version below by Tian Bo fixes that problem and improves performance by 10% 68 | // http://coliru.stacked-crooked.com/a/2e28f0d71f47ca5e 69 | double pow10(int n) 70 | { 71 | double ret = 1.0; 72 | double r = 10.0; 73 | if (n < 0) { 74 | n = -n; 75 | r = 0.1; 76 | } 77 | 78 | while (n) { 79 | if (n & 1) { 80 | ret *= r; 81 | } 82 | r *= r; 83 | n >>= 1; 84 | } 85 | return ret; 86 | } 87 | 88 | double crack_atof(const char* num) 89 | { 90 | if (!num || !*num) { 91 | return 0; 92 | } 93 | 94 | int sign = 1; 95 | double integerPart = 0.0; 96 | double fractionPart = 0.0; 97 | bool hasFraction = false; 98 | bool hasExpo = false; 99 | 100 | // Take care of +/- sign 101 | if (*num == '-') { 102 | ++num; 103 | sign = -1; 104 | } 105 | else if (*num == '+') { 106 | ++num; 107 | } 108 | 109 | while (*num != '\0') { 110 | if (*num >= '0' && *num <= '9') { 111 | integerPart = integerPart * 10 + (*num - '0'); 112 | } 113 | else if (*num == '.') { 114 | hasFraction = true; 115 | ++num; 116 | break; 117 | } 118 | else if (*num == 'e') { 119 | hasExpo = true; 120 | ++num; 121 | break; 122 | } 123 | else { 124 | return sign * integerPart; 125 | } 126 | ++num; 127 | } 128 | 129 | if (hasFraction) { 130 | double fractionExpo = 0.1; 131 | 132 | while (*num != '\0') { 133 | if (*num >= '0' && *num <= '9') { 134 | fractionPart += fractionExpo * (*num - '0'); 135 | fractionExpo *= 0.1; 136 | } 137 | else if (*num == 'e') { 138 | hasExpo = true; 139 | ++num; 140 | break; 141 | } 142 | else { 143 | return sign * (integerPart + fractionPart); 144 | } 145 | ++num; 146 | } 147 | } 148 | 149 | // parsing exponet part 150 | double expPart = 1.0; 151 | if (*num != '\0' && hasExpo) { 152 | int expSign = 1; 153 | if (*num == '-') { 154 | expSign = -1; 155 | ++num; 156 | } 157 | else if (*num == '+') { 158 | ++num; 159 | } 160 | 161 | int e = 0; 162 | while (*num != '\0' && *num >= '0' && *num <= '9') { 163 | e = e * 10 + *num - '0'; 164 | ++num; 165 | } 166 | 167 | expPart = pow10(expSign * e); 168 | } 169 | 170 | return sign * (integerPart + fractionPart) * expPart; 171 | } 172 | 173 | 174 | #define white_space(c) ((c) == ' ' || (c) == '\t') 175 | #define valid_digit(c) ((c) >= '0' && (c) <= '9') 176 | // http://www.leapsecond.com/tools/fast_atof.c 177 | // Do not use this one because the converison is imprecise. 178 | double fast_atof(const char *p) 179 | { 180 | int frac; 181 | double sign, value, scale; 182 | 183 | // Skip leading white space, if any. 184 | 185 | while (white_space(*p)) { 186 | p += 1; 187 | } 188 | 189 | // Get sign, if any. 190 | 191 | sign = 1.0; 192 | if (*p == '-') { 193 | sign = -1.0; 194 | p += 1; 195 | 196 | } 197 | else if (*p == '+') { 198 | p += 1; 199 | } 200 | 201 | // Get digits before decimal point or exponent, if any. 202 | 203 | for (value = 0.0; valid_digit(*p); p += 1) { 204 | value = value * 10.0 + (*p - '0'); 205 | } 206 | 207 | // Get digits after decimal point, if any. 208 | 209 | if (*p == '.') { 210 | double pow10 = 10.0; 211 | p += 1; 212 | while (valid_digit(*p)) { 213 | value += (*p - '0') / pow10; 214 | pow10 *= 10.0; 215 | p += 1; 216 | } 217 | } 218 | 219 | // Handle exponent, if any. 220 | 221 | frac = 0; 222 | scale = 1.0; 223 | if ((*p == 'e') || (*p == 'E')) { 224 | unsigned int expon; 225 | 226 | // Get sign of exponent, if any. 227 | 228 | p += 1; 229 | if (*p == '-') { 230 | frac = 1; 231 | p += 1; 232 | 233 | } 234 | else if (*p == '+') { 235 | p += 1; 236 | } 237 | 238 | // Get digits of exponent, if any. 239 | 240 | for (expon = 0; valid_digit(*p); p += 1) { 241 | expon = expon * 10 + (*p - '0'); 242 | } 243 | if (expon > 308) expon = 308; 244 | 245 | // Calculate scaling factor. 246 | 247 | while (expon >= 50) { scale *= 1E50; expon -= 50; } 248 | while (expon >= 8) { scale *= 1E8; expon -= 8; } 249 | while (expon > 0) { scale *= 10.0; expon -= 1; } 250 | } 251 | 252 | // Return signed and scaled floating point result. 253 | 254 | return sign * (frac ? (value / scale) : (value * scale)); 255 | } 256 | int main(int argc, char *argv []) 257 | { 258 | const size_t MAX_LOOP = (argc == 2) ? atoi(argv[1]) : 100000; 259 | 260 | vector_type vec; 261 | init(vec); 262 | timer stopwatch; 263 | double d = 0.0; 264 | 265 | stopwatch.start("atof"); 266 | for (size_t k = 0; k(pr.first.c_str()); 285 | do_not_optimize_away(&d); 286 | MYASSERT(d, pr.second); 287 | } 288 | } 289 | stopwatch.stop(); 290 | 291 | stopwatch.start("std::istringstream"); 292 | for (size_t k = 0; k < MAX_LOOP; ++k) 293 | { 294 | for (size_t i = 0; i> d; 299 | do_not_optimize_away(&d); 300 | MYASSERT(d, pr.second); 301 | } 302 | } 303 | stopwatch.stop(); 304 | 305 | stopwatch.start("std::stod"); 306 | for (size_t k = 0; k < MAX_LOOP; ++k) 307 | { 308 | for (size_t i = 0; i 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3C355360-BE86-48B0-B3D0-192BE91E770B} 23 | BenchmarkFloatConv 24 | Win32Proj 25 | 10.0.17134.0 26 | 27 | 28 | 29 | Application 30 | v141 31 | Unicode 32 | true 33 | 34 | 35 | Application 36 | v141 37 | Unicode 38 | true 39 | 40 | 41 | Application 42 | v141 43 | Unicode 44 | 45 | 46 | Application 47 | v141 48 | Unicode 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>12.0.30501.0 68 | 69 | 70 | $(SolutionDir)$(Configuration)\ 71 | $(Configuration)\ 72 | true 73 | D:\boost_1_67_0;$(IncludePath) 74 | 75 | 76 | true 77 | D:\boost_1_67_0;$(IncludePath) 78 | 79 | 80 | $(SolutionDir)$(Configuration)\ 81 | $(Configuration)\ 82 | false 83 | D:\boost_1_67_0;$(IncludePath) 84 | 85 | 86 | false 87 | D:\boost_1_68_0;$(IncludePath) 88 | 89 | 90 | 91 | Disabled 92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | EnableFastChecks 95 | MultiThreadedDebugDLL 96 | NotUsing 97 | Level3 98 | EditAndContinue 99 | stdcpp17 100 | 101 | 102 | true 103 | Console 104 | MachineX86 105 | 106 | 107 | 108 | 109 | Disabled 110 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | EnableFastChecks 112 | MultiThreadedDebugDLL 113 | NotUsing 114 | Level3 115 | ProgramDatabase 116 | stdcpp17 117 | 118 | 119 | true 120 | Console 121 | 122 | 123 | 124 | 125 | MaxSpeed 126 | true 127 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | MultiThreadedDLL 129 | true 130 | NotUsing 131 | Level3 132 | ProgramDatabase 133 | Speed 134 | stdcpp17 135 | 136 | 137 | true 138 | Console 139 | true 140 | true 141 | MachineX86 142 | 143 | 144 | 145 | 146 | MaxSpeed 147 | true 148 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | MultiThreadedDLL 150 | true 151 | NotUsing 152 | Level3 153 | ProgramDatabase 154 | Speed 155 | stdcpp17 156 | 157 | 158 | true 159 | Console 160 | true 161 | true 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/BenchmarkFloatConv.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/Makefile: -------------------------------------------------------------------------------- 1 | # Project: MiniCSV 2 | 3 | CPP = clang++ -stdlib=libstdc++ -lstdc++ -std=c++11 4 | #CPP = g++ -lstdc++ -std=c++11 5 | CC = gcc 6 | OBJ = BenchmarkFloatConv.o $(RES) 7 | LINKOBJ = BenchmarkFloatConv.o $(RES) 8 | BIN = BenchmarkFloatConv 9 | CXXFLAGS = -Wall -g -O1 10 | CFLAGS = -Wall -g -O1 11 | RM = rm -f 12 | 13 | .PHONY: all all-before all-after clean clean-custom 14 | 15 | all: all-before BenchmarkFloatConv all-after 16 | 17 | clean: clean-custom 18 | ${RM} $(OBJ) $(BIN) 19 | 20 | $(BIN): $(OBJ) 21 | $(CPP) $(LINKOBJ) -o "BenchmarkFloatConv" $(LIBS) 22 | 23 | BenchmarkFloatConv.o: BenchmarkFloatConv.cpp 24 | $(CPP) -c BenchmarkFloatConv.cpp -o BenchmarkFloatConv.o $(CXXFLAGS) 25 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(headers 3 | bignum.h 4 | cached-powers.h 5 | diy-fp.h 6 | double-conversion.h 7 | fast-dtoa.h 8 | fixed-dtoa.h 9 | ieee.h 10 | strtod.h 11 | utils.h 12 | ) 13 | 14 | add_library(double-conversion 15 | bignum.cc 16 | bignum-dtoa.cc 17 | cached-powers.cc 18 | diy-fp.cc 19 | double-conversion.cc 20 | fast-dtoa.cc 21 | fixed-dtoa.cc 22 | strtod.cc 23 | ${headers} 24 | ) 25 | 26 | # 27 | # associates the list of headers with the library 28 | # for the purposes of installation/import into other projects 29 | set_target_properties(double-conversion 30 | PROPERTIES PUBLIC_HEADER "${headers}") 31 | 32 | # 33 | # install command to set up library install 34 | # given the above PUBLIC_HEADER property set, this 35 | # pulls along all the header files with the library. 36 | install(TARGETS double-conversion 37 | EXPORT double-conversionLibraryDepends 38 | RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin 39 | LIBRARY DESTINATION "${INSTALL_LIB_DIR}/lib" COMPONENT shlib 40 | ARCHIVE DESTINATION "${INSTALL_LIB_DIR}/lib" COMPONENT lib 41 | PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/include/double-conversion" 42 | COMPONENT dev) 43 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/SConscript: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | double_conversion_sources = [ 3 | 'bignum.cc', 4 | 'bignum-dtoa.cc', 5 | 'cached-powers.cc', 6 | 'diy-fp.cc', 7 | 'double-conversion.cc', 8 | 'fast-dtoa.cc', 9 | 'fixed-dtoa.cc', 10 | 'strtod.cc' 11 | ] 12 | Return('double_conversion_sources') 13 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/bignum-dtoa.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #include 29 | 30 | #include "bignum-dtoa.h" 31 | 32 | #include "bignum.h" 33 | #include "ieee.h" 34 | 35 | namespace double_conversion { 36 | 37 | static int NormalizedExponent(uint64_t significand, int exponent) { 38 | ASSERT(significand != 0); 39 | while ((significand & Double::kHiddenBit) == 0) { 40 | significand = significand << 1; 41 | exponent = exponent - 1; 42 | } 43 | return exponent; 44 | } 45 | 46 | 47 | // Forward declarations: 48 | // Returns an estimation of k such that 10^(k-1) <= v < 10^k. 49 | static int EstimatePower(int exponent); 50 | // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator 51 | // and denominator. 52 | static void InitialScaledStartValues(uint64_t significand, 53 | int exponent, 54 | bool lower_boundary_is_closer, 55 | int estimated_power, 56 | bool need_boundary_deltas, 57 | Bignum* numerator, 58 | Bignum* denominator, 59 | Bignum* delta_minus, 60 | Bignum* delta_plus); 61 | // Multiplies numerator/denominator so that its values lies in the range 1-10. 62 | // Returns decimal_point s.t. 63 | // v = numerator'/denominator' * 10^(decimal_point-1) 64 | // where numerator' and denominator' are the values of numerator and 65 | // denominator after the call to this function. 66 | static void FixupMultiply10(int estimated_power, bool is_even, 67 | int* decimal_point, 68 | Bignum* numerator, Bignum* denominator, 69 | Bignum* delta_minus, Bignum* delta_plus); 70 | // Generates digits from the left to the right and stops when the generated 71 | // digits yield the shortest decimal representation of v. 72 | static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, 73 | Bignum* delta_minus, Bignum* delta_plus, 74 | bool is_even, 75 | Vector buffer, int* length); 76 | // Generates 'requested_digits' after the decimal point. 77 | static void BignumToFixed(int requested_digits, int* decimal_point, 78 | Bignum* numerator, Bignum* denominator, 79 | Vector(buffer), int* length); 80 | // Generates 'count' digits of numerator/denominator. 81 | // Once 'count' digits have been produced rounds the result depending on the 82 | // remainder (remainders of exactly .5 round upwards). Might update the 83 | // decimal_point when rounding up (for example for 0.9999). 84 | static void GenerateCountedDigits(int count, int* decimal_point, 85 | Bignum* numerator, Bignum* denominator, 86 | Vector(buffer), int* length); 87 | 88 | 89 | void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, 90 | Vector buffer, int* length, int* decimal_point) { 91 | ASSERT(v > 0); 92 | ASSERT(!Double(v).IsSpecial()); 93 | uint64_t significand; 94 | int exponent; 95 | bool lower_boundary_is_closer; 96 | if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) { 97 | float f = static_cast(v); 98 | ASSERT(f == v); 99 | significand = Single(f).Significand(); 100 | exponent = Single(f).Exponent(); 101 | lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser(); 102 | } else { 103 | significand = Double(v).Significand(); 104 | exponent = Double(v).Exponent(); 105 | lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser(); 106 | } 107 | bool need_boundary_deltas = 108 | (mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE); 109 | 110 | bool is_even = (significand & 1) == 0; 111 | int normalized_exponent = NormalizedExponent(significand, exponent); 112 | // estimated_power might be too low by 1. 113 | int estimated_power = EstimatePower(normalized_exponent); 114 | 115 | // Shortcut for Fixed. 116 | // The requested digits correspond to the digits after the point. If the 117 | // number is much too small, then there is no need in trying to get any 118 | // digits. 119 | if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) { 120 | buffer[0] = '\0'; 121 | *length = 0; 122 | // Set decimal-point to -requested_digits. This is what Gay does. 123 | // Note that it should not have any effect anyways since the string is 124 | // empty. 125 | *decimal_point = -requested_digits; 126 | return; 127 | } 128 | 129 | Bignum numerator; 130 | Bignum denominator; 131 | Bignum delta_minus; 132 | Bignum delta_plus; 133 | // Make sure the bignum can grow large enough. The smallest double equals 134 | // 4e-324. In this case the denominator needs fewer than 324*4 binary digits. 135 | // The maximum double is 1.7976931348623157e308 which needs fewer than 136 | // 308*4 binary digits. 137 | ASSERT(Bignum::kMaxSignificantBits >= 324*4); 138 | InitialScaledStartValues(significand, exponent, lower_boundary_is_closer, 139 | estimated_power, need_boundary_deltas, 140 | &numerator, &denominator, 141 | &delta_minus, &delta_plus); 142 | // We now have v = (numerator / denominator) * 10^estimated_power. 143 | FixupMultiply10(estimated_power, is_even, decimal_point, 144 | &numerator, &denominator, 145 | &delta_minus, &delta_plus); 146 | // We now have v = (numerator / denominator) * 10^(decimal_point-1), and 147 | // 1 <= (numerator + delta_plus) / denominator < 10 148 | switch (mode) { 149 | case BIGNUM_DTOA_SHORTEST: 150 | case BIGNUM_DTOA_SHORTEST_SINGLE: 151 | GenerateShortestDigits(&numerator, &denominator, 152 | &delta_minus, &delta_plus, 153 | is_even, buffer, length); 154 | break; 155 | case BIGNUM_DTOA_FIXED: 156 | BignumToFixed(requested_digits, decimal_point, 157 | &numerator, &denominator, 158 | buffer, length); 159 | break; 160 | case BIGNUM_DTOA_PRECISION: 161 | GenerateCountedDigits(requested_digits, decimal_point, 162 | &numerator, &denominator, 163 | buffer, length); 164 | break; 165 | default: 166 | UNREACHABLE(); 167 | } 168 | buffer[*length] = '\0'; 169 | } 170 | 171 | 172 | // The procedure starts generating digits from the left to the right and stops 173 | // when the generated digits yield the shortest decimal representation of v. A 174 | // decimal representation of v is a number lying closer to v than to any other 175 | // double, so it converts to v when read. 176 | // 177 | // This is true if d, the decimal representation, is between m- and m+, the 178 | // upper and lower boundaries. d must be strictly between them if !is_even. 179 | // m- := (numerator - delta_minus) / denominator 180 | // m+ := (numerator + delta_plus) / denominator 181 | // 182 | // Precondition: 0 <= (numerator+delta_plus) / denominator < 10. 183 | // If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit 184 | // will be produced. This should be the standard precondition. 185 | static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, 186 | Bignum* delta_minus, Bignum* delta_plus, 187 | bool is_even, 188 | Vector buffer, int* length) { 189 | // Small optimization: if delta_minus and delta_plus are the same just reuse 190 | // one of the two bignums. 191 | if (Bignum::Equal(*delta_minus, *delta_plus)) { 192 | delta_plus = delta_minus; 193 | } 194 | *length = 0; 195 | for (;;) { 196 | uint16_t digit; 197 | digit = numerator->DivideModuloIntBignum(*denominator); 198 | ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. 199 | // digit = numerator / denominator (integer division). 200 | // numerator = numerator % denominator. 201 | buffer[(*length)++] = static_cast(digit + '0'); 202 | 203 | // Can we stop already? 204 | // If the remainder of the division is less than the distance to the lower 205 | // boundary we can stop. In this case we simply round down (discarding the 206 | // remainder). 207 | // Similarly we test if we can round up (using the upper boundary). 208 | bool in_delta_room_minus; 209 | bool in_delta_room_plus; 210 | if (is_even) { 211 | in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus); 212 | } else { 213 | in_delta_room_minus = Bignum::Less(*numerator, *delta_minus); 214 | } 215 | if (is_even) { 216 | in_delta_room_plus = 217 | Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; 218 | } else { 219 | in_delta_room_plus = 220 | Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; 221 | } 222 | if (!in_delta_room_minus && !in_delta_room_plus) { 223 | // Prepare for next iteration. 224 | numerator->Times10(); 225 | delta_minus->Times10(); 226 | // We optimized delta_plus to be equal to delta_minus (if they share the 227 | // same value). So don't multiply delta_plus if they point to the same 228 | // object. 229 | if (delta_minus != delta_plus) { 230 | delta_plus->Times10(); 231 | } 232 | } else if (in_delta_room_minus && in_delta_room_plus) { 233 | // Let's see if 2*numerator < denominator. 234 | // If yes, then the next digit would be < 5 and we can round down. 235 | int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator); 236 | if (compare < 0) { 237 | // Remaining digits are less than .5. -> Round down (== do nothing). 238 | } else if (compare > 0) { 239 | // Remaining digits are more than .5 of denominator. -> Round up. 240 | // Note that the last digit could not be a '9' as otherwise the whole 241 | // loop would have stopped earlier. 242 | // We still have an assert here in case the preconditions were not 243 | // satisfied. 244 | ASSERT(buffer[(*length) - 1] != '9'); 245 | buffer[(*length) - 1]++; 246 | } else { 247 | // Halfway case. 248 | // TODO(floitsch): need a way to solve half-way cases. 249 | // For now let's round towards even (since this is what Gay seems to 250 | // do). 251 | 252 | if ((buffer[(*length) - 1] - '0') % 2 == 0) { 253 | // Round down => Do nothing. 254 | } else { 255 | ASSERT(buffer[(*length) - 1] != '9'); 256 | buffer[(*length) - 1]++; 257 | } 258 | } 259 | return; 260 | } else if (in_delta_room_minus) { 261 | // Round down (== do nothing). 262 | return; 263 | } else { // in_delta_room_plus 264 | // Round up. 265 | // Note again that the last digit could not be '9' since this would have 266 | // stopped the loop earlier. 267 | // We still have an ASSERT here, in case the preconditions were not 268 | // satisfied. 269 | ASSERT(buffer[(*length) -1] != '9'); 270 | buffer[(*length) - 1]++; 271 | return; 272 | } 273 | } 274 | } 275 | 276 | 277 | // Let v = numerator / denominator < 10. 278 | // Then we generate 'count' digits of d = x.xxxxx... (without the decimal point) 279 | // from left to right. Once 'count' digits have been produced we decide wether 280 | // to round up or down. Remainders of exactly .5 round upwards. Numbers such 281 | // as 9.999999 propagate a carry all the way, and change the 282 | // exponent (decimal_point), when rounding upwards. 283 | static void GenerateCountedDigits(int count, int* decimal_point, 284 | Bignum* numerator, Bignum* denominator, 285 | Vector buffer, int* length) { 286 | ASSERT(count >= 0); 287 | for (int i = 0; i < count - 1; ++i) { 288 | uint16_t digit; 289 | digit = numerator->DivideModuloIntBignum(*denominator); 290 | ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. 291 | // digit = numerator / denominator (integer division). 292 | // numerator = numerator % denominator. 293 | buffer[i] = static_cast(digit + '0'); 294 | // Prepare for next iteration. 295 | numerator->Times10(); 296 | } 297 | // Generate the last digit. 298 | uint16_t digit; 299 | digit = numerator->DivideModuloIntBignum(*denominator); 300 | if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { 301 | digit++; 302 | } 303 | ASSERT(digit <= 10); 304 | buffer[count - 1] = static_cast(digit + '0'); 305 | // Correct bad digits (in case we had a sequence of '9's). Propagate the 306 | // carry until we hat a non-'9' or til we reach the first digit. 307 | for (int i = count - 1; i > 0; --i) { 308 | if (buffer[i] != '0' + 10) break; 309 | buffer[i] = '0'; 310 | buffer[i - 1]++; 311 | } 312 | if (buffer[0] == '0' + 10) { 313 | // Propagate a carry past the top place. 314 | buffer[0] = '1'; 315 | (*decimal_point)++; 316 | } 317 | *length = count; 318 | } 319 | 320 | 321 | // Generates 'requested_digits' after the decimal point. It might omit 322 | // trailing '0's. If the input number is too small then no digits at all are 323 | // generated (ex.: 2 fixed digits for 0.00001). 324 | // 325 | // Input verifies: 1 <= (numerator + delta) / denominator < 10. 326 | static void BignumToFixed(int requested_digits, int* decimal_point, 327 | Bignum* numerator, Bignum* denominator, 328 | Vector(buffer), int* length) { 329 | // Note that we have to look at more than just the requested_digits, since 330 | // a number could be rounded up. Example: v=0.5 with requested_digits=0. 331 | // Even though the power of v equals 0 we can't just stop here. 332 | if (-(*decimal_point) > requested_digits) { 333 | // The number is definitively too small. 334 | // Ex: 0.001 with requested_digits == 1. 335 | // Set decimal-point to -requested_digits. This is what Gay does. 336 | // Note that it should not have any effect anyways since the string is 337 | // empty. 338 | *decimal_point = -requested_digits; 339 | *length = 0; 340 | return; 341 | } else if (-(*decimal_point) == requested_digits) { 342 | // We only need to verify if the number rounds down or up. 343 | // Ex: 0.04 and 0.06 with requested_digits == 1. 344 | ASSERT(*decimal_point == -requested_digits); 345 | // Initially the fraction lies in range (1, 10]. Multiply the denominator 346 | // by 10 so that we can compare more easily. 347 | denominator->Times10(); 348 | if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { 349 | // If the fraction is >= 0.5 then we have to include the rounded 350 | // digit. 351 | buffer[0] = '1'; 352 | *length = 1; 353 | (*decimal_point)++; 354 | } else { 355 | // Note that we caught most of similar cases earlier. 356 | *length = 0; 357 | } 358 | return; 359 | } else { 360 | // The requested digits correspond to the digits after the point. 361 | // The variable 'needed_digits' includes the digits before the point. 362 | int needed_digits = (*decimal_point) + requested_digits; 363 | GenerateCountedDigits(needed_digits, decimal_point, 364 | numerator, denominator, 365 | buffer, length); 366 | } 367 | } 368 | 369 | 370 | // Returns an estimation of k such that 10^(k-1) <= v < 10^k where 371 | // v = f * 2^exponent and 2^52 <= f < 2^53. 372 | // v is hence a normalized double with the given exponent. The output is an 373 | // approximation for the exponent of the decimal approimation .digits * 10^k. 374 | // 375 | // The result might undershoot by 1 in which case 10^k <= v < 10^k+1. 376 | // Note: this property holds for v's upper boundary m+ too. 377 | // 10^k <= m+ < 10^k+1. 378 | // (see explanation below). 379 | // 380 | // Examples: 381 | // EstimatePower(0) => 16 382 | // EstimatePower(-52) => 0 383 | // 384 | // Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0. 385 | static int EstimatePower(int exponent) { 386 | // This function estimates log10 of v where v = f*2^e (with e == exponent). 387 | // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)). 388 | // Note that f is bounded by its container size. Let p = 53 (the double's 389 | // significand size). Then 2^(p-1) <= f < 2^p. 390 | // 391 | // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close 392 | // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)). 393 | // The computed number undershoots by less than 0.631 (when we compute log3 394 | // and not log10). 395 | // 396 | // Optimization: since we only need an approximated result this computation 397 | // can be performed on 64 bit integers. On x86/x64 architecture the speedup is 398 | // not really measurable, though. 399 | // 400 | // Since we want to avoid overshooting we decrement by 1e10 so that 401 | // floating-point imprecisions don't affect us. 402 | // 403 | // Explanation for v's boundary m+: the computation takes advantage of 404 | // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement 405 | // (even for denormals where the delta can be much more important). 406 | 407 | const double k1Log10 = 0.30102999566398114; // 1/lg(10) 408 | 409 | // For doubles len(f) == 53 (don't forget the hidden bit). 410 | const int kSignificandSize = Double::kSignificandSize; 411 | double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10); 412 | return static_cast(estimate); 413 | } 414 | 415 | 416 | // See comments for InitialScaledStartValues. 417 | static void InitialScaledStartValuesPositiveExponent( 418 | uint64_t significand, int exponent, 419 | int estimated_power, bool need_boundary_deltas, 420 | Bignum* numerator, Bignum* denominator, 421 | Bignum* delta_minus, Bignum* delta_plus) { 422 | // A positive exponent implies a positive power. 423 | ASSERT(estimated_power >= 0); 424 | // Since the estimated_power is positive we simply multiply the denominator 425 | // by 10^estimated_power. 426 | 427 | // numerator = v. 428 | numerator->AssignUInt64(significand); 429 | numerator->ShiftLeft(exponent); 430 | // denominator = 10^estimated_power. 431 | denominator->AssignPowerUInt16(10, estimated_power); 432 | 433 | if (need_boundary_deltas) { 434 | // Introduce a common denominator so that the deltas to the boundaries are 435 | // integers. 436 | denominator->ShiftLeft(1); 437 | numerator->ShiftLeft(1); 438 | // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common 439 | // denominator (of 2) delta_plus equals 2^e. 440 | delta_plus->AssignUInt16(1); 441 | delta_plus->ShiftLeft(exponent); 442 | // Same for delta_minus. The adjustments if f == 2^p-1 are done later. 443 | delta_minus->AssignUInt16(1); 444 | delta_minus->ShiftLeft(exponent); 445 | } 446 | } 447 | 448 | 449 | // See comments for InitialScaledStartValues 450 | static void InitialScaledStartValuesNegativeExponentPositivePower( 451 | uint64_t significand, int exponent, 452 | int estimated_power, bool need_boundary_deltas, 453 | Bignum* numerator, Bignum* denominator, 454 | Bignum* delta_minus, Bignum* delta_plus) { 455 | // v = f * 2^e with e < 0, and with estimated_power >= 0. 456 | // This means that e is close to 0 (have a look at how estimated_power is 457 | // computed). 458 | 459 | // numerator = significand 460 | // since v = significand * 2^exponent this is equivalent to 461 | // numerator = v * / 2^-exponent 462 | numerator->AssignUInt64(significand); 463 | // denominator = 10^estimated_power * 2^-exponent (with exponent < 0) 464 | denominator->AssignPowerUInt16(10, estimated_power); 465 | denominator->ShiftLeft(-exponent); 466 | 467 | if (need_boundary_deltas) { 468 | // Introduce a common denominator so that the deltas to the boundaries are 469 | // integers. 470 | denominator->ShiftLeft(1); 471 | numerator->ShiftLeft(1); 472 | // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common 473 | // denominator (of 2) delta_plus equals 2^e. 474 | // Given that the denominator already includes v's exponent the distance 475 | // to the boundaries is simply 1. 476 | delta_plus->AssignUInt16(1); 477 | // Same for delta_minus. The adjustments if f == 2^p-1 are done later. 478 | delta_minus->AssignUInt16(1); 479 | } 480 | } 481 | 482 | 483 | // See comments for InitialScaledStartValues 484 | static void InitialScaledStartValuesNegativeExponentNegativePower( 485 | uint64_t significand, int exponent, 486 | int estimated_power, bool need_boundary_deltas, 487 | Bignum* numerator, Bignum* denominator, 488 | Bignum* delta_minus, Bignum* delta_plus) { 489 | // Instead of multiplying the denominator with 10^estimated_power we 490 | // multiply all values (numerator and deltas) by 10^-estimated_power. 491 | 492 | // Use numerator as temporary container for power_ten. 493 | Bignum* power_ten = numerator; 494 | power_ten->AssignPowerUInt16(10, -estimated_power); 495 | 496 | if (need_boundary_deltas) { 497 | // Since power_ten == numerator we must make a copy of 10^estimated_power 498 | // before we complete the computation of the numerator. 499 | // delta_plus = delta_minus = 10^estimated_power 500 | delta_plus->AssignBignum(*power_ten); 501 | delta_minus->AssignBignum(*power_ten); 502 | } 503 | 504 | // numerator = significand * 2 * 10^-estimated_power 505 | // since v = significand * 2^exponent this is equivalent to 506 | // numerator = v * 10^-estimated_power * 2 * 2^-exponent. 507 | // Remember: numerator has been abused as power_ten. So no need to assign it 508 | // to itself. 509 | ASSERT(numerator == power_ten); 510 | numerator->MultiplyByUInt64(significand); 511 | 512 | // denominator = 2 * 2^-exponent with exponent < 0. 513 | denominator->AssignUInt16(1); 514 | denominator->ShiftLeft(-exponent); 515 | 516 | if (need_boundary_deltas) { 517 | // Introduce a common denominator so that the deltas to the boundaries are 518 | // integers. 519 | numerator->ShiftLeft(1); 520 | denominator->ShiftLeft(1); 521 | // With this shift the boundaries have their correct value, since 522 | // delta_plus = 10^-estimated_power, and 523 | // delta_minus = 10^-estimated_power. 524 | // These assignments have been done earlier. 525 | // The adjustments if f == 2^p-1 (lower boundary is closer) are done later. 526 | } 527 | } 528 | 529 | 530 | // Let v = significand * 2^exponent. 531 | // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator 532 | // and denominator. The functions GenerateShortestDigits and 533 | // GenerateCountedDigits will then convert this ratio to its decimal 534 | // representation d, with the required accuracy. 535 | // Then d * 10^estimated_power is the representation of v. 536 | // (Note: the fraction and the estimated_power might get adjusted before 537 | // generating the decimal representation.) 538 | // 539 | // The initial start values consist of: 540 | // - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power. 541 | // - a scaled (common) denominator. 542 | // optionally (used by GenerateShortestDigits to decide if it has the shortest 543 | // decimal converting back to v): 544 | // - v - m-: the distance to the lower boundary. 545 | // - m+ - v: the distance to the upper boundary. 546 | // 547 | // v, m+, m-, and therefore v - m- and m+ - v all share the same denominator. 548 | // 549 | // Let ep == estimated_power, then the returned values will satisfy: 550 | // v / 10^ep = numerator / denominator. 551 | // v's boundarys m- and m+: 552 | // m- / 10^ep == v / 10^ep - delta_minus / denominator 553 | // m+ / 10^ep == v / 10^ep + delta_plus / denominator 554 | // Or in other words: 555 | // m- == v - delta_minus * 10^ep / denominator; 556 | // m+ == v + delta_plus * 10^ep / denominator; 557 | // 558 | // Since 10^(k-1) <= v < 10^k (with k == estimated_power) 559 | // or 10^k <= v < 10^(k+1) 560 | // we then have 0.1 <= numerator/denominator < 1 561 | // or 1 <= numerator/denominator < 10 562 | // 563 | // It is then easy to kickstart the digit-generation routine. 564 | // 565 | // The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST 566 | // or BIGNUM_DTOA_SHORTEST_SINGLE. 567 | 568 | static void InitialScaledStartValues(uint64_t significand, 569 | int exponent, 570 | bool lower_boundary_is_closer, 571 | int estimated_power, 572 | bool need_boundary_deltas, 573 | Bignum* numerator, 574 | Bignum* denominator, 575 | Bignum* delta_minus, 576 | Bignum* delta_plus) { 577 | if (exponent >= 0) { 578 | InitialScaledStartValuesPositiveExponent( 579 | significand, exponent, estimated_power, need_boundary_deltas, 580 | numerator, denominator, delta_minus, delta_plus); 581 | } else if (estimated_power >= 0) { 582 | InitialScaledStartValuesNegativeExponentPositivePower( 583 | significand, exponent, estimated_power, need_boundary_deltas, 584 | numerator, denominator, delta_minus, delta_plus); 585 | } else { 586 | InitialScaledStartValuesNegativeExponentNegativePower( 587 | significand, exponent, estimated_power, need_boundary_deltas, 588 | numerator, denominator, delta_minus, delta_plus); 589 | } 590 | 591 | if (need_boundary_deltas && lower_boundary_is_closer) { 592 | // The lower boundary is closer at half the distance of "normal" numbers. 593 | // Increase the common denominator and adapt all but the delta_minus. 594 | denominator->ShiftLeft(1); // *2 595 | numerator->ShiftLeft(1); // *2 596 | delta_plus->ShiftLeft(1); // *2 597 | } 598 | } 599 | 600 | 601 | // This routine multiplies numerator/denominator so that its values lies in the 602 | // range 1-10. That is after a call to this function we have: 603 | // 1 <= (numerator + delta_plus) /denominator < 10. 604 | // Let numerator the input before modification and numerator' the argument 605 | // after modification, then the output-parameter decimal_point is such that 606 | // numerator / denominator * 10^estimated_power == 607 | // numerator' / denominator' * 10^(decimal_point - 1) 608 | // In some cases estimated_power was too low, and this is already the case. We 609 | // then simply adjust the power so that 10^(k-1) <= v < 10^k (with k == 610 | // estimated_power) but do not touch the numerator or denominator. 611 | // Otherwise the routine multiplies the numerator and the deltas by 10. 612 | static void FixupMultiply10(int estimated_power, bool is_even, 613 | int* decimal_point, 614 | Bignum* numerator, Bignum* denominator, 615 | Bignum* delta_minus, Bignum* delta_plus) { 616 | bool in_range; 617 | if (is_even) { 618 | // For IEEE doubles half-way cases (in decimal system numbers ending with 5) 619 | // are rounded to the closest floating-point number with even significand. 620 | in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; 621 | } else { 622 | in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; 623 | } 624 | if (in_range) { 625 | // Since numerator + delta_plus >= denominator we already have 626 | // 1 <= numerator/denominator < 10. Simply update the estimated_power. 627 | *decimal_point = estimated_power + 1; 628 | } else { 629 | *decimal_point = estimated_power; 630 | numerator->Times10(); 631 | if (Bignum::Equal(*delta_minus, *delta_plus)) { 632 | delta_minus->Times10(); 633 | delta_plus->AssignBignum(*delta_minus); 634 | } else { 635 | delta_minus->Times10(); 636 | delta_plus->Times10(); 637 | } 638 | } 639 | } 640 | 641 | } // namespace double_conversion 642 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/bignum-dtoa.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_ 29 | #define DOUBLE_CONVERSION_BIGNUM_DTOA_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | enum BignumDtoaMode { 36 | // Return the shortest correct representation. 37 | // For example the output of 0.299999999999999988897 is (the less accurate but 38 | // correct) 0.3. 39 | BIGNUM_DTOA_SHORTEST, 40 | // Same as BIGNUM_DTOA_SHORTEST but for single-precision floats. 41 | BIGNUM_DTOA_SHORTEST_SINGLE, 42 | // Return a fixed number of digits after the decimal point. 43 | // For instance fixed(0.1, 4) becomes 0.1000 44 | // If the input number is big, the output will be big. 45 | BIGNUM_DTOA_FIXED, 46 | // Return a fixed number of digits, no matter what the exponent is. 47 | BIGNUM_DTOA_PRECISION 48 | }; 49 | 50 | // Converts the given double 'v' to ascii. 51 | // The result should be interpreted as buffer * 10^(point-length). 52 | // The buffer will be null-terminated. 53 | // 54 | // The input v must be > 0 and different from NaN, and Infinity. 55 | // 56 | // The output depends on the given mode: 57 | // - SHORTEST: produce the least amount of digits for which the internal 58 | // identity requirement is still satisfied. If the digits are printed 59 | // (together with the correct exponent) then reading this number will give 60 | // 'v' again. The buffer will choose the representation that is closest to 61 | // 'v'. If there are two at the same distance, than the number is round up. 62 | // In this mode the 'requested_digits' parameter is ignored. 63 | // - FIXED: produces digits necessary to print a given number with 64 | // 'requested_digits' digits after the decimal point. The produced digits 65 | // might be too short in which case the caller has to fill the gaps with '0's. 66 | // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. 67 | // Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns 68 | // buffer="2", point=0. 69 | // Note: the length of the returned buffer has no meaning wrt the significance 70 | // of its digits. That is, just because it contains '0's does not mean that 71 | // any other digit would not satisfy the internal identity requirement. 72 | // - PRECISION: produces 'requested_digits' where the first digit is not '0'. 73 | // Even though the length of produced digits usually equals 74 | // 'requested_digits', the function is allowed to return fewer digits, in 75 | // which case the caller has to fill the missing digits with '0's. 76 | // Halfway cases are again rounded up. 77 | // 'BignumDtoa' expects the given buffer to be big enough to hold all digits 78 | // and a terminating null-character. 79 | void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, 80 | Vector buffer, int* length, int* point); 81 | 82 | } // namespace double_conversion 83 | 84 | #endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_ 85 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/bignum.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #include "bignum.h" 29 | #include "utils.h" 30 | 31 | namespace double_conversion { 32 | 33 | Bignum::Bignum() 34 | : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { 35 | for (int i = 0; i < kBigitCapacity; ++i) { 36 | bigits_[i] = 0; 37 | } 38 | } 39 | 40 | 41 | template 42 | static int BitSize(S value) { 43 | (void) value; // Mark variable as used. 44 | return 8 * sizeof(value); 45 | } 46 | 47 | // Guaranteed to lie in one Bigit. 48 | void Bignum::AssignUInt16(uint16_t value) { 49 | ASSERT(kBigitSize >= BitSize(value)); 50 | Zero(); 51 | if (value == 0) return; 52 | 53 | EnsureCapacity(1); 54 | bigits_[0] = value; 55 | used_digits_ = 1; 56 | } 57 | 58 | 59 | void Bignum::AssignUInt64(uint64_t value) { 60 | const int kUInt64Size = 64; 61 | 62 | Zero(); 63 | if (value == 0) return; 64 | 65 | int needed_bigits = kUInt64Size / kBigitSize + 1; 66 | EnsureCapacity(needed_bigits); 67 | for (int i = 0; i < needed_bigits; ++i) { 68 | bigits_[i] = value & kBigitMask; 69 | value = value >> kBigitSize; 70 | } 71 | used_digits_ = needed_bigits; 72 | Clamp(); 73 | } 74 | 75 | 76 | void Bignum::AssignBignum(const Bignum& other) { 77 | exponent_ = other.exponent_; 78 | for (int i = 0; i < other.used_digits_; ++i) { 79 | bigits_[i] = other.bigits_[i]; 80 | } 81 | // Clear the excess digits (if there were any). 82 | for (int i = other.used_digits_; i < used_digits_; ++i) { 83 | bigits_[i] = 0; 84 | } 85 | used_digits_ = other.used_digits_; 86 | } 87 | 88 | 89 | static uint64_t ReadUInt64(Vector buffer, 90 | int from, 91 | int digits_to_read) { 92 | uint64_t result = 0; 93 | for (int i = from; i < from + digits_to_read; ++i) { 94 | int digit = buffer[i] - '0'; 95 | ASSERT(0 <= digit && digit <= 9); 96 | result = result * 10 + digit; 97 | } 98 | return result; 99 | } 100 | 101 | 102 | void Bignum::AssignDecimalString(Vector value) { 103 | // 2^64 = 18446744073709551616 > 10^19 104 | const int kMaxUint64DecimalDigits = 19; 105 | Zero(); 106 | int length = value.length(); 107 | int pos = 0; 108 | // Let's just say that each digit needs 4 bits. 109 | while (length >= kMaxUint64DecimalDigits) { 110 | uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); 111 | pos += kMaxUint64DecimalDigits; 112 | length -= kMaxUint64DecimalDigits; 113 | MultiplyByPowerOfTen(kMaxUint64DecimalDigits); 114 | AddUInt64(digits); 115 | } 116 | uint64_t digits = ReadUInt64(value, pos, length); 117 | MultiplyByPowerOfTen(length); 118 | AddUInt64(digits); 119 | Clamp(); 120 | } 121 | 122 | 123 | static int HexCharValue(char c) { 124 | if ('0' <= c && c <= '9') return c - '0'; 125 | if ('a' <= c && c <= 'f') return 10 + c - 'a'; 126 | ASSERT('A' <= c && c <= 'F'); 127 | return 10 + c - 'A'; 128 | } 129 | 130 | 131 | void Bignum::AssignHexString(Vector value) { 132 | Zero(); 133 | int length = value.length(); 134 | 135 | int needed_bigits = length * 4 / kBigitSize + 1; 136 | EnsureCapacity(needed_bigits); 137 | int string_index = length - 1; 138 | for (int i = 0; i < needed_bigits - 1; ++i) { 139 | // These bigits are guaranteed to be "full". 140 | Chunk current_bigit = 0; 141 | for (int j = 0; j < kBigitSize / 4; j++) { 142 | current_bigit += HexCharValue(value[string_index--]) << (j * 4); 143 | } 144 | bigits_[i] = current_bigit; 145 | } 146 | used_digits_ = needed_bigits - 1; 147 | 148 | Chunk most_significant_bigit = 0; // Could be = 0; 149 | for (int j = 0; j <= string_index; ++j) { 150 | most_significant_bigit <<= 4; 151 | most_significant_bigit += HexCharValue(value[j]); 152 | } 153 | if (most_significant_bigit != 0) { 154 | bigits_[used_digits_] = most_significant_bigit; 155 | used_digits_++; 156 | } 157 | Clamp(); 158 | } 159 | 160 | 161 | void Bignum::AddUInt64(uint64_t operand) { 162 | if (operand == 0) return; 163 | Bignum other; 164 | other.AssignUInt64(operand); 165 | AddBignum(other); 166 | } 167 | 168 | 169 | void Bignum::AddBignum(const Bignum& other) { 170 | ASSERT(IsClamped()); 171 | ASSERT(other.IsClamped()); 172 | 173 | // If this has a greater exponent than other append zero-bigits to this. 174 | // After this call exponent_ <= other.exponent_. 175 | Align(other); 176 | 177 | // There are two possibilities: 178 | // aaaaaaaaaaa 0000 (where the 0s represent a's exponent) 179 | // bbbbb 00000000 180 | // ---------------- 181 | // ccccccccccc 0000 182 | // or 183 | // aaaaaaaaaa 0000 184 | // bbbbbbbbb 0000000 185 | // ----------------- 186 | // cccccccccccc 0000 187 | // In both cases we might need a carry bigit. 188 | 189 | EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); 190 | Chunk carry = 0; 191 | int bigit_pos = other.exponent_ - exponent_; 192 | ASSERT(bigit_pos >= 0); 193 | for (int i = 0; i < other.used_digits_; ++i) { 194 | Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; 195 | bigits_[bigit_pos] = sum & kBigitMask; 196 | carry = sum >> kBigitSize; 197 | bigit_pos++; 198 | } 199 | 200 | while (carry != 0) { 201 | Chunk sum = bigits_[bigit_pos] + carry; 202 | bigits_[bigit_pos] = sum & kBigitMask; 203 | carry = sum >> kBigitSize; 204 | bigit_pos++; 205 | } 206 | used_digits_ = Max(bigit_pos, used_digits_); 207 | ASSERT(IsClamped()); 208 | } 209 | 210 | 211 | void Bignum::SubtractBignum(const Bignum& other) { 212 | ASSERT(IsClamped()); 213 | ASSERT(other.IsClamped()); 214 | // We require this to be bigger than other. 215 | ASSERT(LessEqual(other, *this)); 216 | 217 | Align(other); 218 | 219 | int offset = other.exponent_ - exponent_; 220 | Chunk borrow = 0; 221 | int i; 222 | for (i = 0; i < other.used_digits_; ++i) { 223 | ASSERT((borrow == 0) || (borrow == 1)); 224 | Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; 225 | bigits_[i + offset] = difference & kBigitMask; 226 | borrow = difference >> (kChunkSize - 1); 227 | } 228 | while (borrow != 0) { 229 | Chunk difference = bigits_[i + offset] - borrow; 230 | bigits_[i + offset] = difference & kBigitMask; 231 | borrow = difference >> (kChunkSize - 1); 232 | ++i; 233 | } 234 | Clamp(); 235 | } 236 | 237 | 238 | void Bignum::ShiftLeft(int shift_amount) { 239 | if (used_digits_ == 0) return; 240 | exponent_ += shift_amount / kBigitSize; 241 | int local_shift = shift_amount % kBigitSize; 242 | EnsureCapacity(used_digits_ + 1); 243 | BigitsShiftLeft(local_shift); 244 | } 245 | 246 | 247 | void Bignum::MultiplyByUInt32(uint32_t factor) { 248 | if (factor == 1) return; 249 | if (factor == 0) { 250 | Zero(); 251 | return; 252 | } 253 | if (used_digits_ == 0) return; 254 | 255 | // The product of a bigit with the factor is of size kBigitSize + 32. 256 | // Assert that this number + 1 (for the carry) fits into double chunk. 257 | ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); 258 | DoubleChunk carry = 0; 259 | for (int i = 0; i < used_digits_; ++i) { 260 | DoubleChunk product = static_cast(factor) * bigits_[i] + carry; 261 | bigits_[i] = static_cast(product & kBigitMask); 262 | carry = (product >> kBigitSize); 263 | } 264 | while (carry != 0) { 265 | EnsureCapacity(used_digits_ + 1); 266 | bigits_[used_digits_] = carry & kBigitMask; 267 | used_digits_++; 268 | carry >>= kBigitSize; 269 | } 270 | } 271 | 272 | 273 | void Bignum::MultiplyByUInt64(uint64_t factor) { 274 | if (factor == 1) return; 275 | if (factor == 0) { 276 | Zero(); 277 | return; 278 | } 279 | ASSERT(kBigitSize < 32); 280 | uint64_t carry = 0; 281 | uint64_t low = factor & 0xFFFFFFFF; 282 | uint64_t high = factor >> 32; 283 | for (int i = 0; i < used_digits_; ++i) { 284 | uint64_t product_low = low * bigits_[i]; 285 | uint64_t product_high = high * bigits_[i]; 286 | uint64_t tmp = (carry & kBigitMask) + product_low; 287 | bigits_[i] = tmp & kBigitMask; 288 | carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + 289 | (product_high << (32 - kBigitSize)); 290 | } 291 | while (carry != 0) { 292 | EnsureCapacity(used_digits_ + 1); 293 | bigits_[used_digits_] = carry & kBigitMask; 294 | used_digits_++; 295 | carry >>= kBigitSize; 296 | } 297 | } 298 | 299 | 300 | void Bignum::MultiplyByPowerOfTen(int exponent) { 301 | const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); 302 | const uint16_t kFive1 = 5; 303 | const uint16_t kFive2 = kFive1 * 5; 304 | const uint16_t kFive3 = kFive2 * 5; 305 | const uint16_t kFive4 = kFive3 * 5; 306 | const uint16_t kFive5 = kFive4 * 5; 307 | const uint16_t kFive6 = kFive5 * 5; 308 | const uint32_t kFive7 = kFive6 * 5; 309 | const uint32_t kFive8 = kFive7 * 5; 310 | const uint32_t kFive9 = kFive8 * 5; 311 | const uint32_t kFive10 = kFive9 * 5; 312 | const uint32_t kFive11 = kFive10 * 5; 313 | const uint32_t kFive12 = kFive11 * 5; 314 | const uint32_t kFive13 = kFive12 * 5; 315 | const uint32_t kFive1_to_12[] = 316 | { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, 317 | kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; 318 | 319 | ASSERT(exponent >= 0); 320 | if (exponent == 0) return; 321 | if (used_digits_ == 0) return; 322 | 323 | // We shift by exponent at the end just before returning. 324 | int remaining_exponent = exponent; 325 | while (remaining_exponent >= 27) { 326 | MultiplyByUInt64(kFive27); 327 | remaining_exponent -= 27; 328 | } 329 | while (remaining_exponent >= 13) { 330 | MultiplyByUInt32(kFive13); 331 | remaining_exponent -= 13; 332 | } 333 | if (remaining_exponent > 0) { 334 | MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); 335 | } 336 | ShiftLeft(exponent); 337 | } 338 | 339 | 340 | void Bignum::Square() { 341 | ASSERT(IsClamped()); 342 | int product_length = 2 * used_digits_; 343 | EnsureCapacity(product_length); 344 | 345 | // Comba multiplication: compute each column separately. 346 | // Example: r = a2a1a0 * b2b1b0. 347 | // r = 1 * a0b0 + 348 | // 10 * (a1b0 + a0b1) + 349 | // 100 * (a2b0 + a1b1 + a0b2) + 350 | // 1000 * (a2b1 + a1b2) + 351 | // 10000 * a2b2 352 | // 353 | // In the worst case we have to accumulate nb-digits products of digit*digit. 354 | // 355 | // Assert that the additional number of bits in a DoubleChunk are enough to 356 | // sum up used_digits of Bigit*Bigit. 357 | if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { 358 | UNIMPLEMENTED(); 359 | } 360 | DoubleChunk accumulator = 0; 361 | // First shift the digits so we don't overwrite them. 362 | int copy_offset = used_digits_; 363 | for (int i = 0; i < used_digits_; ++i) { 364 | bigits_[copy_offset + i] = bigits_[i]; 365 | } 366 | // We have two loops to avoid some 'if's in the loop. 367 | for (int i = 0; i < used_digits_; ++i) { 368 | // Process temporary digit i with power i. 369 | // The sum of the two indices must be equal to i. 370 | int bigit_index1 = i; 371 | int bigit_index2 = 0; 372 | // Sum all of the sub-products. 373 | while (bigit_index1 >= 0) { 374 | Chunk chunk1 = bigits_[copy_offset + bigit_index1]; 375 | Chunk chunk2 = bigits_[copy_offset + bigit_index2]; 376 | accumulator += static_cast(chunk1) * chunk2; 377 | bigit_index1--; 378 | bigit_index2++; 379 | } 380 | bigits_[i] = static_cast(accumulator) & kBigitMask; 381 | accumulator >>= kBigitSize; 382 | } 383 | for (int i = used_digits_; i < product_length; ++i) { 384 | int bigit_index1 = used_digits_ - 1; 385 | int bigit_index2 = i - bigit_index1; 386 | // Invariant: sum of both indices is again equal to i. 387 | // Inner loop runs 0 times on last iteration, emptying accumulator. 388 | while (bigit_index2 < used_digits_) { 389 | Chunk chunk1 = bigits_[copy_offset + bigit_index1]; 390 | Chunk chunk2 = bigits_[copy_offset + bigit_index2]; 391 | accumulator += static_cast(chunk1) * chunk2; 392 | bigit_index1--; 393 | bigit_index2++; 394 | } 395 | // The overwritten bigits_[i] will never be read in further loop iterations, 396 | // because bigit_index1 and bigit_index2 are always greater 397 | // than i - used_digits_. 398 | bigits_[i] = static_cast(accumulator) & kBigitMask; 399 | accumulator >>= kBigitSize; 400 | } 401 | // Since the result was guaranteed to lie inside the number the 402 | // accumulator must be 0 now. 403 | ASSERT(accumulator == 0); 404 | 405 | // Don't forget to update the used_digits and the exponent. 406 | used_digits_ = product_length; 407 | exponent_ *= 2; 408 | Clamp(); 409 | } 410 | 411 | 412 | void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { 413 | ASSERT(base != 0); 414 | ASSERT(power_exponent >= 0); 415 | if (power_exponent == 0) { 416 | AssignUInt16(1); 417 | return; 418 | } 419 | Zero(); 420 | int shifts = 0; 421 | // We expect base to be in range 2-32, and most often to be 10. 422 | // It does not make much sense to implement different algorithms for counting 423 | // the bits. 424 | while ((base & 1) == 0) { 425 | base >>= 1; 426 | shifts++; 427 | } 428 | int bit_size = 0; 429 | int tmp_base = base; 430 | while (tmp_base != 0) { 431 | tmp_base >>= 1; 432 | bit_size++; 433 | } 434 | int final_size = bit_size * power_exponent; 435 | // 1 extra bigit for the shifting, and one for rounded final_size. 436 | EnsureCapacity(final_size / kBigitSize + 2); 437 | 438 | // Left to Right exponentiation. 439 | int mask = 1; 440 | while (power_exponent >= mask) mask <<= 1; 441 | 442 | // The mask is now pointing to the bit above the most significant 1-bit of 443 | // power_exponent. 444 | // Get rid of first 1-bit; 445 | mask >>= 2; 446 | uint64_t this_value = base; 447 | 448 | bool delayed_multipliciation = false; 449 | const uint64_t max_32bits = 0xFFFFFFFF; 450 | while (mask != 0 && this_value <= max_32bits) { 451 | this_value = this_value * this_value; 452 | // Verify that there is enough space in this_value to perform the 453 | // multiplication. The first bit_size bits must be 0. 454 | if ((power_exponent & mask) != 0) { 455 | uint64_t base_bits_mask = 456 | ~((static_cast(1) << (64 - bit_size)) - 1); 457 | bool high_bits_zero = (this_value & base_bits_mask) == 0; 458 | if (high_bits_zero) { 459 | this_value *= base; 460 | } else { 461 | delayed_multipliciation = true; 462 | } 463 | } 464 | mask >>= 1; 465 | } 466 | AssignUInt64(this_value); 467 | if (delayed_multipliciation) { 468 | MultiplyByUInt32(base); 469 | } 470 | 471 | // Now do the same thing as a bignum. 472 | while (mask != 0) { 473 | Square(); 474 | if ((power_exponent & mask) != 0) { 475 | MultiplyByUInt32(base); 476 | } 477 | mask >>= 1; 478 | } 479 | 480 | // And finally add the saved shifts. 481 | ShiftLeft(shifts * power_exponent); 482 | } 483 | 484 | 485 | // Precondition: this/other < 16bit. 486 | uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { 487 | ASSERT(IsClamped()); 488 | ASSERT(other.IsClamped()); 489 | ASSERT(other.used_digits_ > 0); 490 | 491 | // Easy case: if we have less digits than the divisor than the result is 0. 492 | // Note: this handles the case where this == 0, too. 493 | if (BigitLength() < other.BigitLength()) { 494 | return 0; 495 | } 496 | 497 | Align(other); 498 | 499 | uint16_t result = 0; 500 | 501 | // Start by removing multiples of 'other' until both numbers have the same 502 | // number of digits. 503 | while (BigitLength() > other.BigitLength()) { 504 | // This naive approach is extremely inefficient if `this` divided by other 505 | // is big. This function is implemented for doubleToString where 506 | // the result should be small (less than 10). 507 | ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); 508 | ASSERT(bigits_[used_digits_ - 1] < 0x10000); 509 | // Remove the multiples of the first digit. 510 | // Example this = 23 and other equals 9. -> Remove 2 multiples. 511 | result += static_cast(bigits_[used_digits_ - 1]); 512 | SubtractTimes(other, bigits_[used_digits_ - 1]); 513 | } 514 | 515 | ASSERT(BigitLength() == other.BigitLength()); 516 | 517 | // Both bignums are at the same length now. 518 | // Since other has more than 0 digits we know that the access to 519 | // bigits_[used_digits_ - 1] is safe. 520 | Chunk this_bigit = bigits_[used_digits_ - 1]; 521 | Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; 522 | 523 | if (other.used_digits_ == 1) { 524 | // Shortcut for easy (and common) case. 525 | int quotient = this_bigit / other_bigit; 526 | bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; 527 | ASSERT(quotient < 0x10000); 528 | result += static_cast(quotient); 529 | Clamp(); 530 | return result; 531 | } 532 | 533 | int division_estimate = this_bigit / (other_bigit + 1); 534 | ASSERT(division_estimate < 0x10000); 535 | result += static_cast(division_estimate); 536 | SubtractTimes(other, division_estimate); 537 | 538 | if (other_bigit * (division_estimate + 1) > this_bigit) { 539 | // No need to even try to subtract. Even if other's remaining digits were 0 540 | // another subtraction would be too much. 541 | return result; 542 | } 543 | 544 | while (LessEqual(other, *this)) { 545 | SubtractBignum(other); 546 | result++; 547 | } 548 | return result; 549 | } 550 | 551 | 552 | template 553 | static int SizeInHexChars(S number) { 554 | ASSERT(number > 0); 555 | int result = 0; 556 | while (number != 0) { 557 | number >>= 4; 558 | result++; 559 | } 560 | return result; 561 | } 562 | 563 | 564 | static char HexCharOfValue(int value) { 565 | ASSERT(0 <= value && value <= 16); 566 | if (value < 10) return static_cast(value + '0'); 567 | return static_cast(value - 10 + 'A'); 568 | } 569 | 570 | 571 | bool Bignum::ToHexString(char* buffer, int buffer_size) const { 572 | ASSERT(IsClamped()); 573 | // Each bigit must be printable as separate hex-character. 574 | ASSERT(kBigitSize % 4 == 0); 575 | const int kHexCharsPerBigit = kBigitSize / 4; 576 | 577 | if (used_digits_ == 0) { 578 | if (buffer_size < 2) return false; 579 | buffer[0] = '0'; 580 | buffer[1] = '\0'; 581 | return true; 582 | } 583 | // We add 1 for the terminating '\0' character. 584 | int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + 585 | SizeInHexChars(bigits_[used_digits_ - 1]) + 1; 586 | if (needed_chars > buffer_size) return false; 587 | int string_index = needed_chars - 1; 588 | buffer[string_index--] = '\0'; 589 | for (int i = 0; i < exponent_; ++i) { 590 | for (int j = 0; j < kHexCharsPerBigit; ++j) { 591 | buffer[string_index--] = '0'; 592 | } 593 | } 594 | for (int i = 0; i < used_digits_ - 1; ++i) { 595 | Chunk current_bigit = bigits_[i]; 596 | for (int j = 0; j < kHexCharsPerBigit; ++j) { 597 | buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); 598 | current_bigit >>= 4; 599 | } 600 | } 601 | // And finally the last bigit. 602 | Chunk most_significant_bigit = bigits_[used_digits_ - 1]; 603 | while (most_significant_bigit != 0) { 604 | buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); 605 | most_significant_bigit >>= 4; 606 | } 607 | return true; 608 | } 609 | 610 | 611 | Bignum::Chunk Bignum::BigitAt(int index) const { 612 | if (index >= BigitLength()) return 0; 613 | if (index < exponent_) return 0; 614 | return bigits_[index - exponent_]; 615 | } 616 | 617 | 618 | int Bignum::Compare(const Bignum& a, const Bignum& b) { 619 | ASSERT(a.IsClamped()); 620 | ASSERT(b.IsClamped()); 621 | int bigit_length_a = a.BigitLength(); 622 | int bigit_length_b = b.BigitLength(); 623 | if (bigit_length_a < bigit_length_b) return -1; 624 | if (bigit_length_a > bigit_length_b) return +1; 625 | for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { 626 | Chunk bigit_a = a.BigitAt(i); 627 | Chunk bigit_b = b.BigitAt(i); 628 | if (bigit_a < bigit_b) return -1; 629 | if (bigit_a > bigit_b) return +1; 630 | // Otherwise they are equal up to this digit. Try the next digit. 631 | } 632 | return 0; 633 | } 634 | 635 | 636 | int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { 637 | ASSERT(a.IsClamped()); 638 | ASSERT(b.IsClamped()); 639 | ASSERT(c.IsClamped()); 640 | if (a.BigitLength() < b.BigitLength()) { 641 | return PlusCompare(b, a, c); 642 | } 643 | if (a.BigitLength() + 1 < c.BigitLength()) return -1; 644 | if (a.BigitLength() > c.BigitLength()) return +1; 645 | // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than 646 | // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one 647 | // of 'a'. 648 | if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { 649 | return -1; 650 | } 651 | 652 | Chunk borrow = 0; 653 | // Starting at min_exponent all digits are == 0. So no need to compare them. 654 | int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); 655 | for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { 656 | Chunk chunk_a = a.BigitAt(i); 657 | Chunk chunk_b = b.BigitAt(i); 658 | Chunk chunk_c = c.BigitAt(i); 659 | Chunk sum = chunk_a + chunk_b; 660 | if (sum > chunk_c + borrow) { 661 | return +1; 662 | } else { 663 | borrow = chunk_c + borrow - sum; 664 | if (borrow > 1) return -1; 665 | borrow <<= kBigitSize; 666 | } 667 | } 668 | if (borrow == 0) return 0; 669 | return -1; 670 | } 671 | 672 | 673 | void Bignum::Clamp() { 674 | while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { 675 | used_digits_--; 676 | } 677 | if (used_digits_ == 0) { 678 | // Zero. 679 | exponent_ = 0; 680 | } 681 | } 682 | 683 | 684 | bool Bignum::IsClamped() const { 685 | return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; 686 | } 687 | 688 | 689 | void Bignum::Zero() { 690 | for (int i = 0; i < used_digits_; ++i) { 691 | bigits_[i] = 0; 692 | } 693 | used_digits_ = 0; 694 | exponent_ = 0; 695 | } 696 | 697 | 698 | void Bignum::Align(const Bignum& other) { 699 | if (exponent_ > other.exponent_) { 700 | // If "X" represents a "hidden" digit (by the exponent) then we are in the 701 | // following case (a == this, b == other): 702 | // a: aaaaaaXXXX or a: aaaaaXXX 703 | // b: bbbbbbX b: bbbbbbbbXX 704 | // We replace some of the hidden digits (X) of a with 0 digits. 705 | // a: aaaaaa000X or a: aaaaa0XX 706 | int zero_digits = exponent_ - other.exponent_; 707 | EnsureCapacity(used_digits_ + zero_digits); 708 | for (int i = used_digits_ - 1; i >= 0; --i) { 709 | bigits_[i + zero_digits] = bigits_[i]; 710 | } 711 | for (int i = 0; i < zero_digits; ++i) { 712 | bigits_[i] = 0; 713 | } 714 | used_digits_ += zero_digits; 715 | exponent_ -= zero_digits; 716 | ASSERT(used_digits_ >= 0); 717 | ASSERT(exponent_ >= 0); 718 | } 719 | } 720 | 721 | 722 | void Bignum::BigitsShiftLeft(int shift_amount) { 723 | ASSERT(shift_amount < kBigitSize); 724 | ASSERT(shift_amount >= 0); 725 | Chunk carry = 0; 726 | for (int i = 0; i < used_digits_; ++i) { 727 | Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); 728 | bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; 729 | carry = new_carry; 730 | } 731 | if (carry != 0) { 732 | bigits_[used_digits_] = carry; 733 | used_digits_++; 734 | } 735 | } 736 | 737 | 738 | void Bignum::SubtractTimes(const Bignum& other, int factor) { 739 | ASSERT(exponent_ <= other.exponent_); 740 | if (factor < 3) { 741 | for (int i = 0; i < factor; ++i) { 742 | SubtractBignum(other); 743 | } 744 | return; 745 | } 746 | Chunk borrow = 0; 747 | int exponent_diff = other.exponent_ - exponent_; 748 | for (int i = 0; i < other.used_digits_; ++i) { 749 | DoubleChunk product = static_cast(factor) * other.bigits_[i]; 750 | DoubleChunk remove = borrow + product; 751 | Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); 752 | bigits_[i + exponent_diff] = difference & kBigitMask; 753 | borrow = static_cast((difference >> (kChunkSize - 1)) + 754 | (remove >> kBigitSize)); 755 | } 756 | for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { 757 | if (borrow == 0) return; 758 | Chunk difference = bigits_[i] - borrow; 759 | bigits_[i] = difference & kBigitMask; 760 | borrow = difference >> (kChunkSize - 1); 761 | } 762 | Clamp(); 763 | } 764 | 765 | 766 | } // namespace double_conversion 767 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/bignum.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_BIGNUM_H_ 29 | #define DOUBLE_CONVERSION_BIGNUM_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | class Bignum { 36 | public: 37 | // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. 38 | // This bignum can encode much bigger numbers, since it contains an 39 | // exponent. 40 | static const int kMaxSignificantBits = 3584; 41 | 42 | Bignum(); 43 | void AssignUInt16(uint16_t value); 44 | void AssignUInt64(uint64_t value); 45 | void AssignBignum(const Bignum& other); 46 | 47 | void AssignDecimalString(Vector value); 48 | void AssignHexString(Vector value); 49 | 50 | void AssignPowerUInt16(uint16_t base, int exponent); 51 | 52 | void AddUInt16(uint16_t operand); 53 | void AddUInt64(uint64_t operand); 54 | void AddBignum(const Bignum& other); 55 | // Precondition: this >= other. 56 | void SubtractBignum(const Bignum& other); 57 | 58 | void Square(); 59 | void ShiftLeft(int shift_amount); 60 | void MultiplyByUInt32(uint32_t factor); 61 | void MultiplyByUInt64(uint64_t factor); 62 | void MultiplyByPowerOfTen(int exponent); 63 | void Times10() { return MultiplyByUInt32(10); } 64 | // Pseudocode: 65 | // int result = this / other; 66 | // this = this % other; 67 | // In the worst case this function is in O(this/other). 68 | uint16_t DivideModuloIntBignum(const Bignum& other); 69 | 70 | bool ToHexString(char* buffer, int buffer_size) const; 71 | 72 | // Returns 73 | // -1 if a < b, 74 | // 0 if a == b, and 75 | // +1 if a > b. 76 | static int Compare(const Bignum& a, const Bignum& b); 77 | static bool Equal(const Bignum& a, const Bignum& b) { 78 | return Compare(a, b) == 0; 79 | } 80 | static bool LessEqual(const Bignum& a, const Bignum& b) { 81 | return Compare(a, b) <= 0; 82 | } 83 | static bool Less(const Bignum& a, const Bignum& b) { 84 | return Compare(a, b) < 0; 85 | } 86 | // Returns Compare(a + b, c); 87 | static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); 88 | // Returns a + b == c 89 | static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { 90 | return PlusCompare(a, b, c) == 0; 91 | } 92 | // Returns a + b <= c 93 | static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { 94 | return PlusCompare(a, b, c) <= 0; 95 | } 96 | // Returns a + b < c 97 | static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { 98 | return PlusCompare(a, b, c) < 0; 99 | } 100 | private: 101 | typedef uint32_t Chunk; 102 | typedef uint64_t DoubleChunk; 103 | 104 | static const int kChunkSize = sizeof(Chunk) * 8; 105 | static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; 106 | // With bigit size of 28 we loose some bits, but a double still fits easily 107 | // into two chunks, and more importantly we can use the Comba multiplication. 108 | static const int kBigitSize = 28; 109 | static const Chunk kBigitMask = (1 << kBigitSize) - 1; 110 | // Every instance allocates kBigitLength chunks on the stack. Bignums cannot 111 | // grow. There are no checks if the stack-allocated space is sufficient. 112 | static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; 113 | 114 | void EnsureCapacity(int size) { 115 | if (size > kBigitCapacity) { 116 | UNREACHABLE(); 117 | } 118 | } 119 | void Align(const Bignum& other); 120 | void Clamp(); 121 | bool IsClamped() const; 122 | void Zero(); 123 | // Requires this to have enough capacity (no tests done). 124 | // Updates used_digits_ if necessary. 125 | // shift_amount must be < kBigitSize. 126 | void BigitsShiftLeft(int shift_amount); 127 | // BigitLength includes the "hidden" digits encoded in the exponent. 128 | int BigitLength() const { return used_digits_ + exponent_; } 129 | Chunk BigitAt(int index) const; 130 | void SubtractTimes(const Bignum& other, int factor); 131 | 132 | Chunk bigits_buffer_[kBigitCapacity]; 133 | // A vector backed by bigits_buffer_. This way accesses to the array are 134 | // checked for out-of-bounds errors. 135 | Vector bigits_; 136 | int used_digits_; 137 | // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). 138 | int exponent_; 139 | 140 | DISALLOW_COPY_AND_ASSIGN(Bignum); 141 | }; 142 | 143 | } // namespace double_conversion 144 | 145 | #endif // DOUBLE_CONVERSION_BIGNUM_H_ 146 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/cached-powers.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "utils.h" 33 | 34 | #include "cached-powers.h" 35 | 36 | namespace double_conversion { 37 | 38 | struct CachedPower { 39 | uint64_t significand; 40 | int16_t binary_exponent; 41 | int16_t decimal_exponent; 42 | }; 43 | 44 | static const CachedPower kCachedPowers[] = { 45 | {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, 46 | {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, 47 | {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, 48 | {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, 49 | {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, 50 | {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, 51 | {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, 52 | {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, 53 | {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, 54 | {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, 55 | {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, 56 | {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, 57 | {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, 58 | {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, 59 | {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, 60 | {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, 61 | {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, 62 | {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, 63 | {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, 64 | {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, 65 | {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, 66 | {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, 67 | {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, 68 | {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, 69 | {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, 70 | {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, 71 | {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, 72 | {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, 73 | {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, 74 | {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, 75 | {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, 76 | {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, 77 | {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, 78 | {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, 79 | {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, 80 | {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, 81 | {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, 82 | {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, 83 | {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, 84 | {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, 85 | {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, 86 | {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, 87 | {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, 88 | {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, 89 | {UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, 90 | {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, 91 | {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, 92 | {UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, 93 | {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, 94 | {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, 95 | {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, 96 | {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, 97 | {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, 98 | {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, 99 | {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, 100 | {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, 101 | {UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, 102 | {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, 103 | {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, 104 | {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, 105 | {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, 106 | {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, 107 | {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, 108 | {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, 109 | {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, 110 | {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, 111 | {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, 112 | {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, 113 | {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, 114 | {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, 115 | {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, 116 | {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, 117 | {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, 118 | {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, 119 | {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, 120 | {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, 121 | {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, 122 | {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, 123 | {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, 124 | {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, 125 | {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, 126 | {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, 127 | {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, 128 | {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, 129 | {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, 130 | {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, 131 | {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, 132 | }; 133 | 134 | static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers); 135 | static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent. 136 | static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10) 137 | // Difference between the decimal exponents in the table above. 138 | const int PowersOfTenCache::kDecimalExponentDistance = 8; 139 | const int PowersOfTenCache::kMinDecimalExponent = -348; 140 | const int PowersOfTenCache::kMaxDecimalExponent = 340; 141 | 142 | void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( 143 | int min_exponent, 144 | int max_exponent, 145 | DiyFp* power, 146 | int* decimal_exponent) { 147 | int kQ = DiyFp::kSignificandSize; 148 | double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10); 149 | int foo = kCachedPowersOffset; 150 | int index = 151 | (foo + static_cast(k) - 1) / kDecimalExponentDistance + 1; 152 | ASSERT(0 <= index && index < kCachedPowersLength); 153 | CachedPower cached_power = kCachedPowers[index]; 154 | ASSERT(min_exponent <= cached_power.binary_exponent); 155 | (void) max_exponent; // Mark variable as used. 156 | ASSERT(cached_power.binary_exponent <= max_exponent); 157 | *decimal_exponent = cached_power.decimal_exponent; 158 | *power = DiyFp(cached_power.significand, cached_power.binary_exponent); 159 | } 160 | 161 | 162 | void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, 163 | DiyFp* power, 164 | int* found_exponent) { 165 | ASSERT(kMinDecimalExponent <= requested_exponent); 166 | ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); 167 | int index = 168 | (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; 169 | CachedPower cached_power = kCachedPowers[index]; 170 | *power = DiyFp(cached_power.significand, cached_power.binary_exponent); 171 | *found_exponent = cached_power.decimal_exponent; 172 | ASSERT(*found_exponent <= requested_exponent); 173 | ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); 174 | } 175 | 176 | } // namespace double_conversion 177 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/cached-powers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_ 29 | #define DOUBLE_CONVERSION_CACHED_POWERS_H_ 30 | 31 | #include "diy-fp.h" 32 | 33 | namespace double_conversion { 34 | 35 | class PowersOfTenCache { 36 | public: 37 | 38 | // Not all powers of ten are cached. The decimal exponent of two neighboring 39 | // cached numbers will differ by kDecimalExponentDistance. 40 | static const int kDecimalExponentDistance; 41 | 42 | static const int kMinDecimalExponent; 43 | static const int kMaxDecimalExponent; 44 | 45 | // Returns a cached power-of-ten with a binary exponent in the range 46 | // [min_exponent; max_exponent] (boundaries included). 47 | static void GetCachedPowerForBinaryExponentRange(int min_exponent, 48 | int max_exponent, 49 | DiyFp* power, 50 | int* decimal_exponent); 51 | 52 | // Returns a cached power of ten x ~= 10^k such that 53 | // k <= decimal_exponent < k + kCachedPowersDecimalDistance. 54 | // The given decimal_exponent must satisfy 55 | // kMinDecimalExponent <= requested_exponent, and 56 | // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance. 57 | static void GetCachedPowerForDecimalExponent(int requested_exponent, 58 | DiyFp* power, 59 | int* found_exponent); 60 | }; 61 | 62 | } // namespace double_conversion 63 | 64 | #endif // DOUBLE_CONVERSION_CACHED_POWERS_H_ 65 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/diy-fp.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | 29 | #include "diy-fp.h" 30 | #include "utils.h" 31 | 32 | namespace double_conversion { 33 | 34 | void DiyFp::Multiply(const DiyFp& other) { 35 | // Simply "emulates" a 128 bit multiplication. 36 | // However: the resulting number only contains 64 bits. The least 37 | // significant 64 bits are only used for rounding the most significant 64 38 | // bits. 39 | const uint64_t kM32 = 0xFFFFFFFFU; 40 | uint64_t a = f_ >> 32; 41 | uint64_t b = f_ & kM32; 42 | uint64_t c = other.f_ >> 32; 43 | uint64_t d = other.f_ & kM32; 44 | uint64_t ac = a * c; 45 | uint64_t bc = b * c; 46 | uint64_t ad = a * d; 47 | uint64_t bd = b * d; 48 | uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32); 49 | // By adding 1U << 31 to tmp we round the final result. 50 | // Halfway cases will be round up. 51 | tmp += 1U << 31; 52 | uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); 53 | e_ += other.e_ + 64; 54 | f_ = result_f; 55 | } 56 | 57 | } // namespace double_conversion 58 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/diy-fp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_DIY_FP_H_ 29 | #define DOUBLE_CONVERSION_DIY_FP_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | // This "Do It Yourself Floating Point" class implements a floating-point number 36 | // with a uint64 significand and an int exponent. Normalized DiyFp numbers will 37 | // have the most significant bit of the significand set. 38 | // Multiplication and Subtraction do not normalize their results. 39 | // DiyFp are not designed to contain special doubles (NaN and Infinity). 40 | class DiyFp { 41 | public: 42 | static const int kSignificandSize = 64; 43 | 44 | DiyFp() : f_(0), e_(0) {} 45 | DiyFp(uint64_t f, int e) : f_(f), e_(e) {} 46 | 47 | // this = this - other. 48 | // The exponents of both numbers must be the same and the significand of this 49 | // must be bigger than the significand of other. 50 | // The result will not be normalized. 51 | void Subtract(const DiyFp& other) { 52 | ASSERT(e_ == other.e_); 53 | ASSERT(f_ >= other.f_); 54 | f_ -= other.f_; 55 | } 56 | 57 | // Returns a - b. 58 | // The exponents of both numbers must be the same and this must be bigger 59 | // than other. The result will not be normalized. 60 | static DiyFp Minus(const DiyFp& a, const DiyFp& b) { 61 | DiyFp result = a; 62 | result.Subtract(b); 63 | return result; 64 | } 65 | 66 | 67 | // this = this * other. 68 | void Multiply(const DiyFp& other); 69 | 70 | // returns a * b; 71 | static DiyFp Times(const DiyFp& a, const DiyFp& b) { 72 | DiyFp result = a; 73 | result.Multiply(b); 74 | return result; 75 | } 76 | 77 | void Normalize() { 78 | ASSERT(f_ != 0); 79 | uint64_t f = f_; 80 | int e = e_; 81 | 82 | // This method is mainly called for normalizing boundaries. In general 83 | // boundaries need to be shifted by 10 bits. We thus optimize for this case. 84 | const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); 85 | while ((f & k10MSBits) == 0) { 86 | f <<= 10; 87 | e -= 10; 88 | } 89 | while ((f & kUint64MSB) == 0) { 90 | f <<= 1; 91 | e--; 92 | } 93 | f_ = f; 94 | e_ = e; 95 | } 96 | 97 | static DiyFp Normalize(const DiyFp& a) { 98 | DiyFp result = a; 99 | result.Normalize(); 100 | return result; 101 | } 102 | 103 | uint64_t f() const { return f_; } 104 | int e() const { return e_; } 105 | 106 | void set_f(uint64_t new_value) { f_ = new_value; } 107 | void set_e(int new_value) { e_ = new_value; } 108 | 109 | private: 110 | static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); 111 | 112 | uint64_t f_; 113 | int e_; 114 | }; 115 | 116 | } // namespace double_conversion 117 | 118 | #endif // DOUBLE_CONVERSION_DIY_FP_H_ 119 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/double-conversion.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 29 | #define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | class DoubleToStringConverter { 36 | public: 37 | // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint 38 | // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the 39 | // function returns false. 40 | static const int kMaxFixedDigitsBeforePoint = 60; 41 | static const int kMaxFixedDigitsAfterPoint = 60; 42 | 43 | // When calling ToExponential with a requested_digits 44 | // parameter > kMaxExponentialDigits then the function returns false. 45 | static const int kMaxExponentialDigits = 120; 46 | 47 | // When calling ToPrecision with a requested_digits 48 | // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits 49 | // then the function returns false. 50 | static const int kMinPrecisionDigits = 1; 51 | static const int kMaxPrecisionDigits = 120; 52 | 53 | enum Flags { 54 | NO_FLAGS = 0, 55 | EMIT_POSITIVE_EXPONENT_SIGN = 1, 56 | EMIT_TRAILING_DECIMAL_POINT = 2, 57 | EMIT_TRAILING_ZERO_AFTER_POINT = 4, 58 | UNIQUE_ZERO = 8 59 | }; 60 | 61 | // Flags should be a bit-or combination of the possible Flags-enum. 62 | // - NO_FLAGS: no special flags. 63 | // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent 64 | // form, emits a '+' for positive exponents. Example: 1.2e+2. 65 | // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is 66 | // converted into decimal format then a trailing decimal point is appended. 67 | // Example: 2345.0 is converted to "2345.". 68 | // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point 69 | // emits a trailing '0'-character. This flag requires the 70 | // EXMIT_TRAILING_DECIMAL_POINT flag. 71 | // Example: 2345.0 is converted to "2345.0". 72 | // - UNIQUE_ZERO: "-0.0" is converted to "0.0". 73 | // 74 | // Infinity symbol and nan_symbol provide the string representation for these 75 | // special values. If the string is NULL and the special value is encountered 76 | // then the conversion functions return false. 77 | // 78 | // The exponent_character is used in exponential representations. It is 79 | // usually 'e' or 'E'. 80 | // 81 | // When converting to the shortest representation the converter will 82 | // represent input numbers in decimal format if they are in the interval 83 | // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[ 84 | // (lower boundary included, greater boundary excluded). 85 | // Example: with decimal_in_shortest_low = -6 and 86 | // decimal_in_shortest_high = 21: 87 | // ToShortest(0.000001) -> "0.000001" 88 | // ToShortest(0.0000001) -> "1e-7" 89 | // ToShortest(111111111111111111111.0) -> "111111111111111110000" 90 | // ToShortest(100000000000000000000.0) -> "100000000000000000000" 91 | // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" 92 | // 93 | // When converting to precision mode the converter may add 94 | // max_leading_padding_zeroes before returning the number in exponential 95 | // format. 96 | // Example with max_leading_padding_zeroes_in_precision_mode = 6. 97 | // ToPrecision(0.0000012345, 2) -> "0.0000012" 98 | // ToPrecision(0.00000012345, 2) -> "1.2e-7" 99 | // Similarily the converter may add up to 100 | // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid 101 | // returning an exponential representation. A zero added by the 102 | // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. 103 | // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: 104 | // ToPrecision(230.0, 2) -> "230" 105 | // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. 106 | // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. 107 | DoubleToStringConverter(int flags, 108 | const char* infinity_symbol, 109 | const char* nan_symbol, 110 | char exponent_character, 111 | int decimal_in_shortest_low, 112 | int decimal_in_shortest_high, 113 | int max_leading_padding_zeroes_in_precision_mode, 114 | int max_trailing_padding_zeroes_in_precision_mode) 115 | : flags_(flags), 116 | infinity_symbol_(infinity_symbol), 117 | nan_symbol_(nan_symbol), 118 | exponent_character_(exponent_character), 119 | decimal_in_shortest_low_(decimal_in_shortest_low), 120 | decimal_in_shortest_high_(decimal_in_shortest_high), 121 | max_leading_padding_zeroes_in_precision_mode_( 122 | max_leading_padding_zeroes_in_precision_mode), 123 | max_trailing_padding_zeroes_in_precision_mode_( 124 | max_trailing_padding_zeroes_in_precision_mode) { 125 | // When 'trailing zero after the point' is set, then 'trailing point' 126 | // must be set too. 127 | ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || 128 | !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)); 129 | } 130 | 131 | // Returns a converter following the EcmaScript specification. 132 | static const DoubleToStringConverter& EcmaScriptConverter(); 133 | 134 | // Computes the shortest string of digits that correctly represent the input 135 | // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high 136 | // (see constructor) it then either returns a decimal representation, or an 137 | // exponential representation. 138 | // Example with decimal_in_shortest_low = -6, 139 | // decimal_in_shortest_high = 21, 140 | // EMIT_POSITIVE_EXPONENT_SIGN activated, and 141 | // EMIT_TRAILING_DECIMAL_POINT deactived: 142 | // ToShortest(0.000001) -> "0.000001" 143 | // ToShortest(0.0000001) -> "1e-7" 144 | // ToShortest(111111111111111111111.0) -> "111111111111111110000" 145 | // ToShortest(100000000000000000000.0) -> "100000000000000000000" 146 | // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" 147 | // 148 | // Note: the conversion may round the output if the returned string 149 | // is accurate enough to uniquely identify the input-number. 150 | // For example the most precise representation of the double 9e59 equals 151 | // "899999999999999918767229449717619953810131273674690656206848", but 152 | // the converter will return the shorter (but still correct) "9e59". 153 | // 154 | // Returns true if the conversion succeeds. The conversion always succeeds 155 | // except when the input value is special and no infinity_symbol or 156 | // nan_symbol has been given to the constructor. 157 | bool ToShortest(double value, StringBuilder* result_builder) const { 158 | return ToShortestIeeeNumber(value, result_builder, SHORTEST); 159 | } 160 | 161 | // Same as ToShortest, but for single-precision floats. 162 | bool ToShortestSingle(float value, StringBuilder* result_builder) const { 163 | return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE); 164 | } 165 | 166 | 167 | // Computes a decimal representation with a fixed number of digits after the 168 | // decimal point. The last emitted digit is rounded. 169 | // 170 | // Examples: 171 | // ToFixed(3.12, 1) -> "3.1" 172 | // ToFixed(3.1415, 3) -> "3.142" 173 | // ToFixed(1234.56789, 4) -> "1234.5679" 174 | // ToFixed(1.23, 5) -> "1.23000" 175 | // ToFixed(0.1, 4) -> "0.1000" 176 | // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00" 177 | // ToFixed(0.1, 30) -> "0.100000000000000005551115123126" 178 | // ToFixed(0.1, 17) -> "0.10000000000000001" 179 | // 180 | // If requested_digits equals 0, then the tail of the result depends on 181 | // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT. 182 | // Examples, for requested_digits == 0, 183 | // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be 184 | // - false and false: then 123.45 -> 123 185 | // 0.678 -> 1 186 | // - true and false: then 123.45 -> 123. 187 | // 0.678 -> 1. 188 | // - true and true: then 123.45 -> 123.0 189 | // 0.678 -> 1.0 190 | // 191 | // Returns true if the conversion succeeds. The conversion always succeeds 192 | // except for the following cases: 193 | // - the input value is special and no infinity_symbol or nan_symbol has 194 | // been provided to the constructor, 195 | // - 'value' > 10^kMaxFixedDigitsBeforePoint, or 196 | // - 'requested_digits' > kMaxFixedDigitsAfterPoint. 197 | // The last two conditions imply that the result will never contain more than 198 | // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters 199 | // (one additional character for the sign, and one for the decimal point). 200 | bool ToFixed(double value, 201 | int requested_digits, 202 | StringBuilder* result_builder) const; 203 | 204 | // Computes a representation in exponential format with requested_digits 205 | // after the decimal point. The last emitted digit is rounded. 206 | // If requested_digits equals -1, then the shortest exponential representation 207 | // is computed. 208 | // 209 | // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and 210 | // exponent_character set to 'e'. 211 | // ToExponential(3.12, 1) -> "3.1e0" 212 | // ToExponential(5.0, 3) -> "5.000e0" 213 | // ToExponential(0.001, 2) -> "1.00e-3" 214 | // ToExponential(3.1415, -1) -> "3.1415e0" 215 | // ToExponential(3.1415, 4) -> "3.1415e0" 216 | // ToExponential(3.1415, 3) -> "3.142e0" 217 | // ToExponential(123456789000000, 3) -> "1.235e14" 218 | // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30" 219 | // ToExponential(1000000000000000019884624838656.0, 32) -> 220 | // "1.00000000000000001988462483865600e30" 221 | // ToExponential(1234, 0) -> "1e3" 222 | // 223 | // Returns true if the conversion succeeds. The conversion always succeeds 224 | // except for the following cases: 225 | // - the input value is special and no infinity_symbol or nan_symbol has 226 | // been provided to the constructor, 227 | // - 'requested_digits' > kMaxExponentialDigits. 228 | // The last condition implies that the result will never contain more than 229 | // kMaxExponentialDigits + 8 characters (the sign, the digit before the 230 | // decimal point, the decimal point, the exponent character, the 231 | // exponent's sign, and at most 3 exponent digits). 232 | bool ToExponential(double value, 233 | int requested_digits, 234 | StringBuilder* result_builder) const; 235 | 236 | // Computes 'precision' leading digits of the given 'value' and returns them 237 | // either in exponential or decimal format, depending on 238 | // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the 239 | // constructor). 240 | // The last computed digit is rounded. 241 | // 242 | // Example with max_leading_padding_zeroes_in_precision_mode = 6. 243 | // ToPrecision(0.0000012345, 2) -> "0.0000012" 244 | // ToPrecision(0.00000012345, 2) -> "1.2e-7" 245 | // Similarily the converter may add up to 246 | // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid 247 | // returning an exponential representation. A zero added by the 248 | // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. 249 | // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: 250 | // ToPrecision(230.0, 2) -> "230" 251 | // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. 252 | // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. 253 | // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no 254 | // EMIT_TRAILING_ZERO_AFTER_POINT: 255 | // ToPrecision(123450.0, 6) -> "123450" 256 | // ToPrecision(123450.0, 5) -> "123450" 257 | // ToPrecision(123450.0, 4) -> "123500" 258 | // ToPrecision(123450.0, 3) -> "123000" 259 | // ToPrecision(123450.0, 2) -> "1.2e5" 260 | // 261 | // Returns true if the conversion succeeds. The conversion always succeeds 262 | // except for the following cases: 263 | // - the input value is special and no infinity_symbol or nan_symbol has 264 | // been provided to the constructor, 265 | // - precision < kMinPericisionDigits 266 | // - precision > kMaxPrecisionDigits 267 | // The last condition implies that the result will never contain more than 268 | // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the 269 | // exponent character, the exponent's sign, and at most 3 exponent digits). 270 | bool ToPrecision(double value, 271 | int precision, 272 | StringBuilder* result_builder) const; 273 | 274 | enum DtoaMode { 275 | // Produce the shortest correct representation. 276 | // For example the output of 0.299999999999999988897 is (the less accurate 277 | // but correct) 0.3. 278 | SHORTEST, 279 | // Same as SHORTEST, but for single-precision floats. 280 | SHORTEST_SINGLE, 281 | // Produce a fixed number of digits after the decimal point. 282 | // For instance fixed(0.1, 4) becomes 0.1000 283 | // If the input number is big, the output will be big. 284 | FIXED, 285 | // Fixed number of digits (independent of the decimal point). 286 | PRECISION 287 | }; 288 | 289 | // The maximal number of digits that are needed to emit a double in base 10. 290 | // A higher precision can be achieved by using more digits, but the shortest 291 | // accurate representation of any double will never use more digits than 292 | // kBase10MaximalLength. 293 | // Note that DoubleToAscii null-terminates its input. So the given buffer 294 | // should be at least kBase10MaximalLength + 1 characters long. 295 | static const int kBase10MaximalLength = 17; 296 | 297 | // Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or 298 | // -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v' 299 | // after it has been casted to a single-precision float. That is, in this 300 | // mode static_cast(v) must not be NaN, +Infinity or -Infinity. 301 | // 302 | // The result should be interpreted as buffer * 10^(point-length). 303 | // 304 | // The output depends on the given mode: 305 | // - SHORTEST: produce the least amount of digits for which the internal 306 | // identity requirement is still satisfied. If the digits are printed 307 | // (together with the correct exponent) then reading this number will give 308 | // 'v' again. The buffer will choose the representation that is closest to 309 | // 'v'. If there are two at the same distance, than the one farther away 310 | // from 0 is chosen (halfway cases - ending with 5 - are rounded up). 311 | // In this mode the 'requested_digits' parameter is ignored. 312 | // - SHORTEST_SINGLE: same as SHORTEST but with single-precision. 313 | // - FIXED: produces digits necessary to print a given number with 314 | // 'requested_digits' digits after the decimal point. The produced digits 315 | // might be too short in which case the caller has to fill the remainder 316 | // with '0's. 317 | // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. 318 | // Halfway cases are rounded towards +/-Infinity (away from 0). The call 319 | // toFixed(0.15, 2) thus returns buffer="2", point=0. 320 | // The returned buffer may contain digits that would be truncated from the 321 | // shortest representation of the input. 322 | // - PRECISION: produces 'requested_digits' where the first digit is not '0'. 323 | // Even though the length of produced digits usually equals 324 | // 'requested_digits', the function is allowed to return fewer digits, in 325 | // which case the caller has to fill the missing digits with '0's. 326 | // Halfway cases are again rounded away from 0. 327 | // DoubleToAscii expects the given buffer to be big enough to hold all 328 | // digits and a terminating null-character. In SHORTEST-mode it expects a 329 | // buffer of at least kBase10MaximalLength + 1. In all other modes the 330 | // requested_digits parameter and the padding-zeroes limit the size of the 331 | // output. Don't forget the decimal point, the exponent character and the 332 | // terminating null-character when computing the maximal output size. 333 | // The given length is only used in debug mode to ensure the buffer is big 334 | // enough. 335 | static void DoubleToAscii(double v, 336 | DtoaMode mode, 337 | int requested_digits, 338 | char* buffer, 339 | int buffer_length, 340 | bool* sign, 341 | int* length, 342 | int* point); 343 | 344 | private: 345 | // Implementation for ToShortest and ToShortestSingle. 346 | bool ToShortestIeeeNumber(double value, 347 | StringBuilder* result_builder, 348 | DtoaMode mode) const; 349 | 350 | // If the value is a special value (NaN or Infinity) constructs the 351 | // corresponding string using the configured infinity/nan-symbol. 352 | // If either of them is NULL or the value is not special then the 353 | // function returns false. 354 | bool HandleSpecialValues(double value, StringBuilder* result_builder) const; 355 | // Constructs an exponential representation (i.e. 1.234e56). 356 | // The given exponent assumes a decimal point after the first decimal digit. 357 | void CreateExponentialRepresentation(const char* decimal_digits, 358 | int length, 359 | int exponent, 360 | StringBuilder* result_builder) const; 361 | // Creates a decimal representation (i.e 1234.5678). 362 | void CreateDecimalRepresentation(const char* decimal_digits, 363 | int length, 364 | int decimal_point, 365 | int digits_after_point, 366 | StringBuilder* result_builder) const; 367 | 368 | const int flags_; 369 | const char* const infinity_symbol_; 370 | const char* const nan_symbol_; 371 | const char exponent_character_; 372 | const int decimal_in_shortest_low_; 373 | const int decimal_in_shortest_high_; 374 | const int max_leading_padding_zeroes_in_precision_mode_; 375 | const int max_trailing_padding_zeroes_in_precision_mode_; 376 | 377 | DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); 378 | }; 379 | 380 | 381 | class StringToDoubleConverter { 382 | public: 383 | // Enumeration for allowing octals and ignoring junk when converting 384 | // strings to numbers. 385 | enum Flags { 386 | NO_FLAGS = 0, 387 | ALLOW_HEX = 1, 388 | ALLOW_OCTALS = 2, 389 | ALLOW_TRAILING_JUNK = 4, 390 | ALLOW_LEADING_SPACES = 8, 391 | ALLOW_TRAILING_SPACES = 16, 392 | ALLOW_SPACES_AFTER_SIGN = 32 393 | }; 394 | 395 | // Flags should be a bit-or combination of the possible Flags-enum. 396 | // - NO_FLAGS: no special flags. 397 | // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers. 398 | // Ex: StringToDouble("0x1234") -> 4660.0 399 | // In StringToDouble("0x1234.56") the characters ".56" are trailing 400 | // junk. The result of the call is hence dependent on 401 | // the ALLOW_TRAILING_JUNK flag and/or the junk value. 402 | // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK, 403 | // the string will not be parsed as "0" followed by junk. 404 | // 405 | // - ALLOW_OCTALS: recognizes the prefix "0" for octals: 406 | // If a sequence of octal digits starts with '0', then the number is 407 | // read as octal integer. Octal numbers may only be integers. 408 | // Ex: StringToDouble("01234") -> 668.0 409 | // StringToDouble("012349") -> 12349.0 // Not a sequence of octal 410 | // // digits. 411 | // In StringToDouble("01234.56") the characters ".56" are trailing 412 | // junk. The result of the call is hence dependent on 413 | // the ALLOW_TRAILING_JUNK flag and/or the junk value. 414 | // In StringToDouble("01234e56") the characters "e56" are trailing 415 | // junk, too. 416 | // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of 417 | // a double literal. 418 | // - ALLOW_LEADING_SPACES: skip over leading spaces. 419 | // - ALLOW_TRAILING_SPACES: ignore trailing spaces. 420 | // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign. 421 | // Ex: StringToDouble("- 123.2") -> -123.2. 422 | // StringToDouble("+ 123.2") -> 123.2 423 | // 424 | // empty_string_value is returned when an empty string is given as input. 425 | // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string 426 | // containing only spaces is converted to the 'empty_string_value', too. 427 | // 428 | // junk_string_value is returned when 429 | // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not 430 | // part of a double-literal) is found. 431 | // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a 432 | // double literal. 433 | // 434 | // infinity_symbol and nan_symbol are strings that are used to detect 435 | // inputs that represent infinity and NaN. They can be null, in which case 436 | // they are ignored. 437 | // The conversion routine first reads any possible signs. Then it compares the 438 | // following character of the input-string with the first character of 439 | // the infinity, and nan-symbol. If either matches, the function assumes, that 440 | // a match has been found, and expects the following input characters to match 441 | // the remaining characters of the special-value symbol. 442 | // This means that the following restrictions apply to special-value symbols: 443 | // - they must not start with signs ('+', or '-'), 444 | // - they must not have the same first character. 445 | // - they must not start with digits. 446 | // 447 | // Examples: 448 | // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK, 449 | // empty_string_value = 0.0, 450 | // junk_string_value = NaN, 451 | // infinity_symbol = "infinity", 452 | // nan_symbol = "nan": 453 | // StringToDouble("0x1234") -> 4660.0. 454 | // StringToDouble("0x1234K") -> 4660.0. 455 | // StringToDouble("") -> 0.0 // empty_string_value. 456 | // StringToDouble(" ") -> NaN // junk_string_value. 457 | // StringToDouble(" 1") -> NaN // junk_string_value. 458 | // StringToDouble("0x") -> NaN // junk_string_value. 459 | // StringToDouble("-123.45") -> -123.45. 460 | // StringToDouble("--123.45") -> NaN // junk_string_value. 461 | // StringToDouble("123e45") -> 123e45. 462 | // StringToDouble("123E45") -> 123e45. 463 | // StringToDouble("123e+45") -> 123e45. 464 | // StringToDouble("123E-45") -> 123e-45. 465 | // StringToDouble("123e") -> 123.0 // trailing junk ignored. 466 | // StringToDouble("123e-") -> 123.0 // trailing junk ignored. 467 | // StringToDouble("+NaN") -> NaN // NaN string literal. 468 | // StringToDouble("-infinity") -> -inf. // infinity literal. 469 | // StringToDouble("Infinity") -> NaN // junk_string_value. 470 | // 471 | // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES, 472 | // empty_string_value = 0.0, 473 | // junk_string_value = NaN, 474 | // infinity_symbol = NULL, 475 | // nan_symbol = NULL: 476 | // StringToDouble("0x1234") -> NaN // junk_string_value. 477 | // StringToDouble("01234") -> 668.0. 478 | // StringToDouble("") -> 0.0 // empty_string_value. 479 | // StringToDouble(" ") -> 0.0 // empty_string_value. 480 | // StringToDouble(" 1") -> 1.0 481 | // StringToDouble("0x") -> NaN // junk_string_value. 482 | // StringToDouble("0123e45") -> NaN // junk_string_value. 483 | // StringToDouble("01239E45") -> 1239e45. 484 | // StringToDouble("-infinity") -> NaN // junk_string_value. 485 | // StringToDouble("NaN") -> NaN // junk_string_value. 486 | StringToDoubleConverter(int flags, 487 | double empty_string_value, 488 | double junk_string_value, 489 | const char* infinity_symbol, 490 | const char* nan_symbol) 491 | : flags_(flags), 492 | empty_string_value_(empty_string_value), 493 | junk_string_value_(junk_string_value), 494 | infinity_symbol_(infinity_symbol), 495 | nan_symbol_(nan_symbol) { 496 | } 497 | 498 | // Performs the conversion. 499 | // The output parameter 'processed_characters_count' is set to the number 500 | // of characters that have been processed to read the number. 501 | // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included 502 | // in the 'processed_characters_count'. Trailing junk is never included. 503 | double StringToDouble(const char* buffer, 504 | int length, 505 | int* processed_characters_count) const { 506 | return StringToIeee(buffer, length, processed_characters_count, true); 507 | } 508 | 509 | // Same as StringToDouble but reads a float. 510 | // Note that this is not equivalent to static_cast(StringToDouble(...)) 511 | // due to potential double-rounding. 512 | float StringToFloat(const char* buffer, 513 | int length, 514 | int* processed_characters_count) const { 515 | return static_cast(StringToIeee(buffer, length, 516 | processed_characters_count, false)); 517 | } 518 | 519 | private: 520 | const int flags_; 521 | const double empty_string_value_; 522 | const double junk_string_value_; 523 | const char* const infinity_symbol_; 524 | const char* const nan_symbol_; 525 | 526 | double StringToIeee(const char* buffer, 527 | int length, 528 | int* processed_characters_count, 529 | bool read_as_double) const; 530 | 531 | DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); 532 | }; 533 | 534 | } // namespace double_conversion 535 | 536 | #endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 537 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/fast-dtoa.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_FAST_DTOA_H_ 29 | #define DOUBLE_CONVERSION_FAST_DTOA_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | enum FastDtoaMode { 36 | // Computes the shortest representation of the given input. The returned 37 | // result will be the most accurate number of this length. Longer 38 | // representations might be more accurate. 39 | FAST_DTOA_SHORTEST, 40 | // Same as FAST_DTOA_SHORTEST but for single-precision floats. 41 | FAST_DTOA_SHORTEST_SINGLE, 42 | // Computes a representation where the precision (number of digits) is 43 | // given as input. The precision is independent of the decimal point. 44 | FAST_DTOA_PRECISION 45 | }; 46 | 47 | // FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not 48 | // include the terminating '\0' character. 49 | static const int kFastDtoaMaximalLength = 17; 50 | // Same for single-precision numbers. 51 | static const int kFastDtoaMaximalSingleLength = 9; 52 | 53 | // Provides a decimal representation of v. 54 | // The result should be interpreted as buffer * 10^(point - length). 55 | // 56 | // Precondition: 57 | // * v must be a strictly positive finite double. 58 | // 59 | // Returns true if it succeeds, otherwise the result can not be trusted. 60 | // There will be *length digits inside the buffer followed by a null terminator. 61 | // If the function returns true and mode equals 62 | // - FAST_DTOA_SHORTEST, then 63 | // the parameter requested_digits is ignored. 64 | // The result satisfies 65 | // v == (double) (buffer * 10^(point - length)). 66 | // The digits in the buffer are the shortest representation possible. E.g. 67 | // if 0.099999999999 and 0.1 represent the same double then "1" is returned 68 | // with point = 0. 69 | // The last digit will be closest to the actual v. That is, even if several 70 | // digits might correctly yield 'v' when read again, the buffer will contain 71 | // the one closest to v. 72 | // - FAST_DTOA_PRECISION, then 73 | // the buffer contains requested_digits digits. 74 | // the difference v - (buffer * 10^(point-length)) is closest to zero for 75 | // all possible representations of requested_digits digits. 76 | // If there are two values that are equally close, then FastDtoa returns 77 | // false. 78 | // For both modes the buffer must be large enough to hold the result. 79 | bool FastDtoa(double d, 80 | FastDtoaMode mode, 81 | int requested_digits, 82 | Vector buffer, 83 | int* length, 84 | int* decimal_point); 85 | 86 | } // namespace double_conversion 87 | 88 | #endif // DOUBLE_CONVERSION_FAST_DTOA_H_ 89 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/fixed-dtoa.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #include 29 | 30 | #include "fixed-dtoa.h" 31 | #include "ieee.h" 32 | 33 | namespace double_conversion { 34 | 35 | // Represents a 128bit type. This class should be replaced by a native type on 36 | // platforms that support 128bit integers. 37 | class UInt128 { 38 | public: 39 | UInt128() : high_bits_(0), low_bits_(0) { } 40 | UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { } 41 | 42 | void Multiply(uint32_t multiplicand) { 43 | uint64_t accumulator; 44 | 45 | accumulator = (low_bits_ & kMask32) * multiplicand; 46 | uint32_t part = static_cast(accumulator & kMask32); 47 | accumulator >>= 32; 48 | accumulator = accumulator + (low_bits_ >> 32) * multiplicand; 49 | low_bits_ = (accumulator << 32) + part; 50 | accumulator >>= 32; 51 | accumulator = accumulator + (high_bits_ & kMask32) * multiplicand; 52 | part = static_cast(accumulator & kMask32); 53 | accumulator >>= 32; 54 | accumulator = accumulator + (high_bits_ >> 32) * multiplicand; 55 | high_bits_ = (accumulator << 32) + part; 56 | ASSERT((accumulator >> 32) == 0); 57 | } 58 | 59 | void Shift(int shift_amount) { 60 | ASSERT(-64 <= shift_amount && shift_amount <= 64); 61 | if (shift_amount == 0) { 62 | return; 63 | } else if (shift_amount == -64) { 64 | high_bits_ = low_bits_; 65 | low_bits_ = 0; 66 | } else if (shift_amount == 64) { 67 | low_bits_ = high_bits_; 68 | high_bits_ = 0; 69 | } else if (shift_amount <= 0) { 70 | high_bits_ <<= -shift_amount; 71 | high_bits_ += low_bits_ >> (64 + shift_amount); 72 | low_bits_ <<= -shift_amount; 73 | } else { 74 | low_bits_ >>= shift_amount; 75 | low_bits_ += high_bits_ << (64 - shift_amount); 76 | high_bits_ >>= shift_amount; 77 | } 78 | } 79 | 80 | // Modifies *this to *this MOD (2^power). 81 | // Returns *this DIV (2^power). 82 | int DivModPowerOf2(int power) { 83 | if (power >= 64) { 84 | int result = static_cast(high_bits_ >> (power - 64)); 85 | high_bits_ -= static_cast(result) << (power - 64); 86 | return result; 87 | } else { 88 | uint64_t part_low = low_bits_ >> power; 89 | uint64_t part_high = high_bits_ << (64 - power); 90 | int result = static_cast(part_low + part_high); 91 | high_bits_ = 0; 92 | low_bits_ -= part_low << power; 93 | return result; 94 | } 95 | } 96 | 97 | bool IsZero() const { 98 | return high_bits_ == 0 && low_bits_ == 0; 99 | } 100 | 101 | int BitAt(int position) { 102 | if (position >= 64) { 103 | return static_cast(high_bits_ >> (position - 64)) & 1; 104 | } else { 105 | return static_cast(low_bits_ >> position) & 1; 106 | } 107 | } 108 | 109 | private: 110 | static const uint64_t kMask32 = 0xFFFFFFFF; 111 | // Value == (high_bits_ << 64) + low_bits_ 112 | uint64_t high_bits_; 113 | uint64_t low_bits_; 114 | }; 115 | 116 | 117 | static const int kDoubleSignificandSize = 53; // Includes the hidden bit. 118 | 119 | 120 | static void FillDigits32FixedLength(uint32_t number, int requested_length, 121 | Vector buffer, int* length) { 122 | for (int i = requested_length - 1; i >= 0; --i) { 123 | buffer[(*length) + i] = '0' + number % 10; 124 | number /= 10; 125 | } 126 | *length += requested_length; 127 | } 128 | 129 | 130 | static void FillDigits32(uint32_t number, Vector buffer, int* length) { 131 | int number_length = 0; 132 | // We fill the digits in reverse order and exchange them afterwards. 133 | while (number != 0) { 134 | int digit = number % 10; 135 | number /= 10; 136 | buffer[(*length) + number_length] = static_cast('0' + digit); 137 | number_length++; 138 | } 139 | // Exchange the digits. 140 | int i = *length; 141 | int j = *length + number_length - 1; 142 | while (i < j) { 143 | char tmp = buffer[i]; 144 | buffer[i] = buffer[j]; 145 | buffer[j] = tmp; 146 | i++; 147 | j--; 148 | } 149 | *length += number_length; 150 | } 151 | 152 | 153 | static void FillDigits64FixedLength(uint64_t number, 154 | Vector buffer, int* length) { 155 | const uint32_t kTen7 = 10000000; 156 | // For efficiency cut the number into 3 uint32_t parts, and print those. 157 | uint32_t part2 = static_cast(number % kTen7); 158 | number /= kTen7; 159 | uint32_t part1 = static_cast(number % kTen7); 160 | uint32_t part0 = static_cast(number / kTen7); 161 | 162 | FillDigits32FixedLength(part0, 3, buffer, length); 163 | FillDigits32FixedLength(part1, 7, buffer, length); 164 | FillDigits32FixedLength(part2, 7, buffer, length); 165 | } 166 | 167 | 168 | static void FillDigits64(uint64_t number, Vector buffer, int* length) { 169 | const uint32_t kTen7 = 10000000; 170 | // For efficiency cut the number into 3 uint32_t parts, and print those. 171 | uint32_t part2 = static_cast(number % kTen7); 172 | number /= kTen7; 173 | uint32_t part1 = static_cast(number % kTen7); 174 | uint32_t part0 = static_cast(number / kTen7); 175 | 176 | if (part0 != 0) { 177 | FillDigits32(part0, buffer, length); 178 | FillDigits32FixedLength(part1, 7, buffer, length); 179 | FillDigits32FixedLength(part2, 7, buffer, length); 180 | } else if (part1 != 0) { 181 | FillDigits32(part1, buffer, length); 182 | FillDigits32FixedLength(part2, 7, buffer, length); 183 | } else { 184 | FillDigits32(part2, buffer, length); 185 | } 186 | } 187 | 188 | 189 | static void RoundUp(Vector buffer, int* length, int* decimal_point) { 190 | // An empty buffer represents 0. 191 | if (*length == 0) { 192 | buffer[0] = '1'; 193 | *decimal_point = 1; 194 | *length = 1; 195 | return; 196 | } 197 | // Round the last digit until we either have a digit that was not '9' or until 198 | // we reached the first digit. 199 | buffer[(*length) - 1]++; 200 | for (int i = (*length) - 1; i > 0; --i) { 201 | if (buffer[i] != '0' + 10) { 202 | return; 203 | } 204 | buffer[i] = '0'; 205 | buffer[i - 1]++; 206 | } 207 | // If the first digit is now '0' + 10, we would need to set it to '0' and add 208 | // a '1' in front. However we reach the first digit only if all following 209 | // digits had been '9' before rounding up. Now all trailing digits are '0' and 210 | // we simply switch the first digit to '1' and update the decimal-point 211 | // (indicating that the point is now one digit to the right). 212 | if (buffer[0] == '0' + 10) { 213 | buffer[0] = '1'; 214 | (*decimal_point)++; 215 | } 216 | } 217 | 218 | 219 | // The given fractionals number represents a fixed-point number with binary 220 | // point at bit (-exponent). 221 | // Preconditions: 222 | // -128 <= exponent <= 0. 223 | // 0 <= fractionals * 2^exponent < 1 224 | // The buffer holds the result. 225 | // The function will round its result. During the rounding-process digits not 226 | // generated by this function might be updated, and the decimal-point variable 227 | // might be updated. If this function generates the digits 99 and the buffer 228 | // already contained "199" (thus yielding a buffer of "19999") then a 229 | // rounding-up will change the contents of the buffer to "20000". 230 | static void FillFractionals(uint64_t fractionals, int exponent, 231 | int fractional_count, Vector buffer, 232 | int* length, int* decimal_point) { 233 | ASSERT(-128 <= exponent && exponent <= 0); 234 | // 'fractionals' is a fixed-point number, with binary point at bit 235 | // (-exponent). Inside the function the non-converted remainder of fractionals 236 | // is a fixed-point number, with binary point at bit 'point'. 237 | if (-exponent <= 64) { 238 | // One 64 bit number is sufficient. 239 | ASSERT(fractionals >> 56 == 0); 240 | int point = -exponent; 241 | for (int i = 0; i < fractional_count; ++i) { 242 | if (fractionals == 0) break; 243 | // Instead of multiplying by 10 we multiply by 5 and adjust the point 244 | // location. This way the fractionals variable will not overflow. 245 | // Invariant at the beginning of the loop: fractionals < 2^point. 246 | // Initially we have: point <= 64 and fractionals < 2^56 247 | // After each iteration the point is decremented by one. 248 | // Note that 5^3 = 125 < 128 = 2^7. 249 | // Therefore three iterations of this loop will not overflow fractionals 250 | // (even without the subtraction at the end of the loop body). At this 251 | // time point will satisfy point <= 61 and therefore fractionals < 2^point 252 | // and any further multiplication of fractionals by 5 will not overflow. 253 | fractionals *= 5; 254 | point--; 255 | int digit = static_cast(fractionals >> point); 256 | ASSERT(digit <= 9); 257 | buffer[*length] = static_cast('0' + digit); 258 | (*length)++; 259 | fractionals -= static_cast(digit) << point; 260 | } 261 | // If the first bit after the point is set we have to round up. 262 | if (((fractionals >> (point - 1)) & 1) == 1) { 263 | RoundUp(buffer, length, decimal_point); 264 | } 265 | } else { // We need 128 bits. 266 | ASSERT(64 < -exponent && -exponent <= 128); 267 | UInt128 fractionals128 = UInt128(fractionals, 0); 268 | fractionals128.Shift(-exponent - 64); 269 | int point = 128; 270 | for (int i = 0; i < fractional_count; ++i) { 271 | if (fractionals128.IsZero()) break; 272 | // As before: instead of multiplying by 10 we multiply by 5 and adjust the 273 | // point location. 274 | // This multiplication will not overflow for the same reasons as before. 275 | fractionals128.Multiply(5); 276 | point--; 277 | int digit = fractionals128.DivModPowerOf2(point); 278 | ASSERT(digit <= 9); 279 | buffer[*length] = static_cast('0' + digit); 280 | (*length)++; 281 | } 282 | if (fractionals128.BitAt(point - 1) == 1) { 283 | RoundUp(buffer, length, decimal_point); 284 | } 285 | } 286 | } 287 | 288 | 289 | // Removes leading and trailing zeros. 290 | // If leading zeros are removed then the decimal point position is adjusted. 291 | static void TrimZeros(Vector buffer, int* length, int* decimal_point) { 292 | while (*length > 0 && buffer[(*length) - 1] == '0') { 293 | (*length)--; 294 | } 295 | int first_non_zero = 0; 296 | while (first_non_zero < *length && buffer[first_non_zero] == '0') { 297 | first_non_zero++; 298 | } 299 | if (first_non_zero != 0) { 300 | for (int i = first_non_zero; i < *length; ++i) { 301 | buffer[i - first_non_zero] = buffer[i]; 302 | } 303 | *length -= first_non_zero; 304 | *decimal_point -= first_non_zero; 305 | } 306 | } 307 | 308 | 309 | bool FastFixedDtoa(double v, 310 | int fractional_count, 311 | Vector buffer, 312 | int* length, 313 | int* decimal_point) { 314 | const uint32_t kMaxUInt32 = 0xFFFFFFFF; 315 | uint64_t significand = Double(v).Significand(); 316 | int exponent = Double(v).Exponent(); 317 | // v = significand * 2^exponent (with significand a 53bit integer). 318 | // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we 319 | // don't know how to compute the representation. 2^73 ~= 9.5*10^21. 320 | // If necessary this limit could probably be increased, but we don't need 321 | // more. 322 | if (exponent > 20) return false; 323 | if (fractional_count > 20) return false; 324 | *length = 0; 325 | // At most kDoubleSignificandSize bits of the significand are non-zero. 326 | // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero 327 | // bits: 0..11*..0xxx..53*..xx 328 | if (exponent + kDoubleSignificandSize > 64) { 329 | // The exponent must be > 11. 330 | // 331 | // We know that v = significand * 2^exponent. 332 | // And the exponent > 11. 333 | // We simplify the task by dividing v by 10^17. 334 | // The quotient delivers the first digits, and the remainder fits into a 64 335 | // bit number. 336 | // Dividing by 10^17 is equivalent to dividing by 5^17*2^17. 337 | const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17 338 | uint64_t divisor = kFive17; 339 | int divisor_power = 17; 340 | uint64_t dividend = significand; 341 | uint32_t quotient; 342 | uint64_t remainder; 343 | // Let v = f * 2^e with f == significand and e == exponent. 344 | // Then need q (quotient) and r (remainder) as follows: 345 | // v = q * 10^17 + r 346 | // f * 2^e = q * 10^17 + r 347 | // f * 2^e = q * 5^17 * 2^17 + r 348 | // If e > 17 then 349 | // f * 2^(e-17) = q * 5^17 + r/2^17 350 | // else 351 | // f = q * 5^17 * 2^(17-e) + r/2^e 352 | if (exponent > divisor_power) { 353 | // We only allow exponents of up to 20 and therefore (17 - e) <= 3 354 | dividend <<= exponent - divisor_power; 355 | quotient = static_cast(dividend / divisor); 356 | remainder = (dividend % divisor) << divisor_power; 357 | } else { 358 | divisor <<= divisor_power - exponent; 359 | quotient = static_cast(dividend / divisor); 360 | remainder = (dividend % divisor) << exponent; 361 | } 362 | FillDigits32(quotient, buffer, length); 363 | FillDigits64FixedLength(remainder, buffer, length); 364 | *decimal_point = *length; 365 | } else if (exponent >= 0) { 366 | // 0 <= exponent <= 11 367 | significand <<= exponent; 368 | FillDigits64(significand, buffer, length); 369 | *decimal_point = *length; 370 | } else if (exponent > -kDoubleSignificandSize) { 371 | // We have to cut the number. 372 | uint64_t integrals = significand >> -exponent; 373 | uint64_t fractionals = significand - (integrals << -exponent); 374 | if (integrals > kMaxUInt32) { 375 | FillDigits64(integrals, buffer, length); 376 | } else { 377 | FillDigits32(static_cast(integrals), buffer, length); 378 | } 379 | *decimal_point = *length; 380 | FillFractionals(fractionals, exponent, fractional_count, 381 | buffer, length, decimal_point); 382 | } else if (exponent < -128) { 383 | // This configuration (with at most 20 digits) means that all digits must be 384 | // 0. 385 | ASSERT(fractional_count <= 20); 386 | buffer[0] = '\0'; 387 | *length = 0; 388 | *decimal_point = -fractional_count; 389 | } else { 390 | *decimal_point = 0; 391 | FillFractionals(significand, exponent, fractional_count, 392 | buffer, length, decimal_point); 393 | } 394 | TrimZeros(buffer, length, decimal_point); 395 | buffer[*length] = '\0'; 396 | if ((*length) == 0) { 397 | // The string is empty and the decimal_point thus has no importance. Mimick 398 | // Gay's dtoa and and set it to -fractional_count. 399 | *decimal_point = -fractional_count; 400 | } 401 | return true; 402 | } 403 | 404 | } // namespace double_conversion 405 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/fixed-dtoa.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_ 29 | #define DOUBLE_CONVERSION_FIXED_DTOA_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | // Produces digits necessary to print a given number with 36 | // 'fractional_count' digits after the decimal point. 37 | // The buffer must be big enough to hold the result plus one terminating null 38 | // character. 39 | // 40 | // The produced digits might be too short in which case the caller has to fill 41 | // the gaps with '0's. 42 | // Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and 43 | // decimal_point = -2. 44 | // Halfway cases are rounded towards +/-Infinity (away from 0). The call 45 | // FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0. 46 | // The returned buffer may contain digits that would be truncated from the 47 | // shortest representation of the input. 48 | // 49 | // This method only works for some parameters. If it can't handle the input it 50 | // returns false. The output is null-terminated when the function succeeds. 51 | bool FastFixedDtoa(double v, int fractional_count, 52 | Vector buffer, int* length, int* decimal_point); 53 | 54 | } // namespace double_conversion 55 | 56 | #endif // DOUBLE_CONVERSION_FIXED_DTOA_H_ 57 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/ieee.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_DOUBLE_H_ 29 | #define DOUBLE_CONVERSION_DOUBLE_H_ 30 | 31 | #include "diy-fp.h" 32 | 33 | namespace double_conversion { 34 | 35 | // We assume that doubles and uint64_t have the same endianness. 36 | static uint64_t double_to_uint64(double d) { return BitCast(d); } 37 | static double uint64_to_double(uint64_t d64) { return BitCast(d64); } 38 | static uint32_t float_to_uint32(float f) { return BitCast(f); } 39 | static float uint32_to_float(uint32_t d32) { return BitCast(d32); } 40 | 41 | // Helper functions for doubles. 42 | class Double { 43 | public: 44 | static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); 45 | static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); 46 | static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); 47 | static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); 48 | static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. 49 | static const int kSignificandSize = 53; 50 | 51 | Double() : d64_(0) {} 52 | explicit Double(double d) : d64_(double_to_uint64(d)) {} 53 | explicit Double(uint64_t d64) : d64_(d64) {} 54 | explicit Double(DiyFp diy_fp) 55 | : d64_(DiyFpToUint64(diy_fp)) {} 56 | 57 | // The value encoded by this Double must be greater or equal to +0.0. 58 | // It must not be special (infinity, or NaN). 59 | DiyFp AsDiyFp() const { 60 | ASSERT(Sign() > 0); 61 | ASSERT(!IsSpecial()); 62 | return DiyFp(Significand(), Exponent()); 63 | } 64 | 65 | // The value encoded by this Double must be strictly greater than 0. 66 | DiyFp AsNormalizedDiyFp() const { 67 | ASSERT(value() > 0.0); 68 | uint64_t f = Significand(); 69 | int e = Exponent(); 70 | 71 | // The current double could be a denormal. 72 | while ((f & kHiddenBit) == 0) { 73 | f <<= 1; 74 | e--; 75 | } 76 | // Do the final shifts in one go. 77 | f <<= DiyFp::kSignificandSize - kSignificandSize; 78 | e -= DiyFp::kSignificandSize - kSignificandSize; 79 | return DiyFp(f, e); 80 | } 81 | 82 | // Returns the double's bit as uint64. 83 | uint64_t AsUint64() const { 84 | return d64_; 85 | } 86 | 87 | // Returns the next greater double. Returns +infinity on input +infinity. 88 | double NextDouble() const { 89 | if (d64_ == kInfinity) return Double(kInfinity).value(); 90 | if (Sign() < 0 && Significand() == 0) { 91 | // -0.0 92 | return 0.0; 93 | } 94 | if (Sign() < 0) { 95 | return Double(d64_ - 1).value(); 96 | } else { 97 | return Double(d64_ + 1).value(); 98 | } 99 | } 100 | 101 | double PreviousDouble() const { 102 | if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity(); 103 | if (Sign() < 0) { 104 | return Double(d64_ + 1).value(); 105 | } else { 106 | if (Significand() == 0) return -0.0; 107 | return Double(d64_ - 1).value(); 108 | } 109 | } 110 | 111 | int Exponent() const { 112 | if (IsDenormal()) return kDenormalExponent; 113 | 114 | uint64_t d64 = AsUint64(); 115 | int biased_e = 116 | static_cast((d64 & kExponentMask) >> kPhysicalSignificandSize); 117 | return biased_e - kExponentBias; 118 | } 119 | 120 | uint64_t Significand() const { 121 | uint64_t d64 = AsUint64(); 122 | uint64_t significand = d64 & kSignificandMask; 123 | if (!IsDenormal()) { 124 | return significand + kHiddenBit; 125 | } else { 126 | return significand; 127 | } 128 | } 129 | 130 | // Returns true if the double is a denormal. 131 | bool IsDenormal() const { 132 | uint64_t d64 = AsUint64(); 133 | return (d64 & kExponentMask) == 0; 134 | } 135 | 136 | // We consider denormals not to be special. 137 | // Hence only Infinity and NaN are special. 138 | bool IsSpecial() const { 139 | uint64_t d64 = AsUint64(); 140 | return (d64 & kExponentMask) == kExponentMask; 141 | } 142 | 143 | bool IsNan() const { 144 | uint64_t d64 = AsUint64(); 145 | return ((d64 & kExponentMask) == kExponentMask) && 146 | ((d64 & kSignificandMask) != 0); 147 | } 148 | 149 | bool IsInfinite() const { 150 | uint64_t d64 = AsUint64(); 151 | return ((d64 & kExponentMask) == kExponentMask) && 152 | ((d64 & kSignificandMask) == 0); 153 | } 154 | 155 | int Sign() const { 156 | uint64_t d64 = AsUint64(); 157 | return (d64 & kSignMask) == 0? 1: -1; 158 | } 159 | 160 | // Precondition: the value encoded by this Double must be greater or equal 161 | // than +0.0. 162 | DiyFp UpperBoundary() const { 163 | ASSERT(Sign() > 0); 164 | return DiyFp(Significand() * 2 + 1, Exponent() - 1); 165 | } 166 | 167 | // Computes the two boundaries of this. 168 | // The bigger boundary (m_plus) is normalized. The lower boundary has the same 169 | // exponent as m_plus. 170 | // Precondition: the value encoded by this Double must be greater than 0. 171 | void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { 172 | ASSERT(value() > 0.0); 173 | DiyFp v = this->AsDiyFp(); 174 | DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); 175 | DiyFp m_minus; 176 | if (LowerBoundaryIsCloser()) { 177 | m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); 178 | } else { 179 | m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); 180 | } 181 | m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); 182 | m_minus.set_e(m_plus.e()); 183 | *out_m_plus = m_plus; 184 | *out_m_minus = m_minus; 185 | } 186 | 187 | bool LowerBoundaryIsCloser() const { 188 | // The boundary is closer if the significand is of the form f == 2^p-1 then 189 | // the lower boundary is closer. 190 | // Think of v = 1000e10 and v- = 9999e9. 191 | // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but 192 | // at a distance of 1e8. 193 | // The only exception is for the smallest normal: the largest denormal is 194 | // at the same distance as its successor. 195 | // Note: denormals have the same exponent as the smallest normals. 196 | bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0); 197 | return physical_significand_is_zero && (Exponent() != kDenormalExponent); 198 | } 199 | 200 | double value() const { return uint64_to_double(d64_); } 201 | 202 | // Returns the significand size for a given order of magnitude. 203 | // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude. 204 | // This function returns the number of significant binary digits v will have 205 | // once it's encoded into a double. In almost all cases this is equal to 206 | // kSignificandSize. The only exceptions are denormals. They start with 207 | // leading zeroes and their effective significand-size is hence smaller. 208 | static int SignificandSizeForOrderOfMagnitude(int order) { 209 | if (order >= (kDenormalExponent + kSignificandSize)) { 210 | return kSignificandSize; 211 | } 212 | if (order <= kDenormalExponent) return 0; 213 | return order - kDenormalExponent; 214 | } 215 | 216 | static double Infinity() { 217 | return Double(kInfinity).value(); 218 | } 219 | 220 | static double NaN() { 221 | return Double(kNaN).value(); 222 | } 223 | 224 | private: 225 | static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; 226 | static const int kDenormalExponent = -kExponentBias + 1; 227 | static const int kMaxExponent = 0x7FF - kExponentBias; 228 | static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); 229 | static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); 230 | 231 | const uint64_t d64_; 232 | 233 | static uint64_t DiyFpToUint64(DiyFp diy_fp) { 234 | uint64_t significand = diy_fp.f(); 235 | int exponent = diy_fp.e(); 236 | while (significand > kHiddenBit + kSignificandMask) { 237 | significand >>= 1; 238 | exponent++; 239 | } 240 | if (exponent >= kMaxExponent) { 241 | return kInfinity; 242 | } 243 | if (exponent < kDenormalExponent) { 244 | return 0; 245 | } 246 | while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) { 247 | significand <<= 1; 248 | exponent--; 249 | } 250 | uint64_t biased_exponent; 251 | if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) { 252 | biased_exponent = 0; 253 | } else { 254 | biased_exponent = static_cast(exponent + kExponentBias); 255 | } 256 | return (significand & kSignificandMask) | 257 | (biased_exponent << kPhysicalSignificandSize); 258 | } 259 | 260 | DISALLOW_COPY_AND_ASSIGN(Double); 261 | }; 262 | 263 | class Single { 264 | public: 265 | static const uint32_t kSignMask = 0x80000000; 266 | static const uint32_t kExponentMask = 0x7F800000; 267 | static const uint32_t kSignificandMask = 0x007FFFFF; 268 | static const uint32_t kHiddenBit = 0x00800000; 269 | static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit. 270 | static const int kSignificandSize = 24; 271 | 272 | Single() : d32_(0) {} 273 | explicit Single(float f) : d32_(float_to_uint32(f)) {} 274 | explicit Single(uint32_t d32) : d32_(d32) {} 275 | 276 | // The value encoded by this Single must be greater or equal to +0.0. 277 | // It must not be special (infinity, or NaN). 278 | DiyFp AsDiyFp() const { 279 | ASSERT(Sign() > 0); 280 | ASSERT(!IsSpecial()); 281 | return DiyFp(Significand(), Exponent()); 282 | } 283 | 284 | // Returns the single's bit as uint64. 285 | uint32_t AsUint32() const { 286 | return d32_; 287 | } 288 | 289 | int Exponent() const { 290 | if (IsDenormal()) return kDenormalExponent; 291 | 292 | uint32_t d32 = AsUint32(); 293 | int biased_e = 294 | static_cast((d32 & kExponentMask) >> kPhysicalSignificandSize); 295 | return biased_e - kExponentBias; 296 | } 297 | 298 | uint32_t Significand() const { 299 | uint32_t d32 = AsUint32(); 300 | uint32_t significand = d32 & kSignificandMask; 301 | if (!IsDenormal()) { 302 | return significand + kHiddenBit; 303 | } else { 304 | return significand; 305 | } 306 | } 307 | 308 | // Returns true if the single is a denormal. 309 | bool IsDenormal() const { 310 | uint32_t d32 = AsUint32(); 311 | return (d32 & kExponentMask) == 0; 312 | } 313 | 314 | // We consider denormals not to be special. 315 | // Hence only Infinity and NaN are special. 316 | bool IsSpecial() const { 317 | uint32_t d32 = AsUint32(); 318 | return (d32 & kExponentMask) == kExponentMask; 319 | } 320 | 321 | bool IsNan() const { 322 | uint32_t d32 = AsUint32(); 323 | return ((d32 & kExponentMask) == kExponentMask) && 324 | ((d32 & kSignificandMask) != 0); 325 | } 326 | 327 | bool IsInfinite() const { 328 | uint32_t d32 = AsUint32(); 329 | return ((d32 & kExponentMask) == kExponentMask) && 330 | ((d32 & kSignificandMask) == 0); 331 | } 332 | 333 | int Sign() const { 334 | uint32_t d32 = AsUint32(); 335 | return (d32 & kSignMask) == 0? 1: -1; 336 | } 337 | 338 | // Computes the two boundaries of this. 339 | // The bigger boundary (m_plus) is normalized. The lower boundary has the same 340 | // exponent as m_plus. 341 | // Precondition: the value encoded by this Single must be greater than 0. 342 | void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { 343 | ASSERT(value() > 0.0); 344 | DiyFp v = this->AsDiyFp(); 345 | DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); 346 | DiyFp m_minus; 347 | if (LowerBoundaryIsCloser()) { 348 | m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); 349 | } else { 350 | m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); 351 | } 352 | m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); 353 | m_minus.set_e(m_plus.e()); 354 | *out_m_plus = m_plus; 355 | *out_m_minus = m_minus; 356 | } 357 | 358 | // Precondition: the value encoded by this Single must be greater or equal 359 | // than +0.0. 360 | DiyFp UpperBoundary() const { 361 | ASSERT(Sign() > 0); 362 | return DiyFp(Significand() * 2 + 1, Exponent() - 1); 363 | } 364 | 365 | bool LowerBoundaryIsCloser() const { 366 | // The boundary is closer if the significand is of the form f == 2^p-1 then 367 | // the lower boundary is closer. 368 | // Think of v = 1000e10 and v- = 9999e9. 369 | // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but 370 | // at a distance of 1e8. 371 | // The only exception is for the smallest normal: the largest denormal is 372 | // at the same distance as its successor. 373 | // Note: denormals have the same exponent as the smallest normals. 374 | bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0); 375 | return physical_significand_is_zero && (Exponent() != kDenormalExponent); 376 | } 377 | 378 | float value() const { return uint32_to_float(d32_); } 379 | 380 | static float Infinity() { 381 | return Single(kInfinity).value(); 382 | } 383 | 384 | static float NaN() { 385 | return Single(kNaN).value(); 386 | } 387 | 388 | private: 389 | static const int kExponentBias = 0x7F + kPhysicalSignificandSize; 390 | static const int kDenormalExponent = -kExponentBias + 1; 391 | static const int kMaxExponent = 0xFF - kExponentBias; 392 | static const uint32_t kInfinity = 0x7F800000; 393 | static const uint32_t kNaN = 0x7FC00000; 394 | 395 | const uint32_t d32_; 396 | 397 | DISALLOW_COPY_AND_ASSIGN(Single); 398 | }; 399 | 400 | } // namespace double_conversion 401 | 402 | #endif // DOUBLE_CONVERSION_DOUBLE_H_ 403 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/strtod.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #include 29 | #include 30 | 31 | #include "strtod.h" 32 | #include "bignum.h" 33 | #include "cached-powers.h" 34 | #include "ieee.h" 35 | 36 | namespace double_conversion { 37 | 38 | // 2^53 = 9007199254740992. 39 | // Any integer with at most 15 decimal digits will hence fit into a double 40 | // (which has a 53bit significand) without loss of precision. 41 | static const int kMaxExactDoubleIntegerDecimalDigits = 15; 42 | // 2^64 = 18446744073709551616 > 10^19 43 | static const int kMaxUint64DecimalDigits = 19; 44 | 45 | // Max double: 1.7976931348623157 x 10^308 46 | // Min non-zero double: 4.9406564584124654 x 10^-324 47 | // Any x >= 10^309 is interpreted as +infinity. 48 | // Any x <= 10^-324 is interpreted as 0. 49 | // Note that 2.5e-324 (despite being smaller than the min double) will be read 50 | // as non-zero (equal to the min non-zero double). 51 | static const int kMaxDecimalPower = 309; 52 | static const int kMinDecimalPower = -324; 53 | 54 | // 2^64 = 18446744073709551616 55 | static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); 56 | 57 | 58 | static const double exact_powers_of_ten[] = { 59 | 1.0, // 10^0 60 | 10.0, 61 | 100.0, 62 | 1000.0, 63 | 10000.0, 64 | 100000.0, 65 | 1000000.0, 66 | 10000000.0, 67 | 100000000.0, 68 | 1000000000.0, 69 | 10000000000.0, // 10^10 70 | 100000000000.0, 71 | 1000000000000.0, 72 | 10000000000000.0, 73 | 100000000000000.0, 74 | 1000000000000000.0, 75 | 10000000000000000.0, 76 | 100000000000000000.0, 77 | 1000000000000000000.0, 78 | 10000000000000000000.0, 79 | 100000000000000000000.0, // 10^20 80 | 1000000000000000000000.0, 81 | // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 82 | 10000000000000000000000.0 83 | }; 84 | static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); 85 | 86 | // Maximum number of significant digits in the decimal representation. 87 | // In fact the value is 772 (see conversions.cc), but to give us some margin 88 | // we round up to 780. 89 | static const int kMaxSignificantDecimalDigits = 780; 90 | 91 | static Vector TrimLeadingZeros(Vector buffer) { 92 | for (int i = 0; i < buffer.length(); i++) { 93 | if (buffer[i] != '0') { 94 | return buffer.SubVector(i, buffer.length()); 95 | } 96 | } 97 | return Vector(buffer.start(), 0); 98 | } 99 | 100 | 101 | static Vector TrimTrailingZeros(Vector buffer) { 102 | for (int i = buffer.length() - 1; i >= 0; --i) { 103 | if (buffer[i] != '0') { 104 | return buffer.SubVector(0, i + 1); 105 | } 106 | } 107 | return Vector(buffer.start(), 0); 108 | } 109 | 110 | 111 | static void CutToMaxSignificantDigits(Vector buffer, 112 | int exponent, 113 | char* significant_buffer, 114 | int* significant_exponent) { 115 | for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { 116 | significant_buffer[i] = buffer[i]; 117 | } 118 | // The input buffer has been trimmed. Therefore the last digit must be 119 | // different from '0'. 120 | ASSERT(buffer[buffer.length() - 1] != '0'); 121 | // Set the last digit to be non-zero. This is sufficient to guarantee 122 | // correct rounding. 123 | significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; 124 | *significant_exponent = 125 | exponent + (buffer.length() - kMaxSignificantDecimalDigits); 126 | } 127 | 128 | 129 | // Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits. 130 | // If possible the input-buffer is reused, but if the buffer needs to be 131 | // modified (due to cutting), then the input needs to be copied into the 132 | // buffer_copy_space. 133 | static void TrimAndCut(Vector buffer, int exponent, 134 | char* buffer_copy_space, int space_size, 135 | Vector* trimmed, int* updated_exponent) { 136 | Vector left_trimmed = TrimLeadingZeros(buffer); 137 | Vector right_trimmed = TrimTrailingZeros(left_trimmed); 138 | exponent += left_trimmed.length() - right_trimmed.length(); 139 | if (right_trimmed.length() > kMaxSignificantDecimalDigits) { 140 | (void) space_size; // Mark variable as used. 141 | ASSERT(space_size >= kMaxSignificantDecimalDigits); 142 | CutToMaxSignificantDigits(right_trimmed, exponent, 143 | buffer_copy_space, updated_exponent); 144 | *trimmed = Vector(buffer_copy_space, 145 | kMaxSignificantDecimalDigits); 146 | } else { 147 | *trimmed = right_trimmed; 148 | *updated_exponent = exponent; 149 | } 150 | } 151 | 152 | 153 | // Reads digits from the buffer and converts them to a uint64. 154 | // Reads in as many digits as fit into a uint64. 155 | // When the string starts with "1844674407370955161" no further digit is read. 156 | // Since 2^64 = 18446744073709551616 it would still be possible read another 157 | // digit if it was less or equal than 6, but this would complicate the code. 158 | static uint64_t ReadUint64(Vector buffer, 159 | int* number_of_read_digits) { 160 | uint64_t result = 0; 161 | int i = 0; 162 | while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { 163 | int digit = buffer[i++] - '0'; 164 | ASSERT(0 <= digit && digit <= 9); 165 | result = 10 * result + digit; 166 | } 167 | *number_of_read_digits = i; 168 | return result; 169 | } 170 | 171 | 172 | // Reads a DiyFp from the buffer. 173 | // The returned DiyFp is not necessarily normalized. 174 | // If remaining_decimals is zero then the returned DiyFp is accurate. 175 | // Otherwise it has been rounded and has error of at most 1/2 ulp. 176 | static void ReadDiyFp(Vector buffer, 177 | DiyFp* result, 178 | int* remaining_decimals) { 179 | int read_digits; 180 | uint64_t significand = ReadUint64(buffer, &read_digits); 181 | if (buffer.length() == read_digits) { 182 | *result = DiyFp(significand, 0); 183 | *remaining_decimals = 0; 184 | } else { 185 | // Round the significand. 186 | if (buffer[read_digits] >= '5') { 187 | significand++; 188 | } 189 | // Compute the binary exponent. 190 | int exponent = 0; 191 | *result = DiyFp(significand, exponent); 192 | *remaining_decimals = buffer.length() - read_digits; 193 | } 194 | } 195 | 196 | 197 | static bool DoubleStrtod(Vector trimmed, 198 | int exponent, 199 | double* result) { 200 | #if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) 201 | // On x86 the floating-point stack can be 64 or 80 bits wide. If it is 202 | // 80 bits wide (as is the case on Linux) then double-rounding occurs and the 203 | // result is not accurate. 204 | // We know that Windows32 uses 64 bits and is therefore accurate. 205 | // Note that the ARM simulator is compiled for 32bits. It therefore exhibits 206 | // the same problem. 207 | return false; 208 | #endif 209 | if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { 210 | int read_digits; 211 | // The trimmed input fits into a double. 212 | // If the 10^exponent (resp. 10^-exponent) fits into a double too then we 213 | // can compute the result-double simply by multiplying (resp. dividing) the 214 | // two numbers. 215 | // This is possible because IEEE guarantees that floating-point operations 216 | // return the best possible approximation. 217 | if (exponent < 0 && -exponent < kExactPowersOfTenSize) { 218 | // 10^-exponent fits into a double. 219 | *result = static_cast(ReadUint64(trimmed, &read_digits)); 220 | ASSERT(read_digits == trimmed.length()); 221 | *result /= exact_powers_of_ten[-exponent]; 222 | return true; 223 | } 224 | if (0 <= exponent && exponent < kExactPowersOfTenSize) { 225 | // 10^exponent fits into a double. 226 | *result = static_cast(ReadUint64(trimmed, &read_digits)); 227 | ASSERT(read_digits == trimmed.length()); 228 | *result *= exact_powers_of_ten[exponent]; 229 | return true; 230 | } 231 | int remaining_digits = 232 | kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); 233 | if ((0 <= exponent) && 234 | (exponent - remaining_digits < kExactPowersOfTenSize)) { 235 | // The trimmed string was short and we can multiply it with 236 | // 10^remaining_digits. As a result the remaining exponent now fits 237 | // into a double too. 238 | *result = static_cast(ReadUint64(trimmed, &read_digits)); 239 | ASSERT(read_digits == trimmed.length()); 240 | *result *= exact_powers_of_ten[remaining_digits]; 241 | *result *= exact_powers_of_ten[exponent - remaining_digits]; 242 | return true; 243 | } 244 | } 245 | return false; 246 | } 247 | 248 | 249 | // Returns 10^exponent as an exact DiyFp. 250 | // The given exponent must be in the range [1; kDecimalExponentDistance[. 251 | static DiyFp AdjustmentPowerOfTen(int exponent) { 252 | ASSERT(0 < exponent); 253 | ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); 254 | // Simply hardcode the remaining powers for the given decimal exponent 255 | // distance. 256 | ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); 257 | switch (exponent) { 258 | case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); 259 | case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); 260 | case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); 261 | case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); 262 | case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); 263 | case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); 264 | case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); 265 | default: 266 | UNREACHABLE(); 267 | } 268 | } 269 | 270 | 271 | // If the function returns true then the result is the correct double. 272 | // Otherwise it is either the correct double or the double that is just below 273 | // the correct double. 274 | static bool DiyFpStrtod(Vector buffer, 275 | int exponent, 276 | double* result) { 277 | DiyFp input; 278 | int remaining_decimals; 279 | ReadDiyFp(buffer, &input, &remaining_decimals); 280 | // Since we may have dropped some digits the input is not accurate. 281 | // If remaining_decimals is different than 0 than the error is at most 282 | // .5 ulp (unit in the last place). 283 | // We don't want to deal with fractions and therefore keep a common 284 | // denominator. 285 | const int kDenominatorLog = 3; 286 | const int kDenominator = 1 << kDenominatorLog; 287 | // Move the remaining decimals into the exponent. 288 | exponent += remaining_decimals; 289 | int error = (remaining_decimals == 0 ? 0 : kDenominator / 2); 290 | 291 | int old_e = input.e(); 292 | input.Normalize(); 293 | error <<= old_e - input.e(); 294 | 295 | ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); 296 | if (exponent < PowersOfTenCache::kMinDecimalExponent) { 297 | *result = 0.0; 298 | return true; 299 | } 300 | DiyFp cached_power; 301 | int cached_decimal_exponent; 302 | PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, 303 | &cached_power, 304 | &cached_decimal_exponent); 305 | 306 | if (cached_decimal_exponent != exponent) { 307 | int adjustment_exponent = exponent - cached_decimal_exponent; 308 | DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); 309 | input.Multiply(adjustment_power); 310 | if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { 311 | // The product of input with the adjustment power fits into a 64 bit 312 | // integer. 313 | ASSERT(DiyFp::kSignificandSize == 64); 314 | } else { 315 | // The adjustment power is exact. There is hence only an error of 0.5. 316 | error += kDenominator / 2; 317 | } 318 | } 319 | 320 | input.Multiply(cached_power); 321 | // The error introduced by a multiplication of a*b equals 322 | // error_a + error_b + error_a*error_b/2^64 + 0.5 323 | // Substituting a with 'input' and b with 'cached_power' we have 324 | // error_b = 0.5 (all cached powers have an error of less than 0.5 ulp), 325 | // error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64 326 | int error_b = kDenominator / 2; 327 | int error_ab = (error == 0 ? 0 : 1); // We round up to 1. 328 | int fixed_error = kDenominator / 2; 329 | error += error_b + error_ab + fixed_error; 330 | 331 | old_e = input.e(); 332 | input.Normalize(); 333 | error <<= old_e - input.e(); 334 | 335 | // See if the double's significand changes if we add/subtract the error. 336 | int order_of_magnitude = DiyFp::kSignificandSize + input.e(); 337 | int effective_significand_size = 338 | Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude); 339 | int precision_digits_count = 340 | DiyFp::kSignificandSize - effective_significand_size; 341 | if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) { 342 | // This can only happen for very small denormals. In this case the 343 | // half-way multiplied by the denominator exceeds the range of an uint64. 344 | // Simply shift everything to the right. 345 | int shift_amount = (precision_digits_count + kDenominatorLog) - 346 | DiyFp::kSignificandSize + 1; 347 | input.set_f(input.f() >> shift_amount); 348 | input.set_e(input.e() + shift_amount); 349 | // We add 1 for the lost precision of error, and kDenominator for 350 | // the lost precision of input.f(). 351 | error = (error >> shift_amount) + 1 + kDenominator; 352 | precision_digits_count -= shift_amount; 353 | } 354 | // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too. 355 | ASSERT(DiyFp::kSignificandSize == 64); 356 | ASSERT(precision_digits_count < 64); 357 | uint64_t one64 = 1; 358 | uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; 359 | uint64_t precision_bits = input.f() & precision_bits_mask; 360 | uint64_t half_way = one64 << (precision_digits_count - 1); 361 | precision_bits *= kDenominator; 362 | half_way *= kDenominator; 363 | DiyFp rounded_input(input.f() >> precision_digits_count, 364 | input.e() + precision_digits_count); 365 | if (precision_bits >= half_way + error) { 366 | rounded_input.set_f(rounded_input.f() + 1); 367 | } 368 | // If the last_bits are too close to the half-way case than we are too 369 | // inaccurate and round down. In this case we return false so that we can 370 | // fall back to a more precise algorithm. 371 | 372 | *result = Double(rounded_input).value(); 373 | if (half_way - error < precision_bits && precision_bits < half_way + error) { 374 | // Too imprecise. The caller will have to fall back to a slower version. 375 | // However the returned number is guaranteed to be either the correct 376 | // double, or the next-lower double. 377 | return false; 378 | } else { 379 | return true; 380 | } 381 | } 382 | 383 | 384 | // Returns 385 | // - -1 if buffer*10^exponent < diy_fp. 386 | // - 0 if buffer*10^exponent == diy_fp. 387 | // - +1 if buffer*10^exponent > diy_fp. 388 | // Preconditions: 389 | // buffer.length() + exponent <= kMaxDecimalPower + 1 390 | // buffer.length() + exponent > kMinDecimalPower 391 | // buffer.length() <= kMaxDecimalSignificantDigits 392 | static int CompareBufferWithDiyFp(Vector buffer, 393 | int exponent, 394 | DiyFp diy_fp) { 395 | ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); 396 | ASSERT(buffer.length() + exponent > kMinDecimalPower); 397 | ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); 398 | // Make sure that the Bignum will be able to hold all our numbers. 399 | // Our Bignum implementation has a separate field for exponents. Shifts will 400 | // consume at most one bigit (< 64 bits). 401 | // ln(10) == 3.3219... 402 | ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); 403 | Bignum buffer_bignum; 404 | Bignum diy_fp_bignum; 405 | buffer_bignum.AssignDecimalString(buffer); 406 | diy_fp_bignum.AssignUInt64(diy_fp.f()); 407 | if (exponent >= 0) { 408 | buffer_bignum.MultiplyByPowerOfTen(exponent); 409 | } else { 410 | diy_fp_bignum.MultiplyByPowerOfTen(-exponent); 411 | } 412 | if (diy_fp.e() > 0) { 413 | diy_fp_bignum.ShiftLeft(diy_fp.e()); 414 | } else { 415 | buffer_bignum.ShiftLeft(-diy_fp.e()); 416 | } 417 | return Bignum::Compare(buffer_bignum, diy_fp_bignum); 418 | } 419 | 420 | 421 | // Returns true if the guess is the correct double. 422 | // Returns false, when guess is either correct or the next-lower double. 423 | static bool ComputeGuess(Vector trimmed, int exponent, 424 | double* guess) { 425 | if (trimmed.length() == 0) { 426 | *guess = 0.0; 427 | return true; 428 | } 429 | if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { 430 | *guess = Double::Infinity(); 431 | return true; 432 | } 433 | if (exponent + trimmed.length() <= kMinDecimalPower) { 434 | *guess = 0.0; 435 | return true; 436 | } 437 | 438 | if (DoubleStrtod(trimmed, exponent, guess) || 439 | DiyFpStrtod(trimmed, exponent, guess)) { 440 | return true; 441 | } 442 | if (*guess == Double::Infinity()) { 443 | return true; 444 | } 445 | return false; 446 | } 447 | 448 | double Strtod(Vector buffer, int exponent) { 449 | char copy_buffer[kMaxSignificantDecimalDigits]; 450 | Vector trimmed; 451 | int updated_exponent; 452 | TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, 453 | &trimmed, &updated_exponent); 454 | exponent = updated_exponent; 455 | 456 | double guess; 457 | bool is_correct = ComputeGuess(trimmed, exponent, &guess); 458 | if (is_correct) return guess; 459 | 460 | DiyFp upper_boundary = Double(guess).UpperBoundary(); 461 | int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); 462 | if (comparison < 0) { 463 | return guess; 464 | } else if (comparison > 0) { 465 | return Double(guess).NextDouble(); 466 | } else if ((Double(guess).Significand() & 1) == 0) { 467 | // Round towards even. 468 | return guess; 469 | } else { 470 | return Double(guess).NextDouble(); 471 | } 472 | } 473 | 474 | float Strtof(Vector buffer, int exponent) { 475 | char copy_buffer[kMaxSignificantDecimalDigits]; 476 | Vector trimmed; 477 | int updated_exponent; 478 | TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, 479 | &trimmed, &updated_exponent); 480 | exponent = updated_exponent; 481 | 482 | double double_guess; 483 | bool is_correct = ComputeGuess(trimmed, exponent, &double_guess); 484 | 485 | float float_guess = static_cast(double_guess); 486 | if (float_guess == double_guess) { 487 | // This shortcut triggers for integer values. 488 | return float_guess; 489 | } 490 | 491 | // We must catch double-rounding. Say the double has been rounded up, and is 492 | // now a boundary of a float, and rounds up again. This is why we have to 493 | // look at previous too. 494 | // Example (in decimal numbers): 495 | // input: 12349 496 | // high-precision (4 digits): 1235 497 | // low-precision (3 digits): 498 | // when read from input: 123 499 | // when rounded from high precision: 124. 500 | // To do this we simply look at the neigbors of the correct result and see 501 | // if they would round to the same float. If the guess is not correct we have 502 | // to look at four values (since two different doubles could be the correct 503 | // double). 504 | 505 | double double_next = Double(double_guess).NextDouble(); 506 | double double_previous = Double(double_guess).PreviousDouble(); 507 | 508 | float f1 = static_cast(double_previous); 509 | float f2 = float_guess; 510 | float f3 = static_cast(double_next); 511 | float f4; 512 | if (is_correct) { 513 | f4 = f3; 514 | } else { 515 | double double_next2 = Double(double_next).NextDouble(); 516 | f4 = static_cast(double_next2); 517 | } 518 | (void) f2; // Mark variable as used. 519 | ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); 520 | 521 | // If the guess doesn't lie near a single-precision boundary we can simply 522 | // return its float-value. 523 | if (f1 == f4) { 524 | return float_guess; 525 | } 526 | 527 | ASSERT((f1 != f2 && f2 == f3 && f3 == f4) || 528 | (f1 == f2 && f2 != f3 && f3 == f4) || 529 | (f1 == f2 && f2 == f3 && f3 != f4)); 530 | 531 | // guess and next are the two possible canditates (in the same way that 532 | // double_guess was the lower candidate for a double-precision guess). 533 | float guess = f1; 534 | float next = f4; 535 | DiyFp upper_boundary; 536 | if (guess == 0.0f) { 537 | float min_float = 1e-45f; 538 | upper_boundary = Double(static_cast(min_float) / 2).AsDiyFp(); 539 | } else { 540 | upper_boundary = Single(guess).UpperBoundary(); 541 | } 542 | int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); 543 | if (comparison < 0) { 544 | return guess; 545 | } else if (comparison > 0) { 546 | return next; 547 | } else if ((Single(guess).Significand() & 1) == 0) { 548 | // Round towards even. 549 | return guess; 550 | } else { 551 | return next; 552 | } 553 | } 554 | 555 | } // namespace double_conversion 556 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/strtod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_STRTOD_H_ 29 | #define DOUBLE_CONVERSION_STRTOD_H_ 30 | 31 | #include "utils.h" 32 | 33 | namespace double_conversion { 34 | 35 | // The buffer must only contain digits in the range [0-9]. It must not 36 | // contain a dot or a sign. It must not start with '0', and must not be empty. 37 | double Strtod(Vector buffer, int exponent); 38 | 39 | // The buffer must only contain digits in the range [0-9]. It must not 40 | // contain a dot or a sign. It must not start with '0', and must not be empty. 41 | float Strtof(Vector buffer, int exponent); 42 | 43 | } // namespace double_conversion 44 | 45 | #endif // DOUBLE_CONVERSION_STRTOD_H_ 46 | -------------------------------------------------------------------------------- /BenchmarkFloatConv/BenchmarkFloatConv/google_double_conversion/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_UTILS_H_ 29 | #define DOUBLE_CONVERSION_UTILS_H_ 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #ifndef ASSERT 36 | #define ASSERT(condition) \ 37 | assert(condition); 38 | #endif 39 | #ifndef UNIMPLEMENTED 40 | #define UNIMPLEMENTED() (abort()) 41 | #endif 42 | #ifndef UNREACHABLE 43 | #define UNREACHABLE() (abort()) 44 | #endif 45 | 46 | // Double operations detection based on target architecture. 47 | // Linux uses a 80bit wide floating point stack on x86. This induces double 48 | // rounding, which in turn leads to wrong results. 49 | // An easy way to test if the floating-point operations are correct is to 50 | // evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then 51 | // the result is equal to 89255e-22. 52 | // The best way to test this, is to create a division-function and to compare 53 | // the output of the division with the expected result. (Inlining must be 54 | // disabled.) 55 | // On Linux,x86 89255e-22 != Div_double(89255.0/1e22) 56 | #if defined(_M_X64) || defined(__x86_64__) || \ 57 | defined(__ARMEL__) || defined(__avr32__) || \ 58 | defined(__hppa__) || defined(__ia64__) || \ 59 | defined(__mips__) || \ 60 | defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ 61 | defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ 62 | defined(__SH4__) || defined(__alpha__) || \ 63 | defined(_MIPS_ARCH_MIPS32R2) || \ 64 | defined(__AARCH64EL__) 65 | #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 66 | #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) 67 | #if defined(_WIN32) 68 | // Windows uses a 64bit wide floating point stack. 69 | #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 70 | #else 71 | #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 72 | #endif // _WIN32 73 | #else 74 | #error Target architecture was not detected as supported by Double-Conversion. 75 | #endif 76 | 77 | #if defined(__GNUC__) 78 | #define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) 79 | #else 80 | #define DOUBLE_CONVERSION_UNUSED 81 | #endif 82 | 83 | #if defined(_WIN32) && !defined(__MINGW32__) 84 | 85 | typedef signed char int8_t; 86 | typedef unsigned char uint8_t; 87 | typedef short int16_t; // NOLINT 88 | typedef unsigned short uint16_t; // NOLINT 89 | typedef int int32_t; 90 | typedef unsigned int uint32_t; 91 | typedef __int64 int64_t; 92 | typedef unsigned __int64 uint64_t; 93 | // intptr_t and friends are defined in crtdefs.h through stdio.h. 94 | 95 | #else 96 | 97 | #include 98 | 99 | #endif 100 | 101 | // The following macro works on both 32 and 64-bit platforms. 102 | // Usage: instead of writing 0x1234567890123456 103 | // write UINT64_2PART_C(0x12345678,90123456); 104 | #define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) 105 | 106 | 107 | // The expression ARRAY_SIZE(a) is a compile-time constant of type 108 | // size_t which represents the number of elements of the given 109 | // array. You should only use ARRAY_SIZE on statically allocated 110 | // arrays. 111 | #ifndef ARRAY_SIZE 112 | #define ARRAY_SIZE(a) \ 113 | ((sizeof(a) / sizeof(*(a))) / \ 114 | static_cast(!(sizeof(a) % sizeof(*(a))))) 115 | #endif 116 | 117 | // A macro to disallow the evil copy constructor and operator= functions 118 | // This should be used in the private: declarations for a class 119 | #ifndef DISALLOW_COPY_AND_ASSIGN 120 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 121 | TypeName(const TypeName&); \ 122 | void operator=(const TypeName&) 123 | #endif 124 | 125 | // A macro to disallow all the implicit constructors, namely the 126 | // default constructor, copy constructor and operator= functions. 127 | // 128 | // This should be used in the private: declarations for a class 129 | // that wants to prevent anyone from instantiating it. This is 130 | // especially useful for classes containing only static methods. 131 | #ifndef DISALLOW_IMPLICIT_CONSTRUCTORS 132 | #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 133 | TypeName(); \ 134 | DISALLOW_COPY_AND_ASSIGN(TypeName) 135 | #endif 136 | 137 | namespace double_conversion { 138 | 139 | static const int kCharSize = sizeof(char); 140 | 141 | // Returns the maximum of the two parameters. 142 | template 143 | static T Max(T a, T b) { 144 | return a < b ? b : a; 145 | } 146 | 147 | 148 | // Returns the minimum of the two parameters. 149 | template 150 | static T Min(T a, T b) { 151 | return a < b ? a : b; 152 | } 153 | 154 | 155 | inline int StrLength(const char* string) { 156 | size_t length = strlen(string); 157 | ASSERT(length == static_cast(static_cast(length))); 158 | return static_cast(length); 159 | } 160 | 161 | // This is a simplified version of V8's Vector class. 162 | template 163 | class Vector { 164 | public: 165 | Vector() : start_(NULL), length_(0) {} 166 | Vector(T* data, int length) : start_(data), length_(length) { 167 | ASSERT(length == 0 || (length > 0 && data != NULL)); 168 | } 169 | 170 | // Returns a vector using the same backing storage as this one, 171 | // spanning from and including 'from', to but not including 'to'. 172 | Vector SubVector(int from, int to) { 173 | ASSERT(to <= length_); 174 | ASSERT(from < to); 175 | ASSERT(0 <= from); 176 | return Vector(start() + from, to - from); 177 | } 178 | 179 | // Returns the length of the vector. 180 | int length() const { return length_; } 181 | 182 | // Returns whether or not the vector is empty. 183 | bool is_empty() const { return length_ == 0; } 184 | 185 | // Returns the pointer to the start of the data in the vector. 186 | T* start() const { return start_; } 187 | 188 | // Access individual vector elements - checks bounds in debug mode. 189 | T& operator[](int index) const { 190 | ASSERT(0 <= index && index < length_); 191 | return start_[index]; 192 | } 193 | 194 | T& first() { return start_[0]; } 195 | 196 | T& last() { return start_[length_ - 1]; } 197 | 198 | private: 199 | T* start_; 200 | int length_; 201 | }; 202 | 203 | 204 | // Helper class for building result strings in a character buffer. The 205 | // purpose of the class is to use safe operations that checks the 206 | // buffer bounds on all operations in debug mode. 207 | class StringBuilder { 208 | public: 209 | StringBuilder(char* buffer, int size) 210 | : buffer_(buffer, size), position_(0) { } 211 | 212 | ~StringBuilder() { if (!is_finalized()) Finalize(); } 213 | 214 | int size() const { return buffer_.length(); } 215 | 216 | // Get the current position in the builder. 217 | int position() const { 218 | ASSERT(!is_finalized()); 219 | return position_; 220 | } 221 | 222 | // Reset the position. 223 | void Reset() { position_ = 0; } 224 | 225 | // Add a single character to the builder. It is not allowed to add 226 | // 0-characters; use the Finalize() method to terminate the string 227 | // instead. 228 | void AddCharacter(char c) { 229 | ASSERT(c != '\0'); 230 | ASSERT(!is_finalized() && position_ < buffer_.length()); 231 | buffer_[position_++] = c; 232 | } 233 | 234 | // Add an entire string to the builder. Uses strlen() internally to 235 | // compute the length of the input string. 236 | void AddString(const char* s) { 237 | AddSubstring(s, StrLength(s)); 238 | } 239 | 240 | // Add the first 'n' characters of the given string 's' to the 241 | // builder. The input string must have enough characters. 242 | void AddSubstring(const char* s, int n) { 243 | ASSERT(!is_finalized() && position_ + n < buffer_.length()); 244 | ASSERT(static_cast(n) <= strlen(s)); 245 | memmove(&buffer_[position_], s, n * kCharSize); 246 | position_ += n; 247 | } 248 | 249 | 250 | // Add character padding to the builder. If count is non-positive, 251 | // nothing is added to the builder. 252 | void AddPadding(char c, int count) { 253 | for (int i = 0; i < count; i++) { 254 | AddCharacter(c); 255 | } 256 | } 257 | 258 | // Finalize the string by 0-terminating it and returning the buffer. 259 | char* Finalize() { 260 | ASSERT(!is_finalized() && position_ < buffer_.length()); 261 | buffer_[position_] = '\0'; 262 | // Make sure nobody managed to add a 0-character to the 263 | // buffer while building the string. 264 | ASSERT(strlen(buffer_.start()) == static_cast(position_)); 265 | position_ = -1; 266 | ASSERT(is_finalized()); 267 | return buffer_.start(); 268 | } 269 | 270 | private: 271 | Vector buffer_; 272 | int position_; 273 | 274 | bool is_finalized() const { return position_ < 0; } 275 | 276 | DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); 277 | }; 278 | 279 | // The type-based aliasing rule allows the compiler to assume that pointers of 280 | // different types (for some definition of different) never alias each other. 281 | // Thus the following code does not work: 282 | // 283 | // float f = foo(); 284 | // int fbits = *(int*)(&f); 285 | // 286 | // The compiler 'knows' that the int pointer can't refer to f since the types 287 | // don't match, so the compiler may cache f in a register, leaving random data 288 | // in fbits. Using C++ style casts makes no difference, however a pointer to 289 | // char data is assumed to alias any other pointer. This is the 'memcpy 290 | // exception'. 291 | // 292 | // Bit_cast uses the memcpy exception to move the bits from a variable of one 293 | // type of a variable of another type. Of course the end result is likely to 294 | // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) 295 | // will completely optimize BitCast away. 296 | // 297 | // There is an additional use for BitCast. 298 | // Recent gccs will warn when they see casts that may result in breakage due to 299 | // the type-based aliasing rule. If you have checked that there is no breakage 300 | // you can use BitCast to cast one pointer type to another. This confuses gcc 301 | // enough that it can no longer see that you have cast one pointer type to 302 | // another thus avoiding the warning. 303 | template 304 | inline Dest BitCast(const Source& source) { 305 | // Compile time assertion: sizeof(Dest) == sizeof(Source) 306 | // A compile error here means your Dest and Source have different sizes. 307 | DOUBLE_CONVERSION_UNUSED 308 | typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; 309 | 310 | Dest dest; 311 | memmove(&dest, &source, sizeof(dest)); 312 | return dest; 313 | } 314 | 315 | template 316 | inline Dest BitCast(Source* source) { 317 | return BitCast(reinterpret_cast(source)); 318 | } 319 | 320 | } // namespace double_conversion 321 | 322 | #endif // DOUBLE_CONVERSION_UTILS_H_ 323 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 shaovoon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C++ String to Float Benchmark 2 | 3 | Looping 1 million times 4 | 5 | ``` 6 | atof: 180ms 7 | lexical_cast: 1309ms 8 | std::istringstream: 1395ms <== Probably unfair comparison since istringstream instaniate a string 9 | std::stod: 255ms 10 | std::strtod: 186ms 11 | crack_atof: 12ms <== Cannot convert float string in scientific notation. 12 | fast_atof: 10ms <== do not use this one because conversion is not correct. 13 | boost_spirit: 52ms <== reported to be inaccurate in some case 14 | google_dconv: 121ms 15 | ``` 16 | 17 | Benchmark Version 1.1 uses crack_atof contributed by Tian Bo which fixes scientific notation conversion problem and and improves performance by 10%. Now crack_atof is as fast as fast_atof. 18 | 19 | ``` 20 | atof: 100ms 21 | lexical_cast: 648ms 22 | std::istringstream: 677ms 23 | std::stod: 109ms 24 | std::strtod: 96ms 25 | crack_atof: 7ms 26 | fast_atof: 7ms 27 | boost_spirit: 17ms 28 | google_dconv: 38ms 29 | std::from_chars: 71ms 30 | ``` 31 | --------------------------------------------------------------------------------