├── .gitignore ├── build ├── premake.bat ├── premake.sh └── premake4.lua ├── license.txt ├── readme.md ├── result ├── corei7920@2.67_cygwin32_gcc4.8.csv ├── corei7920@2.67_cygwin32_gcc4.8.html ├── corei7920@2.67_cygwin64_gcc4.8.csv ├── corei7920@2.67_cygwin64_gcc4.8.html ├── corei7920@2.67_win32_vc2013.csv ├── corei7920@2.67_win32_vc2013.html ├── corei7920@2.67_win64_vc2013.csv ├── corei7920@2.67_win64_vc2013.html ├── corei7920@2.67_win64_vc2013_randomdigit_time.png ├── corei7920@2.67_win64_vc2013_randomdigit_timedigit.png ├── makefile ├── template.php ├── unknown_mac32_clang7.0.csv ├── unknown_mac32_clang7.0.html ├── unknown_mac64_clang7.0.csv └── unknown_mac64_clang7.0.html ├── src ├── double-conversion │ ├── LICENSE │ ├── 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 ├── doubleconvtest.cpp ├── emyg │ ├── emyg_dtoa.c │ └── emyg_dtoa.h ├── emygtest.cpp ├── floaxie │ ├── atof.h │ ├── bit_ops.h │ ├── cached_power.h │ ├── conversion_status.h │ ├── default_fallback.h │ ├── diy_fp.h │ ├── fraction.h │ ├── ftoa.h │ ├── grisu.h │ ├── huge_val.h │ ├── integer_of_size.h │ ├── k_comp.h │ ├── krosh.h │ ├── memwrap.h │ ├── powers_ten.h │ ├── powers_ten_double.h │ ├── powers_ten_single.h │ ├── prettify.h │ ├── print.h │ ├── static_pow.h │ └── type_punning_cast.h ├── floaxietest.cpp ├── fpconv │ ├── fpconv.c │ ├── fpconv.h │ ├── license │ └── powers.h ├── fpconvtest.cpp ├── gay │ ├── dtoa.c │ └── g_fmt.c ├── gaytest.cpp ├── grisu │ ├── LICENSE │ ├── diy_fp.h │ ├── double.h │ ├── fast_exponent.h │ ├── grisu2.h │ ├── grisu2b_59_56.c │ ├── k_comp.h │ ├── powers.h │ ├── powers_ten_round64.h │ └── prettify.h ├── grisu2btest.cpp ├── main.cpp ├── milo │ └── dtoa_milo.h ├── milotest.cpp ├── msinttypes │ ├── inttypes.h │ └── stdint.h ├── null.cpp ├── ostringstream.cpp ├── ostrstream.cpp ├── resultfilename.h ├── sprintf.cpp ├── test.h └── timer.h ├── stb_sprintf.cpp └── stb_sprintf └── stb_sprintf.h /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/* 2 | /build/gmake 3 | /build/vs*/ 4 | /intermediate 5 | result/result.csv 6 | result/result.html 7 | -------------------------------------------------------------------------------- /build/premake.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | premake4 vs2005 3 | premake4 vs2008 4 | premake4 vs2010 5 | premake4 gmake -------------------------------------------------------------------------------- /build/premake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | premake4 vs2005 3 | premake4 vs2008 4 | premake4 vs2010 5 | premake4 gmake 6 | -------------------------------------------------------------------------------- /build/premake4.lua: -------------------------------------------------------------------------------- 1 | function setTargetObjDir(outDir) 2 | for _, cfg in ipairs(configurations()) do 3 | for _, plat in ipairs(platforms()) do 4 | local action = _ACTION or "" 5 | 6 | local prj = project() 7 | 8 | --"_debug_win32_vs2008" 9 | local suffix = "_" .. cfg .. "_" .. plat .. "_" .. action 10 | 11 | targetPath = outDir 12 | 13 | suffix = string.lower(suffix) 14 | 15 | local obj_path = "../intermediate/" .. cfg .. "/" .. action .. "/" .. prj.name 16 | 17 | obj_path = string.lower(obj_path) 18 | 19 | configuration {cfg, plat} 20 | targetdir(targetPath) 21 | objdir(obj_path) 22 | targetsuffix(suffix) 23 | end 24 | end 25 | end 26 | 27 | solution "benchmark" 28 | configurations { "debug", "release" } 29 | platforms { "x32", "x64" } 30 | 31 | location ("./" .. (_ACTION or "")) 32 | language "C++" 33 | flags { "ExtraWarnings" } 34 | defines { "__STDC_FORMAT_MACROS=1" } 35 | 36 | configuration "debug" 37 | defines { "DEBUG" } 38 | flags { "Symbols" } 39 | 40 | configuration "release" 41 | defines { "NDEBUG" } 42 | flags { "Optimize" } 43 | 44 | configuration "vs*" 45 | defines { "_CRT_SECURE_NO_WARNINGS" } 46 | 47 | configuration "gmake" 48 | buildoptions "-msse4.2 -Wall -Wextra" 49 | 50 | project "dtoa" 51 | kind "ConsoleApp" 52 | 53 | files { 54 | "../src/**.h", 55 | "../src/**.cpp", 56 | "../src/**.cc", 57 | "../src/**.c", 58 | } 59 | 60 | setTargetObjDir("../bin") 61 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 Milo Yip 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # dtoa Benchmark 2 | 3 | Copyright(c) 2014 Milo Yip (miloyip@gmail.com) 4 | 5 | ## Introduction 6 | 7 | This benchmark evaluates the performance of conversion from double precision IEEE-754 floating point (`double`) to ASCII string. The function prototype is: 8 | 9 | ~~~~~~~~cpp 10 | void dtoa(double value, char* buffer); 11 | ~~~~~~~~ 12 | 13 | The character string result **must** be convertible to the original value **exactly** via some correct implementation of `strtod()`, i.e. roundtrip convertible. 14 | 15 | Note that `dtoa()` is *not* a standard function in C and C++. 16 | 17 | ## Procedure 18 | 19 | Firstly the program verifies the correctness of implementations. 20 | 21 | Then, one case for benchmark is carried out: 22 | 23 | 1. **RandomDigit**: Generates 1000 random `double` values, filtered out `+/-inf` and `nan`. Then convert them to limited precision (1 to 17 decimal digits in significand). Finally convert these numbers into ASCII. 24 | 25 | Each digit group is run for 100 times. The minimum time duration is measured for 10 trials. 26 | 27 | ## Build and Run 28 | 29 | 1. Obtain [premake4](http://industriousone.com/premake/download). 30 | 2. Copy premake4 executable to `dtoa-benchmark/build` folder (or system path). 31 | 3. Run `premake.bat` or `premake.sh` in `dtoa-benchmark/build` 32 | 4. On Windows, build the solution at `dtoa-benchmark/build/vs2008/` or `/vs2010/`. 33 | 5. On other platforms, run GNU `make config=release32` (or `release64`) at `dtoa-benchmark/build/gmake/` 34 | 6. On success, run the `dtoa` executable is generated at `dtoa-benchmark/` 35 | 7. The results in CSV format will be written to `dtoa-benchmark/result`. 36 | 8. Run GNU `make` in `dtoa-benchmark/result` to generate results in HTML. 37 | 38 | ## Results 39 | 40 | The following are `sequential` results measured on a PC (Core i7 920 @2.67Ghz), where `u32toa()` is compiled by Visual C++ 2013 and run on Windows 64-bit. The speedup is based on `sprintf()`. 41 | 42 | Function  | Time (ns)  | Speedup  43 | --------------|-----------:|-------: 44 | ostringstream | 2,778.748 | 0.45x 45 | ostrstream | 2,628.365 | 0.48x 46 | gay | 1,646.310 | 0.76x 47 | sprintf | 1,256.376 | 1.00x 48 | fpconv | 273.822 | 4.59x 49 | grisu2 | 220.251 | 5.70x 50 | doubleconv | 201.645 | 6.23x 51 | milo | 138.021 | 9.10x 52 | null | 2.146 | 585.58x 53 | 54 | ![corei7920@2.67_win64_vc2013_randomdigit_time](result/corei7920@2.67_win64_vc2013_randomdigit_time.png) 55 | 56 | ![corei7920@2.67_win64_vc2013_randomdigit_timedigit](result/corei7920@2.67_win64_vc2013_randomdigit_timedigit.png) 57 | 58 | Note that the `null` implementation does nothing. It measures the overheads of looping and function call. 59 | 60 | Some results of various configurations are located at `dtoa-benchmark/result`. They can be accessed online, with interactivity provided by [Google Charts](https://developers.google.com/chart/): 61 | 62 | * [corei7920@2.67_win32_vc2013](http://rawgit.com/miloyip/dtoa-benchmark/master/result/corei7920@2.67_win32_vc2013.html) 63 | * [corei7920@2.67_win64_vc2013](http://rawgit.com/miloyip/dtoa-benchmark/master/result/corei7920@2.67_win64_vc2013.html) 64 | * [corei7920@2.67_cygwin32_gcc4.8](http://rawgit.com/miloyip/dtoa-benchmark/master/result/corei7920@2.67_cygwin32_gcc4.8.html) 65 | * [corei7920@2.67_cygwin64_gcc4.8](http://rawgit.com/miloyip/dtoa-benchmark/master/result/corei7920@2.67_cygwin64_gcc4.8.html) 66 | 67 | ## Implementations 68 | 69 | Function  | Description 70 | --------------|----------- 71 | ostringstream | `std::ostringstream` in C++ standard library with `setprecision(17)`. 72 | ostrstream | `std::ostrstream` in C++ standard library with `setprecision(17)`. 73 | sprintf | `sprintf()` in C standard library with `"%.17g"` format. 74 | [stb_sprintf](https://github.com/nothings/stb) | fast sprintf replacement with `"%.17g"` format. 75 | [gay](http://www.netlib.org/fp/) | David M. Gay's `dtoa()` C implementation. 76 | [grisu2](http://florian.loitsch.com/publications/bench.tar.gz?attredirects=0) | Florian Loitsch's Grisu2 C implementation [1]. 77 | [doubleconv](https://code.google.com/p/double-conversion/) | C++ implementation extracted from Google's V8 JavaScript Engine with `EcmaScriptConverter().ToShortest()` (based on Grisu3, fall back to slower bignum algorithm when Grisu3 failed to produce shortest implementation). 78 | [fpconv](https://github.com/night-shift/fpconv) | [night-shift](https://github.com/night-shift)'s Grisu2 C implementation. 79 | milo | [miloyip](https://github.com/miloyip)'s Grisu2 C++ header-only implementation. 80 | null | Do nothing. 81 | 82 | Notes: 83 | 84 | 1. `tostring()` is not tested as it does not fulfill the roundtrip requirement. 85 | 86 | 2. Grisu2 is chosen because it can generate better human-readable number and >99.9% of results are in shortest. Grisu3 needs another `dtoa()` implementation for not meeting the shortest requirement. 87 | 88 | ## FAQ 89 | 90 | 1. How to add an implementation? 91 | 92 | You may clone an existing implementation file. And then modify it. Re-run `premake` to add it to project or makefile. Note that it will automatically register to the benchmark by macro `REGISTER_TEST(name)`. 93 | 94 | Making pull request of new implementations is welcome. 95 | 96 | 2. Why not converting `double` to `std::string`? 97 | 98 | It may introduce heap allocation, which is a big overhead. User can easily wrap these low-level functions to return `std::string`, if needed. 99 | 100 | 3. Why fast `dtoa()` functions is needed? 101 | 102 | They are a very common operations in writing data in text format. The standard way of `sprintf()`, `std::stringstream`, often provides poor performance. The author of this benchmark would optimize the `sprintf` implementation in [RapidJSON](https://github.com/miloyip/rapidjson/), thus he creates this project. 103 | 104 | ## References 105 | 106 | [1] Loitsch, Florian. ["Printing floating-point numbers quickly and accurately with integers."](http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) ACM Sigplan Notices 45.6 (2010): 233-243. 107 | 108 | ## Related Benchmarks and Discussions 109 | 110 | * [Printing Floating-Point Numbers](http://www.ryanjuckett.com/programming/printing-floating-point-numbers/) 111 | -------------------------------------------------------------------------------- /result/corei7920@2.67_cygwin32_gcc4.8.csv: -------------------------------------------------------------------------------- 1 | doubleype,Function,Digit,doubleime(ms) 2 | randomdigit,doubleconv,1,217.500000 3 | randomdigit,doubleconv,2,253.400000 4 | randomdigit,doubleconv,3,255.000000 5 | randomdigit,doubleconv,4,272.500000 6 | randomdigit,doubleconv,5,300.800000 7 | randomdigit,doubleconv,6,314.900000 8 | randomdigit,doubleconv,7,318.700000 9 | randomdigit,doubleconv,8,337.800000 10 | randomdigit,doubleconv,9,348.800000 11 | randomdigit,doubleconv,10,355.300000 12 | randomdigit,doubleconv,11,349.900000 13 | randomdigit,doubleconv,12,377.500000 14 | randomdigit,doubleconv,13,377.500000 15 | randomdigit,doubleconv,14,404.500000 16 | randomdigit,doubleconv,15,406.900000 17 | randomdigit,doubleconv,16,421.000000 18 | randomdigit,doubleconv,17,439.500000 19 | randomdigit,fpconv,1,221.500000 20 | randomdigit,fpconv,2,245.900000 21 | randomdigit,fpconv,3,263.400000 22 | randomdigit,fpconv,4,292.000000 23 | randomdigit,fpconv,5,322.400000 24 | randomdigit,fpconv,6,337.300000 25 | randomdigit,fpconv,7,347.600000 26 | randomdigit,fpconv,8,360.400000 27 | randomdigit,fpconv,9,368.300000 28 | randomdigit,fpconv,10,370.400000 29 | randomdigit,fpconv,11,376.600000 30 | randomdigit,fpconv,12,381.900000 31 | randomdigit,fpconv,13,385.600000 32 | randomdigit,fpconv,14,393.500000 33 | randomdigit,fpconv,15,398.800000 34 | randomdigit,fpconv,16,409.100000 35 | randomdigit,fpconv,17,419.300000 36 | randomdigit,grisu2,1,259.000000 37 | randomdigit,grisu2,2,285.200000 38 | randomdigit,grisu2,3,327.000000 39 | randomdigit,grisu2,4,340.400000 40 | randomdigit,grisu2,5,368.400000 41 | randomdigit,grisu2,6,381.500000 42 | randomdigit,grisu2,7,394.300000 43 | randomdigit,grisu2,8,404.600000 44 | randomdigit,grisu2,9,419.300000 45 | randomdigit,grisu2,10,424.600000 46 | randomdigit,grisu2,11,429.400000 47 | randomdigit,grisu2,12,440.500000 48 | randomdigit,grisu2,13,449.500000 49 | randomdigit,grisu2,14,461.600000 50 | randomdigit,grisu2,15,469.700000 51 | randomdigit,grisu2,16,484.200000 52 | randomdigit,grisu2,17,497.700000 53 | randomdigit,milo,1,114.300000 54 | randomdigit,milo,2,134.800000 55 | randomdigit,milo,3,168.300000 56 | randomdigit,milo,4,179.900000 57 | randomdigit,milo,5,204.000000 58 | randomdigit,milo,6,218.700000 59 | randomdigit,milo,7,229.500000 60 | randomdigit,milo,8,238.900000 61 | randomdigit,milo,9,247.600000 62 | randomdigit,milo,10,253.100000 63 | randomdigit,milo,11,261.000000 64 | randomdigit,milo,12,268.600000 65 | randomdigit,milo,13,278.200000 66 | randomdigit,milo,14,290.100000 67 | randomdigit,milo,15,296.700000 68 | randomdigit,milo,16,306.800000 69 | randomdigit,milo,17,312.700000 70 | randomdigit,null,1,2.200000 71 | randomdigit,null,2,2.200000 72 | randomdigit,null,3,2.300000 73 | randomdigit,null,4,2.200000 74 | randomdigit,null,5,2.100000 75 | randomdigit,null,6,2.400000 76 | randomdigit,null,7,2.300000 77 | randomdigit,null,8,2.200000 78 | randomdigit,null,9,2.100000 79 | randomdigit,null,10,2.400000 80 | randomdigit,null,11,2.100000 81 | randomdigit,null,12,2.200000 82 | randomdigit,null,13,2.500000 83 | randomdigit,null,14,2.500000 84 | randomdigit,null,15,2.500000 85 | randomdigit,null,16,2.500000 86 | randomdigit,null,17,2.600000 87 | randomdigit,ostringstream,1,27840.700000 88 | randomdigit,ostringstream,2,27928.600000 89 | randomdigit,ostringstream,3,28415.000000 90 | randomdigit,ostringstream,4,28211.500000 91 | randomdigit,ostringstream,5,28691.500000 92 | randomdigit,ostringstream,6,28965.700000 93 | randomdigit,ostringstream,7,28937.600000 94 | randomdigit,ostringstream,8,29289.700000 95 | randomdigit,ostringstream,9,29239.700000 96 | randomdigit,ostringstream,10,29659.600000 97 | randomdigit,ostringstream,11,29692.500000 98 | randomdigit,ostringstream,12,29940.400000 99 | randomdigit,ostringstream,13,30202.200000 100 | randomdigit,ostringstream,14,30140.400000 101 | randomdigit,ostringstream,15,30338.200000 102 | randomdigit,ostringstream,16,30254.900000 103 | randomdigit,ostringstream,17,30279.500000 104 | randomdigit,ostrstream,1,27103.500000 105 | randomdigit,ostrstream,2,27230.500000 106 | randomdigit,ostrstream,3,27809.600000 107 | randomdigit,ostrstream,4,27574.000000 108 | randomdigit,ostrstream,5,28044.000000 109 | randomdigit,ostrstream,6,28292.300000 110 | randomdigit,ostrstream,7,28185.000000 111 | randomdigit,ostrstream,8,28582.500000 112 | randomdigit,ostrstream,9,28547.400000 113 | randomdigit,ostrstream,10,28943.300000 114 | randomdigit,ostrstream,11,29040.900000 115 | randomdigit,ostrstream,12,29305.700000 116 | randomdigit,ostrstream,13,29507.500000 117 | randomdigit,ostrstream,14,29456.500000 118 | randomdigit,ostrstream,15,29713.700000 119 | randomdigit,ostrstream,16,29629.600000 120 | randomdigit,ostrstream,17,29580.100000 121 | randomdigit,sprintf,1,25700.900000 122 | randomdigit,sprintf,2,25767.000000 123 | randomdigit,sprintf,3,26311.900000 124 | randomdigit,sprintf,4,26091.100000 125 | randomdigit,sprintf,5,26613.200000 126 | randomdigit,sprintf,6,26876.000000 127 | randomdigit,sprintf,7,26786.200000 128 | randomdigit,sprintf,8,27164.700000 129 | randomdigit,sprintf,9,27181.100000 130 | randomdigit,sprintf,10,27593.100000 131 | randomdigit,sprintf,11,27558.300000 132 | randomdigit,sprintf,12,27812.000000 133 | randomdigit,sprintf,13,28046.200000 134 | randomdigit,sprintf,14,28046.600000 135 | randomdigit,sprintf,15,28203.700000 136 | randomdigit,sprintf,16,28172.700000 137 | randomdigit,sprintf,17,28161.400000 138 | -------------------------------------------------------------------------------- /result/corei7920@2.67_cygwin64_gcc4.8.csv: -------------------------------------------------------------------------------- 1 | doubleype,Function,Digit,doubleime(ms) 2 | randomdigit,doubleconv,1,147.100000 3 | randomdigit,doubleconv,2,162.900000 4 | randomdigit,doubleconv,3,166.800000 5 | randomdigit,doubleconv,4,178.800000 6 | randomdigit,doubleconv,5,184.600000 7 | randomdigit,doubleconv,6,193.900000 8 | randomdigit,doubleconv,7,194.100000 9 | randomdigit,doubleconv,8,202.600000 10 | randomdigit,doubleconv,9,205.400000 11 | randomdigit,doubleconv,10,218.900000 12 | randomdigit,doubleconv,11,209.700000 13 | randomdigit,doubleconv,12,225.500000 14 | randomdigit,doubleconv,13,222.100000 15 | randomdigit,doubleconv,14,239.500000 16 | randomdigit,doubleconv,15,236.700000 17 | randomdigit,doubleconv,16,244.400000 18 | randomdigit,doubleconv,17,258.000000 19 | randomdigit,fpconv,1,158.200000 20 | randomdigit,fpconv,2,176.500000 21 | randomdigit,fpconv,3,192.000000 22 | randomdigit,fpconv,4,209.300000 23 | randomdigit,fpconv,5,220.400000 24 | randomdigit,fpconv,6,228.600000 25 | randomdigit,fpconv,7,238.100000 26 | randomdigit,fpconv,8,245.300000 27 | randomdigit,fpconv,9,243.600000 28 | randomdigit,fpconv,10,247.800000 29 | randomdigit,fpconv,11,252.400000 30 | randomdigit,fpconv,12,255.800000 31 | randomdigit,fpconv,13,258.100000 32 | randomdigit,fpconv,14,263.000000 33 | randomdigit,fpconv,15,264.700000 34 | randomdigit,fpconv,16,282.400000 35 | randomdigit,fpconv,17,276.600000 36 | randomdigit,grisu2,1,195.200000 37 | randomdigit,grisu2,2,209.900000 38 | randomdigit,grisu2,3,215.900000 39 | randomdigit,grisu2,4,218.700000 40 | randomdigit,grisu2,5,222.400000 41 | randomdigit,grisu2,6,230.500000 42 | randomdigit,grisu2,7,251.400000 43 | randomdigit,grisu2,8,252.300000 44 | randomdigit,grisu2,9,246.300000 45 | randomdigit,grisu2,10,253.200000 46 | randomdigit,grisu2,11,256.600000 47 | randomdigit,grisu2,12,258.600000 48 | randomdigit,grisu2,13,265.300000 49 | randomdigit,grisu2,14,270.500000 50 | randomdigit,grisu2,15,275.500000 51 | randomdigit,grisu2,16,278.100000 52 | randomdigit,grisu2,17,289.400000 53 | randomdigit,milo,1,64.700000 54 | randomdigit,milo,2,74.000000 55 | randomdigit,milo,3,82.700000 56 | randomdigit,milo,4,87.200000 57 | randomdigit,milo,5,92.900000 58 | randomdigit,milo,6,100.600000 59 | randomdigit,milo,7,106.400000 60 | randomdigit,milo,8,112.900000 61 | randomdigit,milo,9,116.500000 62 | randomdigit,milo,10,122.000000 63 | randomdigit,milo,11,124.900000 64 | randomdigit,milo,12,130.400000 65 | randomdigit,milo,13,133.200000 66 | randomdigit,milo,14,138.200000 67 | randomdigit,milo,15,141.200000 68 | randomdigit,milo,16,147.500000 69 | randomdigit,milo,17,151.600000 70 | randomdigit,null,1,2.400000 71 | randomdigit,null,2,2.500000 72 | randomdigit,null,3,2.500000 73 | randomdigit,null,4,2.500000 74 | randomdigit,null,5,2.500000 75 | randomdigit,null,6,2.500000 76 | randomdigit,null,7,2.400000 77 | randomdigit,null,8,2.400000 78 | randomdigit,null,9,2.500000 79 | randomdigit,null,10,2.500000 80 | randomdigit,null,11,2.400000 81 | randomdigit,null,12,2.500000 82 | randomdigit,null,13,2.400000 83 | randomdigit,null,14,2.500000 84 | randomdigit,null,15,2.400000 85 | randomdigit,null,16,2.500000 86 | randomdigit,null,17,2.500000 87 | randomdigit,ostringstream,1,27762.600000 88 | randomdigit,ostringstream,2,27869.100000 89 | randomdigit,ostringstream,3,28370.700000 90 | randomdigit,ostringstream,4,28167.200000 91 | randomdigit,ostringstream,5,28682.300000 92 | randomdigit,ostringstream,6,28907.800000 93 | randomdigit,ostringstream,7,28837.400000 94 | randomdigit,ostringstream,8,29257.000000 95 | randomdigit,ostringstream,9,29114.900000 96 | randomdigit,ostringstream,10,29542.300000 97 | randomdigit,ostringstream,11,29575.900000 98 | randomdigit,ostringstream,12,29871.900000 99 | randomdigit,ostringstream,13,30168.700000 100 | randomdigit,ostringstream,14,30028.000000 101 | randomdigit,ostringstream,15,30322.700000 102 | randomdigit,ostringstream,16,30295.900000 103 | randomdigit,ostringstream,17,30310.000000 104 | randomdigit,ostrstream,1,27134.400000 105 | randomdigit,ostrstream,2,27252.700000 106 | randomdigit,ostrstream,3,27842.000000 107 | randomdigit,ostrstream,4,27587.600000 108 | randomdigit,ostrstream,5,28130.800000 109 | randomdigit,ostrstream,6,28373.200000 110 | randomdigit,ostrstream,7,28340.500000 111 | randomdigit,ostrstream,8,28672.400000 112 | randomdigit,ostrstream,9,28608.100000 113 | randomdigit,ostrstream,10,29019.600000 114 | randomdigit,ostrstream,11,29031.700000 115 | randomdigit,ostrstream,12,29316.600000 116 | randomdigit,ostrstream,13,29577.100000 117 | randomdigit,ostrstream,14,29442.700000 118 | randomdigit,ostrstream,15,29683.300000 119 | randomdigit,ostrstream,16,29698.500000 120 | randomdigit,ostrstream,17,29686.500000 121 | randomdigit,sprintf,1,26098.700000 122 | randomdigit,sprintf,2,26255.500000 123 | randomdigit,sprintf,3,26778.900000 124 | randomdigit,sprintf,4,26585.600000 125 | randomdigit,sprintf,5,27087.700000 126 | randomdigit,sprintf,6,27329.800000 127 | randomdigit,sprintf,7,27276.300000 128 | randomdigit,sprintf,8,27654.700000 129 | randomdigit,sprintf,9,27609.800000 130 | randomdigit,sprintf,10,28000.700000 131 | randomdigit,sprintf,11,28049.400000 132 | randomdigit,sprintf,12,28279.400000 133 | randomdigit,sprintf,13,29267.000000 134 | randomdigit,sprintf,14,28797.600000 135 | randomdigit,sprintf,15,29197.700000 136 | randomdigit,sprintf,16,29212.100000 137 | randomdigit,sprintf,17,29144.300000 138 | -------------------------------------------------------------------------------- /result/corei7920@2.67_win32_vc2013.csv: -------------------------------------------------------------------------------- 1 | doubleype,Function,Digit,doubleime(ms) 2 | randomdigit,doubleconv,1,296.024842 3 | randomdigit,doubleconv,2,320.759669 4 | randomdigit,doubleconv,3,326.475958 5 | randomdigit,doubleconv,4,345.670735 6 | randomdigit,doubleconv,5,359.053441 7 | randomdigit,doubleconv,6,386.064055 8 | randomdigit,doubleconv,7,389.221041 9 | randomdigit,doubleconv,8,409.749108 10 | randomdigit,doubleconv,9,415.794888 11 | randomdigit,doubleconv,10,435.614166 12 | randomdigit,doubleconv,11,427.281104 13 | randomdigit,doubleconv,12,458.111517 14 | randomdigit,doubleconv,13,453.544616 15 | randomdigit,doubleconv,14,486.930502 16 | randomdigit,doubleconv,15,481.999628 17 | randomdigit,doubleconv,16,499.520131 18 | randomdigit,doubleconv,17,518.753221 19 | randomdigit,fpconv,1,321.077666 20 | randomdigit,fpconv,2,340.850968 21 | randomdigit,fpconv,3,380.351598 22 | randomdigit,fpconv,4,405.488710 23 | randomdigit,fpconv,5,427.679558 24 | randomdigit,fpconv,6,445.131097 25 | randomdigit,fpconv,7,459.716829 26 | randomdigit,fpconv,8,474.930893 27 | randomdigit,fpconv,9,485.329022 28 | randomdigit,fpconv,10,495.497273 29 | randomdigit,fpconv,11,505.899233 30 | randomdigit,fpconv,12,516.408469 31 | randomdigit,fpconv,13,527.358304 32 | randomdigit,fpconv,14,537.411617 33 | randomdigit,fpconv,15,546.009038 34 | randomdigit,fpconv,16,554.583471 35 | randomdigit,fpconv,17,570.038907 36 | randomdigit,gay,1,866.239988 37 | randomdigit,gay,2,1109.205256 38 | randomdigit,gay,3,1401.670827 39 | randomdigit,gay,4,1671.842105 40 | randomdigit,gay,5,1949.369465 41 | randomdigit,gay,6,2216.502528 42 | randomdigit,gay,7,2483.762023 43 | randomdigit,gay,8,2753.373932 44 | randomdigit,gay,9,3015.323256 45 | randomdigit,gay,10,3263.250047 46 | randomdigit,gay,11,3635.092344 47 | randomdigit,gay,12,3997.210819 48 | randomdigit,gay,13,4271.393460 49 | randomdigit,gay,14,4498.964593 50 | randomdigit,gay,15,4761.189770 51 | randomdigit,gay,16,5046.563618 52 | randomdigit,gay,17,5162.674779 53 | randomdigit,grisu2,1,270.891561 54 | randomdigit,grisu2,2,296.672331 55 | randomdigit,grisu2,3,317.024158 56 | randomdigit,grisu2,4,324.288289 57 | randomdigit,grisu2,5,340.264781 58 | randomdigit,grisu2,6,354.490371 59 | randomdigit,grisu2,7,367.670018 60 | randomdigit,grisu2,8,377.796125 61 | randomdigit,grisu2,9,392.240099 62 | randomdigit,grisu2,10,401.324095 63 | randomdigit,grisu2,11,408.457962 64 | randomdigit,grisu2,12,424.120287 65 | randomdigit,grisu2,13,431.208179 66 | randomdigit,grisu2,14,442.096713 67 | randomdigit,grisu2,15,452.410554 68 | randomdigit,grisu2,16,465.502081 69 | randomdigit,grisu2,17,485.106807 70 | randomdigit,milo,1,181.982579 71 | randomdigit,milo,2,200.142907 72 | randomdigit,milo,3,219.487105 73 | randomdigit,milo,4,232.069071 74 | randomdigit,milo,5,251.026308 75 | randomdigit,milo,6,263.278782 76 | randomdigit,milo,7,276.328166 77 | randomdigit,milo,8,287.580673 78 | randomdigit,milo,9,297.932826 79 | randomdigit,milo,10,306.422971 80 | randomdigit,milo,11,314.652588 81 | randomdigit,milo,12,324.525830 82 | randomdigit,milo,13,332.947011 83 | randomdigit,milo,14,339.931458 84 | randomdigit,milo,15,348.482904 85 | randomdigit,milo,16,356.731677 86 | randomdigit,milo,17,364.141398 87 | randomdigit,null,1,2.498003 88 | randomdigit,null,2,2.498003 89 | randomdigit,null,3,2.498003 90 | randomdigit,null,4,2.498003 91 | randomdigit,null,5,2.498003 92 | randomdigit,null,6,2.498003 93 | randomdigit,null,7,2.498003 94 | randomdigit,null,8,2.498003 95 | randomdigit,null,9,2.498003 96 | randomdigit,null,10,2.498003 97 | randomdigit,null,11,2.498003 98 | randomdigit,null,12,2.498003 99 | randomdigit,null,13,2.498003 100 | randomdigit,null,14,2.498003 101 | randomdigit,null,15,2.498003 102 | randomdigit,null,16,2.498003 103 | randomdigit,null,17,2.498003 104 | randomdigit,ostringstream,1,2874.415967 105 | randomdigit,ostringstream,2,2877.975238 106 | randomdigit,ostringstream,3,2895.043648 107 | randomdigit,ostringstream,4,2899.832764 108 | randomdigit,ostringstream,5,2917.046763 109 | randomdigit,ostringstream,6,2930.402650 110 | randomdigit,ostringstream,7,2937.570999 111 | randomdigit,ostringstream,8,2932.444729 112 | randomdigit,ostringstream,9,2948.459533 113 | randomdigit,ostringstream,10,2980.408684 114 | randomdigit,ostringstream,11,2984.956429 115 | randomdigit,ostringstream,12,2994.316277 116 | randomdigit,ostringstream,13,2995.695542 117 | randomdigit,ostringstream,14,3006.335043 118 | randomdigit,ostringstream,15,3022.234908 119 | randomdigit,ostringstream,16,3010.085878 120 | randomdigit,ostringstream,17,3004.423228 121 | randomdigit,ostrstream,1,2703.996230 122 | randomdigit,ostrstream,2,2703.314260 123 | randomdigit,ostrstream,3,2715.160617 124 | randomdigit,ostrstream,4,2722.424749 125 | randomdigit,ostrstream,5,2732.987623 126 | randomdigit,ostrstream,6,2736.516244 127 | randomdigit,ostrstream,7,2747.826220 128 | randomdigit,ostrstream,8,2753.228343 129 | randomdigit,ostrstream,9,2764.385068 130 | randomdigit,ostrstream,10,2787.012683 131 | randomdigit,ostrstream,11,2792.916706 132 | randomdigit,ostrstream,12,2789.123726 133 | randomdigit,ostrstream,13,2797.606208 134 | randomdigit,ostrstream,14,2813.061644 135 | randomdigit,ostrstream,15,2817.007875 136 | randomdigit,ostrstream,16,2819.620817 137 | randomdigit,ostrstream,17,2803.606013 138 | randomdigit,sprintf,1,1293.486611 139 | randomdigit,sprintf,2,1284.831720 140 | randomdigit,sprintf,3,1301.248810 141 | randomdigit,sprintf,4,1307.076206 142 | randomdigit,sprintf,5,1313.462972 143 | randomdigit,sprintf,6,1319.688822 144 | randomdigit,sprintf,7,1342.557809 145 | randomdigit,sprintf,8,1357.254649 146 | randomdigit,sprintf,9,1361.825381 147 | randomdigit,sprintf,10,1352.170523 148 | randomdigit,sprintf,11,1358.978731 149 | randomdigit,sprintf,12,1354.496118 150 | randomdigit,sprintf,13,1364.361697 151 | randomdigit,sprintf,14,1369.714013 152 | randomdigit,sprintf,15,1362.342606 153 | randomdigit,sprintf,16,1373.514656 154 | randomdigit,sprintf,17,1337.446865 155 | -------------------------------------------------------------------------------- /result/corei7920@2.67_win64_vc2013.csv: -------------------------------------------------------------------------------- 1 | doubleype,Function,Digit,doubleime(ms) 2 | randomdigit,doubleconv,1,150.037259 3 | randomdigit,doubleconv,2,165.439057 4 | randomdigit,doubleconv,3,170.477207 5 | randomdigit,doubleconv,4,180.158884 6 | randomdigit,doubleconv,5,185.319635 7 | randomdigit,doubleconv,6,194.928518 8 | randomdigit,doubleconv,7,192.384539 9 | randomdigit,doubleconv,8,202.123686 10 | randomdigit,doubleconv,9,200.759745 11 | randomdigit,doubleconv,10,209.280541 12 | randomdigit,doubleconv,11,205.725101 13 | randomdigit,doubleconv,12,220.851045 14 | randomdigit,doubleconv,13,215.713281 15 | randomdigit,doubleconv,14,231.283656 16 | randomdigit,doubleconv,15,224.509930 17 | randomdigit,doubleconv,16,232.858317 18 | randomdigit,doubleconv,17,246.106928 19 | randomdigit,fpconv,1,194.510907 20 | randomdigit,fpconv,2,216.548503 21 | randomdigit,fpconv,3,232.636102 22 | randomdigit,fpconv,4,246.907668 23 | randomdigit,fpconv,5,257.179364 24 | randomdigit,fpconv,6,266.205890 25 | randomdigit,fpconv,7,272.964290 26 | randomdigit,fpconv,8,281.071306 27 | randomdigit,fpconv,9,283.488852 28 | randomdigit,fpconv,10,288.707073 29 | randomdigit,fpconv,11,292.277838 30 | randomdigit,fpconv,12,294.883117 31 | randomdigit,fpconv,13,297.480733 32 | randomdigit,fpconv,14,300.300565 33 | randomdigit,fpconv,15,302.859869 34 | randomdigit,fpconv,16,308.982275 35 | randomdigit,fpconv,17,317.966656 36 | randomdigit,gay,1,612.650546 37 | randomdigit,gay,2,740.995025 38 | randomdigit,gay,3,881.258656 39 | randomdigit,gay,4,1005.266112 40 | randomdigit,gay,5,1125.633840 41 | randomdigit,gay,6,1248.258198 42 | randomdigit,gay,7,1368.300266 43 | randomdigit,gay,8,1495.185023 44 | randomdigit,gay,9,1616.928184 45 | randomdigit,gay,10,1739.502737 46 | randomdigit,gay,11,1915.148357 47 | randomdigit,gay,12,2076.472605 48 | randomdigit,gay,13,2196.399734 49 | randomdigit,gay,14,2312.966819 50 | randomdigit,gay,15,2432.445687 51 | randomdigit,gay,16,2576.004230 52 | randomdigit,gay,17,2643.852595 53 | randomdigit,grisu2,1,177.055537 54 | randomdigit,grisu2,2,188.702667 55 | randomdigit,grisu2,3,198.330706 56 | randomdigit,grisu2,4,200.955141 57 | randomdigit,grisu2,5,201.947446 58 | randomdigit,grisu2,6,207.223136 59 | randomdigit,grisu2,7,210.705782 60 | randomdigit,grisu2,8,217.678735 61 | randomdigit,grisu2,9,220.004329 62 | randomdigit,grisu2,10,226.919813 63 | randomdigit,grisu2,11,227.804842 64 | randomdigit,grisu2,12,234.996178 65 | randomdigit,grisu2,13,236.038290 66 | randomdigit,grisu2,14,241.130078 67 | randomdigit,grisu2,15,245.294693 68 | randomdigit,grisu2,16,248.627918 69 | randomdigit,grisu2,17,260.845911 70 | randomdigit,milo,1,92.905020 71 | randomdigit,milo,2,106.590398 72 | randomdigit,milo,3,117.214573 73 | randomdigit,milo,4,122.923200 74 | randomdigit,milo,5,125.306264 75 | randomdigit,milo,6,131.543609 76 | randomdigit,milo,7,134.639293 77 | randomdigit,milo,8,139.899658 78 | randomdigit,milo,9,143.160089 79 | randomdigit,milo,10,144.960796 80 | randomdigit,milo,11,147.033526 81 | randomdigit,milo,12,150.937613 82 | randomdigit,milo,13,152.949042 83 | randomdigit,milo,14,154.864688 84 | randomdigit,milo,15,155.807186 85 | randomdigit,milo,16,160.328112 86 | randomdigit,milo,17,165.297299 87 | randomdigit,null,1,2.145524 88 | randomdigit,null,2,2.145524 89 | randomdigit,null,3,2.145524 90 | randomdigit,null,4,2.145524 91 | randomdigit,null,5,2.145524 92 | randomdigit,null,6,2.145524 93 | randomdigit,null,7,2.145524 94 | randomdigit,null,8,2.145524 95 | randomdigit,null,9,2.145524 96 | randomdigit,null,10,2.145524 97 | randomdigit,null,11,2.145524 98 | randomdigit,null,12,2.145524 99 | randomdigit,null,13,2.145524 100 | randomdigit,null,14,2.145524 101 | randomdigit,null,15,2.145524 102 | randomdigit,null,16,2.145524 103 | randomdigit,null,17,2.145524 104 | randomdigit,ostringstream,1,2725.930382 105 | randomdigit,ostringstream,2,2733.416728 106 | randomdigit,ostringstream,3,2728.409228 107 | randomdigit,ostringstream,4,2738.684755 108 | randomdigit,ostringstream,5,2756.170776 109 | randomdigit,ostringstream,6,2751.672838 110 | randomdigit,ostringstream,7,2759.473350 111 | randomdigit,ostringstream,8,2757.599848 112 | randomdigit,ostringstream,9,2774.492018 113 | randomdigit,ostringstream,10,2793.728940 114 | randomdigit,ostringstream,11,2795.288276 115 | randomdigit,ostringstream,12,2806.920081 116 | randomdigit,ostringstream,13,2811.483151 117 | randomdigit,ostringstream,14,2819.456071 118 | randomdigit,ostringstream,15,2833.440290 119 | randomdigit,ostringstream,16,2834.524546 120 | randomdigit,ostringstream,17,2818.023168 121 | randomdigit,ostrstream,1,2578.214886 122 | randomdigit,ostrstream,2,2574.460219 123 | randomdigit,ostrstream,3,2594.202871 124 | randomdigit,ostrstream,4,2595.118550 125 | randomdigit,ostrstream,5,2610.696587 126 | randomdigit,ostrstream,6,2609.987797 127 | randomdigit,ostrstream,7,2619.228876 128 | randomdigit,ostrstream,8,2612.646715 129 | randomdigit,ostrstream,9,2626.473850 130 | randomdigit,ostrstream,10,2642.496317 131 | randomdigit,ostrstream,11,2641.829672 132 | randomdigit,ostrstream,12,2651.300628 133 | randomdigit,ostrstream,13,2654.948019 134 | randomdigit,ostrstream,14,2652.856133 135 | randomdigit,ostrstream,15,2683.096528 136 | randomdigit,ostrstream,16,2670.326828 137 | randomdigit,ostrstream,17,2664.323193 138 | randomdigit,sprintf,1,1224.186186 139 | randomdigit,sprintf,2,1225.856629 140 | randomdigit,sprintf,3,1240.132026 141 | randomdigit,sprintf,4,1236.618731 142 | randomdigit,sprintf,5,1252.874906 143 | randomdigit,sprintf,6,1250.668082 144 | randomdigit,sprintf,7,1253.177579 145 | randomdigit,sprintf,8,1251.855782 146 | randomdigit,sprintf,9,1255.909290 147 | randomdigit,sprintf,10,1254.733083 148 | randomdigit,sprintf,11,1253.690972 149 | randomdigit,sprintf,12,1256.392033 150 | randomdigit,sprintf,13,1261.801819 151 | randomdigit,sprintf,14,1258.277029 152 | randomdigit,sprintf,15,1267.311218 153 | randomdigit,sprintf,16,1313.436152 154 | randomdigit,sprintf,17,1301.463362 155 | -------------------------------------------------------------------------------- /result/corei7920@2.67_win64_vc2013_randomdigit_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miloyip/dtoa-benchmark/bf1fb58ade01658c908a498679e47f0b4e89aff7/result/corei7920@2.67_win64_vc2013_randomdigit_time.png -------------------------------------------------------------------------------- /result/corei7920@2.67_win64_vc2013_randomdigit_timedigit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miloyip/dtoa-benchmark/bf1fb58ade01658c908a498679e47f0b4e89aff7/result/corei7920@2.67_win64_vc2013_randomdigit_timedigit.png -------------------------------------------------------------------------------- /result/makefile: -------------------------------------------------------------------------------- 1 | %.html: %.csv template.php 2 | php template.php $< > $@ 3 | 4 | CSVFILES = $(basename $(wildcard *.csv)) 5 | all: $(addsuffix .html, $(CSVFILES)) 6 | -------------------------------------------------------------------------------- /result/unknown_mac32_clang7.0.csv: -------------------------------------------------------------------------------- 1 | Type,Function,Digit,Time(ns) 2 | randomdigit,doubleconv,1,119.300000 3 | randomdigit,doubleconv,2,133.000000 4 | randomdigit,doubleconv,3,136.000000 5 | randomdigit,doubleconv,4,146.000000 6 | randomdigit,doubleconv,5,152.800000 7 | randomdigit,doubleconv,6,161.500000 8 | randomdigit,doubleconv,7,164.300000 9 | randomdigit,doubleconv,8,173.700000 10 | randomdigit,doubleconv,9,177.400000 11 | randomdigit,doubleconv,10,185.300000 12 | randomdigit,doubleconv,11,184.800000 13 | randomdigit,doubleconv,12,199.400000 14 | randomdigit,doubleconv,13,199.100000 15 | randomdigit,doubleconv,14,214.000000 16 | randomdigit,doubleconv,15,214.900000 17 | randomdigit,doubleconv,16,225.000000 18 | randomdigit,doubleconv,17,239.900000 19 | randomdigit,emyg,1,74.800000 20 | randomdigit,emyg,2,84.600000 21 | randomdigit,emyg,3,91.300000 22 | randomdigit,emyg,4,97.100000 23 | randomdigit,emyg,5,107.800000 24 | randomdigit,emyg,6,107.800000 25 | randomdigit,emyg,7,113.900000 26 | randomdigit,emyg,8,120.700000 27 | randomdigit,emyg,9,125.600000 28 | randomdigit,emyg,10,130.600000 29 | randomdigit,emyg,11,136.500000 30 | randomdigit,emyg,12,143.100000 31 | randomdigit,emyg,13,147.900000 32 | randomdigit,emyg,14,153.300000 33 | randomdigit,emyg,15,159.800000 34 | randomdigit,emyg,16,166.300000 35 | randomdigit,emyg,17,173.200000 36 | randomdigit,fpconv,1,171.800000 37 | randomdigit,fpconv,2,190.500000 38 | randomdigit,fpconv,3,208.000000 39 | randomdigit,fpconv,4,222.500000 40 | randomdigit,fpconv,5,233.900000 41 | randomdigit,fpconv,6,244.900000 42 | randomdigit,fpconv,7,257.100000 43 | randomdigit,fpconv,8,263.100000 44 | randomdigit,fpconv,9,266.700000 45 | randomdigit,fpconv,10,271.400000 46 | randomdigit,fpconv,11,275.700000 47 | randomdigit,fpconv,12,279.600000 48 | randomdigit,fpconv,13,283.700000 49 | randomdigit,fpconv,14,288.000000 50 | randomdigit,fpconv,15,292.300000 51 | randomdigit,fpconv,16,297.200000 52 | randomdigit,fpconv,17,310.800000 53 | randomdigit,grisu2,1,151.500000 54 | randomdigit,grisu2,2,165.600000 55 | randomdigit,grisu2,3,170.100000 56 | randomdigit,grisu2,4,175.600000 57 | randomdigit,grisu2,5,179.800000 58 | randomdigit,grisu2,6,186.600000 59 | randomdigit,grisu2,7,193.200000 60 | randomdigit,grisu2,8,200.000000 61 | randomdigit,grisu2,9,206.800000 62 | randomdigit,grisu2,10,212.800000 63 | randomdigit,grisu2,11,218.700000 64 | randomdigit,grisu2,12,226.000000 65 | randomdigit,grisu2,13,230.600000 66 | randomdigit,grisu2,14,237.700000 67 | randomdigit,grisu2,15,244.100000 68 | randomdigit,grisu2,16,251.700000 69 | randomdigit,grisu2,17,264.400000 70 | randomdigit,milo,1,87.400000 71 | randomdigit,milo,2,96.400000 72 | randomdigit,milo,3,101.300000 73 | randomdigit,milo,4,108.000000 74 | randomdigit,milo,5,117.300000 75 | randomdigit,milo,6,116.500000 76 | randomdigit,milo,7,122.700000 77 | randomdigit,milo,8,129.500000 78 | randomdigit,milo,9,134.100000 79 | randomdigit,milo,10,140.100000 80 | randomdigit,milo,11,146.100000 81 | randomdigit,milo,12,152.500000 82 | randomdigit,milo,13,157.600000 83 | randomdigit,milo,14,163.400000 84 | randomdigit,milo,15,168.500000 85 | randomdigit,milo,16,175.800000 86 | randomdigit,milo,17,184.400000 87 | randomdigit,null,1,1.800000 88 | randomdigit,null,2,1.800000 89 | randomdigit,null,3,1.800000 90 | randomdigit,null,4,1.800000 91 | randomdigit,null,5,1.800000 92 | randomdigit,null,6,1.800000 93 | randomdigit,null,7,1.800000 94 | randomdigit,null,8,1.800000 95 | randomdigit,null,9,1.800000 96 | randomdigit,null,10,1.800000 97 | randomdigit,null,11,1.800000 98 | randomdigit,null,12,1.800000 99 | randomdigit,null,13,1.800000 100 | randomdigit,null,14,1.800000 101 | randomdigit,null,15,1.800000 102 | randomdigit,null,16,1.800000 103 | randomdigit,null,17,1.800000 104 | randomdigit,ostringstream,1,1998.500000 105 | randomdigit,ostringstream,2,2007.200000 106 | randomdigit,ostringstream,3,2041.000000 107 | randomdigit,ostringstream,4,2086.600000 108 | randomdigit,ostringstream,5,2142.300000 109 | randomdigit,ostringstream,6,2170.300000 110 | randomdigit,ostringstream,7,2196.900000 111 | randomdigit,ostringstream,8,2226.600000 112 | randomdigit,ostringstream,9,2192.700000 113 | randomdigit,ostringstream,10,2180.400000 114 | randomdigit,ostringstream,11,2217.400000 115 | randomdigit,ostringstream,12,2241.200000 116 | randomdigit,ostringstream,13,2276.100000 117 | randomdigit,ostringstream,14,2269.100000 118 | randomdigit,ostringstream,15,2266.200000 119 | randomdigit,ostringstream,16,2281.700000 120 | randomdigit,ostringstream,17,2267.900000 121 | randomdigit,ostrstream,1,1794.300000 122 | randomdigit,ostrstream,2,1795.200000 123 | randomdigit,ostrstream,3,1844.200000 124 | randomdigit,ostrstream,4,1853.000000 125 | randomdigit,ostrstream,5,1882.700000 126 | randomdigit,ostrstream,6,1901.700000 127 | randomdigit,ostrstream,7,1920.100000 128 | randomdigit,ostrstream,8,1944.200000 129 | randomdigit,ostrstream,9,1914.100000 130 | randomdigit,ostrstream,10,1903.400000 131 | randomdigit,ostrstream,11,1954.000000 132 | randomdigit,ostrstream,12,1985.000000 133 | randomdigit,ostrstream,13,2014.200000 134 | randomdigit,ostrstream,14,1997.400000 135 | randomdigit,ostrstream,15,2014.600000 136 | randomdigit,ostrstream,16,2023.000000 137 | randomdigit,ostrstream,17,1996.800000 138 | randomdigit,sprintf,1,1512.900000 139 | randomdigit,sprintf,2,1511.200000 140 | randomdigit,sprintf,3,1561.200000 141 | randomdigit,sprintf,4,1577.900000 142 | randomdigit,sprintf,5,1612.100000 143 | randomdigit,sprintf,6,1631.700000 144 | randomdigit,sprintf,7,1645.900000 145 | randomdigit,sprintf,8,1666.700000 146 | randomdigit,sprintf,9,1639.200000 147 | randomdigit,sprintf,10,1630.900000 148 | randomdigit,sprintf,11,1674.600000 149 | randomdigit,sprintf,12,1704.700000 150 | randomdigit,sprintf,13,1724.900000 151 | randomdigit,sprintf,14,1716.600000 152 | randomdigit,sprintf,15,1730.000000 153 | randomdigit,sprintf,16,1739.600000 154 | randomdigit,sprintf,17,1729.200000 155 | -------------------------------------------------------------------------------- /result/unknown_mac64_clang7.0.csv: -------------------------------------------------------------------------------- 1 | Type,Function,Digit,Time(ns) 2 | randomdigit,doubleconv,1,73.600000 3 | randomdigit,doubleconv,2,86.200000 4 | randomdigit,doubleconv,3,91.000000 5 | randomdigit,doubleconv,4,98.400000 6 | randomdigit,doubleconv,5,101.800000 7 | randomdigit,doubleconv,6,105.500000 8 | randomdigit,doubleconv,7,104.500000 9 | randomdigit,doubleconv,8,108.500000 10 | randomdigit,doubleconv,9,106.700000 11 | randomdigit,doubleconv,10,108.600000 12 | randomdigit,doubleconv,11,108.800000 13 | randomdigit,doubleconv,12,114.000000 14 | randomdigit,doubleconv,13,112.400000 15 | randomdigit,doubleconv,14,120.900000 16 | randomdigit,doubleconv,15,119.700000 17 | randomdigit,doubleconv,16,123.700000 18 | randomdigit,doubleconv,17,129.900000 19 | randomdigit,emyg,1,46.200000 20 | randomdigit,emyg,2,52.700000 21 | randomdigit,emyg,3,56.200000 22 | randomdigit,emyg,4,60.800000 23 | randomdigit,emyg,5,62.700000 24 | randomdigit,emyg,6,65.100000 25 | randomdigit,emyg,7,70.500000 26 | randomdigit,emyg,8,71.700000 27 | randomdigit,emyg,9,72.000000 28 | randomdigit,emyg,10,70.500000 29 | randomdigit,emyg,11,71.900000 30 | randomdigit,emyg,12,74.300000 31 | randomdigit,emyg,13,76.500000 32 | randomdigit,emyg,14,78.300000 33 | randomdigit,emyg,15,80.800000 34 | randomdigit,emyg,16,83.200000 35 | randomdigit,emyg,17,86.200000 36 | randomdigit,fpconv,1,105.600000 37 | randomdigit,fpconv,2,117.600000 38 | randomdigit,fpconv,3,127.200000 39 | randomdigit,fpconv,4,134.300000 40 | randomdigit,fpconv,5,141.200000 41 | randomdigit,fpconv,6,146.200000 42 | randomdigit,fpconv,7,150.800000 43 | randomdigit,fpconv,8,153.800000 44 | randomdigit,fpconv,9,153.200000 45 | randomdigit,fpconv,10,154.400000 46 | randomdigit,fpconv,11,155.800000 47 | randomdigit,fpconv,12,157.100000 48 | randomdigit,fpconv,13,159.100000 49 | randomdigit,fpconv,14,160.800000 50 | randomdigit,fpconv,15,161.700000 51 | randomdigit,fpconv,16,164.100000 52 | randomdigit,fpconv,17,172.000000 53 | randomdigit,grisu2,1,111.800000 54 | randomdigit,grisu2,2,123.700000 55 | randomdigit,grisu2,3,120.300000 56 | randomdigit,grisu2,4,121.600000 57 | randomdigit,grisu2,5,121.800000 58 | randomdigit,grisu2,6,124.600000 59 | randomdigit,grisu2,7,126.600000 60 | randomdigit,grisu2,8,128.800000 61 | randomdigit,grisu2,9,130.600000 62 | randomdigit,grisu2,10,132.800000 63 | randomdigit,grisu2,11,134.400000 64 | randomdigit,grisu2,12,136.900000 65 | randomdigit,grisu2,13,137.900000 66 | randomdigit,grisu2,14,140.400000 67 | randomdigit,grisu2,15,142.800000 68 | randomdigit,grisu2,16,145.100000 69 | randomdigit,grisu2,17,151.700000 70 | randomdigit,milo,1,54.700000 71 | randomdigit,milo,2,60.300000 72 | randomdigit,milo,3,63.800000 73 | randomdigit,milo,4,68.100000 74 | randomdigit,milo,5,70.600000 75 | randomdigit,milo,6,72.100000 76 | randomdigit,milo,7,77.100000 77 | randomdigit,milo,8,76.800000 78 | randomdigit,milo,9,77.900000 79 | randomdigit,milo,10,79.400000 80 | randomdigit,milo,11,82.000000 81 | randomdigit,milo,12,85.400000 82 | randomdigit,milo,13,88.500000 83 | randomdigit,milo,14,91.500000 84 | randomdigit,milo,15,94.200000 85 | randomdigit,milo,16,98.100000 86 | randomdigit,milo,17,103.300000 87 | randomdigit,null,1,1.500000 88 | randomdigit,null,2,1.500000 89 | randomdigit,null,3,1.400000 90 | randomdigit,null,4,1.400000 91 | randomdigit,null,5,1.400000 92 | randomdigit,null,6,1.400000 93 | randomdigit,null,7,1.400000 94 | randomdigit,null,8,1.400000 95 | randomdigit,null,9,1.400000 96 | randomdigit,null,10,1.400000 97 | randomdigit,null,11,1.400000 98 | randomdigit,null,12,1.400000 99 | randomdigit,null,13,1.400000 100 | randomdigit,null,14,1.400000 101 | randomdigit,null,15,1.400000 102 | randomdigit,null,16,1.400000 103 | randomdigit,null,17,1.400000 104 | randomdigit,ostringstream,1,1738.400000 105 | randomdigit,ostringstream,2,1764.100000 106 | randomdigit,ostringstream,3,1794.900000 107 | randomdigit,ostringstream,4,1821.500000 108 | randomdigit,ostringstream,5,1826.700000 109 | randomdigit,ostringstream,6,1825.500000 110 | randomdigit,ostringstream,7,1817.200000 111 | randomdigit,ostringstream,8,1824.200000 112 | randomdigit,ostringstream,9,1815.100000 113 | randomdigit,ostringstream,10,1704.400000 114 | randomdigit,ostringstream,11,1792.400000 115 | randomdigit,ostringstream,12,1865.500000 116 | randomdigit,ostringstream,13,1798.000000 117 | randomdigit,ostringstream,14,1778.300000 118 | randomdigit,ostringstream,15,1849.800000 119 | randomdigit,ostringstream,16,1879.400000 120 | randomdigit,ostringstream,17,1798.000000 121 | randomdigit,ostrstream,1,1281.400000 122 | randomdigit,ostrstream,2,1280.800000 123 | randomdigit,ostrstream,3,1311.100000 124 | randomdigit,ostrstream,4,1318.100000 125 | randomdigit,ostrstream,5,1332.400000 126 | randomdigit,ostrstream,6,1346.800000 127 | randomdigit,ostrstream,7,1354.400000 128 | randomdigit,ostrstream,8,1374.900000 129 | randomdigit,ostrstream,9,1346.500000 130 | randomdigit,ostrstream,10,1343.800000 131 | randomdigit,ostrstream,11,1364.100000 132 | randomdigit,ostrstream,12,1383.400000 133 | randomdigit,ostrstream,13,1397.900000 134 | randomdigit,ostrstream,14,1388.800000 135 | randomdigit,ostrstream,15,1404.800000 136 | randomdigit,ostrstream,16,1395.500000 137 | randomdigit,ostrstream,17,1391.800000 138 | randomdigit,sprintf,1,1040.200000 139 | randomdigit,sprintf,2,1043.000000 140 | randomdigit,sprintf,3,1074.000000 141 | randomdigit,sprintf,4,1084.500000 142 | randomdigit,sprintf,5,1098.400000 143 | randomdigit,sprintf,6,1111.600000 144 | randomdigit,sprintf,7,1117.400000 145 | randomdigit,sprintf,8,1136.700000 146 | randomdigit,sprintf,9,1109.200000 147 | randomdigit,sprintf,10,1099.600000 148 | randomdigit,sprintf,11,1125.700000 149 | randomdigit,sprintf,12,1143.800000 150 | randomdigit,sprintf,13,1154.500000 151 | randomdigit,sprintf,14,1149.000000 152 | randomdigit,sprintf,15,1153.400000 153 | randomdigit,sprintf,16,1155.000000 154 | randomdigit,sprintf,17,1146.200000 155 | -------------------------------------------------------------------------------- /src/double-conversion/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2006-2011, 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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/doubleconvtest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include "double-conversion/double-conversion.h" 3 | 4 | using namespace double_conversion; 5 | 6 | void dtoa_doubleconv(double value, char* buffer) { 7 | StringBuilder sb(buffer, 26); 8 | DoubleToStringConverter::EcmaScriptConverter().ToShortest(value, &sb); 9 | } 10 | 11 | REGISTER_TEST(doubleconv); 12 | -------------------------------------------------------------------------------- /src/emyg/emyg_dtoa.h: -------------------------------------------------------------------------------- 1 | /* emyg_dtoa.h */ 2 | 3 | void emyg_dtoa (double value, char* buffer); 4 | -------------------------------------------------------------------------------- /src/emygtest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | extern "C" { 4 | #include "emyg/emyg_dtoa.h" 5 | } 6 | 7 | #define dtoa_emyg emyg_dtoa 8 | 9 | REGISTER_TEST(emyg); 10 | -------------------------------------------------------------------------------- /src/floaxie/atof.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016, 2017 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_ATOF_H 18 | #define FLOAXIE_ATOF_H 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "default_fallback.h" 25 | 26 | #include "conversion_status.h" 27 | 28 | /** \brief Floaxie functions templates. 29 | * 30 | * This namespace contains two main public floaxie functions (`atof()` and 31 | * `ftoa()`), as well as several helper functions (e.g. `max_buffer_size()`) 32 | * and internal type and function templates. 33 | */ 34 | namespace floaxie 35 | { 36 | /** \brief Small decorator around returning value to help the client 37 | * optionally receive minor error states along with it. 38 | * 39 | * \tparam FloatType target floating point type to store results. 40 | */ 41 | template struct value_and_status 42 | { 43 | /** \brief The returning result value itself. */ 44 | FloatType value; 45 | /** \brief Conversion status indicating any problems occurred. */ 46 | conversion_status status; 47 | 48 | /** \brief Constructs the object with empty value and successful status */ 49 | value_and_status() noexcept : value(), status(conversion_status::success) { } 50 | /** \brief Default conversion operator to `FloatType` to make use of the 51 | * wrapper more transparent. */ 52 | operator FloatType() const noexcept { return value; } 53 | }; 54 | 55 | /** \brief Parses floating point string representation. 56 | * 57 | * Interprets string representation of floating point value using Krosh 58 | * algorithm and, if successful, value of the specified type is returned. 59 | * 60 | * The accepted representation format is ordinary or exponential decimal 61 | * floating point expression, containing: 62 | * - optional sign ('+' or '-') 63 | * - sequence of one or more decimal digits optionally containing decimal 64 | * point character ('.') 65 | * - optional 'e' of 'E' character followed by optional sign ('+' or '-') 66 | * and sequence of one or more decimal digits. 67 | * 68 | * Function doesn't expects any preceding spacing characters and treats the 69 | * representation as incorrect, if there's any. 70 | * 71 | * \tparam FloatType target floating point type to store results. 72 | * \tparam CharType character type (typically `char` or `wchar_t`) the input 73 | * string \p **str** consists of. 74 | * \tparam FallbackCallable fallback conversion function type, in case of 75 | * Krosh is unsure if the result is correctly rounded (default is `strtof()` 76 | * for `float`'s, `strtod()` for `double`'s, `strtold()` for `long double`'s). 77 | * 78 | * \param str buffer containing the string representation of the value. 79 | * \param str_end out parameter, which will contain a pointer to first 80 | * character after the parsed value in the specified buffer. If str_end is 81 | * NULL, it is ignored. 82 | * \param fallback_func pointer to fallback function. 83 | * 84 | * \return parsed value, if the input is correct, default constructed value 85 | * otherwise. 86 | */ 87 | template 88 | < 89 | typename FloatType, 90 | typename CharType, 91 | typename FallbackCallable = FloatType (const CharType*, CharType**) 92 | > 93 | inline value_and_status atof(const CharType* str, CharType** str_end, FallbackCallable fallback_func = default_fallback) 94 | { 95 | value_and_status result; 96 | 97 | const auto& cr(krosh(str)); 98 | 99 | if (cr.str_end != str) 100 | { 101 | if (cr.is_accurate) 102 | { 103 | result.value = cr.value; 104 | result.status = cr.status; 105 | } 106 | else 107 | { 108 | result.value = fallback_func(str, str_end); 109 | result.status = check_errno(result.value); 110 | 111 | return result; 112 | } 113 | } 114 | 115 | if (str_end) 116 | *str_end = const_cast(cr.str_end); 117 | 118 | return result; 119 | } 120 | 121 | /** \brief Tiny overload for `atof()` function to allow passing `nullptr` 122 | * as `str_end` parameter. 123 | */ 124 | template 125 | < 126 | typename FloatType, 127 | typename CharType, 128 | typename FallbackCallable = FloatType (const CharType*, CharType**) 129 | > 130 | inline value_and_status atof(const CharType* str, std::nullptr_t str_end, FallbackCallable fallback_func = default_fallback) 131 | { 132 | return atof(str, static_cast(str_end), fallback_func); 133 | } 134 | 135 | /** \brief Parses floating point represented in `std::basic_string`. 136 | * 137 | * `atof()` adapter, which may be more useful for cases, where 138 | * `std::basic_string` strings are widely used. Please note, that it 139 | * might be slightly slower, than pure `atof()` due to additional 140 | * operations performed. 141 | * 142 | * \tparam FloatType target floating point type to store results. 143 | * \tparam CharType character type (typically `char` or `wchar_t`) the input 144 | * string \p **str** consists of. 145 | * \tparam FallbackCallable fallback conversion function type, in case of 146 | * Krosh is unsure if the result is correctly rounded (default is `strtof()` 147 | * for `float`'s, `strtod()` for `double`'s, `strtold()` for `long double`'s). 148 | * 149 | * \param str string representation of the value. 150 | * \param fallback_func pointer to fallback function. 151 | * 152 | * \return parsed value, if the input is correct, default constructed value 153 | * otherwise. 154 | */ 155 | template 156 | < 157 | typename FloatType, 158 | typename CharType, 159 | typename FallbackCallable = FloatType (const CharType*, CharType**) 160 | > 161 | inline value_and_status from_string(const std::basic_string& str, FallbackCallable fallback_func = default_fallback) 162 | { 163 | return atof(str.c_str(), nullptr, fallback_func); 164 | } 165 | } 166 | 167 | #endif // FLOAXIE_ATOF_H 168 | -------------------------------------------------------------------------------- /src/floaxie/bit_ops.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * diy_fp class and helper functions use code and influenced by 17 | * Florian Loitsch's original Grisu algorithms implementation 18 | * (http://florian.loitsch.com/publications/bench.tar.gz) 19 | * and "Printing Floating-Point Numbers Quickly and Accurately with 20 | * Integers" paper 21 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 22 | */ 23 | 24 | #ifndef FLOAXIE_BIT_OPS_H 25 | #define FLOAXIE_BIT_OPS_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "integer_of_size.h" 33 | 34 | namespace floaxie 35 | { 36 | /** \brief Calculates size of type in bits in compile time. 37 | * 38 | * \tparam NumericType type to calculate size in bits of 39 | * 40 | * \return Type size in bits. 41 | */ 42 | template constexpr std::size_t bit_size() noexcept 43 | { 44 | return sizeof(NumericType) * std::numeric_limits::digits; 45 | } 46 | 47 | /** \brief Returns a value with bit of the specified power raised. 48 | * 49 | * Calculates a value, which equals to 2 in the specified power, i.e. with 50 | * bit at \p `power` position is `1` and all the remaining bits are `0`. 51 | * 52 | * \tparam NumericType type to store the calculated value 53 | * 54 | * \param power power (0-based index, counting right to left) of bit to 55 | * raise 56 | * 57 | * \return Value of \p **NumericType** with \p **power**-th bit is `1` and 58 | * all the remaining bits are `0`. 59 | */ 60 | template constexpr NumericType raised_bit(std::size_t power) 61 | { 62 | assert(power < bit_size()); 63 | return NumericType(1) << power; 64 | } 65 | 66 | /** \brief Returns Most Significant Bit (MSB) value for the specified type. 67 | * 68 | * Calculates a value, which is equal to the value of Most 69 | * Significant Bit of the integer type, which has the same length, as the 70 | * specified one. The left most bit of the calculated value is equal to 71 | * `1`, and the remaining bits are `0`. 72 | * 73 | * \tparam FloatType type to calculate MSB value for 74 | * \tparam NumericType integer type of the same size, as \p **FloatType** 75 | * 76 | * \return Value of Most Significant Bit (MSB). 77 | */ 78 | template::type> 80 | constexpr NumericType msb_value() noexcept 81 | { 82 | return raised_bit(bit_size() - 1); 83 | } 84 | 85 | /** \brief Returns maximum unsigned integer value for the specified type. 86 | * 87 | * Calculates maximum value (using `std::numeric_limits`) of the integer 88 | * type, which has the same length, as the specified one. Thus, all bits 89 | * of the calculated value are equal to `1`. 90 | * 91 | * \tparam FloatType type to calculate MSB value for 92 | * \tparam NumericType integer type of the same size, as \p **FloatType** 93 | * 94 | * \return Maximum value of size the same as of the specified type. 95 | */ 96 | template::type> 98 | constexpr NumericType max_integer_value() noexcept 99 | { 100 | return std::numeric_limits::max(); 101 | } 102 | 103 | /** \brief Masks `n`-th bit of the specified value. 104 | * 105 | * Calculates a mask standing for the `n`-th bit, performs bitwise **AND** 106 | * operation and returns the value of it. 107 | * 108 | * \param value the value, of which the specified bit is returned 109 | * \param power power (0-based right-to-left index) of bit to return 110 | * 111 | * \return Integer value, which has \p `power`-th bit of the \p **value** 112 | * and the remaining bits equal to `0`. 113 | * 114 | */ 115 | template constexpr bool nth_bit(NumericType value, std::size_t power) noexcept 116 | { 117 | return value & raised_bit(power); 118 | } 119 | 120 | /** \brief Returns Most Significant Bit (MSB) of the specified value. 121 | * 122 | * Masks the left most bit of the given value, performs bitwise **AND** 123 | * operation with the mask and the value and returns the result. 124 | * 125 | * \tparam NumericType type of the value 126 | * 127 | * \param value value to get the highest bit of 128 | * 129 | * \return Integer value, which left most bit of the \p **value** and the 130 | * remaining bits equal to `0`. 131 | */ 132 | template constexpr bool highest_bit(NumericType value) noexcept 133 | { 134 | return nth_bit(value, bit_size() - 1); 135 | } 136 | 137 | /** \brief Returns mask of \p **n** bits from the right. 138 | * 139 | * \tparam NumericType type of the returned value 140 | * \param n number of bits from the right to mask 141 | * 142 | * \return Integer value with \p **n** right bits equal to `1` and the 143 | * remaining bits equal to `0`. 144 | */ 145 | template constexpr NumericType mask(std::size_t n) noexcept 146 | { 147 | static_assert(!std::is_signed::value, "Unsigned integral type is expected."); 148 | return n < bit_size() ? raised_bit(n) - 1 : std::numeric_limits::max(); 149 | } 150 | 151 | /** \brief Rectified linear function. 152 | * 153 | * Returns the argument (\p **value**), if it's positive and `0` otherwise. 154 | * 155 | * \param value the argument 156 | * 157 | * \return \p **value**, if \p **value** > `0`, `0` otherwise. 158 | * 159 | */ 160 | template constexpr typename std::make_unsigned::type positive_part(NumericType value) noexcept 161 | { 162 | return std::max(0, value); 163 | } 164 | 165 | /** \brief Return structure for `round_up` function. */ 166 | struct round_result 167 | { 168 | /** \brief Round up result — flag indicating if the value should be 169 | *rounded up (i.e. incremented). 170 | */ 171 | bool value; 172 | /** \brief Flag indicating if the rounding was accurate. */ 173 | bool is_accurate; 174 | }; 175 | 176 | /** \brief Detects if rounding up should be done. 177 | * 178 | * Applies IEEE algorithm of rounding up detection. The rounding criteria 179 | * requires, that rounding bit (the bit to the right of target position, 180 | * which rounding is being performed to) equals to `1`, and one of the 181 | * following conditions is true: 182 | * - at least one bit to the right of the rounding bit equals to `1` 183 | * - the bit in the target position equals to `1` 184 | * 185 | * \tparam NumericType type of \p **last_bits** parameter (auto-calculated) 186 | * 187 | * \param last_bits right suffix of the value, where rounding takes place 188 | * \param round_to_power the power (0-based right-to-left index) of the 189 | * target position (which rounding is being performed to) 190 | * 191 | * \returns `round_result` structure with the rounding decision. 192 | */ 193 | template inline round_result round_up(NumericType last_bits, std::size_t round_to_power) noexcept 194 | { 195 | round_result ret; 196 | 197 | const NumericType round_bit(raised_bit(round_to_power - 1)); 198 | const NumericType check_mask(mask(round_to_power + 1) ^ round_bit); 199 | ret.is_accurate = (last_bits & mask(round_to_power)) != round_bit; 200 | ret.value = (last_bits & round_bit) && (last_bits & check_mask); 201 | 202 | return ret; 203 | } 204 | 205 | /** \brief `constexpr` version of `std::abs`, as the latter lacks `constepxr`. 206 | * 207 | * And is really not `constexpr` in e.g. Clang. 208 | * 209 | * \returns absolute value of the specified value. 210 | */ 211 | template constexpr NumericType constexpr_abs(NumericType value) 212 | { 213 | return NumericType(0) < value ? value : -value; 214 | } 215 | } 216 | 217 | #endif // FLOAXIE_BIT_OPS_H 218 | -------------------------------------------------------------------------------- /src/floaxie/cached_power.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * cached power literals and cached_power() function use code taken from 17 | * Florian Loitsch's original Grisu algorithms implementation 18 | * (http://florian.loitsch.com/publications/bench.tar.gz) 19 | * and "Printing Floating-Point Numbers Quickly and Accurately with 20 | * Integers" paper 21 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 22 | */ 23 | 24 | #ifndef FLOAXIE_CACHED_POWER_H 25 | #define FLOAXIE_CACHED_POWER_H 26 | 27 | #include 28 | #include 29 | 30 | #include "powers_ten_single.h" 31 | #include "powers_ten_double.h" 32 | 33 | #include "diy_fp.h" 34 | 35 | namespace floaxie 36 | { 37 | /** \brief Returns pre-calculated `diy_fp` value of 10 in the specified 38 | * power using pre-calculated and compiled version of binary mantissa 39 | * and exponent. 40 | * 41 | * \tparam FloatType floating point type to call the values for. 42 | */ 43 | template inline diy_fp cached_power(int k) noexcept 44 | { 45 | assert(k >= -static_cast(powers_ten::pow_0_offset)); 46 | 47 | const std::size_t index = powers_ten::pow_0_offset + k; 48 | 49 | return diy_fp(powers_ten::f[index], powers_ten::e[index]); 50 | } 51 | } 52 | 53 | #endif // FLOAXIE_CACHED_POWER_H 54 | -------------------------------------------------------------------------------- /src/floaxie/conversion_status.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016, 2017 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_CONVERSION_STATUS_H 18 | #define FLOAXIE_CONVERSION_STATUS_H 19 | 20 | namespace floaxie 21 | { 22 | /** \brief Enumeration of possible conversion results, either successful or 23 | * not. 24 | */ 25 | enum class conversion_status : unsigned char 26 | { 27 | 28 | success, /**< the conversion was successful */ 29 | underflow, /**< an underflow occurred during the conversion */ 30 | overflow /**< an overflow occurred during the conversion */ 31 | }; 32 | } 33 | 34 | #endif // FLOAXIE_CONVERSION_STATUS_H 35 | -------------------------------------------------------------------------------- /src/floaxie/default_fallback.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_DEFAULT_FALLBACK_H 18 | #define FLOAXIE_DEFAULT_FALLBACK_H 19 | 20 | #include 21 | #include 22 | 23 | #include "conversion_status.h" 24 | 25 | namespace floaxie 26 | { 27 | /** \brief Function template to wrap C Standard Library floating point 28 | * parse function based on floating-point type and character type (normal 29 | * or wide). 30 | * 31 | * \tparam FloatType floating point type to parse 32 | * \tparam CharType character type of string to parse 33 | */ 34 | template FloatType default_fallback(const CharType* str, CharType** str_end); 35 | 36 | /** \brief `float` and `char`. */ 37 | template<> inline float default_fallback(const char* str, char** str_end) 38 | { 39 | return std::strtof(str, str_end); 40 | } 41 | 42 | /** \brief `double` and `char`. */ 43 | template<> inline double default_fallback(const char* str, char** str_end) 44 | { 45 | return std::strtod(str, str_end); 46 | } 47 | 48 | /** \brief `long double` and `char`. */ 49 | template<> inline long double default_fallback(const char* str, char** str_end) 50 | { 51 | return std::strtold(str, str_end); 52 | } 53 | 54 | /** \brief `float` and `wchar_t`. */ 55 | template<> inline float default_fallback(const wchar_t* str, wchar_t** str_end) 56 | { 57 | return std::wcstof(str, str_end); 58 | } 59 | 60 | /** \brief `double` and `wchar_t`. */ 61 | template<> inline double default_fallback(const wchar_t* str, wchar_t** str_end) 62 | { 63 | return std::wcstod(str, str_end); 64 | } 65 | 66 | /** \brief `long double` and `wchar_t`. */ 67 | template<> inline long double default_fallback(const wchar_t* str, wchar_t** str_end) 68 | { 69 | return std::wcstold(str, str_end); 70 | } 71 | 72 | template conversion_status check_errno(FloatType returned_value) 73 | { 74 | if (errno != ERANGE) 75 | return conversion_status::success; 76 | 77 | return returned_value ? conversion_status::overflow : conversion_status::underflow; 78 | } 79 | } 80 | 81 | #endif // FLOAXIE_DEFAULT_FALLBACK_H 82 | -------------------------------------------------------------------------------- /src/floaxie/fraction.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_FRACTION_H 18 | #define FLOAXIE_FRACTION_H 19 | 20 | #include 21 | 22 | #include "static_pow.h" 23 | 24 | namespace floaxie 25 | { 26 | /** \brief Recursive structure template used to convert decimal common 27 | * fraction to binary common fraction. 28 | * 29 | * The structure template hierarchy is used to calculate the binary common 30 | * fraction value, which is approximately equal to given decimal common 31 | * fraction. 32 | * 33 | * Example: 34 | * ~~~ 35 | * 0.625 = 0.101 36 | * ~~~ 37 | * 38 | * \tparam T numeric type of input value and result 39 | * \tparam decimal_digits number of significant decimal digits in 40 | * numerator (equals to the power of ten in denominator); for example, for 41 | * 0.625 \p **decimal_digits** is 3 42 | * \tparam binary_digits number of significant binary digits in numerator 43 | * of the result, which is defined by the necessary accuracy of 44 | * result approximation; for example, for 0.101 \p **decimal_digits** is 3 45 | * \tparam current_binary_digit template cursor used to implement 46 | * recursive descent 47 | * \tparam terminal automatically calculated flag of recursion termination 48 | */ 49 | template 50 | < 51 | typename T, 52 | std::size_t decimal_digits, 53 | std::size_t binary_digits, 54 | std::size_t current_binary_digit, 55 | bool terminal = (binary_digits == current_binary_digit) 56 | > 57 | struct fraction_converter; 58 | 59 | /** \brief Intermediate step implementation of `fraction_converter` 60 | * template. 61 | */ 62 | template 63 | < 64 | typename T, 65 | std::size_t decimal_digits, 66 | std::size_t binary_digits, 67 | std::size_t current_binary_digit 68 | > 69 | struct fraction_converter 70 | { 71 | /** \brief Calculates \p `current_binary_digit`-th digit of the result. 72 | * 73 | * \param decimal_numerator value of decimal numerator of common 74 | * fraction to convert 75 | * 76 | * \return Properly shifted value of \p `current_binary_digit`-th 77 | * digit of the result. 78 | */ 79 | static T convert(T decimal_numerator) 80 | { 81 | constexpr T numerator(static_pow<10, decimal_digits>()); 82 | constexpr T denominator(static_pow<2, current_binary_digit>()); 83 | constexpr T decimal_fraction(numerator / denominator); 84 | 85 | constexpr std::size_t shift_amount(binary_digits - current_binary_digit); 86 | 87 | const T decision(decimal_numerator >= decimal_fraction); 88 | const T residue(decimal_numerator - decision * decimal_fraction); 89 | 90 | return (decision << shift_amount) | 91 | fraction_converter::convert(residue); 92 | } 93 | }; 94 | 95 | /** \brief Terminal step implementation of `fraction_converter` template. 96 | * 97 | */ 98 | template 99 | < 100 | typename T, 101 | std::size_t decimal_digits, 102 | std::size_t binary_digits, 103 | std::size_t current_binary_digit 104 | > 105 | struct fraction_converter 106 | { 107 | /** \brief Calculates least significant digit of the result. 108 | * 109 | * \param decimal_numerator value of decimal numerator of common 110 | * fraction to convert 111 | * 112 | * \return Right most (least significant) digit of the result. 113 | */ 114 | static T convert(T decimal_numerator) 115 | { 116 | constexpr T numerator(static_pow<10, decimal_digits>()); 117 | constexpr T denominator(static_pow<2, current_binary_digit>()); 118 | constexpr T decimal_fraction(numerator / denominator); 119 | 120 | return decimal_numerator >= decimal_fraction; 121 | } 122 | }; 123 | 124 | /** \brief Wrapper function to convert numerator of decimal common fraction 125 | * to numerator of approximately equal binary common fraction with the 126 | * specified accuracy. 127 | * 128 | * \tparam decimal_digits number of digits in decimal numerator to observe 129 | * (input accuracy) 130 | * \tparam binary_digits number of digits in binary numerator to generate 131 | * (output accuracy) 132 | * 133 | * \return Value of binary numerator with the specified accuracy as 134 | * calculated by `fraction_converter`. 135 | */ 136 | template inline T convert_numerator(T decimal_numerator) 137 | { 138 | return fraction_converter::convert(decimal_numerator); 139 | } 140 | } 141 | 142 | #endif // FLOAXIE_FRACTION_H 143 | -------------------------------------------------------------------------------- /src/floaxie/ftoa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_FTOA_H 18 | #define FLOAXIE_FTOA_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "grisu.h" 27 | #include "prettify.h" 28 | 29 | namespace floaxie 30 | { 31 | /** \brief Returns maximum size of buffer can ever be required by `ftoa()`. 32 | * 33 | * Maximum size of buffer passed to `ftoa()` guaranteed not to lead to 34 | * undefined behaviour. 35 | * 36 | * \tparam FloatType floating point type, which value is planned to be 37 | * printed to the buffer. 38 | * 39 | * \return maximum size of buffer, which can ever be used in the very worst 40 | * case. 41 | */ 42 | template constexpr std::size_t max_buffer_size() noexcept 43 | { 44 | typedef typename std::decay::type FloatType; 45 | 46 | // digits, '.' (or 'e' plus three-digit power with optional sign) and '\0' 47 | return max_digits() + 1 + 1 + 3 + 1; 48 | } 49 | 50 | /** \brief Prints floating point value to optimal string representation. 51 | * 52 | * The function prints the string representation of the specified floating 53 | * point value using 54 | * [**Grisu2**](http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 55 | * algorithm and tries to get it as shorter, as possible. Usually it 56 | * succeeds, but sometimes fails, and the output representation is not 57 | * the shortest for this value. For the sake of speed improvement this is 58 | * ignored, while there's **Grisu3** algorithm which rules this out 59 | * informing the caller of the failure, so that it can call slower, but 60 | * more accurate algorithm in this case. 61 | * 62 | * The format of the string representation is one of the following: 63 | * 1. Decimal notation, which contains: 64 | * - minus sign ('-') in case of negative value 65 | * - sequence of one or more decimal digits optionally containing 66 | * decimal point character ('.') 67 | * 2. Decimal exponent notation, which contains: 68 | * - minus ('-') sign in case of negative value 69 | * - sequence of one or more decimal digits optionally containing 70 | * decimal point character ('.') 71 | * - 'e' character followed by minus sign ('-') in case of negative 72 | * power of the value (i.e. the specified value is < 1) and 73 | * sequence of one, two of three decimal digits. 74 | * 75 | * \tparam FloatType type of floating point value, calculated using passed 76 | * input parameter \p **v** 77 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 78 | * output buffer \p **buffer** 79 | * 80 | * \param v floating point value to print 81 | * \param buffer character buffer of enough size (see `max_buffer_size()`) 82 | * to print the representation to 83 | * 84 | * \see `max_buffer_size()` 85 | */ 86 | template inline void ftoa(FloatType v, CharType* buffer) noexcept 87 | { 88 | assert(!std::isnan(v)); 89 | assert(!std::isinf(v)); 90 | 91 | if (v == 0) 92 | { 93 | buffer[0] = '0'; 94 | buffer[1] = '.'; 95 | buffer[2] = '0'; 96 | buffer[3] = '\0'; 97 | } 98 | else 99 | { 100 | *buffer = '-'; 101 | buffer += v < 0; 102 | 103 | constexpr int alpha(grisu_parameters.alpha), gamma(grisu_parameters.gamma); 104 | constexpr unsigned int decimal_scientific_threshold(16); 105 | 106 | int len, K; 107 | 108 | grisu2(v, buffer, &len, &K); 109 | prettify(buffer, len, K); 110 | } 111 | } 112 | 113 | /** \brief Prints floating point value to optimal representation in 114 | * `std::basic_string`. 115 | * 116 | * Wrapper function around `ftoa()`, which returns `std::basic_string`, 117 | * rather than writing to the specified character buffer. This may be 118 | * more useful, if working with `std::basic_string` strings is preferred. 119 | * Please note, however, than common usage scenarios might be significantly 120 | * slower, when many `std::basic_string`'s are created with this function 121 | * and concatenated to each other, than when the outputs of `ftoa()` calls 122 | * are written to one long buffer. 123 | * 124 | * \tparam FloatType type of floating point value, calculated using passed 125 | * input parameter \p **v** 126 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 127 | * output buffer \p **buffer** 128 | * 129 | * \param v floating point value to print 130 | * \param buffer character buffer of enough size (see `max_buffer_size()`) 131 | * to print the representation to 132 | * 133 | * \see `ftoa()` 134 | */ 135 | template inline std::basic_string to_basic_string(FloatType v) 136 | { 137 | std::basic_string result(max_buffer_size(), CharType()); 138 | 139 | ftoa(v, &result.front()); 140 | 141 | result.resize(std::char_traits::length(result.data())); 142 | result.shrink_to_fit(); 143 | 144 | return result; 145 | } 146 | 147 | /** \brief 'Specialization' of `to_basic_string()` template for `std::string`. */ 148 | template inline std::string to_string(FloatType v) 149 | { 150 | return to_basic_string(v); 151 | } 152 | 153 | /** \brief 'Specialization' of `to_basic_string()` template for `std::wstring`. */ 154 | template inline std::wstring to_wstring(FloatType v) 155 | { 156 | return to_basic_string(v); 157 | } 158 | 159 | /** \brief 'Specialization' of `to_basic_string()` template for `std::u16string`. */ 160 | template inline std::u16string to_u16string(FloatType v) 161 | { 162 | return to_basic_string(v); 163 | } 164 | 165 | /** \brief 'Specialization' of `to_basic_string()` template for `std::u32string`. */ 166 | template inline std::u32string to_u32string(FloatType v) 167 | { 168 | return to_basic_string(v); 169 | } 170 | } 171 | 172 | #endif // FLOAXIE_FTOA_H 173 | -------------------------------------------------------------------------------- /src/floaxie/huge_val.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016, 2017 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_HUGE_VAL_H 18 | #define FLOAXIE_HUGE_VAL_H 19 | 20 | #include 21 | #include 22 | 23 | namespace floaxie 24 | { 25 | /** \brief Variable template to unify getting `HUGE_VAL` for 26 | * different floating point types in parameterized manner. 27 | * 28 | * \tparam FloatType floating point type to get `HUGE_VAL` for. 29 | * 30 | * \see [HUGE_VALF, HUGE_VAL, HUGE_VALL] 31 | * (http://en.cppreference.com/w/cpp/numeric/math/HUGE_VAL) 32 | */ 33 | template constexpr FloatType huge_value = std::numeric_limits::infinity(); 34 | 35 | /** \brief `float`. */ 36 | template<> constexpr float huge_value = HUGE_VALF; 37 | 38 | /** \brief `double`. */ 39 | template<> constexpr double huge_value = HUGE_VAL; 40 | 41 | /** \brief `long double`. */ 42 | template<> constexpr long double huge_value = HUGE_VALL; 43 | } 44 | 45 | #endif // FLOAXIE_HUGE_VAL_H 46 | -------------------------------------------------------------------------------- /src/floaxie/integer_of_size.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_INTEGER_OF_SIZE_H 18 | #define FLOAXIE_INTEGER_OF_SIZE_H 19 | 20 | #include 21 | #include 22 | 23 | namespace floaxie 24 | { 25 | /** \brief Identity type — hold the specified type in internal `typedef`. 26 | * 27 | * \tparam T type to hold 28 | */ 29 | template struct identity 30 | { 31 | /** \brief Held type. */ 32 | typedef T type; 33 | }; 34 | 35 | /** \brief Maps some of unsigned integer types to their sizes. 36 | * 37 | * Useful for choosing unsigned integer type of the same width as some 38 | * target type (e.g. floating point) to increase possible accuracy. 39 | * 40 | * \tparam size size in bytes of the desired type 41 | */ 42 | template struct integer_of_size : identity {}; 43 | 44 | /** \brief Specialization for 64-bit unsigned integer. */ 45 | template<> struct integer_of_size : identity {}; 46 | 47 | /** \brief Specialization for 32-bit unsigned integer. */ 48 | template<> struct integer_of_size : identity {}; 49 | } 50 | 51 | #endif // FLOAXIE_INTEGER_OF_SIZE_H 52 | -------------------------------------------------------------------------------- /src/floaxie/k_comp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * k_comp() function uses code taken from 17 | * Florian Loitsch's "Printing Floating-Point Numbers Quickly 18 | * and Accurately with Integers" paper 19 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 20 | */ 21 | 22 | #ifndef FLOAXIE_K_COMP_H 23 | #define FLOAXIE_K_COMP_H 24 | 25 | namespace floaxie 26 | { 27 | /** \brief Compiled value of \f$log{10} 2 \f$ */ 28 | constexpr auto lg_2(0.30102999566398114); // 1 / log2(10) = lg(2) ≈ 0.30102999566398114 29 | 30 | /** \brief Calculate **K** decimal exponent value by binary exponent. 31 | * 32 | * We ignore mantissa component (q) in exponent to eliminate 33 | * excessive add and subtract of it during K computation. 34 | * 35 | * Function name was changed to not confuse it with the original 36 | * k_comp() function from reference paper where this component 37 | * is considered. 38 | * 39 | * \tparam alpha α value of **Grisu** algorithm 40 | * \tparam gamma γ value of **Grisu** algorithm 41 | * 42 | * \param e binary exponent of the floating point value 43 | * 44 | * \see [Printing Floating-Point Numbers Quickly and Accurately with 45 | * Integers] 46 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 47 | */ 48 | template constexpr int k_comp_exp(int e) 49 | { 50 | return (alpha - e - 1) * lg_2 + (e + 1 < alpha); 51 | } 52 | } 53 | 54 | #endif // FLOAXIE_K_COMP_H 55 | -------------------------------------------------------------------------------- /src/floaxie/memwrap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef FLOAXIE_MEMWRAP_H 18 | #define FLOAXIE_MEMWRAP_H 19 | 20 | #include 21 | #include 22 | 23 | namespace floaxie 24 | { 25 | namespace wrap 26 | { 27 | /** \brief wrapper to template `std::(w)memset` by character type. 28 | * 29 | * \tparam CharType character type used. 30 | */ 31 | template inline CharType* memset(CharType* dest, CharType ch, std::size_t count); 32 | 33 | template<> inline char* memset(char* dest, char ch, std::size_t count) 34 | { 35 | return static_cast(std::memset(dest, ch, count)); 36 | } 37 | 38 | template<> inline wchar_t* memset(wchar_t* dest, wchar_t ch, std::size_t count) 39 | { 40 | return std::wmemset(dest, ch, count); 41 | } 42 | 43 | /** \brief wrapper to template `std::(w)memmove` by character type. 44 | * 45 | * \tparam CharType character type used. 46 | */ 47 | template inline CharType* memmove(CharType* dest, const CharType* src, std::size_t count); 48 | 49 | template<> inline char* memmove(char* dest, const char* src, std::size_t count) 50 | { 51 | return static_cast(std::memmove(dest, src, count)); 52 | } 53 | 54 | template<> inline wchar_t* memmove(wchar_t* dest, const wchar_t* src, std::size_t count) 55 | { 56 | return std::wmemmove(dest, src, count); 57 | } 58 | } 59 | } 60 | 61 | #endif // FLOAXIE_MEMWRAP_H 62 | -------------------------------------------------------------------------------- /src/floaxie/powers_ten.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * cached power literals and cached_power() function use code taken from 17 | * Florian Loitsch's original Grisu algorithms implementation 18 | * (http://florian.loitsch.com/publications/bench.tar.gz) 19 | * and "Printing Floating-Point Numbers Quickly and Accurately with 20 | * Integers" paper 21 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 22 | */ 23 | 24 | #ifndef FLOAXIE_POWERS_TEN_H 25 | #define FLOAXIE_POWERS_TEN_H 26 | 27 | namespace floaxie 28 | { 29 | /** \brief Structure template to store compile-time values of powers of ten. 30 | * 31 | * The template represents a structure family, which stores pre-calculated 32 | * values of significands and exponents of powers of ten, represented in 33 | * integer form of the specified precision. 34 | * 35 | * The exact values are written in specializations of the template for 36 | * single precision or double precision floating point type. 37 | * 38 | * The template specializations are used in **Grisu** and **Krosh** algorithms 39 | * to get the pre-calculated cached power of ten. 40 | * 41 | * \tparam FloatType floating point type, for which precision the values are 42 | * calculated. 43 | */ 44 | template struct powers_ten; 45 | } 46 | 47 | #endif // FLOAXIE_POWERS_TEN_H 48 | -------------------------------------------------------------------------------- /src/floaxie/powers_ten_single.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * cached power literals and cached_power() function use code taken from 17 | * Florian Loitsch's original Grisu algorithms implementation 18 | * (http://florian.loitsch.com/publications/bench.tar.gz) 19 | * and "Printing Floating-Point Numbers Quickly and Accurately with 20 | * Integers" paper 21 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 22 | */ 23 | 24 | #ifndef FLOAXIE_POWERS_TEN_SINGLE_H 25 | #define FLOAXIE_POWERS_TEN_SINGLE_H 26 | 27 | #include 28 | 29 | #include "powers_ten.h" 30 | 31 | namespace floaxie 32 | { 33 | /** \brief Specialization of **powers_ten** for single precision 34 | * floating point type (`float`). 35 | * 36 | * Significand (mantissa) type is `std::uint32_t`, exponent type is 37 | * `int` (typically 32 bit, at least 16 bit). 38 | * 39 | * Values are calculated for powers of 10 in the range of [-50, 50] 40 | * exponent. 41 | */ 42 | template<> struct powers_ten 43 | { 44 | /** \brief Pre-calculated binary 32-bit representation of mantissa of 45 | * powers of 10 in the range of [-50, 50] for single precision 46 | * floating point values. 47 | */ 48 | static constexpr std::uint32_t f[] = 49 | { 50 | 0xef73d257, 51 | 0x95a86376, 52 | 0xbb127c54, 53 | 0xe9d71b69, 54 | 0x92267121, 55 | 0xb6b00d6a, 56 | 0xe45c10c4, 57 | 0x8eb98a7b, 58 | 0xb267ed19, 59 | 0xdf01e860, 60 | 0x8b61313c, 61 | 0xae397d8b, 62 | 0xd9c7dced, 63 | 0x881cea14, 64 | 0xaa242499, 65 | 0xd4ad2dc0, 66 | 0x84ec3c98, 67 | 0xa6274bbe, 68 | 0xcfb11ead, 69 | 0x81ceb32c, 70 | 0xa2425ff7, 71 | 0xcad2f7f5, 72 | 0xfd87b5f3, 73 | 0x9e74d1b8, 74 | 0xc6120625, 75 | 0xf79687af, 76 | 0x9abe14cd, 77 | 0xc16d9a01, 78 | 0xf1c90081, 79 | 0x971da050, 80 | 0xbce50865, 81 | 0xec1e4a7e, 82 | 0x9392ee8f, 83 | 0xb877aa32, 84 | 0xe69594bf, 85 | 0x901d7cf7, 86 | 0xb424dc35, 87 | 0xe12e1342, 88 | 0x8cbccc09, 89 | 0xafebff0c, 90 | 0xdbe6fecf, 91 | 0x89705f41, 92 | 0xabcc7712, 93 | 0xd6bf94d6, 94 | 0x8637bd06, 95 | 0xa7c5ac47, 96 | 0xd1b71759, 97 | 0x83126e98, 98 | 0xa3d70a3d, 99 | 0xcccccccd, 100 | 0x80000000, 101 | 0xa0000000, 102 | 0xc8000000, 103 | 0xfa000000, 104 | 0x9c400000, 105 | 0xc3500000, 106 | 0xf4240000, 107 | 0x98968000, 108 | 0xbebc2000, 109 | 0xee6b2800, 110 | 0x9502f900, 111 | 0xba43b740, 112 | 0xe8d4a510, 113 | 0x9184e72a, 114 | 0xb5e620f4, 115 | 0xe35fa932, 116 | 0x8e1bc9bf, 117 | 0xb1a2bc2f, 118 | 0xde0b6b3a, 119 | 0x8ac72305, 120 | 0xad78ebc6, 121 | 0xd8d726b7, 122 | 0x87867832, 123 | 0xa968163f, 124 | 0xd3c21bcf, 125 | 0x84595161, 126 | 0xa56fa5ba, 127 | 0xcecb8f28, 128 | 0x813f3979, 129 | 0xa18f07d7, 130 | 0xc9f2c9cd, 131 | 0xfc6f7c40, 132 | 0x9dc5ada8, 133 | 0xc5371912, 134 | 0xf684df57, 135 | 0x9a130b96, 136 | 0xc097ce7c, 137 | 0xf0bdc21b, 138 | 0x96769951, 139 | 0xbc143fa5, 140 | 0xeb194f8e, 141 | 0x92efd1b9, 142 | 0xb7abc627, 143 | 0xe596b7b1, 144 | 0x8f7e32ce, 145 | 0xb35dbf82, 146 | 0xe0352f63, 147 | 0x8c213d9e, 148 | 0xaf298d05, 149 | 0xdaf3f046, 150 | 0x88d8762c 151 | }; 152 | 153 | /** \brief Pre-calculated values of binary exponent of powers of 10 in the 154 | * range of [-50, 50]. 155 | */ 156 | static constexpr int e[] = 157 | { 158 | -198, 159 | -194, 160 | -191, 161 | -188, 162 | -184, 163 | -181, 164 | -178, 165 | -174, 166 | -171, 167 | -168, 168 | -164, 169 | -161, 170 | -158, 171 | -154, 172 | -151, 173 | -148, 174 | -144, 175 | -141, 176 | -138, 177 | -134, 178 | -131, 179 | -128, 180 | -125, 181 | -121, 182 | -118, 183 | -115, 184 | -111, 185 | -108, 186 | -105, 187 | -101, 188 | -98, 189 | -95, 190 | -91, 191 | -88, 192 | -85, 193 | -81, 194 | -78, 195 | -75, 196 | -71, 197 | -68, 198 | -65, 199 | -61, 200 | -58, 201 | -55, 202 | -51, 203 | -48, 204 | -45, 205 | -41, 206 | -38, 207 | -35, 208 | -31, 209 | -28, 210 | -25, 211 | -22, 212 | -18, 213 | -15, 214 | -12, 215 | -8, 216 | -5, 217 | -2, 218 | 2, 219 | 5, 220 | 8, 221 | 12, 222 | 15, 223 | 18, 224 | 22, 225 | 25, 226 | 28, 227 | 32, 228 | 35, 229 | 38, 230 | 42, 231 | 45, 232 | 48, 233 | 52, 234 | 55, 235 | 58, 236 | 62, 237 | 65, 238 | 68, 239 | 71, 240 | 75, 241 | 78, 242 | 81, 243 | 85, 244 | 88, 245 | 91, 246 | 95, 247 | 98, 248 | 101, 249 | 105, 250 | 108, 251 | 111, 252 | 115, 253 | 118, 254 | 121, 255 | 125, 256 | 128, 257 | 131, 258 | 135 259 | }; 260 | 261 | /** \brief Offsef of the values for zero power in the arrays. 262 | */ 263 | static constexpr std::size_t pow_0_offset = 50; 264 | 265 | /** \brief Boundaries of possible powers of ten for the type. 266 | */ 267 | static constexpr std::pair boundaries = { -50, 50 }; 268 | }; 269 | 270 | constexpr decltype(powers_ten::f) powers_ten::f; 271 | constexpr decltype(powers_ten::e) powers_ten::e; 272 | constexpr std::size_t powers_ten::pow_0_offset; 273 | constexpr std::pair powers_ten::boundaries; 274 | } 275 | 276 | #endif // FLOAXIE_POWERS_TEN_SINGLE_H 277 | -------------------------------------------------------------------------------- /src/floaxie/prettify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, 2016 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * prettify_string() and fill_exponent() functions use code taken from 17 | * Florian Loitsch's original Grisu algorithms implementation 18 | * (http://florian.loitsch.com/publications/bench.tar.gz) 19 | * and "Printing Floating-Point Numbers Quickly and Accurately with 20 | * Integers" paper 21 | * (http://florian.loitsch.com/publications/dtoa-pldi2010.pdf) 22 | */ 23 | 24 | #ifndef FLOAXIE_PRETTIFY_H 25 | #define FLOAXIE_PRETTIFY_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "static_pow.h" 33 | #include "print.h" 34 | #include "memwrap.h" 35 | 36 | namespace floaxie 37 | { 38 | /** \brief Format enumeration. 39 | * 40 | */ 41 | enum format { 42 | /** \brief Decimal format */ 43 | decimal, 44 | /** \brief Decimal exponent (a.k.a. *scientific*) format */ 45 | scientific 46 | }; 47 | 48 | /** \brief LUT of two-digit decimal values to speed up their printing. */ 49 | constexpr const char digits_lut[200] = { 50 | '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', 51 | '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', 52 | '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', 53 | '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', 54 | '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', 55 | '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', 56 | '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', 57 | '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', 58 | '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', 59 | '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' 60 | }; 61 | 62 | /** \brief Detects the more appropriate format to print based on 63 | * \p **threshold** value. 64 | * \tparam threshold the maximum number of digits in the string 65 | * representation, when decimal format can be used (otherwise decimal 66 | * exponent or *scientific* format is used) 67 | * 68 | * \return `format` value of the chosen format 69 | */ 70 | template inline format choose_format(const std::size_t field_width) noexcept 71 | { 72 | static_assert(threshold > static_pow<10, 1>(), "Only 10 ⩽ |threshold| ⩽ 100 is supported"); 73 | 74 | return field_width > threshold ? format::scientific : format::decimal; 75 | } 76 | 77 | /** \brief Prints decimal exponent value. 78 | * 79 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 80 | * output buffer \p **buffer** 81 | * 82 | * \param K decimal exponent value 83 | * \param buffer character buffer to print to 84 | */ 85 | template inline void fill_exponent(unsigned int K, CharType* buffer) noexcept 86 | { 87 | const unsigned char hundreds = K / 100; 88 | K %= 100; 89 | buffer[0] = '0' + hundreds; 90 | buffer += (hundreds > 0); 91 | 92 | const char* d = digits_lut + K * 2; 93 | buffer[0] = d[0]; 94 | buffer[1] = d[1]; 95 | 96 | buffer[2] = '\0'; 97 | } 98 | 99 | /** \brief Prints exponent (*scientific*) part of value representation in 100 | * decimal exponent format. 101 | * 102 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 103 | * output buffer \p **buffer** 104 | * 105 | * \param buffer character buffer with properly printed mantissa 106 | * \param len output parameter to return the length of printed 107 | * representation 108 | * \param dot_pos number of character, where dot position should be placed 109 | * 110 | * \see `print_decimal()` 111 | */ 112 | template inline void print_scientific(CharType* buffer, const unsigned int len, const int dot_pos) noexcept 113 | { 114 | const int K = dot_pos - 1; 115 | if (len > 1) 116 | { 117 | /* leave the first digit. then add a '.' and at the end 'e...' */ 118 | wrap::memmove(buffer + 2, buffer + 1, len - 1); 119 | buffer[1] = '.'; 120 | buffer += len; 121 | } 122 | 123 | /* add 'e...' */ 124 | buffer[1] = 'e'; 125 | buffer[2] = '-'; 126 | buffer += K < 0; 127 | 128 | fill_exponent(std::abs(K), buffer + 2); 129 | } 130 | 131 | /** \brief Formats decimal mantissa part of value representation. 132 | * 133 | * Tides up the printed digits in \p **buffer**, adding leading zeros, 134 | * placing the decimal point into the proper place etc. 135 | * 136 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 137 | * output buffer \p **buffer** 138 | * 139 | * \param buffer character buffer with printed digits 140 | * \param len length of current representation in \p **buffer** 141 | * \param k decimal exponent of the value 142 | */ 143 | template inline void print_decimal(CharType* buffer, const unsigned int len, const int k) noexcept 144 | { 145 | const int dot_pos = static_cast(len) + k; 146 | 147 | const unsigned int actual_dot_pos = dot_pos > 0 ? dot_pos : 1; 148 | 149 | const unsigned int left_offset = dot_pos > 0 ? 0 : 2 - dot_pos; 150 | const unsigned int right_offset = positive_part(k); 151 | 152 | const unsigned int left_shift_src = positive_part(dot_pos); 153 | const unsigned int left_shift_dest = dot_pos > 0 ? left_shift_src + (k < 0) : left_offset; 154 | const unsigned int left_shift_len = positive_part(static_cast(len) - static_cast(left_shift_src)); 155 | 156 | const unsigned int term_pos = len + right_offset + (left_shift_dest - left_shift_src); 157 | 158 | wrap::memmove(buffer + left_shift_dest, buffer + left_shift_src, left_shift_len); 159 | wrap::memset(buffer, CharType('0'), left_offset); 160 | wrap::memset(buffer + len, CharType('0'), right_offset); 161 | buffer[actual_dot_pos] = '.'; 162 | buffer[term_pos] = '\0'; 163 | } 164 | 165 | /** \brief Makes final format corrections to have the string representation 166 | * be properly and pretty printed (with decimal point in place, exponent 167 | * part, where appropriate etc.). 168 | * 169 | * \tparam decimal_scientific_threshold the maximum number of digits in the 170 | * string representation, when decimal format can be used (otherwise 171 | * decimal exponent or *scientific* format is used) 172 | * \tparam CharType character type (typically `char` or `wchar_t`) of the 173 | * output buffer \p **buffer** 174 | * 175 | * \param buffer character buffer with printed digits 176 | * \param len length of current representation in \p **buffer** 177 | * \param k decimal exponent of the value 178 | * 179 | * \see `print_decimal()` 180 | * \see `print_scientific()` 181 | */ 182 | template 183 | inline void prettify(CharType* buffer, const unsigned int len, const int k) noexcept 184 | { 185 | /* v = buffer * 10 ^ k 186 | dot_pos is such that 10 ^ (dot_pos - 1) <= v < 10 ^ dot_pos 187 | this way dot_pos gives the position of the comma. 188 | */ 189 | const int dot_pos = static_cast(len) + k; 190 | 191 | // is always positive, since dot_pos is negative only when k is negative 192 | const std::size_t field_width = std::max(dot_pos, -k); 193 | 194 | switch (choose_format(field_width)) 195 | { 196 | case format::decimal: 197 | print_decimal(buffer, len, k); 198 | break; 199 | 200 | case format::scientific: 201 | print_scientific(buffer, len, dot_pos); 202 | break; 203 | } 204 | } 205 | } 206 | 207 | #endif // FLOAXIE_PRETTIFY_H 208 | -------------------------------------------------------------------------------- /src/floaxie/print.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * Several utility functions as printing binary representation of floating 17 | * point values and other stuff. 18 | * 19 | */ 20 | 21 | #ifndef FLOAXIE_PRINT_H 22 | #define FLOAXIE_PRINT_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "type_punning_cast.h" 29 | #include "bit_ops.h" 30 | 31 | namespace floaxie 32 | { 33 | /** \brief Prints `double` value in binary format, splitting sign, exponent 34 | * and mantissa parts with spaces. 35 | * 36 | * Useful for debugging purposes. 37 | */ 38 | std::string inline print_binary(double f) 39 | { 40 | auto s(std::bitset<64>(type_punning_cast(f)).to_string()); 41 | s.insert(1, 1, ' '); 42 | s.insert(13, 1, ' '); 43 | return s; 44 | } 45 | 46 | /** \brief Print arbitrary numeric value in binary format. */ 47 | template inline std::string print_binary(NumericType v) 48 | { 49 | return std::bitset()>(v).to_string(); 50 | } 51 | 52 | /** \brief Print arbitrary numeric value as if it were `double`. */ 53 | template inline std::string print_double_presentation(NumericType v) 54 | { 55 | auto s(std::bitset<64>(v).to_string()); 56 | s.insert(1, 1, ' '); 57 | s.insert(54, 1, ' '); 58 | s.insert(56, 1, ' '); 59 | return s; 60 | } 61 | } 62 | 63 | #endif // FLOAXIE_PRINT_H 64 | -------------------------------------------------------------------------------- /src/floaxie/static_pow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef FLOAXIE_STATIC_POW_H 19 | #define FLOAXIE_STATIC_POW_H 20 | 21 | #include 22 | #include 23 | 24 | namespace floaxie 25 | { 26 | /** \brief Helper class template to calculate integer positive power in 27 | * compile time. 28 | * 29 | * Unspecialized template contains intermediate steps implementation. 30 | * 31 | * \tparam base base of the power 32 | * \tparam pow exponent to power base 33 | */ 34 | template struct static_pow_helper 35 | { 36 | /** \brief Result of power calculation (in compile time). 37 | * 38 | * Is calculated recursively in intermediate steps. 39 | */ 40 | static const unsigned int value = base * static_pow_helper::value; 41 | }; 42 | 43 | /** \brief Terminal specialization of `static_pow_helper` template. */ 44 | template struct static_pow_helper 45 | { 46 | /** \brief Any value in zero power is `1`. */ 47 | static const unsigned int value = 1; 48 | }; 49 | 50 | /** \brief Handy wrapper function to calculate positive power in compile 51 | * time. 52 | * 53 | * \tparam base base of the power 54 | * \tparam pow exponent to power base 55 | * 56 | * \return Result of power calculation (in compile time). 57 | */ 58 | template constexpr unsigned long static_pow() 59 | { 60 | static_assert(base > 0, "Base should be positive"); 61 | return static_pow_helper::value; 62 | } 63 | 64 | /** \brief Helper structure template to append value to 65 | * `std::integer_sequence`. 66 | * 67 | * \tparam T type of elements of `std::integer_sequence` 68 | * \tparam Add element to add to the specified sequence 69 | * \tparam Seq original `std::integer_sequence` expressed by parameter pack 70 | * of its elements in template parameters 71 | */ 72 | template struct concat_sequence; 73 | 74 | /** \brief Implements the concatenation itself. 75 | * 76 | * Steals parameters (read: contents) of passed `std::integer_sequence`-like 77 | * type and creates another `std::integer_sequence`-like type with the 78 | * specified value appended at the end. 79 | */ 80 | template struct concat_sequence> 81 | { 82 | /** \brief New `std::integer_sequence`-like type with the specified 83 | * element added to the end. 84 | */ 85 | using type = std::integer_sequence; 86 | }; 87 | 88 | /** \brief Helper structure template to convert `std::integer_sequence` 89 | * to `std::array`. 90 | * 91 | * \tparam Seq sequence to convert 92 | */ 93 | template struct make_integer_array; 94 | 95 | /** \brief Main specialization of `make_integer_array` with the specified 96 | * input `std::integer_sequence`. 97 | * 98 | * \tparam T type of elements of `std::integer_sequence` 99 | * \tparam Ints elements of the `std::integer_sequence` to convert 100 | */ 101 | template struct make_integer_array> 102 | { 103 | /** \brief Type of the resulting `std::array` (specialized with 104 | * element type and length). */ 105 | using type = std::array; 106 | 107 | /** \brief Instance of the resulting `std::array` filled in with 108 | * elements from the specified `std::integer_sequence` in compile time. 109 | */ 110 | static constexpr type value = type{{Ints...}}; 111 | }; 112 | 113 | /** \brief Creates `std::integer_sequence` with sequence of powers of 114 | * \p **base** up to the exponent value, defined by \p **current_pow**. 115 | * 116 | * For example, if \p base is `10` and \p current_pow is `3`, the result 117 | * will contain values `1000`, `100`, `10`, `1`. 118 | * 119 | * \tparam T type of elements 120 | * \tparam base base of powers to calculate 121 | * \tparam current_pow the maximum exponent value to calculate power for 122 | */ 123 | template struct pow_sequencer 124 | { 125 | /** \brief Value of power on the current step (in recursion). */ 126 | static const T value = pow_sequencer::value * base; 127 | 128 | /** \brief `std::integer_sequence`-like type containing all the 129 | * calculated powers at the moment. 130 | */ 131 | typedef typename concat_sequence::sequence_type>::type sequence_type; 132 | }; 133 | 134 | /** \brief Terminal step specialization for `pow_sequencer` template. */ 135 | template struct pow_sequencer 136 | { 137 | /** \brief Zero power of base. */ 138 | static constexpr T value = 1; 139 | /** \brief `std::integer_sequence` with zero power only yet. */ 140 | typedef std::integer_sequence sequence_type; 141 | }; 142 | 143 | /** \brief Handy wrapper function to calculate a sequence of powers. 144 | * 145 | * \tparam T type of elements 146 | * \tparam base base for powers to calculate 147 | * \tparam max_pow maximum exponent, up to which the calculation will be 148 | * performed 149 | * 150 | * \return `std::array` filled with powers of the specified arguments in 151 | * reverse order. I.e. for \p **T** of `unsigned int`, \p **base** of 10 152 | * and \p **max_pow** 3 this would be: 153 | * `std::array({{1000, 100, 10, 1}})`. 154 | */ 155 | template constexpr T seq_pow(std::size_t pow) 156 | { 157 | typedef make_integer_array::sequence_type> maker; 158 | constexpr typename maker::type arr(maker::value); 159 | 160 | return arr[pow]; 161 | } 162 | } 163 | 164 | #endif // FLOAXIE_STATIC_POW_H 165 | -------------------------------------------------------------------------------- /src/floaxie/type_punning_cast.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Alexey Chernov <4ernov@gmail.com> 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * type_punning_cast is copy-paste of pseudo_cast as posted by plasmacel 17 | * at StackOverflow 18 | * (http://stackoverflow.com/questions/17789928/whats-a-proper-way-of-type-punning-a-float-to-an-int-and-vice-versa) 19 | * 20 | */ 21 | 22 | #ifndef FLOAXIE_TYPE_PUNNING_CAST 23 | #define FLOAXIE_TYPE_PUNNING_CAST 24 | 25 | #include 26 | 27 | namespace floaxie 28 | { 29 | /** \brief Correct type-punning cast implementation to avoid any possible 30 | * undefined behaviour. 31 | * 32 | * \see https://en.wikipedia.org/wiki/Type_punning 33 | */ 34 | template inline T type_punning_cast(const U& x) 35 | { 36 | static_assert(sizeof(T) == sizeof(U), 37 | "type_punning_cast can't handle types with different size"); 38 | 39 | T to; 40 | std::memcpy(&to, &x, sizeof(T)); 41 | return to; 42 | } 43 | } 44 | 45 | #endif // FLOAXIE_TYPE_PUNNING_CAST 46 | -------------------------------------------------------------------------------- /src/floaxietest.cpp: -------------------------------------------------------------------------------- 1 | #if __cplusplus >= 201402L 2 | 3 | #include "test.h" 4 | #include "floaxie/ftoa.h" 5 | 6 | void dtoa_floaxie(double v, char* buffer) 7 | { 8 | floaxie::ftoa(v, buffer); 9 | } 10 | 11 | REGISTER_TEST(floaxie); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/fpconv/fpconv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fpconv.h" 5 | #include "powers.h" 6 | 7 | #define fracmask 0x000FFFFFFFFFFFFFU 8 | #define expmask 0x7FF0000000000000U 9 | #define hiddenbit 0x0010000000000000U 10 | #define signmask 0x8000000000000000U 11 | #define expbias (1023 + 52) 12 | 13 | #define absv(n) ((n) < 0 ? -(n) : (n)) 14 | #define minv(a, b) ((a) < (b) ? (a) : (b)) 15 | 16 | static uint64_t tens[] = { 17 | 10000000000000000000U, 1000000000000000000U, 100000000000000000U, 18 | 10000000000000000U, 1000000000000000U, 100000000000000U, 19 | 10000000000000U, 1000000000000U, 100000000000U, 20 | 10000000000U, 1000000000U, 100000000U, 21 | 10000000U, 1000000U, 100000U, 22 | 10000U, 1000U, 100U, 23 | 10U, 1U 24 | }; 25 | 26 | static /*inline */uint64_t get_dbits(double d) 27 | { 28 | union { 29 | double dbl; 30 | uint64_t i; 31 | } dbl_bits = { d }; 32 | 33 | return dbl_bits.i; 34 | } 35 | 36 | static Fp build_fp(double d) 37 | { 38 | uint64_t bits = get_dbits(d); 39 | 40 | Fp fp; 41 | fp.frac = bits & fracmask; 42 | fp.exp = (bits & expmask) >> 52; 43 | 44 | if(fp.exp) { 45 | fp.frac += hiddenbit; 46 | fp.exp -= expbias; 47 | 48 | } else { 49 | fp.exp = -expbias + 1; 50 | } 51 | 52 | return fp; 53 | } 54 | 55 | static void normalize(Fp* fp) 56 | { 57 | while ((fp->frac & hiddenbit) == 0) { 58 | fp->frac <<= 1; 59 | fp->exp--; 60 | } 61 | 62 | int shift = 64 - 52 - 1; 63 | fp->frac <<= shift; 64 | fp->exp -= shift; 65 | } 66 | 67 | static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper) 68 | { 69 | upper->frac = (fp->frac << 1) + 1; 70 | upper->exp = fp->exp - 1; 71 | 72 | while ((upper->frac & (hiddenbit << 1)) == 0) { 73 | upper->frac <<= 1; 74 | upper->exp--; 75 | } 76 | 77 | int u_shift = 64 - 52 - 2; 78 | 79 | upper->frac <<= u_shift; 80 | upper->exp = upper->exp - u_shift; 81 | 82 | 83 | int l_shift = fp->frac == hiddenbit ? 2 : 1; 84 | 85 | lower->frac = (fp->frac << l_shift) - 1; 86 | lower->exp = fp->exp - l_shift; 87 | 88 | 89 | lower->frac <<= lower->exp - upper->exp; 90 | lower->exp = upper->exp; 91 | } 92 | 93 | static Fp multiply(Fp* a, Fp* b) 94 | { 95 | const uint64_t lomask = 0x00000000FFFFFFFF; 96 | 97 | uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask); 98 | uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32); 99 | uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask); 100 | uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32); 101 | 102 | uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32); 103 | /* round up */ 104 | tmp += 1U << 31; 105 | 106 | Fp fp = { 107 | ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32), 108 | a->exp + b->exp + 64 109 | }; 110 | 111 | return fp; 112 | } 113 | 114 | static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac) 115 | { 116 | while (rem < frac && delta - rem >= kappa && 117 | (rem + kappa < frac || frac - rem > rem + kappa - frac)) { 118 | 119 | digits[ndigits - 1]--; 120 | rem += kappa; 121 | } 122 | } 123 | 124 | static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K) 125 | { 126 | uint64_t wfrac = upper->frac - fp->frac; 127 | uint64_t delta = upper->frac - lower->frac; 128 | 129 | Fp one; 130 | one.frac = 1ULL << -upper->exp; 131 | one.exp = upper->exp; 132 | 133 | uint64_t part1 = upper->frac >> -one.exp; 134 | uint64_t part2 = upper->frac & (one.frac - 1); 135 | 136 | int idx = 0, kappa = 10; 137 | uint64_t* divp; 138 | /* 1000000000 */ 139 | for(divp = tens + 10; kappa > 0; divp++) { 140 | 141 | uint64_t div = *divp; 142 | unsigned digit = part1 / div; 143 | 144 | if (digit || idx) { 145 | digits[idx++] = digit + '0'; 146 | } 147 | 148 | part1 -= digit * div; 149 | kappa--; 150 | 151 | uint64_t tmp = (part1 <<-one.exp) + part2; 152 | if (tmp <= delta) { 153 | *K += kappa; 154 | round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac); 155 | 156 | return idx; 157 | } 158 | } 159 | 160 | /* 10 */ 161 | uint64_t* unit = tens + 18; 162 | 163 | while(true) { 164 | part2 *= 10; 165 | delta *= 10; 166 | kappa--; 167 | 168 | unsigned digit = part2 >> -one.exp; 169 | if (digit || idx) { 170 | digits[idx++] = digit + '0'; 171 | } 172 | 173 | part2 &= one.frac - 1; 174 | if (part2 < delta) { 175 | *K += kappa; 176 | round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit); 177 | 178 | return idx; 179 | } 180 | 181 | unit--; 182 | } 183 | } 184 | 185 | static int grisu2(double d, char* digits, int* K) 186 | { 187 | Fp w = build_fp(d); 188 | 189 | Fp lower, upper; 190 | get_normalized_boundaries(&w, &lower, &upper); 191 | 192 | normalize(&w); 193 | 194 | int k; 195 | Fp cp = find_cachedpow10(upper.exp, &k); 196 | 197 | w = multiply(&w, &cp); 198 | upper = multiply(&upper, &cp); 199 | lower = multiply(&lower, &cp); 200 | 201 | lower.frac++; 202 | upper.frac--; 203 | 204 | *K = -k; 205 | 206 | return generate_digits(&w, &upper, &lower, digits, K); 207 | } 208 | 209 | static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg) 210 | { 211 | int exp = absv(K + ndigits - 1); 212 | 213 | /* write plain integer */ 214 | if(K >= 0 && (exp < (ndigits + 7))) { 215 | memcpy(dest, digits, ndigits); 216 | memset(dest + ndigits, '0', K); 217 | 218 | return ndigits + K; 219 | } 220 | 221 | /* write decimal w/o scientific notation */ 222 | if(K < 0 && (K > -7 || exp < 4)) { 223 | int offset = ndigits - absv(K); 224 | /* fp < 1.0 -> write leading zero */ 225 | if(offset <= 0) { 226 | offset = -offset; 227 | dest[0] = '0'; 228 | dest[1] = '.'; 229 | memset(dest + 2, '0', offset); 230 | memcpy(dest + offset + 2, digits, ndigits); 231 | 232 | return ndigits + 2 + offset; 233 | 234 | /* fp > 1.0 */ 235 | } else { 236 | memcpy(dest, digits, offset); 237 | dest[offset] = '.'; 238 | memcpy(dest + offset + 1, digits + offset, ndigits - offset); 239 | 240 | return ndigits + 1; 241 | } 242 | } 243 | 244 | /* write decimal w/ scientific notation */ 245 | ndigits = minv(ndigits, 18 - neg); 246 | 247 | int idx = 0; 248 | dest[idx++] = digits[0]; 249 | 250 | if(ndigits > 1) { 251 | dest[idx++] = '.'; 252 | memcpy(dest + idx, digits + 1, ndigits - 1); 253 | idx += ndigits - 1; 254 | } 255 | 256 | dest[idx++] = 'e'; 257 | 258 | char sign = K + ndigits - 1 < 0 ? '-' : '+'; 259 | dest[idx++] = sign; 260 | 261 | int cent = 0; 262 | 263 | if(exp > 99) { 264 | cent = exp / 100; 265 | dest[idx++] = cent + '0'; 266 | exp -= cent * 100; 267 | } 268 | if(exp > 9) { 269 | int dec = exp / 10; 270 | dest[idx++] = dec + '0'; 271 | exp -= dec * 10; 272 | 273 | } else if(cent) { 274 | dest[idx++] = '0'; 275 | } 276 | 277 | dest[idx++] = exp % 10 + '0'; 278 | 279 | return idx; 280 | } 281 | 282 | static int filter_special(double fp, char* dest) 283 | { 284 | if(fp == 0.0) { 285 | dest[0] = '0'; 286 | return 1; 287 | } 288 | 289 | uint64_t bits = get_dbits(fp); 290 | 291 | bool nan = (bits & expmask) == expmask; 292 | 293 | if(!nan) { 294 | return 0; 295 | } 296 | 297 | if(bits & fracmask) { 298 | dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n'; 299 | 300 | } else { 301 | dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f'; 302 | } 303 | 304 | return 3; 305 | } 306 | 307 | int fpconv_dtoa(double d, char dest[24]) 308 | { 309 | char digits[18]; 310 | 311 | int str_len = 0; 312 | bool neg = false; 313 | 314 | if(get_dbits(d) & signmask) { 315 | dest[0] = '-'; 316 | str_len++; 317 | neg = true; 318 | } 319 | 320 | int spec = filter_special(d, dest + str_len); 321 | 322 | if(spec) { 323 | return str_len + spec; 324 | } 325 | 326 | int K = 0; 327 | int ndigits = grisu2(d, digits, &K); 328 | 329 | str_len += emit_digits(digits, ndigits, dest + str_len, K, neg); 330 | 331 | return str_len; 332 | } 333 | -------------------------------------------------------------------------------- /src/fpconv/fpconv.h: -------------------------------------------------------------------------------- 1 | #ifndef FPCONV_H 2 | #define FPCONV_H 3 | 4 | /* Fast and accurate double to string conversion based on Florian Loitsch's 5 | * Grisu-algorithm[1]. 6 | * 7 | * Input: 8 | * fp -> the double to convert, dest -> destination buffer. 9 | * The generated string will never be longer than 24 characters. 10 | * Make sure to pass a pointer to at least 24 bytes of memory. 11 | * The emitted string will not be null terminated. 12 | * 13 | * Output: 14 | * The number of written characters. 15 | * 16 | * Exemplary usage: 17 | * 18 | * void print(double d) 19 | * { 20 | * char buf[24 + 1] // plus null terminator 21 | * int str_len = fpconv_dtoa(d, buf); 22 | * 23 | * buf[str_len] = '\0'; 24 | * printf("%s", buf); 25 | * } 26 | * 27 | */ 28 | 29 | int fpconv_dtoa(double fp, char dest[24]); 30 | 31 | #endif 32 | 33 | /* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */ 34 | -------------------------------------------------------------------------------- /src/fpconv/license: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 Andreas Samoljuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/fpconv/powers.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define npowers 87 4 | #define steppowers 8 5 | #define firstpower -348 /* 10 ^ -348 */ 6 | 7 | #define expmax -32 8 | #define expmin -60 9 | 10 | 11 | typedef struct Fp { 12 | uint64_t frac; 13 | int exp; 14 | } Fp; 15 | 16 | static Fp powers_ten[] = { 17 | { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 }, 18 | { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 }, 19 | { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 }, 20 | { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 }, 21 | { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 }, 22 | { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 }, 23 | { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 }, 24 | { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 }, 25 | { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 }, 26 | { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 }, 27 | { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 }, 28 | { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 }, 29 | { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 }, 30 | { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 }, 31 | { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 }, 32 | { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 }, 33 | { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 }, 34 | { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 }, 35 | { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 }, 36 | { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 }, 37 | { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 }, 38 | { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 }, 39 | { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 }, 40 | { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 }, 41 | { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 }, 42 | { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 }, 43 | { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 }, 44 | { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 }, 45 | { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 }, 46 | { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 }, 47 | { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 }, 48 | { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 }, 49 | { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 }, 50 | { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 }, 51 | { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 }, 52 | { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 }, 53 | { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 }, 54 | { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 }, 55 | { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 }, 56 | { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 }, 57 | { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 }, 58 | { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 }, 59 | { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 }, 60 | { 12648080533535911531U, 1066 } 61 | }; 62 | 63 | static Fp find_cachedpow10(int exp, int* k) 64 | { 65 | const double one_log_ten = 0.30102999566398114; 66 | 67 | int approx = -(exp + npowers) * one_log_ten; 68 | int idx = (approx - firstpower) / steppowers; 69 | 70 | while(1) { 71 | int current = exp + powers_ten[idx].exp + 64; 72 | 73 | if(current < expmin) { 74 | idx++; 75 | continue; 76 | } 77 | 78 | if(current > expmax) { 79 | idx--; 80 | continue; 81 | } 82 | 83 | *k = (firstpower + idx * steppowers); 84 | 85 | return powers_ten[idx]; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/fpconvtest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | extern "C" { 4 | #include "fpconv/fpconv.h" 5 | } 6 | 7 | void dtoa_fpconv(double value, char* buffer) { 8 | buffer[fpconv_dtoa(value, buffer)] = '\0'; 9 | } 10 | 11 | REGISTER_TEST(fpconv); 12 | -------------------------------------------------------------------------------- /src/gay/g_fmt.c: -------------------------------------------------------------------------------- 1 | /**************************************************************** 2 | * 3 | * The author of this software is David M. Gay. 4 | * 5 | * Copyright (c) 1991, 1996 by Lucent Technologies. 6 | * 7 | * Permission to use, copy, modify, and distribute this software for any 8 | * purpose without fee is hereby granted, provided that this entire notice 9 | * is included in all copies of any software which is or includes a copy 10 | * or modification of this software and in all copies of the supporting 11 | * documentation for such software. 12 | * 13 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 14 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY 15 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 16 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 17 | * 18 | ***************************************************************/ 19 | 20 | /* g_fmt(buf,x) stores the closest decimal approximation to x in buf; 21 | * it suffices to declare buf 22 | * char buf[32]; 23 | */ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | extern char *dtoa(double, int, int, int *, int *, char **); 29 | extern char *g_fmt(char *, double); 30 | extern void freedtoa(char*); 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | char * 36 | g_fmt(register char *b, double x) 37 | { 38 | register int i, k; 39 | register char *s; 40 | int decpt, j, sign; 41 | char *b0, *s0, *se; 42 | 43 | b0 = b; 44 | #ifdef IGNORE_ZERO_SIGN 45 | if (!x) { 46 | *b++ = '0'; 47 | *b = 0; 48 | goto done; 49 | } 50 | #endif 51 | s = s0 = dtoa(x, 0, 0, &decpt, &sign, &se); 52 | if (sign) 53 | *b++ = '-'; 54 | if (decpt == 9999) /* Infinity or Nan */ { 55 | while(*b++ = *s++); 56 | goto done0; 57 | } 58 | if (decpt <= -4 || decpt > se - s + 5) { 59 | *b++ = *s++; 60 | if (*s) { 61 | *b++ = '.'; 62 | while(*b = *s++) 63 | b++; 64 | } 65 | *b++ = 'e'; 66 | /* sprintf(b, "%+.2d", decpt - 1); */ 67 | if (--decpt < 0) { 68 | *b++ = '-'; 69 | decpt = -decpt; 70 | } 71 | else 72 | *b++ = '+'; 73 | for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10); 74 | for(;;) { 75 | i = decpt / k; 76 | *b++ = i + '0'; 77 | if (--j <= 0) 78 | break; 79 | decpt -= i*k; 80 | decpt *= 10; 81 | } 82 | *b = 0; 83 | } 84 | else if (decpt <= 0) { 85 | *b++ = '.'; 86 | for(; decpt < 0; decpt++) 87 | *b++ = '0'; 88 | while(*b++ = *s++); 89 | } 90 | else { 91 | while(*b = *s++) { 92 | b++; 93 | if (--decpt == 0 && *s) 94 | *b++ = '.'; 95 | } 96 | for(; decpt > 0; decpt--) 97 | *b++ = '0'; 98 | *b = 0; 99 | } 100 | done0: 101 | freedtoa(s0); 102 | done: 103 | return b0; 104 | } 105 | -------------------------------------------------------------------------------- /src/gaytest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | extern "C" { 4 | char *g_fmt(char *, double); 5 | } 6 | 7 | void dtoa_gay(double value, char* buffer) { 8 | g_fmt(buffer, value); 9 | } 10 | 11 | //REGISTER_TEST(gay); 12 | -------------------------------------------------------------------------------- /src/grisu/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Florian Loitsch 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/grisu/diy_fp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | 29 | typedef struct diy_fp_t { 30 | uint64_t f; 31 | int e; 32 | } diy_fp_t; 33 | 34 | static diy_fp_t minus(diy_fp_t x, diy_fp_t y) { 35 | assert(x.e == y.e); 36 | assert(x.f >= y.f); 37 | diy_fp_t r = {.f = x.f - y.f, .e = x.e}; 38 | return r; 39 | } 40 | 41 | /* 42 | static diy_fp_t minus(diy_fp_t x, diy_fp_t y) { 43 | assert(x.e == y.e); 44 | assert(x.f >= y.f); 45 | diy_fp_t r = {.f = x.f - y.f, .e = x.e}; 46 | return r; 47 | } 48 | */ 49 | 50 | static diy_fp_t multiply(diy_fp_t x, diy_fp_t y) { 51 | uint64_t a,b,c,d,ac,bc,ad,bd,tmp,h; 52 | diy_fp_t r; uint64_t M32 = 0xFFFFFFFF; 53 | a = x.f >> 32; b = x.f & M32; 54 | c = y.f >> 32; d = y.f & M32; 55 | ac = a*c; bc = b*c; ad = a*d; bd = b*d; 56 | tmp = (bd>>32) + (ad&M32) + (bc&M32); 57 | tmp += 1U << 31; /// mult_round 58 | r.f = ac+(ad>>32)+(bc>>32)+(tmp >>32); 59 | r.e = x.e + y.e + 64; 60 | return r; 61 | } 62 | -------------------------------------------------------------------------------- /src/grisu/double.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | 27 | #include "diy_fp.h" 28 | #include "powers.h" 29 | #include 30 | #include 31 | 32 | typedef union { 33 | double d; 34 | uint64_t n; 35 | } converter_t; 36 | 37 | static uint64_t double_to_uint64(double d) { converter_t tmp; tmp.d = d; return tmp.n; } 38 | static double uint64_to_double(uint64_t d64) { converter_t tmp; tmp.n = d64; return tmp.d; } 39 | 40 | #define DP_SIGNIFICAND_SIZE 52 41 | #define DP_EXPONENT_BIAS (0x3FF + DP_SIGNIFICAND_SIZE) 42 | #define DP_MIN_EXPONENT (-DP_EXPONENT_BIAS) 43 | #define DP_EXPONENT_MASK 0x7FF0000000000000 44 | #define DP_SIGNIFICAND_MASK 0x000FFFFFFFFFFFFF 45 | #define DP_HIDDEN_BIT 0x0010000000000000 46 | 47 | static diy_fp_t normalize_diy_fp(diy_fp_t in) { 48 | diy_fp_t res = in; 49 | /* Normalize now */ 50 | /* the original number could have been a denormal. */ 51 | while (! (res.f & DP_HIDDEN_BIT)) 52 | { 53 | res.f <<= 1; 54 | res.e--; 55 | } 56 | /* do the final shifts in one go. Don't forget the hidden bit (the '-1') */ 57 | res.f <<= (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 1); 58 | res.e = res.e - (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 1); 59 | return res; 60 | } 61 | 62 | static diy_fp_t double2diy_fp(double d) { 63 | uint64_t d64 = double_to_uint64(d); 64 | int biased_e = (d64 & DP_EXPONENT_MASK) >> DP_SIGNIFICAND_SIZE; 65 | uint64_t significand = (d64 & DP_SIGNIFICAND_MASK); 66 | diy_fp_t res; 67 | if (biased_e != 0) 68 | { 69 | res.f = significand + DP_HIDDEN_BIT; 70 | res.e = biased_e - DP_EXPONENT_BIAS; 71 | } else { 72 | res.f = significand; 73 | res.e = DP_MIN_EXPONENT + 1; 74 | } 75 | return res; 76 | } 77 | 78 | static diy_fp_t normalize_boundary(diy_fp_t in) { 79 | diy_fp_t res = in; 80 | /* Normalize now */ 81 | /* the original number could have been a denormal. */ 82 | while (! (res.f & (DP_HIDDEN_BIT << 1))) 83 | { 84 | res.f <<= 1; 85 | res.e--; 86 | } 87 | /* do the final shifts in one go. Don't forget the hidden bit (the '-1') */ 88 | res.f <<= (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2); 89 | res.e = res.e - (DIY_SIGNIFICAND_SIZE - DP_SIGNIFICAND_SIZE - 2); 90 | return res; 91 | } 92 | 93 | static void normalized_boundaries(double d, diy_fp_t* out_m_minus, diy_fp_t* out_m_plus) { 94 | diy_fp_t v = double2diy_fp(d); 95 | diy_fp_t pl, mi; 96 | bool significand_is_zero = v.f == DP_HIDDEN_BIT; 97 | pl.f = (v.f << 1) + 1; pl.e = v.e - 1; 98 | pl = normalize_boundary(pl); 99 | if (significand_is_zero) 100 | { 101 | mi.f = (v.f << 2) - 1; 102 | mi.e = v.e - 2; 103 | } else { 104 | mi.f = (v.f << 1) - 1; 105 | mi.e = v.e - 1; 106 | } 107 | mi.f <<= mi.e - pl.e; 108 | mi.e = pl.e; 109 | *out_m_plus = pl; 110 | *out_m_minus = mi; 111 | } 112 | 113 | static double random_double() { 114 | uint64_t tmp = 0; 115 | int i; 116 | for (i = 0; i < 8; i++) { 117 | tmp <<= 8; 118 | tmp += rand() % 256; 119 | } 120 | return uint64_to_double(tmp); 121 | } 122 | -------------------------------------------------------------------------------- /src/grisu/fast_exponent.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | 27 | static void fill_exponent(int K, char* buffer) { 28 | int i = 0; 29 | if (K < 0) { 30 | buffer[i++] = '-'; 31 | K = -K; 32 | } 33 | if (K >= 100) { 34 | buffer[i++] = '0' + K / 100; K %= 100; 35 | buffer[i++] = '0' + K / 10; K %= 10; 36 | buffer[i++] = '0' + K; 37 | } else if (K >= 10) { 38 | buffer[i++] = '0' + K / 10; K %= 10; 39 | buffer[i++] = '0' + K; 40 | } else { 41 | buffer[i++] = '0' + K; 42 | } 43 | buffer[i] = '\0'; 44 | } 45 | -------------------------------------------------------------------------------- /src/grisu/grisu2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "prettify.h" 27 | #include "fast_exponent.h" 28 | 29 | #define HUMAN_READABLE 30 | 31 | void grisu2(double v, char* buffer, int* length, int* K); 32 | 33 | void fill_double_init() {} 34 | 35 | bool fill_double(double v, char* buffer) { 36 | int length, K; 37 | grisu2(v, buffer, &length, &K); 38 | #ifndef HUMAN_READABLE 39 | buffer[length] = 'e'; 40 | fill_exponent(K, &buffer[length+1]); 41 | #else 42 | prettify_string(buffer, 0, length, K); 43 | #endif 44 | return 1; 45 | } 46 | -------------------------------------------------------------------------------- /src/grisu/grisu2b_59_56.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #include "diy_fp.h" 26 | #include "k_comp.h" 27 | #include "double.h" 28 | #include "powers.h" 29 | #include 30 | #include 31 | #include "grisu2.h" 32 | #include 33 | 34 | #define TEN9 1000000000 35 | 36 | void grisu_round(char* buffer, int len, 37 | uint64_t delta, uint64_t rest, 38 | uint64_t ten_kappa, uint64_t wp_w) { 39 | while (rest < wp_w && 40 | delta - rest >= ten_kappa && 41 | (rest + ten_kappa < wp_w || /// closer 42 | wp_w - rest > rest+ten_kappa - wp_w)) 43 | { 44 | buffer[len-1]--; rest += ten_kappa; 45 | } 46 | } 47 | 48 | void digit_gen(diy_fp_t W, diy_fp_t Mp, diy_fp_t delta, 49 | char* buffer, int* len, int* K) { 50 | uint32_t div; int d,kappa; diy_fp_t one, wp_w; 51 | wp_w = minus(Mp, W); 52 | one.f = ((uint64_t) 1) << -Mp.e; one.e = Mp.e; 53 | uint32_t p1 = Mp.f >> -one.e; /// Mp_cut 54 | uint64_t p2 = Mp.f & (one.f - 1); 55 | *len = 0; kappa = 10; div = TEN9; 56 | while (kappa > 0) { 57 | d = p1 / div; 58 | if (d || *len) buffer[(*len)++] = '0' + d; /// Mp_inv1 59 | p1 %= div; kappa--; 60 | uint64_t tmp = (((uint64_t)p1)<<-one.e)+p2; 61 | if (tmp <= delta.f) { /// Mp_delta 62 | *K += kappa; 63 | grisu_round(buffer, *len, delta.f, tmp, ((uint64_t)div) << -one.e, wp_w.f); 64 | return; 65 | } 66 | div /= 10; 67 | } 68 | uint64_t unit = 1; 69 | while (1) { 70 | p2 *= 10; delta.f *= 10; unit *= 10; 71 | d = p2 >> -one.e; 72 | if (d || *len) buffer[(*len)++] = '0' + d; 73 | p2 &= one.f - 1; kappa--; 74 | if (p2 < delta.f) { 75 | *K += kappa; 76 | grisu_round(buffer, *len, delta.f, p2, one.f, wp_w.f*unit); 77 | return; 78 | } 79 | } 80 | } 81 | 82 | void grisu2(double v, char* buffer, int* length, int* K) { 83 | diy_fp_t w_m, w_p; 84 | int q = 64, alpha = -59, gamma = -56; int pos; 85 | normalized_boundaries(v, &w_m, &w_p); 86 | diy_fp_t w = normalize_diy_fp(double2diy_fp(v)); 87 | int mk = k_comp(w_p.e + q, alpha, gamma); 88 | diy_fp_t c_mk = cached_power(mk); 89 | diy_fp_t W = multiply(w, c_mk); 90 | diy_fp_t Wp = multiply(w_p, c_mk); 91 | diy_fp_t Wm = multiply(w_m, c_mk); 92 | Wm.f++; Wp.f--; 93 | diy_fp_t delta = minus(Wp, Wm); 94 | *K = -mk; 95 | digit_gen(W, Wp, delta, buffer, length, K); 96 | } 97 | -------------------------------------------------------------------------------- /src/grisu/k_comp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | 28 | #define D_1_LOG2_10 0.30102999566398114 // 1 / lg(10) 29 | 30 | static int k_comp(int e, int alpha, int gamma) { 31 | return ceil((alpha-e+63) * D_1_LOG2_10); 32 | } 33 | -------------------------------------------------------------------------------- /src/grisu/powers.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "diy_fp.h" 27 | #include "powers_ten_round64.h" 28 | -------------------------------------------------------------------------------- /src/grisu/prettify.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Florian Loitsch 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "fast_exponent.h" 27 | #include 28 | 29 | static void prettify_string(char* buffer, int from_pos, int end_pos, int k) { 30 | int nb_digits = end_pos - from_pos; 31 | int i, offset; 32 | /* v = buffer * 10^k 33 | kk is such that 10^(kk-1) <= v < 10^kk 34 | this way kk gives the position of the comma. 35 | */ 36 | int kk = nb_digits + k; 37 | 38 | buffer[end_pos] = '\0'; 39 | if (nb_digits <= kk && kk <= 21) { 40 | /* the first digits are already in. Add some 0s and call it a day. */ 41 | /* the 21 is a personal choice. Only 16 digits could possibly be relevant. 42 | * Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */ 43 | for (i = nb_digits; i < kk; i++) 44 | buffer[from_pos + i] = '0'; 45 | buffer[kk] = '.'; 46 | buffer[kk+1] = '0'; 47 | buffer[kk+2] = '\0'; 48 | } else if (0 < kk && kk <= 21) { 49 | /* comma number. Just insert a '.' at the correct location. */ 50 | memmove(&buffer[from_pos + kk + 1], &buffer[from_pos + kk], nb_digits - kk); 51 | buffer[from_pos + kk] = '.'; 52 | buffer[from_pos + nb_digits + 1] = '\0'; 53 | } else if (-6 < kk && kk <= 0) { 54 | /* something like 0.000abcde. 55 | * add '0.' and some '0's */ 56 | offset = 2-kk; 57 | memmove(&buffer[from_pos + offset], &buffer[from_pos], nb_digits); 58 | buffer[from_pos] = '0'; 59 | buffer[from_pos + 1] = '.'; 60 | for (i = from_pos + 2; i < from_pos + offset; i++) 61 | buffer[i] = '0'; 62 | buffer[from_pos + nb_digits + offset] = '\0'; 63 | } else if (nb_digits == 1) { 64 | /* just add 'e...' */ 65 | buffer[from_pos + 1] = 'e'; 66 | /* fill_positive_fixnum will terminate the string */ 67 | fill_exponent(kk - 1, &buffer[from_pos + 2]); 68 | } else { 69 | /* leave the first digit. then add a '.' and at the end 'e...' */ 70 | memmove(&buffer[from_pos + 2], &buffer[from_pos + 1], nb_digits-1); 71 | buffer[from_pos + 1] = '.'; 72 | buffer[from_pos + nb_digits + 1] = 'e'; 73 | /* fill_fixnum will terminate the string */ 74 | fill_exponent(kk - 1, &buffer[from_pos + nb_digits + 2]); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/grisu2btest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | extern "C" { 4 | bool fill_double(double v, char* buffer); 5 | } 6 | 7 | void dtoa_grisu2(double value, char* buffer) { 8 | if (value == 0) 9 | strcpy(buffer, "0.0"); 10 | else { 11 | if (value < 0) { 12 | *buffer++ = '-'; 13 | value = -value; 14 | } 15 | fill_double(value, buffer); 16 | } 17 | } 18 | 19 | REGISTER_TEST(grisu2); 20 | -------------------------------------------------------------------------------- /src/milotest.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include "milo/dtoa_milo.h" 3 | 4 | REGISTER_TEST(milo); 5 | -------------------------------------------------------------------------------- /src/msinttypes/inttypes.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant inttypes.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | #ifndef _MSC_VER // [ 34 | #error "Use this header only with Microsoft Visual C++ compilers!" 35 | #endif // _MSC_VER ] 36 | 37 | #ifndef _MSC_INTTYPES_H_ // [ 38 | #define _MSC_INTTYPES_H_ 39 | 40 | #if _MSC_VER > 1000 41 | #pragma once 42 | #endif 43 | 44 | #include "stdint.h" 45 | 46 | // 7.8 Format conversion of integer types 47 | 48 | typedef struct { 49 | intmax_t quot; 50 | intmax_t rem; 51 | } imaxdiv_t; 52 | 53 | // 7.8.1 Macros for format specifiers 54 | 55 | #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 56 | 57 | // The fprintf macros for signed integers are: 58 | #define PRId8 "d" 59 | #define PRIi8 "i" 60 | #define PRIdLEAST8 "d" 61 | #define PRIiLEAST8 "i" 62 | #define PRIdFAST8 "d" 63 | #define PRIiFAST8 "i" 64 | 65 | #define PRId16 "hd" 66 | #define PRIi16 "hi" 67 | #define PRIdLEAST16 "hd" 68 | #define PRIiLEAST16 "hi" 69 | #define PRIdFAST16 "hd" 70 | #define PRIiFAST16 "hi" 71 | 72 | #define PRId32 "I32d" 73 | #define PRIi32 "I32i" 74 | #define PRIdLEAST32 "I32d" 75 | #define PRIiLEAST32 "I32i" 76 | #define PRIdFAST32 "I32d" 77 | #define PRIiFAST32 "I32i" 78 | 79 | #define PRId64 "I64d" 80 | #define PRIi64 "I64i" 81 | #define PRIdLEAST64 "I64d" 82 | #define PRIiLEAST64 "I64i" 83 | #define PRIdFAST64 "I64d" 84 | #define PRIiFAST64 "I64i" 85 | 86 | #define PRIdMAX "I64d" 87 | #define PRIiMAX "I64i" 88 | 89 | #define PRIdPTR "Id" 90 | #define PRIiPTR "Ii" 91 | 92 | // The fprintf macros for unsigned integers are: 93 | #define PRIo8 "o" 94 | #define PRIu8 "u" 95 | #define PRIx8 "x" 96 | #define PRIX8 "X" 97 | #define PRIoLEAST8 "o" 98 | #define PRIuLEAST8 "u" 99 | #define PRIxLEAST8 "x" 100 | #define PRIXLEAST8 "X" 101 | #define PRIoFAST8 "o" 102 | #define PRIuFAST8 "u" 103 | #define PRIxFAST8 "x" 104 | #define PRIXFAST8 "X" 105 | 106 | #define PRIo16 "ho" 107 | #define PRIu16 "hu" 108 | #define PRIx16 "hx" 109 | #define PRIX16 "hX" 110 | #define PRIoLEAST16 "ho" 111 | #define PRIuLEAST16 "hu" 112 | #define PRIxLEAST16 "hx" 113 | #define PRIXLEAST16 "hX" 114 | #define PRIoFAST16 "ho" 115 | #define PRIuFAST16 "hu" 116 | #define PRIxFAST16 "hx" 117 | #define PRIXFAST16 "hX" 118 | 119 | #define PRIo32 "I32o" 120 | #define PRIu32 "I32u" 121 | #define PRIx32 "I32x" 122 | #define PRIX32 "I32X" 123 | #define PRIoLEAST32 "I32o" 124 | #define PRIuLEAST32 "I32u" 125 | #define PRIxLEAST32 "I32x" 126 | #define PRIXLEAST32 "I32X" 127 | #define PRIoFAST32 "I32o" 128 | #define PRIuFAST32 "I32u" 129 | #define PRIxFAST32 "I32x" 130 | #define PRIXFAST32 "I32X" 131 | 132 | #define PRIo64 "I64o" 133 | #define PRIu64 "I64u" 134 | #define PRIx64 "I64x" 135 | #define PRIX64 "I64X" 136 | #define PRIoLEAST64 "I64o" 137 | #define PRIuLEAST64 "I64u" 138 | #define PRIxLEAST64 "I64x" 139 | #define PRIXLEAST64 "I64X" 140 | #define PRIoFAST64 "I64o" 141 | #define PRIuFAST64 "I64u" 142 | #define PRIxFAST64 "I64x" 143 | #define PRIXFAST64 "I64X" 144 | 145 | #define PRIoMAX "I64o" 146 | #define PRIuMAX "I64u" 147 | #define PRIxMAX "I64x" 148 | #define PRIXMAX "I64X" 149 | 150 | #define PRIoPTR "Io" 151 | #define PRIuPTR "Iu" 152 | #define PRIxPTR "Ix" 153 | #define PRIXPTR "IX" 154 | 155 | // The fscanf macros for signed integers are: 156 | #define SCNd8 "d" 157 | #define SCNi8 "i" 158 | #define SCNdLEAST8 "d" 159 | #define SCNiLEAST8 "i" 160 | #define SCNdFAST8 "d" 161 | #define SCNiFAST8 "i" 162 | 163 | #define SCNd16 "hd" 164 | #define SCNi16 "hi" 165 | #define SCNdLEAST16 "hd" 166 | #define SCNiLEAST16 "hi" 167 | #define SCNdFAST16 "hd" 168 | #define SCNiFAST16 "hi" 169 | 170 | #define SCNd32 "ld" 171 | #define SCNi32 "li" 172 | #define SCNdLEAST32 "ld" 173 | #define SCNiLEAST32 "li" 174 | #define SCNdFAST32 "ld" 175 | #define SCNiFAST32 "li" 176 | 177 | #define SCNd64 "I64d" 178 | #define SCNi64 "I64i" 179 | #define SCNdLEAST64 "I64d" 180 | #define SCNiLEAST64 "I64i" 181 | #define SCNdFAST64 "I64d" 182 | #define SCNiFAST64 "I64i" 183 | 184 | #define SCNdMAX "I64d" 185 | #define SCNiMAX "I64i" 186 | 187 | #ifdef _WIN64 // [ 188 | # define SCNdPTR "I64d" 189 | # define SCNiPTR "I64i" 190 | #else // _WIN64 ][ 191 | # define SCNdPTR "ld" 192 | # define SCNiPTR "li" 193 | #endif // _WIN64 ] 194 | 195 | // The fscanf macros for unsigned integers are: 196 | #define SCNo8 "o" 197 | #define SCNu8 "u" 198 | #define SCNx8 "x" 199 | #define SCNX8 "X" 200 | #define SCNoLEAST8 "o" 201 | #define SCNuLEAST8 "u" 202 | #define SCNxLEAST8 "x" 203 | #define SCNXLEAST8 "X" 204 | #define SCNoFAST8 "o" 205 | #define SCNuFAST8 "u" 206 | #define SCNxFAST8 "x" 207 | #define SCNXFAST8 "X" 208 | 209 | #define SCNo16 "ho" 210 | #define SCNu16 "hu" 211 | #define SCNx16 "hx" 212 | #define SCNX16 "hX" 213 | #define SCNoLEAST16 "ho" 214 | #define SCNuLEAST16 "hu" 215 | #define SCNxLEAST16 "hx" 216 | #define SCNXLEAST16 "hX" 217 | #define SCNoFAST16 "ho" 218 | #define SCNuFAST16 "hu" 219 | #define SCNxFAST16 "hx" 220 | #define SCNXFAST16 "hX" 221 | 222 | #define SCNo32 "lo" 223 | #define SCNu32 "lu" 224 | #define SCNx32 "lx" 225 | #define SCNX32 "lX" 226 | #define SCNoLEAST32 "lo" 227 | #define SCNuLEAST32 "lu" 228 | #define SCNxLEAST32 "lx" 229 | #define SCNXLEAST32 "lX" 230 | #define SCNoFAST32 "lo" 231 | #define SCNuFAST32 "lu" 232 | #define SCNxFAST32 "lx" 233 | #define SCNXFAST32 "lX" 234 | 235 | #define SCNo64 "I64o" 236 | #define SCNu64 "I64u" 237 | #define SCNx64 "I64x" 238 | #define SCNX64 "I64X" 239 | #define SCNoLEAST64 "I64o" 240 | #define SCNuLEAST64 "I64u" 241 | #define SCNxLEAST64 "I64x" 242 | #define SCNXLEAST64 "I64X" 243 | #define SCNoFAST64 "I64o" 244 | #define SCNuFAST64 "I64u" 245 | #define SCNxFAST64 "I64x" 246 | #define SCNXFAST64 "I64X" 247 | 248 | #define SCNoMAX "I64o" 249 | #define SCNuMAX "I64u" 250 | #define SCNxMAX "I64x" 251 | #define SCNXMAX "I64X" 252 | 253 | #ifdef _WIN64 // [ 254 | # define SCNoPTR "I64o" 255 | # define SCNuPTR "I64u" 256 | # define SCNxPTR "I64x" 257 | # define SCNXPTR "I64X" 258 | #else // _WIN64 ][ 259 | # define SCNoPTR "lo" 260 | # define SCNuPTR "lu" 261 | # define SCNxPTR "lx" 262 | # define SCNXPTR "lX" 263 | #endif // _WIN64 ] 264 | 265 | #endif // __STDC_FORMAT_MACROS ] 266 | 267 | // 7.8.2 Functions for greatest-width integer types 268 | 269 | // 7.8.2.1 The imaxabs function 270 | #define imaxabs _abs64 271 | 272 | // 7.8.2.2 The imaxdiv function 273 | 274 | // This is modified version of div() function from Microsoft's div.c found 275 | // in %MSVC.NET%\crt\src\div.c 276 | #ifdef STATIC_IMAXDIV // [ 277 | static 278 | #else // STATIC_IMAXDIV ][ 279 | _inline 280 | #endif // STATIC_IMAXDIV ] 281 | imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) 282 | { 283 | imaxdiv_t result; 284 | 285 | result.quot = numer / denom; 286 | result.rem = numer % denom; 287 | 288 | if (numer < 0 && result.rem > 0) { 289 | // did division wrong; must fix up 290 | ++result.quot; 291 | result.rem -= denom; 292 | } 293 | 294 | return result; 295 | } 296 | 297 | // 7.8.2.3 The strtoimax and strtoumax functions 298 | #define strtoimax _strtoi64 299 | #define strtoumax _strtoui64 300 | 301 | // 7.8.2.4 The wcstoimax and wcstoumax functions 302 | #define wcstoimax _wcstoi64 303 | #define wcstoumax _wcstoui64 304 | 305 | 306 | #endif // _MSC_INTTYPES_H_ ] 307 | -------------------------------------------------------------------------------- /src/msinttypes/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | #ifndef _MSC_VER // [ 34 | #error "Use this header only with Microsoft Visual C++ compilers!" 35 | #endif // _MSC_VER ] 36 | 37 | #ifndef _MSC_STDINT_H_ // [ 38 | #define _MSC_STDINT_H_ 39 | 40 | #if _MSC_VER > 1000 41 | #pragma once 42 | #endif 43 | 44 | // miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. 45 | #if _MSC_VER >= 1600 // [ 46 | #include 47 | 48 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 49 | 50 | #undef INT8_C 51 | #undef INT16_C 52 | #undef INT32_C 53 | #undef INT64_C 54 | #undef UINT8_C 55 | #undef UINT16_C 56 | #undef UINT32_C 57 | #undef UINT64_C 58 | 59 | // 7.18.4.1 Macros for minimum-width integer constants 60 | 61 | #define INT8_C(val) val##i8 62 | #define INT16_C(val) val##i16 63 | #define INT32_C(val) val##i32 64 | #define INT64_C(val) val##i64 65 | 66 | #define UINT8_C(val) val##ui8 67 | #define UINT16_C(val) val##ui16 68 | #define UINT32_C(val) val##ui32 69 | #define UINT64_C(val) val##ui64 70 | 71 | // 7.18.4.2 Macros for greatest-width integer constants 72 | // These #ifndef's are needed to prevent collisions with . 73 | // Check out Issue 9 for the details. 74 | #ifndef INTMAX_C // [ 75 | # define INTMAX_C INT64_C 76 | #endif // INTMAX_C ] 77 | #ifndef UINTMAX_C // [ 78 | # define UINTMAX_C UINT64_C 79 | #endif // UINTMAX_C ] 80 | 81 | #endif // __STDC_CONSTANT_MACROS ] 82 | 83 | #else // ] _MSC_VER >= 1700 [ 84 | 85 | #include 86 | 87 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 88 | // compiling for ARM we should wrap include with 'extern "C++" {}' 89 | // or compiler give many errors like this: 90 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 91 | #ifdef __cplusplus 92 | extern "C" { 93 | #endif 94 | # include 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | // Define _W64 macros to mark types changing their size, like intptr_t. 100 | #ifndef _W64 101 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 102 | # define _W64 __w64 103 | # else 104 | # define _W64 105 | # endif 106 | #endif 107 | 108 | 109 | // 7.18.1 Integer types 110 | 111 | // 7.18.1.1 Exact-width integer types 112 | 113 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 114 | // realize that, e.g. char has the same size as __int8 115 | // so we give up on __intX for them. 116 | #if (_MSC_VER < 1300) 117 | typedef signed char int8_t; 118 | typedef signed short int16_t; 119 | typedef signed int int32_t; 120 | typedef unsigned char uint8_t; 121 | typedef unsigned short uint16_t; 122 | typedef unsigned int uint32_t; 123 | #else 124 | typedef signed __int8 int8_t; 125 | typedef signed __int16 int16_t; 126 | typedef signed __int32 int32_t; 127 | typedef unsigned __int8 uint8_t; 128 | typedef unsigned __int16 uint16_t; 129 | typedef unsigned __int32 uint32_t; 130 | #endif 131 | typedef signed __int64 int64_t; 132 | typedef unsigned __int64 uint64_t; 133 | 134 | 135 | // 7.18.1.2 Minimum-width integer types 136 | typedef int8_t int_least8_t; 137 | typedef int16_t int_least16_t; 138 | typedef int32_t int_least32_t; 139 | typedef int64_t int_least64_t; 140 | typedef uint8_t uint_least8_t; 141 | typedef uint16_t uint_least16_t; 142 | typedef uint32_t uint_least32_t; 143 | typedef uint64_t uint_least64_t; 144 | 145 | // 7.18.1.3 Fastest minimum-width integer types 146 | typedef int8_t int_fast8_t; 147 | typedef int16_t int_fast16_t; 148 | typedef int32_t int_fast32_t; 149 | typedef int64_t int_fast64_t; 150 | typedef uint8_t uint_fast8_t; 151 | typedef uint16_t uint_fast16_t; 152 | typedef uint32_t uint_fast32_t; 153 | typedef uint64_t uint_fast64_t; 154 | 155 | // 7.18.1.4 Integer types capable of holding object pointers 156 | #ifdef _WIN64 // [ 157 | typedef signed __int64 intptr_t; 158 | typedef unsigned __int64 uintptr_t; 159 | #else // _WIN64 ][ 160 | typedef _W64 signed int intptr_t; 161 | typedef _W64 unsigned int uintptr_t; 162 | #endif // _WIN64 ] 163 | 164 | // 7.18.1.5 Greatest-width integer types 165 | typedef int64_t intmax_t; 166 | typedef uint64_t uintmax_t; 167 | 168 | 169 | // 7.18.2 Limits of specified-width integer types 170 | 171 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 172 | 173 | // 7.18.2.1 Limits of exact-width integer types 174 | #define INT8_MIN ((int8_t)_I8_MIN) 175 | #define INT8_MAX _I8_MAX 176 | #define INT16_MIN ((int16_t)_I16_MIN) 177 | #define INT16_MAX _I16_MAX 178 | #define INT32_MIN ((int32_t)_I32_MIN) 179 | #define INT32_MAX _I32_MAX 180 | #define INT64_MIN ((int64_t)_I64_MIN) 181 | #define INT64_MAX _I64_MAX 182 | #define UINT8_MAX _UI8_MAX 183 | #define UINT16_MAX _UI16_MAX 184 | #define UINT32_MAX _UI32_MAX 185 | #define UINT64_MAX _UI64_MAX 186 | 187 | // 7.18.2.2 Limits of minimum-width integer types 188 | #define INT_LEAST8_MIN INT8_MIN 189 | #define INT_LEAST8_MAX INT8_MAX 190 | #define INT_LEAST16_MIN INT16_MIN 191 | #define INT_LEAST16_MAX INT16_MAX 192 | #define INT_LEAST32_MIN INT32_MIN 193 | #define INT_LEAST32_MAX INT32_MAX 194 | #define INT_LEAST64_MIN INT64_MIN 195 | #define INT_LEAST64_MAX INT64_MAX 196 | #define UINT_LEAST8_MAX UINT8_MAX 197 | #define UINT_LEAST16_MAX UINT16_MAX 198 | #define UINT_LEAST32_MAX UINT32_MAX 199 | #define UINT_LEAST64_MAX UINT64_MAX 200 | 201 | // 7.18.2.3 Limits of fastest minimum-width integer types 202 | #define INT_FAST8_MIN INT8_MIN 203 | #define INT_FAST8_MAX INT8_MAX 204 | #define INT_FAST16_MIN INT16_MIN 205 | #define INT_FAST16_MAX INT16_MAX 206 | #define INT_FAST32_MIN INT32_MIN 207 | #define INT_FAST32_MAX INT32_MAX 208 | #define INT_FAST64_MIN INT64_MIN 209 | #define INT_FAST64_MAX INT64_MAX 210 | #define UINT_FAST8_MAX UINT8_MAX 211 | #define UINT_FAST16_MAX UINT16_MAX 212 | #define UINT_FAST32_MAX UINT32_MAX 213 | #define UINT_FAST64_MAX UINT64_MAX 214 | 215 | // 7.18.2.4 Limits of integer types capable of holding object pointers 216 | #ifdef _WIN64 // [ 217 | # define INTPTR_MIN INT64_MIN 218 | # define INTPTR_MAX INT64_MAX 219 | # define UINTPTR_MAX UINT64_MAX 220 | #else // _WIN64 ][ 221 | # define INTPTR_MIN INT32_MIN 222 | # define INTPTR_MAX INT32_MAX 223 | # define UINTPTR_MAX UINT32_MAX 224 | #endif // _WIN64 ] 225 | 226 | // 7.18.2.5 Limits of greatest-width integer types 227 | #define INTMAX_MIN INT64_MIN 228 | #define INTMAX_MAX INT64_MAX 229 | #define UINTMAX_MAX UINT64_MAX 230 | 231 | // 7.18.3 Limits of other integer types 232 | 233 | #ifdef _WIN64 // [ 234 | # define PTRDIFF_MIN _I64_MIN 235 | # define PTRDIFF_MAX _I64_MAX 236 | #else // _WIN64 ][ 237 | # define PTRDIFF_MIN _I32_MIN 238 | # define PTRDIFF_MAX _I32_MAX 239 | #endif // _WIN64 ] 240 | 241 | #define SIG_ATOMIC_MIN INT_MIN 242 | #define SIG_ATOMIC_MAX INT_MAX 243 | 244 | #ifndef SIZE_MAX // [ 245 | # ifdef _WIN64 // [ 246 | # define SIZE_MAX _UI64_MAX 247 | # else // _WIN64 ][ 248 | # define SIZE_MAX _UI32_MAX 249 | # endif // _WIN64 ] 250 | #endif // SIZE_MAX ] 251 | 252 | // WCHAR_MIN and WCHAR_MAX are also defined in 253 | #ifndef WCHAR_MIN // [ 254 | # define WCHAR_MIN 0 255 | #endif // WCHAR_MIN ] 256 | #ifndef WCHAR_MAX // [ 257 | # define WCHAR_MAX _UI16_MAX 258 | #endif // WCHAR_MAX ] 259 | 260 | #define WINT_MIN 0 261 | #define WINT_MAX _UI16_MAX 262 | 263 | #endif // __STDC_LIMIT_MACROS ] 264 | 265 | 266 | // 7.18.4 Limits of other integer types 267 | 268 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 269 | 270 | // 7.18.4.1 Macros for minimum-width integer constants 271 | 272 | #define INT8_C(val) val##i8 273 | #define INT16_C(val) val##i16 274 | #define INT32_C(val) val##i32 275 | #define INT64_C(val) val##i64 276 | 277 | #define UINT8_C(val) val##ui8 278 | #define UINT16_C(val) val##ui16 279 | #define UINT32_C(val) val##ui32 280 | #define UINT64_C(val) val##ui64 281 | 282 | // 7.18.4.2 Macros for greatest-width integer constants 283 | // These #ifndef's are needed to prevent collisions with . 284 | // Check out Issue 9 for the details. 285 | #ifndef INTMAX_C // [ 286 | # define INTMAX_C INT64_C 287 | #endif // INTMAX_C ] 288 | #ifndef UINTMAX_C // [ 289 | # define UINTMAX_C UINT64_C 290 | #endif // UINTMAX_C ] 291 | 292 | #endif // __STDC_CONSTANT_MACROS ] 293 | 294 | #endif // _MSC_VER >= 1600 ] 295 | 296 | #endif // _MSC_STDINT_H_ ] 297 | -------------------------------------------------------------------------------- /src/null.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | void dtoa_null(double, char*) { 4 | } 5 | 6 | REGISTER_TEST(null); 7 | -------------------------------------------------------------------------------- /src/ostringstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "test.h" 4 | 5 | void dtoa_ostringstream(double value, char* buffer) { 6 | std::ostringstream oss; 7 | oss << std::setprecision(17) << value; 8 | strcpy(buffer, oss.str().c_str()); 9 | } 10 | 11 | //#if RUN_CPPDTOA 12 | REGISTER_TEST(ostringstream); 13 | //#endif 14 | -------------------------------------------------------------------------------- /src/ostrstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "test.h" 4 | 5 | void dtoa_ostrstream(double value, char* buffer) { 6 | std::ostrstream oss(buffer, 25); 7 | oss << std::setprecision(17) << value << std::ends; 8 | strcpy(buffer, oss.str()); 9 | } 10 | 11 | //#if RUN_CPPITOA 12 | REGISTER_TEST(ostrstream); 13 | //#endif 14 | -------------------------------------------------------------------------------- /src/resultfilename.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef MACHINE 4 | #define MACHINE "unknown" 5 | #endif 6 | 7 | #if defined(_WIN64) 8 | # define OS "win64" 9 | #elif defined(_WIN32) 10 | # define OS "win32" 11 | #elif defined(__CYGWIN__) && defined(__x86_64) 12 | # define OS "cygwin64" 13 | #elif defined(__CYGWIN__) 14 | # define OS "cygwin32" 15 | #elif defined(__APPLE__) 16 | # include "TargetConditionals.h" 17 | # if TARGET_OS_IPHONE 18 | # ifdef __LP64__ 19 | # define OS "ios64" 20 | # else 21 | # define OS "ios32" 22 | # endif 23 | # elif TARGET_OS_MAC 24 | # ifdef __amd64__ 25 | # define OS "mac64" 26 | # else 27 | # define OS "mac32" 28 | # endif 29 | # endif 30 | #endif 31 | 32 | #ifndef OS 33 | #define OS "unknown" 34 | #endif 35 | 36 | #define STR_HELPER(x) #x 37 | #define STR(x) STR_HELPER(x) 38 | 39 | #if defined(_MSC_VER) 40 | # if _MSC_VER >= 1800 41 | # define COMPILER "vc2013" 42 | # elif _MSC_VER >= 1700 43 | # define COMPILER "vc2012" 44 | # elif _MSC_VER >= 1600 45 | # define COMPILER "vc2010" 46 | # elif _MSC_VER >= 1500 47 | # define COMPILER "vc2008" 48 | # elif _MSC_VER >= 1400 49 | # define COMPILER "vc2005" 50 | # else 51 | # define COMPILER "vc" 52 | # endif 53 | #elif defined(__clang__) 54 | # define COMPILER "clang" STR(__clang_major__) "." STR(__clang_minor__) 55 | #elif defined(__GNUC__) 56 | # define COMPILER "gcc" STR(__GNUC__) "." STR(__GNUC_MINOR__) 57 | #else 58 | # define COMPILER "Unknown" 59 | #endif 60 | 61 | #define RESULT_FILENAME MACHINE "_" OS "_" COMPILER ".csv" 62 | -------------------------------------------------------------------------------- /src/sprintf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "test.h" 3 | 4 | void dtoa_sprintf(double value, char* buffer) { 5 | sprintf(buffer, "%.17g", value); 6 | } 7 | 8 | REGISTER_TEST(sprintf); 9 | -------------------------------------------------------------------------------- /src/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Test; 7 | typedef std::vector TestList; 8 | class TestManager { 9 | public: 10 | static TestManager& Instance() { 11 | static TestManager singleton; 12 | return singleton; 13 | } 14 | 15 | void AddTest(const Test* test) { 16 | mTests.push_back(test); 17 | } 18 | 19 | const TestList& GetTests() const { 20 | return mTests; 21 | } 22 | 23 | TestList& GetTests() { 24 | return mTests; 25 | } 26 | 27 | private: 28 | TestList mTests; 29 | }; 30 | 31 | struct Test { 32 | Test( 33 | const char* fname, 34 | void (*dtoa)(double, char*)) 35 | : 36 | fname(fname), 37 | dtoa(dtoa) 38 | { 39 | TestManager::Instance().AddTest(this); 40 | } 41 | 42 | bool operator<(const Test& rhs) const { 43 | return strcmp(fname, rhs.fname) < 0; 44 | } 45 | 46 | const char* fname; 47 | void (*dtoa)(double, char*); 48 | }; 49 | 50 | 51 | #define STRINGIFY(x) #x 52 | #define REGISTER_TEST(f) static Test gRegister##f(STRINGIFY(f), dtoa##_##f) 53 | -------------------------------------------------------------------------------- /src/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | 5 | #define WIN32_LEAN_AND_MEAN 6 | #include 7 | 8 | class Timer { 9 | public: 10 | Timer() : start_(), end_() { 11 | } 12 | 13 | void Start() { 14 | QueryPerformanceCounter(&start_); 15 | } 16 | 17 | void Stop() { 18 | QueryPerformanceCounter(&end_); 19 | } 20 | 21 | double GetElapsedMilliseconds() { 22 | LARGE_INTEGER freq; 23 | QueryPerformanceFrequency(&freq); 24 | return (end_.QuadPart - start_.QuadPart) * 1000.0 / freq.QuadPart; 25 | } 26 | 27 | private: 28 | LARGE_INTEGER start_; 29 | LARGE_INTEGER end_; 30 | }; 31 | 32 | // Undefine Windows bad macros 33 | #undef min 34 | #undef max 35 | 36 | #else 37 | 38 | #include 39 | 40 | class Timer { 41 | public: 42 | Timer() : start_(), end_() { 43 | } 44 | 45 | void Start() { 46 | gettimeofday(&start_, NULL); 47 | } 48 | 49 | void Stop() { 50 | gettimeofday(&end_, NULL); 51 | } 52 | 53 | double GetElapsedMilliseconds() { 54 | return (end_.tv_sec - start_.tv_sec) * 1000.0 55 | + (end_.tv_usec - start_.tv_usec) / 1000.0; 56 | } 57 | 58 | private: 59 | struct timeval start_; 60 | struct timeval end_; 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /stb_sprintf.cpp: -------------------------------------------------------------------------------- 1 | #define STB_SPRINTF_IMPLEMENTATION 2 | #include "stb_sprintf/stb_sprintf.h" 3 | #include "test.h" 4 | 5 | void dtoa_stb_sprintf(double value, char* buffer) { 6 | stbsp_sprintf(buffer, "%.17g", value); 7 | } 8 | 9 | REGISTER_TEST(stb_sprintf); 10 | --------------------------------------------------------------------------------