├── test ├── catch_main.cc ├── CMakeLists.txt └── scan_number.h ├── resources ├── bench_digits.png ├── bench_uniform.png ├── bench_random_bits.png └── bench_uniform_e10.png ├── bench ├── results │ ├── grisu2_not_short.png │ ├── grisu2_not_optimal.png │ ├── clang-10.0 │ │ └── i7-9750H │ │ │ ├── ryu.png │ │ │ ├── grisu3.png │ │ │ ├── dragonbox.png │ │ │ ├── schubfach.png │ │ │ └── plot.py │ └── plot.py ├── CMakeLists.txt └── bench_strtod.cc ├── ext ├── CMakeLists.txt ├── ryu │ ├── CMakeLists.txt │ ├── ryu │ │ ├── ryu.h │ │ ├── digit_table.h │ │ ├── common.h │ │ └── d2s_intrinsics.h │ ├── LICENSE-Boost │ └── README.md ├── google_benchmark │ ├── CMakeLists.txt │ └── src │ │ ├── benchmark_api_internal.cc │ │ ├── sleep.h │ │ ├── colorprint.h │ │ ├── counter.h │ │ ├── arraysize.h │ │ ├── timers.h │ │ ├── statistics.h │ │ ├── benchmark_api_internal.h │ │ ├── benchmark_runner.h │ │ ├── thread_manager.h │ │ ├── string_util.h │ │ ├── sleep.cc │ │ ├── benchmark_name.cc │ │ ├── log.h │ │ ├── complexity.h │ │ ├── counter.cc │ │ ├── thread_timer.h │ │ ├── internal_macros.h │ │ ├── check.h │ │ ├── commandlineflags.h │ │ ├── benchmark_register.h │ │ ├── reporter.cc │ │ ├── re.h │ │ ├── csv_reporter.cc │ │ ├── mutex.h │ │ ├── colorprint.cc │ │ ├── console_reporter.cc │ │ ├── statistics.cc │ │ ├── timers.cc │ │ └── cycleclock.h └── google_double_conversion │ ├── CMakeLists.txt │ ├── LICENSE │ ├── README.md │ └── double-conversion │ ├── double-conversion.h │ ├── strtod.h │ ├── fixed-dtoa.h │ ├── cached-powers.h │ ├── fast-dtoa.h │ ├── bignum-dtoa.h │ ├── diy-fp.h │ └── bignum.h ├── .gitignore ├── src ├── CMakeLists.txt ├── dragon4.h ├── grisu2.h ├── grisu3.h ├── grisu2b.h ├── dragonbox.h ├── schubfach_32.h ├── schubfach_64.h ├── ryu_32.h └── ryu_64.h ├── scripts ├── mod.py ├── ryu │ ├── compute_table_sizes.py │ ├── compute_powers.py │ ├── euclid_min_max.py │ └── compute_bit_sizes.py └── dtoa │ ├── dtoa_adams.py │ └── dtoa_burger_dybvig.py ├── CMakeLists.txt ├── LICENSE ├── .appveyor.yml ├── .travis.yml └── README.md /test/catch_main.cc: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" 3 | -------------------------------------------------------------------------------- /resources/bench_digits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/resources/bench_digits.png -------------------------------------------------------------------------------- /resources/bench_uniform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/resources/bench_uniform.png -------------------------------------------------------------------------------- /resources/bench_random_bits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/resources/bench_random_bits.png -------------------------------------------------------------------------------- /resources/bench_uniform_e10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/resources/bench_uniform_e10.png -------------------------------------------------------------------------------- /bench/results/grisu2_not_short.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/grisu2_not_short.png -------------------------------------------------------------------------------- /bench/results/grisu2_not_optimal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/grisu2_not_optimal.png -------------------------------------------------------------------------------- /ext/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(google_benchmark) 2 | add_subdirectory(google_double_conversion) 3 | add_subdirectory(ryu) 4 | -------------------------------------------------------------------------------- /bench/results/clang-10.0/i7-9750H/ryu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/clang-10.0/i7-9750H/ryu.png -------------------------------------------------------------------------------- /bench/results/clang-10.0/i7-9750H/grisu3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/clang-10.0/i7-9750H/grisu3.png -------------------------------------------------------------------------------- /bench/results/clang-10.0/i7-9750H/dragonbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/clang-10.0/i7-9750H/dragonbox.png -------------------------------------------------------------------------------- /bench/results/clang-10.0/i7-9750H/schubfach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abolz/Drachennest/HEAD/bench/results/clang-10.0/i7-9750H/schubfach.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs/ 2 | /.vscode/ 3 | /backups/ 4 | /build*/ 5 | /doc/ 6 | /out/ 7 | /scratch/ 8 | /scripts/dtoa/*.pyc 9 | /scripts/grisu/*.pyc 10 | /scripts/ryu/*.pyc 11 | /vs/ 12 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB drachennest_sources "*.h" "*.cc") 2 | 3 | add_library(drachennest STATIC ${drachennest_sources}) 4 | 5 | target_link_libraries( 6 | drachennest 7 | INTERFACE 8 | ${DN_INTERFACE} 9 | ) 10 | -------------------------------------------------------------------------------- /ext/ryu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE ryu_sources "*.h" "*.c") 2 | 3 | add_library(ryu STATIC ${ryu_sources}) 4 | 5 | target_include_directories( 6 | ryu 7 | PUBLIC 8 | "${CMAKE_SOURCE_DIR}/ext/ryu" 9 | ) 10 | 11 | target_link_libraries( 12 | ryu 13 | INTERFACE 14 | ${DN_INTERFACE} 15 | ) 16 | -------------------------------------------------------------------------------- /src/dragon4.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | namespace dragon4 { 11 | 12 | void Dragon4(uint64_t& digits, int& exponent, uint64_t f, int e, bool accept_bounds, bool lower_boundary_is_closer); 13 | 14 | } // namespace dragon4 15 | -------------------------------------------------------------------------------- /ext/google_benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE google_benchmark_sources "*.h" "*.cc") 2 | 3 | add_library(google_benchmark STATIC ${google_benchmark_sources}) 4 | 5 | target_include_directories( 6 | google_benchmark 7 | PUBLIC 8 | "${CMAKE_SOURCE_DIR}/ext/google_benchmark/include" 9 | ) 10 | 11 | target_link_libraries( 12 | google_benchmark 13 | INTERFACE 14 | ${DN_INTERFACE} 15 | PRIVATE 16 | shlwapi 17 | ) 18 | -------------------------------------------------------------------------------- /ext/google_double_conversion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE google_double_conversion_sources "*.h" "*.cc") 2 | 3 | add_library(google_double_conversion STATIC ${google_double_conversion_sources}) 4 | 5 | target_include_directories( 6 | google_double_conversion 7 | PUBLIC 8 | "${CMAKE_SOURCE_DIR}/ext/google_double_conversion/" 9 | ) 10 | 11 | target_link_libraries( 12 | google_double_conversion 13 | INTERFACE 14 | ${DN_INTERFACE} 15 | ) 16 | -------------------------------------------------------------------------------- /bench/results/clang-10.0/i7-9750H/plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pandas as pd 3 | import seaborn as sns 4 | 5 | names = [ 6 | "grisu3", 7 | "ryu", 8 | "schubfach", 9 | "dragonbox", 10 | ] 11 | 12 | for name in names: 13 | data = pd.read_csv(name + '.csv') 14 | data = data.pivot('len(N)', 'E', 'ns') 15 | data = data.transpose() 16 | ax = sns.heatmap(data, vmin=0.0, vmax=40.0, cmap="inferno") 17 | plt.savefig(name + '.png') 18 | plt.close() 19 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/benchmark_api_internal.cc: -------------------------------------------------------------------------------- 1 | #include "benchmark_api_internal.h" 2 | 3 | namespace benchmark { 4 | namespace internal { 5 | 6 | State BenchmarkInstance::Run(IterationCount iters, int thread_id, 7 | internal::ThreadTimer* timer, 8 | internal::ThreadManager* manager) const { 9 | State st(iters, arg, thread_id, threads, timer, manager); 10 | benchmark->Run(st); 11 | return st; 12 | } 13 | 14 | } // internal 15 | } // benchmark 16 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/sleep.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_SLEEP_H_ 2 | #define BENCHMARK_SLEEP_H_ 3 | 4 | namespace benchmark { 5 | const int kNumMillisPerSecond = 1000; 6 | const int kNumMicrosPerMilli = 1000; 7 | const int kNumMicrosPerSecond = kNumMillisPerSecond * 1000; 8 | const int kNumNanosPerMicro = 1000; 9 | const int kNumNanosPerSecond = kNumNanosPerMicro * kNumMicrosPerSecond; 10 | 11 | void SleepForMilliseconds(int milliseconds); 12 | void SleepForSeconds(double seconds); 13 | } // end namespace benchmark 14 | 15 | #endif // BENCHMARK_SLEEP_H_ 16 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(test_all_sources 2 | "catch.hpp" 3 | "catch_main.cc" 4 | "scan_number.h" 5 | "test_dtoa.cc" 6 | "test_strtod.cc" 7 | ) 8 | 9 | add_executable(test_all ${test_all_sources}) 10 | 11 | target_include_directories( 12 | test_all 13 | PUBLIC 14 | "${CMAKE_SOURCE_DIR}/ext/google_benchmark/" 15 | "${CMAKE_SOURCE_DIR}/ext/google_double_conversion/" 16 | "${CMAKE_SOURCE_DIR}/src/" 17 | ) 18 | 19 | target_link_libraries( 20 | test_all 21 | INTERFACE 22 | ${DN_INTERFACE} 23 | PRIVATE 24 | drachennest 25 | google_double_conversion 26 | ) 27 | -------------------------------------------------------------------------------- /src/grisu2.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace grisu2 { 9 | 10 | // char* output_end = Dtoa(buffer, value); 11 | // 12 | // Converts the given double-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // Note: 20 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 21 | 22 | constexpr int DtoaMinBufferLength = 64; 23 | 24 | char* Dtoa(char* buffer, double value); 25 | 26 | } // namespace grisu2 27 | -------------------------------------------------------------------------------- /src/grisu3.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace grisu3 { 9 | 10 | // char* output_end = Dtoa(buffer, value); 11 | // 12 | // Converts the given double-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // Note: 20 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 21 | 22 | constexpr int DtoaMinBufferLength = 64; 23 | 24 | char* Dtoa(char* buffer, double value); 25 | 26 | } // namespace grisu3 27 | -------------------------------------------------------------------------------- /src/grisu2b.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace grisu2b { 9 | 10 | // char* output_end = Dtoa(buffer, value); 11 | // 12 | // Converts the given double-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // Note: 20 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 21 | 22 | constexpr int DtoaMinBufferLength = 64; 23 | 24 | char* Dtoa(char* buffer, double value); 25 | 26 | } // namespace grisu2b 27 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/colorprint.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_COLORPRINT_H_ 2 | #define BENCHMARK_COLORPRINT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace benchmark { 9 | enum LogColor { 10 | COLOR_DEFAULT, 11 | COLOR_RED, 12 | COLOR_GREEN, 13 | COLOR_YELLOW, 14 | COLOR_BLUE, 15 | COLOR_MAGENTA, 16 | COLOR_CYAN, 17 | COLOR_WHITE 18 | }; 19 | 20 | std::string FormatString(const char* msg, va_list args); 21 | std::string FormatString(const char* msg, ...); 22 | 23 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, 24 | va_list args); 25 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...); 26 | 27 | // Returns true if stdout appears to be a terminal that supports colored 28 | // output, false otherwise. 29 | bool IsColorTerminal(); 30 | 31 | } // end namespace benchmark 32 | 33 | #endif // BENCHMARK_COLORPRINT_H_ 34 | -------------------------------------------------------------------------------- /scripts/mod.py: -------------------------------------------------------------------------------- 1 | def ExtendedGCD(a, b): 2 | if a == 0: 3 | return b, 0, 1 4 | else: 5 | g, y, x = ExtendedGCD(b % a, a) 6 | return g, x - (b // a) * y, y 7 | 8 | def ModularInverse(a, m): 9 | assert a >= 0 10 | assert m >= 1 11 | g, x, _ = ExtendedGCD(a, m) 12 | assert g == 1 13 | return x % m 14 | 15 | def PrintTable(base, max_exp, bits): 16 | assert bits % 4 == 0 17 | print('{{0x{:0{}X}u, 0x{:0{}X}u}}, // {}^{}'.format(1, bits // 4, 2**bits - 1, bits // 4, base, 0)) 18 | e = 1 19 | while True: 20 | a = base**e 21 | if a >= 2**bits: 22 | break 23 | m = ModularInverse(a, 2**bits) 24 | assert (a * m) % 2**bits == 1 25 | print('{{0x{:0{}X}u, 0x{:0{}X}u}}, // {}^{}'.format(m, bits // 4, 2**bits // a, bits // 4, base, e)) 26 | e += 1 27 | print('') 28 | 29 | PrintTable(base=5, max_exp=10, bits=32) # 10 = floor(log_5(2^26)) 30 | PrintTable(base=5, max_exp=22, bits=64) # 22 = floor(log_5(2^55)) 31 | -------------------------------------------------------------------------------- /bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(bench_dtoa_sources "bench_dtoa.cc") 2 | 3 | add_executable(bench_dtoa ${bench_dtoa_sources}) 4 | 5 | target_include_directories( 6 | bench_dtoa 7 | PUBLIC 8 | "${CMAKE_SOURCE_DIR}/ext/" 9 | "${CMAKE_SOURCE_DIR}/src/" 10 | ) 11 | 12 | target_link_libraries( 13 | bench_dtoa 14 | INTERFACE 15 | ${DN_INTERFACE} 16 | PRIVATE 17 | drachennest 18 | google_benchmark 19 | google_double_conversion 20 | ryu 21 | ) 22 | 23 | set(bench_strtod_sources "bench_strtod.cc") 24 | 25 | add_executable(bench_strtod ${bench_strtod_sources}) 26 | 27 | target_include_directories( 28 | bench_strtod 29 | PUBLIC 30 | "${CMAKE_SOURCE_DIR}/ext/" 31 | "${CMAKE_SOURCE_DIR}/src/" 32 | ) 33 | 34 | target_link_libraries( 35 | bench_strtod 36 | INTERFACE 37 | ${DN_INTERFACE} 38 | PRIVATE 39 | drachennest 40 | google_benchmark 41 | google_double_conversion 42 | ryu 43 | ) 44 | -------------------------------------------------------------------------------- /src/dragonbox.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace dragonbox { 9 | 10 | // char* output_end = Dtoa(buffer, value); 11 | // 12 | // Converts the given double-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // The output is optimal, i.e. the output string 20 | // 1. rounds back to the input number when read in (using round-to-nearest-even) 21 | // 2. is as short as possible, 22 | // 3. is as close to the input number as possible. 23 | // 24 | // Note: 25 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 26 | 27 | constexpr int DtoaMinBufferLength = 64; 28 | 29 | char* Dtoa(char* buffer, double value); 30 | 31 | } // namespace dragonbox 32 | -------------------------------------------------------------------------------- /src/schubfach_32.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace schubfach { 9 | 10 | // char* output_end = Ftoa(buffer, value); 11 | // 12 | // Converts the given single-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= FtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // The output is optimal, i.e. the output string 20 | // 1. rounds back to the input number when read in (using round-to-nearest-even) 21 | // 2. is as short as possible, 22 | // 3. is as close to the input number as possible. 23 | // 24 | // Note: 25 | // This function may temporarily write up to FtoaMinBufferLength characters into the buffer. 26 | 27 | constexpr int FtoaMinBufferLength = 32; 28 | 29 | char* Ftoa(char* buffer, float value); 30 | 31 | } // namespace schubfach 32 | -------------------------------------------------------------------------------- /src/schubfach_64.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Alexander Bolz 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #pragma once 7 | 8 | namespace schubfach { 9 | 10 | // char* output_end = Dtoa(buffer, value); 11 | // 12 | // Converts the given double-precision number into decimal form and stores the result in the given 13 | // buffer. 14 | // 15 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 16 | // The output format is similar to printf("%g"). 17 | // The output is _not_ null-terminted. 18 | // 19 | // The output is optimal, i.e. the output string 20 | // 1. rounds back to the input number when read in (using round-to-nearest-even) 21 | // 2. is as short as possible, 22 | // 3. is as close to the input number as possible. 23 | // 24 | // Note: 25 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 26 | 27 | constexpr int DtoaMinBufferLength = 64; 28 | 29 | char* Dtoa(char* buffer, double value); 30 | 31 | } // namespace schubfach 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | 3 | #------------------------------------------------------------------------------- 4 | # Drachennest 5 | # Algorithms to convert binary to decimal floating-point 6 | #------------------------------------------------------------------------------- 7 | 8 | project(Drachennest 9 | VERSION 0.0.0.1 10 | DESCRIPTION "Algorithms to convert binary to decimal floating-point" 11 | LANGUAGES C CXX 12 | ) 13 | 14 | set(DN_INTERFACE ${PROJECT_NAME}) 15 | 16 | #------------------------------------------------------------------------------- 17 | # 18 | #------------------------------------------------------------------------------- 19 | 20 | add_library(${DN_INTERFACE} INTERFACE) 21 | 22 | target_compile_features( 23 | ${DN_INTERFACE} 24 | INTERFACE 25 | cxx_std_17 26 | ) 27 | 28 | #------------------------------------------------------------------------------- 29 | # 30 | #------------------------------------------------------------------------------- 31 | 32 | add_subdirectory(bench) 33 | add_subdirectory(ext) 34 | add_subdirectory(src) 35 | add_subdirectory(test) 36 | -------------------------------------------------------------------------------- /ext/ryu/ryu/ryu.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ulf Adams 2 | // 3 | // The contents of this file may be used under the terms of the Apache License, 4 | // Version 2.0. 5 | // 6 | // (See accompanying file LICENSE-Apache or copy at 7 | // http://www.apache.org/licenses/LICENSE-2.0) 8 | // 9 | // Alternatively, the contents of this file may be used under the terms of 10 | // the Boost Software License, Version 1.0. 11 | // (See accompanying file LICENSE-Boost or copy at 12 | // https://www.boost.org/LICENSE_1_0.txt) 13 | // 14 | // Unless required by applicable law or agreed to in writing, this software 15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. 17 | #ifndef RYU_H 18 | #define RYU_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | int d2s_buffered_n(double f, char* result); 25 | void d2s_buffered(double f, char* result); 26 | char* d2s(double f); 27 | 28 | int f2s_buffered_n(float f, char* result); 29 | void f2s_buffered(float f, char* result); 30 | char* f2s(float f); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif // RYU_H 37 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/counter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | 17 | namespace benchmark { 18 | 19 | // these counter-related functions are hidden to reduce API surface. 20 | namespace internal { 21 | void Finish(UserCounters* l, IterationCount iterations, double time, 22 | double num_threads); 23 | void Increment(UserCounters* l, UserCounters const& r); 24 | bool SameNames(UserCounters const& l, UserCounters const& r); 25 | } // end namespace internal 26 | 27 | } // end namespace benchmark 28 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/arraysize.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_ARRAYSIZE_H_ 2 | #define BENCHMARK_ARRAYSIZE_H_ 3 | 4 | #include "internal_macros.h" 5 | 6 | namespace benchmark { 7 | namespace internal { 8 | // The arraysize(arr) macro returns the # of elements in an array arr. 9 | // The expression is a compile-time constant, and therefore can be 10 | // used in defining new arrays, for example. If you use arraysize on 11 | // a pointer by mistake, you will get a compile-time error. 12 | // 13 | 14 | // This template function declaration is used in defining arraysize. 15 | // Note that the function doesn't need an implementation, as we only 16 | // use its type. 17 | template 18 | char (&ArraySizeHelper(T (&array)[N]))[N]; 19 | 20 | // That gcc wants both of these prototypes seems mysterious. VC, for 21 | // its part, can't decide which to use (another mystery). Matching of 22 | // template overloads: the final frontier. 23 | #ifndef COMPILER_MSVC 24 | template 25 | char (&ArraySizeHelper(const T (&array)[N]))[N]; 26 | #endif 27 | 28 | #define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array))) 29 | 30 | } // end namespace internal 31 | } // end namespace benchmark 32 | 33 | #endif // BENCHMARK_ARRAYSIZE_H_ 34 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/timers.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_TIMERS_H 2 | #define BENCHMARK_TIMERS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace benchmark { 8 | 9 | // Return the CPU usage of the current process 10 | double ProcessCPUUsage(); 11 | 12 | // Return the CPU usage of the children of the current process 13 | double ChildrenCPUUsage(); 14 | 15 | // Return the CPU usage of the current thread 16 | double ThreadCPUUsage(); 17 | 18 | #if defined(HAVE_STEADY_CLOCK) 19 | template 20 | struct ChooseSteadyClock { 21 | typedef std::chrono::high_resolution_clock type; 22 | }; 23 | 24 | template <> 25 | struct ChooseSteadyClock { 26 | typedef std::chrono::steady_clock type; 27 | }; 28 | #endif 29 | 30 | struct ChooseClockType { 31 | #if defined(HAVE_STEADY_CLOCK) 32 | typedef ChooseSteadyClock<>::type type; 33 | #else 34 | typedef std::chrono::high_resolution_clock type; 35 | #endif 36 | }; 37 | 38 | inline double ChronoClockNow() { 39 | typedef ChooseClockType::type ClockType; 40 | using FpSeconds = std::chrono::duration; 41 | return FpSeconds(ClockType::now().time_since_epoch()).count(); 42 | } 43 | 44 | std::string LocalDateTimeString(); 45 | 46 | } // end namespace benchmark 47 | 48 | #endif // BENCHMARK_TIMERS_H 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ext/ryu/LICENSE-Boost: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/statistics.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // Copyright 2017 Roman Lebedev. All rights reserved. 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 | #ifndef STATISTICS_H_ 17 | #define STATISTICS_H_ 18 | 19 | #include 20 | 21 | #include "benchmark/benchmark.h" 22 | 23 | namespace benchmark { 24 | 25 | // Return a vector containing the mean, median and standard devation information 26 | // (and any user-specified info) for the specified list of reports. If 'reports' 27 | // contains less than two non-errored runs an empty vector is returned 28 | std::vector ComputeStats( 29 | const std::vector& reports); 30 | 31 | double StatisticsMean(const std::vector& v); 32 | double StatisticsMedian(const std::vector& v); 33 | double StatisticsStdDev(const std::vector& v); 34 | 35 | } // end namespace benchmark 36 | 37 | #endif // STATISTICS_H_ 38 | -------------------------------------------------------------------------------- /ext/google_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 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/benchmark_api_internal.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_API_INTERNAL_H 2 | #define BENCHMARK_API_INTERNAL_H 3 | 4 | #include "benchmark/benchmark.h" 5 | #include "commandlineflags.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace benchmark { 15 | namespace internal { 16 | 17 | // Information kept per benchmark we may want to run 18 | struct BenchmarkInstance { 19 | BenchmarkName name; 20 | Benchmark* benchmark; 21 | AggregationReportMode aggregation_report_mode; 22 | std::vector arg; 23 | TimeUnit time_unit; 24 | int range_multiplier; 25 | bool measure_process_cpu_time; 26 | bool use_real_time; 27 | bool use_manual_time; 28 | BigO complexity; 29 | BigOFunc* complexity_lambda; 30 | UserCounters counters; 31 | const std::vector* statistics; 32 | bool last_benchmark_instance; 33 | int repetitions; 34 | double min_time; 35 | IterationCount iterations; 36 | int threads; // Number of concurrent threads to us 37 | 38 | State Run(IterationCount iters, int thread_id, internal::ThreadTimer* timer, 39 | internal::ThreadManager* manager) const; 40 | }; 41 | 42 | bool FindBenchmarksInternal(const std::string& re, 43 | std::vector* benchmarks, 44 | std::ostream* Err); 45 | 46 | bool IsZero(double n); 47 | 48 | ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false); 49 | 50 | } // end namespace internal 51 | } // end namespace benchmark 52 | 53 | #endif // BENCHMARK_API_INTERNAL_H 54 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/benchmark_runner.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef BENCHMARK_RUNNER_H_ 16 | #define BENCHMARK_RUNNER_H_ 17 | 18 | #include "benchmark_api_internal.h" 19 | #include "internal_macros.h" 20 | 21 | DECLARE_double(benchmark_min_time); 22 | 23 | DECLARE_int32(benchmark_repetitions); 24 | 25 | DECLARE_bool(benchmark_report_aggregates_only); 26 | 27 | DECLARE_bool(benchmark_display_aggregates_only); 28 | 29 | namespace benchmark { 30 | 31 | namespace internal { 32 | 33 | extern MemoryManager* memory_manager; 34 | 35 | struct RunResults { 36 | std::vector non_aggregates; 37 | std::vector aggregates_only; 38 | 39 | bool display_report_aggregates_only = false; 40 | bool file_report_aggregates_only = false; 41 | }; 42 | 43 | RunResults RunBenchmark( 44 | const benchmark::internal::BenchmarkInstance& b, 45 | std::vector* complexity_reports); 46 | 47 | } // namespace internal 48 | 49 | } // end namespace benchmark 50 | 51 | #endif // BENCHMARK_RUNNER_H_ 52 | -------------------------------------------------------------------------------- /ext/google_double_conversion/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/google/double-conversion 2 | 3 | This project (double-conversion) provides binary-decimal and decimal-binary 4 | routines for IEEE doubles. 5 | 6 | The library consists of efficient conversion routines that have been extracted 7 | from the V8 JavaScript engine. The code has been refactored and improved so that 8 | it can be used more easily in other projects. 9 | 10 | There is extensive documentation in `double-conversion/string-to-double.h` and 11 | `double-conversion/double-to-string.h`. Other examples can be found in 12 | `test/cctest/test-conversions.cc`. 13 | 14 | 15 | Building 16 | ======== 17 | 18 | This library can be built with [scons][0] or [cmake][1]. 19 | The checked-in Makefile simply forwards to scons, and provides a 20 | shortcut to run all tests: 21 | 22 | make 23 | make test 24 | 25 | Scons 26 | ----- 27 | 28 | The easiest way to install this library is to use `scons`. It builds 29 | the static and shared library, and is set up to install those at the 30 | correct locations: 31 | 32 | scons install 33 | 34 | Use the `DESTDIR` option to change the target directory: 35 | 36 | scons DESTDIR=alternative_directory install 37 | 38 | Cmake 39 | ----- 40 | 41 | To use cmake run `cmake .` in the root directory. This overwrites the 42 | existing Makefile. 43 | 44 | Use `-DBUILD_SHARED_LIBS=ON` to enable the compilation of shared libraries. 45 | Note that this disables static libraries. There is currently no way to 46 | build both libraries at the same time with cmake. 47 | 48 | Use `-DBUILD_TESTING=ON` to build the test executable. 49 | 50 | cmake . -DBUILD_TESTING=ON 51 | make 52 | test/cctest/cctest --list | tr -d '<' | xargs test/cctest/cctest 53 | 54 | [0]: http://www.scons.org/ 55 | [1]: https://cmake.org/ 56 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/thread_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_THREAD_MANAGER_H 2 | #define BENCHMARK_THREAD_MANAGER_H 3 | 4 | #include 5 | 6 | #include "benchmark/benchmark.h" 7 | #include "mutex.h" 8 | 9 | namespace benchmark { 10 | namespace internal { 11 | 12 | class ThreadManager { 13 | public: 14 | ThreadManager(int num_threads) 15 | : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} 16 | 17 | Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { 18 | return benchmark_mutex_; 19 | } 20 | 21 | bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { 22 | return start_stop_barrier_.wait(); 23 | } 24 | 25 | void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { 26 | start_stop_barrier_.removeThread(); 27 | if (--alive_threads_ == 0) { 28 | MutexLock lock(end_cond_mutex_); 29 | end_condition_.notify_all(); 30 | } 31 | } 32 | 33 | void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { 34 | MutexLock lock(end_cond_mutex_); 35 | end_condition_.wait(lock.native_handle(), 36 | [this]() { return alive_threads_ == 0; }); 37 | } 38 | 39 | public: 40 | struct Result { 41 | IterationCount iterations = 0; 42 | double real_time_used = 0; 43 | double cpu_time_used = 0; 44 | double manual_time_used = 0; 45 | int64_t complexity_n = 0; 46 | std::string report_label_; 47 | std::string error_message_; 48 | bool has_error_ = false; 49 | UserCounters counters; 50 | }; 51 | GUARDED_BY(GetBenchmarkMutex()) Result results; 52 | 53 | private: 54 | mutable Mutex benchmark_mutex_; 55 | std::atomic alive_threads_; 56 | Barrier start_stop_barrier_; 57 | Mutex end_cond_mutex_; 58 | Condition end_condition_; 59 | }; 60 | 61 | } // namespace internal 62 | } // namespace benchmark 63 | 64 | #endif // BENCHMARK_THREAD_MANAGER_H 65 | -------------------------------------------------------------------------------- /ext/ryu/ryu/digit_table.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ulf Adams 2 | // 3 | // The contents of this file may be used under the terms of the Apache License, 4 | // Version 2.0. 5 | // 6 | // (See accompanying file LICENSE-Apache or copy at 7 | // http://www.apache.org/licenses/LICENSE-2.0) 8 | // 9 | // Alternatively, the contents of this file may be used under the terms of 10 | // the Boost Software License, Version 1.0. 11 | // (See accompanying file LICENSE-Boost or copy at 12 | // https://www.boost.org/LICENSE_1_0.txt) 13 | // 14 | // Unless required by applicable law or agreed to in writing, this software 15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. 17 | #ifndef RYU_DIGIT_TABLE_H 18 | #define RYU_DIGIT_TABLE_H 19 | 20 | // A table of all two-digit numbers. This is used to speed up decimal digit 21 | // generation by copying pairs of digits into the final output. 22 | static const char DIGIT_TABLE[200] = { 23 | '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', 24 | '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', 25 | '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', 26 | '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', 27 | '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', 28 | '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', 29 | '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', 30 | '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', 31 | '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', 32 | '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' 33 | }; 34 | 35 | #endif // RYU_DIGIT_TABLE_H 36 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/string_util.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_STRING_UTIL_H_ 2 | #define BENCHMARK_STRING_UTIL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "internal_macros.h" 8 | 9 | namespace benchmark { 10 | 11 | void AppendHumanReadable(int n, std::string* str); 12 | 13 | std::string HumanReadableNumber(double n, double one_k = 1024.0); 14 | 15 | #if defined(__MINGW32__) 16 | __attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2))) 17 | #elif defined(__GNUC__) 18 | __attribute__((format(printf, 1, 2))) 19 | #endif 20 | std::string 21 | StrFormat(const char* format, ...); 22 | 23 | inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { 24 | return out; 25 | } 26 | 27 | template 28 | inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) { 29 | out << std::forward(f); 30 | return StrCatImp(out, std::forward(rest)...); 31 | } 32 | 33 | template 34 | inline std::string StrCat(Args&&... args) { 35 | std::ostringstream ss; 36 | StrCatImp(ss, std::forward(args)...); 37 | return ss.str(); 38 | } 39 | 40 | #ifdef BENCHMARK_STL_ANDROID_GNUSTL 41 | /* 42 | * GNU STL in Android NDK lacks support for some C++11 functions, including 43 | * stoul, stoi, stod. We reimplement them here using C functions strtoul, 44 | * strtol, strtod. Note that reimplemented functions are in benchmark:: 45 | * namespace, not std:: namespace. 46 | */ 47 | unsigned long stoul(const std::string& str, size_t* pos = nullptr, 48 | int base = 10); 49 | int stoi(const std::string& str, size_t* pos = nullptr, int base = 10); 50 | double stod(const std::string& str, size_t* pos = nullptr); 51 | #else 52 | using std::stoul; 53 | using std::stoi; 54 | using std::stod; 55 | #endif 56 | 57 | } // end namespace benchmark 58 | 59 | #endif // BENCHMARK_STRING_UTIL_H_ 60 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/sleep.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "sleep.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "internal_macros.h" 22 | 23 | #ifdef BENCHMARK_OS_WINDOWS 24 | #include 25 | #endif 26 | 27 | namespace benchmark { 28 | #ifdef BENCHMARK_OS_WINDOWS 29 | // Window's Sleep takes milliseconds argument. 30 | void SleepForMilliseconds(int milliseconds) { Sleep(milliseconds); } 31 | void SleepForSeconds(double seconds) { 32 | SleepForMilliseconds(static_cast(kNumMillisPerSecond * seconds)); 33 | } 34 | #else // BENCHMARK_OS_WINDOWS 35 | void SleepForMicroseconds(int microseconds) { 36 | struct timespec sleep_time; 37 | sleep_time.tv_sec = microseconds / kNumMicrosPerSecond; 38 | sleep_time.tv_nsec = (microseconds % kNumMicrosPerSecond) * kNumNanosPerMicro; 39 | while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) 40 | ; // Ignore signals and wait for the full interval to elapse. 41 | } 42 | 43 | void SleepForMilliseconds(int milliseconds) { 44 | SleepForMicroseconds(milliseconds * kNumMicrosPerMilli); 45 | } 46 | 47 | void SleepForSeconds(double seconds) { 48 | SleepForMicroseconds(static_cast(seconds * kNumMicrosPerSecond)); 49 | } 50 | #endif // BENCHMARK_OS_WINDOWS 51 | } // end namespace benchmark 52 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/benchmark_name.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | namespace benchmark { 18 | 19 | namespace { 20 | 21 | // Compute the total size of a pack of std::strings 22 | size_t size_impl() { return 0; } 23 | 24 | template 25 | size_t size_impl(const Head& head, const Tail&... tail) { 26 | return head.size() + size_impl(tail...); 27 | } 28 | 29 | // Join a pack of std::strings using a delimiter 30 | // TODO: use absl::StrJoin 31 | void join_impl(std::string&, char) {} 32 | 33 | template 34 | void join_impl(std::string& s, const char delimiter, const Head& head, 35 | const Tail&... tail) { 36 | if (!s.empty() && !head.empty()) { 37 | s += delimiter; 38 | } 39 | 40 | s += head; 41 | 42 | join_impl(s, delimiter, tail...); 43 | } 44 | 45 | template 46 | std::string join(char delimiter, const Ts&... ts) { 47 | std::string s; 48 | s.reserve(sizeof...(Ts) + size_impl(ts...)); 49 | join_impl(s, delimiter, ts...); 50 | return s; 51 | } 52 | } // namespace 53 | 54 | std::string BenchmarkName::str() const { 55 | return join('/', function_name, args, min_time, iterations, repetitions, 56 | time_type, threads); 57 | } 58 | } // namespace benchmark 59 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/log.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_LOG_H_ 2 | #define BENCHMARK_LOG_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "benchmark/benchmark.h" 8 | 9 | namespace benchmark { 10 | namespace internal { 11 | 12 | typedef std::basic_ostream&(EndLType)(std::basic_ostream&); 13 | 14 | class LogType { 15 | friend LogType& GetNullLogInstance(); 16 | friend LogType& GetErrorLogInstance(); 17 | 18 | // FIXME: Add locking to output. 19 | template 20 | friend LogType& operator<<(LogType&, Tp const&); 21 | friend LogType& operator<<(LogType&, EndLType*); 22 | 23 | private: 24 | LogType(std::ostream* out) : out_(out) {} 25 | std::ostream* out_; 26 | BENCHMARK_DISALLOW_COPY_AND_ASSIGN(LogType); 27 | }; 28 | 29 | template 30 | LogType& operator<<(LogType& log, Tp const& value) { 31 | if (log.out_) { 32 | *log.out_ << value; 33 | } 34 | return log; 35 | } 36 | 37 | inline LogType& operator<<(LogType& log, EndLType* m) { 38 | if (log.out_) { 39 | *log.out_ << m; 40 | } 41 | return log; 42 | } 43 | 44 | inline int& LogLevel() { 45 | static int log_level = 0; 46 | return log_level; 47 | } 48 | 49 | inline LogType& GetNullLogInstance() { 50 | static LogType log(nullptr); 51 | return log; 52 | } 53 | 54 | inline LogType& GetErrorLogInstance() { 55 | static LogType log(&std::clog); 56 | return log; 57 | } 58 | 59 | inline LogType& GetLogInstanceForLevel(int level) { 60 | if (level <= LogLevel()) { 61 | return GetErrorLogInstance(); 62 | } 63 | return GetNullLogInstance(); 64 | } 65 | 66 | } // end namespace internal 67 | } // end namespace benchmark 68 | 69 | // clang-format off 70 | #define VLOG(x) \ 71 | (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \ 72 | " ") 73 | // clang-format on 74 | #endif 75 | -------------------------------------------------------------------------------- /ext/google_double_conversion/double-conversion/double-conversion.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 the V8 project authors. All rights reserved. 2 | // Redistribution and use in source and binary forms, with or without 3 | // modification, are permitted provided that the following conditions are 4 | // met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above 9 | // copyright notice, this list of conditions and the following 10 | // disclaimer in the documentation and/or other materials provided 11 | // with the distribution. 12 | // * Neither the name of Google Inc. nor the names of its 13 | // contributors may be used to endorse or promote products derived 14 | // from this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | #ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 29 | #define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 30 | 31 | #include "string-to-double.h" 32 | #include "double-to-string.h" 33 | 34 | #endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ 35 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 4 | configuration: Debug 5 | platform: x64 6 | GENERATOR: Visual Studio 15 2017 7 | ARCHITECTURE: x64 8 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 9 | configuration: Release 10 | platform: x64 11 | GENERATOR: Visual Studio 15 2017 12 | ARCHITECTURE: x64 13 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 14 | configuration: Debug 15 | platform: x64 16 | GENERATOR: Visual Studio 16 2019 17 | ARCHITECTURE: x64 18 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 19 | configuration: Release 20 | platform: x64 21 | GENERATOR: Visual Studio 16 2019 22 | ARCHITECTURE: x64 23 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 24 | configuration: Debug 25 | platform: x86 26 | GENERATOR: Visual Studio 15 2017 27 | ARCHITECTURE: Win32 28 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 29 | configuration: Release 30 | platform: x86 31 | GENERATOR: Visual Studio 15 2017 32 | ARCHITECTURE: Win32 33 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 34 | configuration: Debug 35 | platform: x86 36 | GENERATOR: Visual Studio 16 2019 37 | ARCHITECTURE: Win32 38 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 39 | configuration: Release 40 | platform: x86 41 | GENERATOR: Visual Studio 16 2019 42 | ARCHITECTURE: Win32 43 | 44 | clone_script: 45 | - cmd: git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER% 46 | - cmd: cd %APPVEYOR_BUILD_FOLDER% 47 | - cmd: git checkout -qf %APPVEYOR_REPO_COMMIT% 48 | - cmd: git submodule update --init --recursive 49 | 50 | init: 51 | - cmake --version 52 | - msbuild /version 53 | 54 | build: 55 | verbosity: quiet 56 | 57 | build_script: 58 | - mkdir build 59 | - cd build 60 | - cmake -G "%GENERATOR%" -A "%ARCHITECTURE%" .. 61 | - cmake --build . --target test_all --config "%configuration%" 62 | 63 | test_script: 64 | - .\test\%configuration%\test_all.exe 65 | -------------------------------------------------------------------------------- /scripts/ryu/compute_table_sizes.py: -------------------------------------------------------------------------------- 1 | # Translated from: 2 | # https://github.com/ulfjack/ryu/blob/c9c3fb19791c44fbe35701ad3b8ca4dc0977eb08/src/main/java/info/adams/ryu/analysis/ComputeTableSize.java 3 | 4 | # Copyright 2018 Ulf Adams 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | def FloorLog10Pow2(e): 19 | assert e >= -28737 20 | assert e <= 28737 21 | return (e * 20201781) >> 26 22 | 23 | def FloorLog10Pow5(e): 24 | assert e >= -28737 25 | assert e <= 28737 26 | return (e * 46907083) >> 26 27 | 28 | def ComputeTableSize(exponent_bits, explicit_mantissa_bits): 29 | bias = 2**(exponent_bits - 1) - 1 30 | 31 | min_e2 = 1 - bias - explicit_mantissa_bits - 2 32 | max_e2 = (2**exponent_bits - 2) - bias - explicit_mantissa_bits - 2 33 | # print 'min_e2 = {}'.format(min_e2) 34 | # print 'max_e2 = {}'.format(max_e2) 35 | 36 | q_for_pos_e2 = max(0, FloorLog10Pow2(max_e2) - 1) 37 | q_for_neg_e2 = max(0, FloorLog10Pow5(-min_e2) - 1) 38 | 39 | min_pow = -q_for_pos_e2 40 | max_pow = -min_e2 - q_for_neg_e2 41 | 42 | return min_pow, max_pow 43 | 44 | #------------------------------------------------------------------------------- 45 | # 46 | #------------------------------------------------------------------------------- 47 | 48 | def PrintTableSize(total_bits, exponent_bits, explicit_mantissa_bits): 49 | b = ComputeTableSize(exponent_bits, explicit_mantissa_bits) 50 | print('float{}: [{}, {}]'.format(total_bits, *b)) 51 | 52 | PrintTableSize(16, 5, 10) # ==> [0, 9] 53 | PrintTableSize(32, 8, 23) # ==> [-29, 47] 54 | PrintTableSize(64, 11, 52) # ==> [-290, 325] 55 | PrintTableSize(80, 15, 63) # ==> [-4911, 4953] 56 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/complexity.h: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Source project : https://github.com/ismaelJimenez/cpp.leastsq 16 | // Adapted to be used with google benchmark 17 | 18 | #ifndef COMPLEXITY_H_ 19 | #define COMPLEXITY_H_ 20 | 21 | #include 22 | #include 23 | 24 | #include "benchmark/benchmark.h" 25 | 26 | namespace benchmark { 27 | 28 | // Return a vector containing the bigO and RMS information for the specified 29 | // list of reports. If 'reports.size() < 2' an empty vector is returned. 30 | std::vector ComputeBigO( 31 | const std::vector& reports); 32 | 33 | // This data structure will contain the result returned by MinimalLeastSq 34 | // - coef : Estimated coeficient for the high-order term as 35 | // interpolated from data. 36 | // - rms : Normalized Root Mean Squared Error. 37 | // - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability 38 | // form has been provided to MinimalLeastSq this will return 39 | // the same value. In case BigO::oAuto has been selected, this 40 | // parameter will return the best fitting curve detected. 41 | 42 | struct LeastSq { 43 | LeastSq() : coef(0.0), rms(0.0), complexity(oNone) {} 44 | 45 | double coef; 46 | double rms; 47 | BigO complexity; 48 | }; 49 | 50 | // Function to return an string for the calculated complexity 51 | std::string GetBigOString(BigO complexity); 52 | 53 | } // end namespace benchmark 54 | 55 | #endif // COMPLEXITY_H_ 56 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/counter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "counter.h" 16 | 17 | namespace benchmark { 18 | namespace internal { 19 | 20 | double Finish(Counter const& c, IterationCount iterations, double cpu_time, 21 | double num_threads) { 22 | double v = c.value; 23 | if (c.flags & Counter::kIsRate) { 24 | v /= cpu_time; 25 | } 26 | if (c.flags & Counter::kAvgThreads) { 27 | v /= num_threads; 28 | } 29 | if (c.flags & Counter::kIsIterationInvariant) { 30 | v *= iterations; 31 | } 32 | if (c.flags & Counter::kAvgIterations) { 33 | v /= iterations; 34 | } 35 | return v; 36 | } 37 | 38 | void Finish(UserCounters* l, IterationCount iterations, double cpu_time, 39 | double num_threads) { 40 | for (auto& c : *l) { 41 | c.second.value = Finish(c.second, iterations, cpu_time, num_threads); 42 | } 43 | } 44 | 45 | void Increment(UserCounters* l, UserCounters const& r) { 46 | // add counters present in both or just in *l 47 | for (auto& c : *l) { 48 | auto it = r.find(c.first); 49 | if (it != r.end()) { 50 | c.second.value = c.second + it->second; 51 | } 52 | } 53 | // add counters present in r, but not in *l 54 | for (auto const& tc : r) { 55 | auto it = l->find(tc.first); 56 | if (it == l->end()) { 57 | (*l)[tc.first] = tc.second; 58 | } 59 | } 60 | } 61 | 62 | bool SameNames(UserCounters const& l, UserCounters const& r) { 63 | if (&l == &r) return true; 64 | if (l.size() != r.size()) { 65 | return false; 66 | } 67 | for (auto const& c : l) { 68 | if (r.find(c.first) == r.end()) { 69 | return false; 70 | } 71 | } 72 | return true; 73 | } 74 | 75 | } // end namespace internal 76 | } // end namespace benchmark 77 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/thread_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_THREAD_TIMER_H 2 | #define BENCHMARK_THREAD_TIMER_H 3 | 4 | #include "check.h" 5 | #include "timers.h" 6 | 7 | namespace benchmark { 8 | namespace internal { 9 | 10 | class ThreadTimer { 11 | explicit ThreadTimer(bool measure_process_cpu_time_) 12 | : measure_process_cpu_time(measure_process_cpu_time_) {} 13 | 14 | public: 15 | static ThreadTimer Create() { 16 | return ThreadTimer(/*measure_process_cpu_time_=*/false); 17 | } 18 | static ThreadTimer CreateProcessCpuTime() { 19 | return ThreadTimer(/*measure_process_cpu_time_=*/true); 20 | } 21 | 22 | // Called by each thread 23 | void StartTimer() { 24 | running_ = true; 25 | start_real_time_ = ChronoClockNow(); 26 | start_cpu_time_ = ReadCpuTimerOfChoice(); 27 | } 28 | 29 | // Called by each thread 30 | void StopTimer() { 31 | CHECK(running_); 32 | running_ = false; 33 | real_time_used_ += ChronoClockNow() - start_real_time_; 34 | // Floating point error can result in the subtraction producing a negative 35 | // time. Guard against that. 36 | cpu_time_used_ += 37 | std::max(ReadCpuTimerOfChoice() - start_cpu_time_, 0); 38 | } 39 | 40 | // Called by each thread 41 | void SetIterationTime(double seconds) { manual_time_used_ += seconds; } 42 | 43 | bool running() const { return running_; } 44 | 45 | // REQUIRES: timer is not running 46 | double real_time_used() { 47 | CHECK(!running_); 48 | return real_time_used_; 49 | } 50 | 51 | // REQUIRES: timer is not running 52 | double cpu_time_used() { 53 | CHECK(!running_); 54 | return cpu_time_used_; 55 | } 56 | 57 | // REQUIRES: timer is not running 58 | double manual_time_used() { 59 | CHECK(!running_); 60 | return manual_time_used_; 61 | } 62 | 63 | private: 64 | double ReadCpuTimerOfChoice() const { 65 | if (measure_process_cpu_time) return ProcessCPUUsage(); 66 | return ThreadCPUUsage(); 67 | } 68 | 69 | // should the thread, or the process, time be measured? 70 | const bool measure_process_cpu_time; 71 | 72 | bool running_ = false; // Is the timer running 73 | double start_real_time_ = 0; // If running_ 74 | double start_cpu_time_ = 0; // If running_ 75 | 76 | // Accumulated time so far (does not contain current slice if running_) 77 | double real_time_used_ = 0; 78 | double cpu_time_used_ = 0; 79 | // Manually set iteration time. User sets this with SetIterationTime(seconds). 80 | double manual_time_used_ = 0; 81 | }; 82 | 83 | } // namespace internal 84 | } // namespace benchmark 85 | 86 | #endif // BENCHMARK_THREAD_TIMER_H 87 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/internal_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_INTERNAL_MACROS_H_ 2 | #define BENCHMARK_INTERNAL_MACROS_H_ 3 | 4 | #include "benchmark/benchmark.h" 5 | 6 | /* Needed to detect STL */ 7 | #include 8 | 9 | // clang-format off 10 | 11 | #ifndef __has_feature 12 | #define __has_feature(x) 0 13 | #endif 14 | 15 | #if defined(__clang__) 16 | #if !defined(COMPILER_CLANG) 17 | #define COMPILER_CLANG 18 | #endif 19 | #elif defined(_MSC_VER) 20 | #if !defined(COMPILER_MSVC) 21 | #define COMPILER_MSVC 22 | #endif 23 | #elif defined(__GNUC__) 24 | #if !defined(COMPILER_GCC) 25 | #define COMPILER_GCC 26 | #endif 27 | #endif 28 | 29 | #if __has_feature(cxx_attributes) 30 | #define BENCHMARK_NORETURN [[noreturn]] 31 | #elif defined(__GNUC__) 32 | #define BENCHMARK_NORETURN __attribute__((noreturn)) 33 | #elif defined(COMPILER_MSVC) 34 | #define BENCHMARK_NORETURN __declspec(noreturn) 35 | #else 36 | #define BENCHMARK_NORETURN 37 | #endif 38 | 39 | #if defined(__CYGWIN__) 40 | #define BENCHMARK_OS_CYGWIN 1 41 | #elif defined(_WIN32) 42 | #define BENCHMARK_OS_WINDOWS 1 43 | #if defined(__MINGW32__) 44 | #define BENCHMARK_OS_MINGW 1 45 | #endif 46 | #elif defined(__APPLE__) 47 | #define BENCHMARK_OS_APPLE 1 48 | #include "TargetConditionals.h" 49 | #if defined(TARGET_OS_MAC) 50 | #define BENCHMARK_OS_MACOSX 1 51 | #if defined(TARGET_OS_IPHONE) 52 | #define BENCHMARK_OS_IOS 1 53 | #endif 54 | #endif 55 | #elif defined(__FreeBSD__) 56 | #define BENCHMARK_OS_FREEBSD 1 57 | #elif defined(__NetBSD__) 58 | #define BENCHMARK_OS_NETBSD 1 59 | #elif defined(__OpenBSD__) 60 | #define BENCHMARK_OS_OPENBSD 1 61 | #elif defined(__linux__) 62 | #define BENCHMARK_OS_LINUX 1 63 | #elif defined(__native_client__) 64 | #define BENCHMARK_OS_NACL 1 65 | #elif defined(__EMSCRIPTEN__) 66 | #define BENCHMARK_OS_EMSCRIPTEN 1 67 | #elif defined(__rtems__) 68 | #define BENCHMARK_OS_RTEMS 1 69 | #elif defined(__Fuchsia__) 70 | #define BENCHMARK_OS_FUCHSIA 1 71 | #elif defined (__SVR4) && defined (__sun) 72 | #define BENCHMARK_OS_SOLARIS 1 73 | #elif defined(__QNX__) 74 | #define BENCHMARK_OS_QNX 1 75 | #endif 76 | 77 | #if defined(__ANDROID__) && defined(__GLIBCXX__) 78 | #define BENCHMARK_STL_ANDROID_GNUSTL 1 79 | #endif 80 | 81 | #if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ 82 | && !defined(__EXCEPTIONS) 83 | #define BENCHMARK_HAS_NO_EXCEPTIONS 84 | #endif 85 | 86 | #if defined(COMPILER_CLANG) || defined(COMPILER_GCC) 87 | #define BENCHMARK_MAYBE_UNUSED __attribute__((unused)) 88 | #else 89 | #define BENCHMARK_MAYBE_UNUSED 90 | #endif 91 | 92 | // clang-format on 93 | 94 | #endif // BENCHMARK_INTERNAL_MACROS_H_ 95 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 | // For special use cases, the heart of the Strtod() function is also available 44 | // separately, it assumes that 'trimmed' is as produced by TrimAndCut(), i.e. 45 | // no leading or trailing zeros, also no lone zero, and not 'too many' digits. 46 | double StrtodTrimmed(Vector trimmed, int exponent); 47 | 48 | } // namespace double_conversion 49 | 50 | #endif // DOUBLE_CONVERSION_STRTOD_H_ 51 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/check.h: -------------------------------------------------------------------------------- 1 | #ifndef CHECK_H_ 2 | #define CHECK_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "internal_macros.h" 9 | #include "log.h" 10 | 11 | namespace benchmark { 12 | namespace internal { 13 | 14 | typedef void(AbortHandlerT)(); 15 | 16 | inline AbortHandlerT*& GetAbortHandler() { 17 | static AbortHandlerT* handler = &std::abort; 18 | return handler; 19 | } 20 | 21 | BENCHMARK_NORETURN inline void CallAbortHandler() { 22 | GetAbortHandler()(); 23 | std::abort(); // fallback to enforce noreturn 24 | } 25 | 26 | // CheckHandler is the class constructed by failing CHECK macros. CheckHandler 27 | // will log information about the failures and abort when it is destructed. 28 | class CheckHandler { 29 | public: 30 | CheckHandler(const char* check, const char* file, const char* func, int line) 31 | : log_(GetErrorLogInstance()) { 32 | log_ << file << ":" << line << ": " << func << ": Check `" << check 33 | << "' failed. "; 34 | } 35 | 36 | LogType& GetLog() { return log_; } 37 | 38 | BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) { 39 | log_ << std::endl; 40 | CallAbortHandler(); 41 | } 42 | 43 | CheckHandler& operator=(const CheckHandler&) = delete; 44 | CheckHandler(const CheckHandler&) = delete; 45 | CheckHandler() = delete; 46 | 47 | private: 48 | LogType& log_; 49 | }; 50 | 51 | } // end namespace internal 52 | } // end namespace benchmark 53 | 54 | // The CHECK macro returns a std::ostream object that can have extra information 55 | // written to it. 56 | #ifndef NDEBUG 57 | #define CHECK(b) \ 58 | (b ? ::benchmark::internal::GetNullLogInstance() \ 59 | : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \ 60 | .GetLog()) 61 | #else 62 | #define CHECK(b) ::benchmark::internal::GetNullLogInstance() 63 | #endif 64 | 65 | // clang-format off 66 | // preserve whitespacing between operators for alignment 67 | #define CHECK_EQ(a, b) CHECK((a) == (b)) 68 | #define CHECK_NE(a, b) CHECK((a) != (b)) 69 | #define CHECK_GE(a, b) CHECK((a) >= (b)) 70 | #define CHECK_LE(a, b) CHECK((a) <= (b)) 71 | #define CHECK_GT(a, b) CHECK((a) > (b)) 72 | #define CHECK_LT(a, b) CHECK((a) < (b)) 73 | 74 | #define CHECK_FLOAT_EQ(a, b, eps) CHECK(std::fabs((a) - (b)) < (eps)) 75 | #define CHECK_FLOAT_NE(a, b, eps) CHECK(std::fabs((a) - (b)) >= (eps)) 76 | #define CHECK_FLOAT_GE(a, b, eps) CHECK((a) - (b) > -(eps)) 77 | #define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps)) 78 | #define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) > (eps)) 79 | #define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) > (eps)) 80 | //clang-format on 81 | 82 | #endif // CHECK_H_ 83 | -------------------------------------------------------------------------------- /src/ryu_32.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Ulf Adams 2 | // Copyright 2020 Alexander Bolz 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 6 | 7 | #pragma once 8 | 9 | #define RYU_STRTOD_FALLBACK() 1 10 | 11 | namespace ryu { 12 | 13 | // char* output_end = Ftoa(buffer, value); 14 | // 15 | // Converts the given single-precision number into decimal form and stores the result in the given 16 | // buffer. 17 | // 18 | // The buffer must be large enough, i.e. >= FtoaMinBufferLength. 19 | // The output format is similar to printf("%g"). 20 | // The output is _not_ null-terminted. 21 | // 22 | // The output is optimal, i.e. the output string 23 | // 1. rounds back to the input number when read in (using round-to-nearest-even) 24 | // 2. is as short as possible, 25 | // 3. is as close to the input number as possible. 26 | // 27 | // Note: 28 | // This function may temporarily write up to FtoaMinBufferLength characters into the buffer. 29 | 30 | constexpr int FtoaMinBufferLength = 32; 31 | 32 | char* Ftoa(char* buffer, float value); 33 | 34 | // StrtofResult conversion_result = Strtof(first, last, value); 35 | // 36 | // Converts the given decimal floating-point number into a single-precision binary floating-point 37 | // number. 38 | // The function accepts the same inputs as std::strtof. 39 | // 40 | // If the input has more than 9 significant digits, the function may return 41 | // StrtofStatus::input_too_long. In this case another algorithm must be used to convert the input 42 | // string (e.g. std::strtof). 43 | // 44 | // Note: 45 | // This function always succeeds to convert the output of Ftoa back into the correct binary 46 | // floating-point number. 47 | 48 | enum class StrtofStatus { 49 | invalid, 50 | integer, // Add StrtofFormat ? 51 | fixed, // Add StrtofFormat ? 52 | scientific, // Add StrtofFormat ? 53 | inf, 54 | nan, 55 | #if !RYU_STRTOD_FALLBACK() 56 | input_too_long, 57 | #endif 58 | }; 59 | 60 | struct StrtofResult 61 | { 62 | const char* next; 63 | StrtofStatus status; 64 | 65 | // Test for success. 66 | explicit operator bool() const noexcept 67 | { 68 | #if !RYU_STRTOD_FALLBACK() 69 | return status != StrtofStatus::invalid && status != StrtofStatus::input_too_long; 70 | #else 71 | return status != StrtofStatus::invalid; 72 | #endif 73 | } 74 | }; 75 | 76 | StrtofResult Strtof(const char* first, const char* last, float& value); 77 | 78 | // Round10(x, n) returns: round(x * 10^-n) / 10^-n 79 | // 80 | // Use this function to round the given value to a specific number of decimal places. 81 | // E.g.: Round10(1.005f, -2) == 1.01f 82 | // Round10(55.0f, 1) == 60.0f 83 | float Round10(float value, int n); 84 | 85 | } // namespace ryu 86 | -------------------------------------------------------------------------------- /src/ryu_64.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Ulf Adams 2 | // Copyright 2020 Alexander Bolz 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) 6 | 7 | #pragma once 8 | 9 | #define RYU_STRTOD_FALLBACK() 1 10 | 11 | namespace ryu { 12 | 13 | // char* output_end = Dtoa(buffer, value); 14 | // 15 | // Converts the given double-precision number into decimal form and stores the result in the given 16 | // buffer. 17 | // 18 | // The buffer must be large enough, i.e. >= DtoaMinBufferLength. 19 | // The output format is similar to printf("%g"). 20 | // The output is _not_ null-terminted. 21 | // 22 | // The output is optimal, i.e. the output string 23 | // 1. rounds back to the input number when read in (using round-to-nearest-even) 24 | // 2. is as short as possible, 25 | // 3. is as close to the input number as possible. 26 | // 27 | // Note: 28 | // This function may temporarily write up to DtoaMinBufferLength characters into the buffer. 29 | 30 | constexpr int DtoaMinBufferLength = 64; 31 | 32 | char* Dtoa(char* buffer, double value); 33 | 34 | // StrtodResult conversion_result = Strtod(first, last, value); 35 | // 36 | // Converts the given decimal floating-point number into a double-precision binary floating-point 37 | // number. 38 | // The function accepts the same inputs as std::strtod. 39 | // 40 | // If the input has more than 17 significant digits, the function may return 41 | // StrtodStatus::input_too_long. In this case another algorithm must be used to convert the input 42 | // string (e.g. std::strtod). 43 | // 44 | // Note: 45 | // This function always succeeds to convert the output of Dtoa back into the correct binary 46 | // floating-point number. 47 | 48 | enum class StrtodStatus { 49 | invalid, 50 | integer, // Add StrtodFormat ? 51 | fixed, // Add StrtodFormat ? 52 | scientific, // Add StrtodFormat ? 53 | inf, 54 | nan, 55 | #if !RYU_STRTOD_FALLBACK() 56 | input_too_long, 57 | #endif 58 | }; 59 | 60 | struct StrtodResult 61 | { 62 | const char* next; 63 | StrtodStatus status; 64 | 65 | // Test for success. 66 | explicit operator bool() const noexcept 67 | { 68 | #if !RYU_STRTOD_FALLBACK() 69 | return status != StrtodStatus::invalid && status != StrtodStatus::input_too_long; 70 | #else 71 | return status != StrtodStatus::invalid; 72 | #endif 73 | } 74 | }; 75 | 76 | StrtodResult Strtod(const char* next, const char* last, double& value); 77 | 78 | // Round10(x, n) returns: round(x * 10^-n) / 10^-n 79 | // 80 | // Use this function to round the given value to a specific number of decimal places. 81 | // E.g.: Round10(1.005, -2) == 1.01 82 | // Round10(55.0, 1) == 60.0 83 | double Round10(double value, int n); 84 | 85 | } // namespace ryu 86 | -------------------------------------------------------------------------------- /scripts/ryu/compute_powers.py: -------------------------------------------------------------------------------- 1 | #=============================================================================== 2 | # 3 | #=============================================================================== 4 | 5 | # def Sum(chunks, bits_per_chunk): 6 | # assert bits_per_chunk > 0 7 | # return sum( map(lambda (i, c): c * (2**bits_per_chunk)**i, enumerate(chunks)) ) 8 | 9 | def Split(n, bits_per_chunk): 10 | assert n >= 0 11 | assert bits_per_chunk > 0 12 | chunks = [] 13 | while True: 14 | n, r = divmod(n, 2**bits_per_chunk) 15 | chunks.append(r) 16 | if n == 0: 17 | break 18 | return chunks 19 | 20 | def ToHexString(n, bits): 21 | assert bits > 0 22 | p = (bits + (4 - 1)) // 4 # Round up to four bits per hexit 23 | # p = 2**((p - 1).bit_length()) # Round up to next power-of-2 24 | assert 4*p >= n.bit_length() 25 | return '0x{:0{}X}u'.format(n, p) 26 | 27 | def FormatHexChunks(n, bits_per_chunk = 64): 28 | chunks = Split(n, bits_per_chunk) 29 | s = ', '.join(map(lambda x: ToHexString(x, bits_per_chunk), reversed(chunks))) 30 | if len(chunks) > 1: 31 | s = '{' + s + '}' 32 | return s 33 | 34 | #=============================================================================== 35 | # Ryu 36 | #=============================================================================== 37 | 38 | def FloorLog2Pow5(e): 39 | assert e >= -12654 40 | assert e <= 12654 41 | return (e * 38955489) >> 24 42 | 43 | def Ceil(num, den): 44 | assert num >= 0 45 | assert den > 0 46 | q, r = divmod(num, den) 47 | if r > 0: 48 | q += 1 49 | return q 50 | 51 | def ComputeRyuPower(k, bits): 52 | assert bits > 0 53 | e = FloorLog2Pow5(k) + 1 - bits 54 | if k >= 0: 55 | if e > 0: 56 | # f = 5**k // 2**e 57 | f = Ceil(5**k, 2**e) 58 | else: 59 | f = 5**k * 2**(-e) 60 | else: 61 | f = Ceil(2**(-e), 5**(-k)) 62 | assert f >= 2**(bits - 1) 63 | assert f < 2**bits 64 | return f, e 65 | 66 | def PrintRyuPowers(bits, min_exponent, max_exponent, bits_per_chunk=64): 67 | print('// Let e = FloorLog2Pow5(k) + 1 - {}'.format(bits)) 68 | print('// For k >= 0, stores 5^k in the form: floor( 5^k / 2^e )') 69 | print('// For k <= 0, stores 5^k in the form: ceil(2^-e / 5^-k)') 70 | for k in range(min_exponent, max_exponent + 1): 71 | f, e = ComputeRyuPower(k, bits) 72 | print(FormatHexChunks(f, bits_per_chunk) + ', // e = {:5d}, k = {:4d}'.format(e, k)) 73 | 74 | # float16: 75 | # PrintRyuPowers(bits=32, min_exponent=0, max_exponent=9, bits_per_chunk=32) 76 | 77 | # float32: 78 | # PrintRyuPowers(bits=64, min_exponent=-29, max_exponent=47, bits_per_chunk=64) 79 | 80 | # float64: 81 | PrintRyuPowers(bits=128, min_exponent=-290, max_exponent=325, bits_per_chunk=64) 82 | 83 | # float80: 84 | # PrintRyuPowers(bits=160, min_exponent=-4911, max_exponent=4953, bits_per_chunk=32) 85 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 | -------------------------------------------------------------------------------- /scripts/ryu/euclid_min_max.py: -------------------------------------------------------------------------------- 1 | # Translated from: 2 | # https://github.com/ulfjack/ryu/blob/c9c3fb19791c44fbe35701ad3b8ca4dc0977eb08/src/main/java/info/adams/ryu/analysis/EuclidMinMax.java 3 | 4 | # Copyright 2018 Ulf Adams 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | from fractions import gcd 19 | 20 | def EuclidMin(multiplier, modulo, maximum): 21 | """ 22 | Computes the modular min using a modified version of Euclid's algorithm. 23 | """ 24 | 25 | c = gcd(multiplier, modulo) 26 | b = modulo // c 27 | a = (multiplier // c) % b 28 | if maximum >= b: 29 | return 0 30 | s = 1 31 | t = 0 32 | u = 0 33 | v = 1 34 | while True: 35 | while b >= a: 36 | b = b - a 37 | u = u - s 38 | v = v - t 39 | if -u >= maximum: 40 | return a * c 41 | if b == 0: 42 | return 0 43 | while a >= b: 44 | old_a = a 45 | a = a - b 46 | s = s - u 47 | t = t - v 48 | if s >= maximum: 49 | if s > maximum: 50 | return old_a * c 51 | else: 52 | return a * c 53 | if a == 0: 54 | return 0 55 | 56 | def EuclidMax(multiplier, modulo, maximum): 57 | """ 58 | Computes the modular max using a modified version of Euclid's algorithm. 59 | """ 60 | 61 | c = gcd(multiplier, modulo) 62 | b = modulo // c 63 | a = (multiplier // c) % b 64 | if maximum >= b: 65 | return modulo - c 66 | s = 1 67 | t = 0 68 | u = 0 69 | v = 1 70 | while True: 71 | while b >= a: 72 | q = b // a 73 | q = min(q, (maximum - (-u)) // s - 1) 74 | q = max(q, 1) 75 | old_b = b 76 | b = b - a * q 77 | u = u - s * q 78 | v = v - t * q 79 | if -u >= maximum: 80 | if -u > maximum: 81 | return modulo - old_b * c 82 | else: 83 | return modulo - b * c 84 | if b == 0: 85 | return modulo - c 86 | while a >= b: 87 | q = 1 88 | if u != 0: 89 | q = min(q, (maximum - s) // (-u + 1)) 90 | q = max(q, 1) 91 | a = a - b * q 92 | s = s - u * q 93 | t = t - v * q 94 | if s >= maximum: 95 | return modulo - b * c 96 | if a == 0: 97 | return modulo - c 98 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/commandlineflags.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_COMMANDLINEFLAGS_H_ 2 | #define BENCHMARK_COMMANDLINEFLAGS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Macro for referencing flags. 8 | #define FLAG(name) FLAGS_##name 9 | 10 | // Macros for declaring flags. 11 | #define DECLARE_bool(name) extern bool FLAG(name) 12 | #define DECLARE_int32(name) extern int32_t FLAG(name) 13 | #define DECLARE_int64(name) extern int64_t FLAG(name) 14 | #define DECLARE_double(name) extern double FLAG(name) 15 | #define DECLARE_string(name) extern std::string FLAG(name) 16 | 17 | // Macros for defining flags. 18 | #define DEFINE_bool(name, default_val, doc) bool FLAG(name) = (default_val) 19 | #define DEFINE_int32(name, default_val, doc) int32_t FLAG(name) = (default_val) 20 | #define DEFINE_int64(name, default_val, doc) int64_t FLAG(name) = (default_val) 21 | #define DEFINE_double(name, default_val, doc) double FLAG(name) = (default_val) 22 | #define DEFINE_string(name, default_val, doc) \ 23 | std::string FLAG(name) = (default_val) 24 | 25 | namespace benchmark { 26 | // Parses a bool/Int32/string from the environment variable 27 | // corresponding to the given Google Test flag. 28 | bool BoolFromEnv(const char* flag, bool default_val); 29 | int32_t Int32FromEnv(const char* flag, int32_t default_val); 30 | const char* StringFromEnv(const char* flag, const char* default_val); 31 | 32 | // Parses a string for a bool flag, in the form of either 33 | // "--flag=value" or "--flag". 34 | // 35 | // In the former case, the value is taken as true if it passes IsTruthyValue(). 36 | // 37 | // In the latter case, the value is taken as true. 38 | // 39 | // On success, stores the value of the flag in *value, and returns 40 | // true. On failure, returns false without changing *value. 41 | bool ParseBoolFlag(const char* str, const char* flag, bool* value); 42 | 43 | // Parses a string for an Int32 flag, in the form of 44 | // "--flag=value". 45 | // 46 | // On success, stores the value of the flag in *value, and returns 47 | // true. On failure, returns false without changing *value. 48 | bool ParseInt32Flag(const char* str, const char* flag, int32_t* value); 49 | 50 | // Parses a string for a Double flag, in the form of 51 | // "--flag=value". 52 | // 53 | // On success, stores the value of the flag in *value, and returns 54 | // true. On failure, returns false without changing *value. 55 | bool ParseDoubleFlag(const char* str, const char* flag, double* value); 56 | 57 | // Parses a string for a string flag, in the form of 58 | // "--flag=value". 59 | // 60 | // On success, stores the value of the flag in *value, and returns 61 | // true. On failure, returns false without changing *value. 62 | bool ParseStringFlag(const char* str, const char* flag, std::string* value); 63 | 64 | // Returns true if the string matches the flag. 65 | bool IsFlag(const char* str, const char* flag); 66 | 67 | // Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or 68 | // some non-alphanumeric character. As a special case, also returns true if 69 | // value is the empty string. 70 | bool IsTruthyFlagValue(const std::string& value); 71 | } // end namespace benchmark 72 | 73 | #endif // BENCHMARK_COMMANDLINEFLAGS_H_ 74 | -------------------------------------------------------------------------------- /scripts/ryu/compute_bit_sizes.py: -------------------------------------------------------------------------------- 1 | # Translated from: 2 | # https://github.com/ulfjack/ryu/blob/c9c3fb19791c44fbe35701ad3b8ca4dc0977eb08/src/main/java/info/adams/ryu/analysis/ComputeRequiredBitSizes.java 3 | 4 | # Copyright 2018 Ulf Adams 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | from euclid_min_max import EuclidMin, EuclidMax 19 | 20 | def FloorLog10Pow2(e): 21 | assert e >= -28737 22 | assert e <= 28737 23 | return (e * 20201781) >> 26 24 | 25 | def FloorLog10Pow5(e): 26 | assert e >= -28737 27 | assert e <= 28737 28 | return (e * 46907083) >> 26 29 | 30 | def ComputeRequiredBitSizes(exponent_bits, explicit_mantissa_bits): 31 | """ 32 | Computes appropriate values for B_0 and B_1 for a given floating point type. 33 | """ 34 | 35 | bias = 2**(exponent_bits - 1) - 1 36 | mbits = explicit_mantissa_bits + 3 37 | # max(w) = 4 * ((1 << format.explicit_mantissa_bits()) * 2 - 1) + 2 38 | # = (1 << (format.explicit_mantissa_bits() + 3)) - 2 39 | max_w = 2**mbits - 2 40 | 41 | # 42 | # For e2 >= 0: 43 | # 44 | min_e2 = 0 45 | max_e2 = (2**exponent_bits - 2) - bias - explicit_mantissa_bits - 2 46 | b0 = 0 47 | for e2 in range(min_e2, max_e2 + 1): 48 | q = max(0, FloorLog10Pow2(e2) - 1) 49 | pow5 = 5**q 50 | pow2 = 2**(e2 - q) 51 | euclid_max = EuclidMax(pow2, pow5, max_w - 1) 52 | bits = ((max_w * pow5 * pow2) // (pow5 - euclid_max)).bit_length() 53 | reqn = bits - pow5.bit_length() 54 | b0 = max(b0, reqn) 55 | 56 | # 57 | # For e2 < 0: 58 | # 59 | min_e2 = 0 60 | max_e2 = -(1 - bias - explicit_mantissa_bits - 2) 61 | b1 = 0 62 | for e2 in range(min_e2, max_e2 + 1): 63 | q = max(0, FloorLog10Pow5(e2) - 1) 64 | pow5 = 5**(e2 - q) 65 | pow2 = 2**q 66 | euclid_min = EuclidMin(pow5, pow2, max_w - 1) 67 | bits = (euclid_min // max_w).bit_length() 68 | reqn = pow5.bit_length() - bits 69 | b1 = max(b1, reqn) 70 | 71 | return b0, b1 72 | 73 | #------------------------------------------------------------------------------- 74 | # 75 | #------------------------------------------------------------------------------- 76 | 77 | def PrintRequiredBitSizes(total_bits, exponent_bits, explicit_mantissa_bits): 78 | b = ComputeRequiredBitSizes(exponent_bits, explicit_mantissa_bits) 79 | print('float{}: [{}, {}]'.format(total_bits, *b)) 80 | 81 | PrintRequiredBitSizes(16, 5, 10) # ==> [15, 21] 82 | PrintRequiredBitSizes(32, 8, 23) # ==> [60, 63] 83 | PrintRequiredBitSizes(64, 11, 52) # ==> [124, 124] 84 | PrintRequiredBitSizes(80, 15, 63) # ==> [150, 152] 85 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 | namespace PowersOfTenCache { 36 | 37 | // Not all powers of ten are cached. The decimal exponent of two neighboring 38 | // cached numbers will differ by kDecimalExponentDistance. 39 | static const int kDecimalExponentDistance = 8; 40 | 41 | static const int kMinDecimalExponent = -348; 42 | static const int kMaxDecimalExponent = 340; 43 | 44 | // Returns a cached power-of-ten with a binary exponent in the range 45 | // [min_exponent; max_exponent] (boundaries included). 46 | void GetCachedPowerForBinaryExponentRange(int min_exponent, 47 | int max_exponent, 48 | DiyFp* power, 49 | int* decimal_exponent); 50 | 51 | // Returns a cached power of ten x ~= 10^k such that 52 | // k <= decimal_exponent < k + kCachedPowersDecimalDistance. 53 | // The given decimal_exponent must satisfy 54 | // kMinDecimalExponent <= requested_exponent, and 55 | // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance. 56 | void GetCachedPowerForDecimalExponent(int requested_exponent, 57 | DiyFp* power, 58 | int* found_exponent); 59 | 60 | } // namespace PowersOfTenCache 61 | 62 | } // namespace double_conversion 63 | 64 | #endif // DOUBLE_CONVERSION_CACHED_POWERS_H_ 65 | -------------------------------------------------------------------------------- /ext/ryu/ryu/common.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ulf Adams 2 | // 3 | // The contents of this file may be used under the terms of the Apache License, 4 | // Version 2.0. 5 | // 6 | // (See accompanying file LICENSE-Apache or copy at 7 | // http://www.apache.org/licenses/LICENSE-2.0) 8 | // 9 | // Alternatively, the contents of this file may be used under the terms of 10 | // the Boost Software License, Version 1.0. 11 | // (See accompanying file LICENSE-Boost or copy at 12 | // https://www.boost.org/LICENSE_1_0.txt) 13 | // 14 | // Unless required by applicable law or agreed to in writing, this software 15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. 17 | #ifndef RYU_COMMON_H 18 | #define RYU_COMMON_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #if defined(_M_IX86) || defined(_M_ARM) 25 | #define RYU_32_BIT_PLATFORM 26 | #endif 27 | 28 | static inline uint32_t decimalLength9(const uint32_t v) { 29 | // Function precondition: v is not a 10-digit number. 30 | // (f2s: 9 digits are sufficient for round-tripping.) 31 | // (d2fixed: We print 9-digit blocks.) 32 | assert(v < 1000000000); 33 | if (v >= 100000000) { return 9; } 34 | if (v >= 10000000) { return 8; } 35 | if (v >= 1000000) { return 7; } 36 | if (v >= 100000) { return 6; } 37 | if (v >= 10000) { return 5; } 38 | if (v >= 1000) { return 4; } 39 | if (v >= 100) { return 3; } 40 | if (v >= 10) { return 2; } 41 | return 1; 42 | } 43 | 44 | // Returns e == 0 ? 1 : ceil(log_2(5^e)). 45 | static inline int32_t pow5bits(const int32_t e) { 46 | // This approximation works up to the point that the multiplication overflows at e = 3529. 47 | // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater 48 | // than 2^9297. 49 | assert(e >= 0); 50 | assert(e <= 3528); 51 | return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1); 52 | } 53 | 54 | // Returns floor(log_10(2^e)). 55 | static inline uint32_t log10Pow2(const int32_t e) { 56 | // The first value this approximation fails for is 2^1651 which is just greater than 10^297. 57 | assert(e >= 0); 58 | assert(e <= 1650); 59 | return (((uint32_t) e) * 78913) >> 18; 60 | } 61 | 62 | // Returns floor(log_10(5^e)). 63 | static inline uint32_t log10Pow5(const int32_t e) { 64 | // The first value this approximation fails for is 5^2621 which is just greater than 10^1832. 65 | assert(e >= 0); 66 | assert(e <= 2620); 67 | return (((uint32_t) e) * 732923) >> 20; 68 | } 69 | 70 | static inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) { 71 | if (mantissa) { 72 | memcpy(result, "NaN", 3); 73 | return 3; 74 | } 75 | if (sign) { 76 | result[0] = '-'; 77 | } 78 | if (exponent) { 79 | memcpy(result + sign, "Infinity", 8); 80 | return sign + 8; 81 | } 82 | memcpy(result + sign, "0E0", 3); 83 | return sign + 3; 84 | } 85 | 86 | static inline uint32_t float_to_bits(const float f) { 87 | uint32_t bits = 0; 88 | memcpy(&bits, &f, sizeof(float)); 89 | return bits; 90 | } 91 | 92 | static inline uint64_t double_to_bits(const double d) { 93 | uint64_t bits = 0; 94 | memcpy(&bits, &d, sizeof(double)); 95 | return bits; 96 | } 97 | 98 | #endif // RYU_COMMON_H 99 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/benchmark_register.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_REGISTER_H 2 | #define BENCHMARK_REGISTER_H 3 | 4 | #include 5 | 6 | #include "check.h" 7 | 8 | namespace benchmark { 9 | namespace internal { 10 | 11 | // Append the powers of 'mult' in the closed interval [lo, hi]. 12 | // Returns iterator to the start of the inserted range. 13 | template 14 | typename std::vector::iterator 15 | AddPowers(std::vector* dst, T lo, T hi, int mult) { 16 | CHECK_GE(lo, 0); 17 | CHECK_GE(hi, lo); 18 | CHECK_GE(mult, 2); 19 | 20 | const size_t start_offset = dst->size(); 21 | 22 | static const T kmax = std::numeric_limits::max(); 23 | 24 | // Space out the values in multiples of "mult" 25 | for (T i = 1; i <= hi; i *= mult) { 26 | if (i >= lo) { 27 | dst->push_back(i); 28 | } 29 | // Break the loop here since multiplying by 30 | // 'mult' would move outside of the range of T 31 | if (i > kmax / mult) break; 32 | } 33 | 34 | return dst->begin() + start_offset; 35 | } 36 | 37 | template 38 | void AddNegatedPowers(std::vector* dst, T lo, T hi, int mult) { 39 | // We negate lo and hi so we require that they cannot be equal to 'min'. 40 | CHECK_GT(lo, std::numeric_limits::min()); 41 | CHECK_GT(hi, std::numeric_limits::min()); 42 | CHECK_GE(hi, lo); 43 | CHECK_LE(hi, 0); 44 | 45 | // Add positive powers, then negate and reverse. 46 | // Casts necessary since small integers get promoted 47 | // to 'int' when negating. 48 | const auto lo_complement = static_cast(-lo); 49 | const auto hi_complement = static_cast(-hi); 50 | 51 | const auto it = AddPowers(dst, hi_complement, lo_complement, mult); 52 | 53 | std::for_each(it, dst->end(), [](T& t) { t *= -1; }); 54 | std::reverse(it, dst->end()); 55 | } 56 | 57 | template 58 | void AddRange(std::vector* dst, T lo, T hi, int mult) { 59 | static_assert(std::is_integral::value && std::is_signed::value, 60 | "Args type must be a signed integer"); 61 | 62 | CHECK_GE(hi, lo); 63 | CHECK_GE(mult, 2); 64 | 65 | // Add "lo" 66 | dst->push_back(lo); 67 | 68 | // Handle lo == hi as a special case, so we then know 69 | // lo < hi and so it is safe to add 1 to lo and subtract 1 70 | // from hi without falling outside of the range of T. 71 | if (lo == hi) return; 72 | 73 | // Ensure that lo_inner <= hi_inner below. 74 | if (lo + 1 == hi) { 75 | dst->push_back(hi); 76 | return; 77 | } 78 | 79 | // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive). 80 | const auto lo_inner = static_cast(lo + 1); 81 | const auto hi_inner = static_cast(hi - 1); 82 | 83 | // Insert negative values 84 | if (lo_inner < 0) { 85 | AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult); 86 | } 87 | 88 | // Treat 0 as a special case (see discussion on #762). 89 | if (lo <= 0 && hi >= 0) { 90 | dst->push_back(0); 91 | } 92 | 93 | // Insert positive values 94 | if (hi_inner > 0) { 95 | AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult); 96 | } 97 | 98 | // Add "hi" (if different from last value). 99 | if (hi != dst->back()) { 100 | dst->push_back(hi); 101 | } 102 | } 103 | 104 | } // namespace internal 105 | } // namespace benchmark 106 | 107 | #endif // BENCHMARK_REGISTER_H 108 | -------------------------------------------------------------------------------- /scripts/dtoa/dtoa_adams.py: -------------------------------------------------------------------------------- 1 | PRECISION = 53 2 | EXPONENT_BITS = 11 3 | 4 | # PRECISION = 24 5 | # EXPONENT_BITS = 8 6 | 7 | HIDDEN_BIT = 2**(PRECISION - 1) 8 | BIAS = 2**(EXPONENT_BITS - 1) - 1 + (PRECISION - 1) 9 | MIN_EXPONENT = 1 - BIAS 10 | MAX_EXPONENT = 2**EXPONENT_BITS - 2 - BIAS 11 | 12 | #=================================================================================================== 13 | # Dtoa 14 | #=================================================================================================== 15 | 16 | def DtoaAdams(m2, e2): 17 | isEven = (m2 % 2 == 0) 18 | acceptSmaller = isEven 19 | acceptLarger = isEven 20 | 21 | # 22 | # Step 2: 23 | # Determine the interval of information preserving outputs. 24 | # 25 | 26 | lowerBoundaryIsCloser = (m2 == HIDDEN_BIT and e2 > MIN_EXPONENT) 27 | 28 | u = 4 * m2 - 2 + (1 if lowerBoundaryIsCloser else 0) 29 | v = 4 * m2 30 | w = 4 * m2 + 2 31 | e2 -= 2 32 | # print 'u = {}'.format(u) 33 | # print 'v = {}'.format(v) 34 | # print 'w = {}'.format(w) 35 | # print 'e2 = {}'.format(e2) 36 | 37 | # 38 | # Step 3: 39 | # Convert (u,v,w) * 2^e2 to a decimal power base. 40 | # 41 | 42 | if e2 >= 0: 43 | e10 = 0 44 | a = u * 2**e2 45 | b = v * 2**e2 46 | c = w * 2**e2 47 | else: 48 | e10 = e2 49 | a = u * 5**(-e2) 50 | b = v * 5**(-e2) 51 | c = w * 5**(-e2) 52 | 53 | assert a < c - 1 54 | # print 'a = {}'.format(a) 55 | # print 'b = {}'.format(b) 56 | # print 'c = {}'.format(c) 57 | # print 'e10 = {}'.format(e10) 58 | 59 | # 60 | # Step 4: 61 | # Find a shortest, correctly-rounded decimal representations in the interval 62 | # of valid representations. 63 | # 64 | 65 | if not acceptLarger: 66 | c -= 1 67 | 68 | atz = True # a[0],...,a[i] are 0s 69 | btz = True # b[0],...,b[i-1] are 0s 70 | bi = 0 71 | while a / 10 < c / 10: 72 | atz = atz and a % 10 == 0 73 | btz = btz and bi == 0 74 | bi = b % 10 75 | a /= 10 76 | b /= 10 77 | c /= 10 78 | e10 += 1 79 | # print '--- a/10 < c/10 ---' 80 | # print 'atz = {}'.format(atz) 81 | # print 'btz = {}'.format(btz) 82 | # print 'bi = {}'.format(bi) 83 | # print 'a = {}'.format(a) 84 | # print 'b = {}'.format(b) 85 | # print 'c = {}'.format(c) 86 | # print 'e10 = {}'.format(e10) 87 | if acceptSmaller and atz: 88 | while a % 10 == 0: 89 | btz = btz and bi == 0 90 | bi = b % 10 91 | a /= 10 92 | b /= 10 93 | c /= 10 94 | e10 += 1 95 | # print '--- a%10 == 0 ---' 96 | # print 'atz = {}'.format(atz) 97 | # print 'btz = {}'.format(btz) 98 | # print 'bi = {}'.format(bi) 99 | # print 'a = {}'.format(a) 100 | # print 'b = {}'.format(b) 101 | # print 'c = {}'.format(c) 102 | # print 'e10 = {}'.format(e10) 103 | 104 | roundDown = bi < 5 or (bi == 5 and btz and b % 2 == 0) 105 | # print 'roundDown = {}'.format(roundDown) 106 | if (not roundDown and b < c) or (a == b and not atz): 107 | # print 'rounding up...' 108 | b += 1 109 | 110 | # print 'result = {} * 10^{}'.format(b, e10) 111 | return b, e10 112 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "timers.h" 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "check.h" 25 | #include "string_util.h" 26 | 27 | namespace benchmark { 28 | 29 | BenchmarkReporter::BenchmarkReporter() 30 | : output_stream_(&std::cout), error_stream_(&std::cerr) {} 31 | 32 | BenchmarkReporter::~BenchmarkReporter() {} 33 | 34 | void BenchmarkReporter::PrintBasicContext(std::ostream *out, 35 | Context const &context) { 36 | CHECK(out) << "cannot be null"; 37 | auto &Out = *out; 38 | 39 | Out << LocalDateTimeString() << "\n"; 40 | 41 | if (context.executable_name) 42 | Out << "Running " << context.executable_name << "\n"; 43 | 44 | const CPUInfo &info = context.cpu_info; 45 | Out << "Run on (" << info.num_cpus << " X " 46 | << (info.cycles_per_second / 1000000.0) << " MHz CPU " 47 | << ((info.num_cpus > 1) ? "s" : "") << ")\n"; 48 | if (info.caches.size() != 0) { 49 | Out << "CPU Caches:\n"; 50 | for (auto &CInfo : info.caches) { 51 | Out << " L" << CInfo.level << " " << CInfo.type << " " 52 | << (CInfo.size / 1000) << "K"; 53 | if (CInfo.num_sharing != 0) 54 | Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")"; 55 | Out << "\n"; 56 | } 57 | } 58 | if (!info.load_avg.empty()) { 59 | Out << "Load Average: "; 60 | for (auto It = info.load_avg.begin(); It != info.load_avg.end();) { 61 | Out << StrFormat("%.2f", *It++); 62 | if (It != info.load_avg.end()) Out << ", "; 63 | } 64 | Out << "\n"; 65 | } 66 | 67 | if (info.scaling_enabled) { 68 | Out << "***WARNING*** CPU scaling is enabled, the benchmark " 69 | "real time measurements may be noisy and will incur extra " 70 | "overhead.\n"; 71 | } 72 | 73 | #ifndef NDEBUG 74 | Out << "***WARNING*** Library was built as DEBUG. Timings may be " 75 | "affected.\n"; 76 | #endif 77 | } 78 | 79 | // No initializer because it's already initialized to NULL. 80 | const char *BenchmarkReporter::Context::executable_name; 81 | 82 | BenchmarkReporter::Context::Context() 83 | : cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {} 84 | 85 | std::string BenchmarkReporter::Run::benchmark_name() const { 86 | std::string name = run_name.str(); 87 | if (run_type == RT_Aggregate) { 88 | name += "_" + aggregate_name; 89 | } 90 | return name; 91 | } 92 | 93 | double BenchmarkReporter::Run::GetAdjustedRealTime() const { 94 | double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit); 95 | if (iterations != 0) new_time /= static_cast(iterations); 96 | return new_time; 97 | } 98 | 99 | double BenchmarkReporter::Run::GetAdjustedCPUTime() const { 100 | double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit); 101 | if (iterations != 0) new_time /= static_cast(iterations); 102 | return new_time; 103 | } 104 | 105 | } // end namespace benchmark 106 | -------------------------------------------------------------------------------- /test/scan_number.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct ScanNumberResult { 9 | std::string digits; 10 | int exponent; 11 | }; 12 | 13 | inline bool IsDigit(char ch) 14 | { 15 | return '0' <= ch && ch <= '9'; 16 | } 17 | 18 | inline int DigitValue(char ch) 19 | { 20 | assert(IsDigit(ch)); 21 | return ch - '0'; 22 | } 23 | 24 | // Assumes JSON number format ¯\_(ツ)_/¯ 25 | inline ScanNumberResult ScanNumber(char const* next, char const* last) 26 | { 27 | // printf("ScanNumber(%.*s)\n", static_cast(last - next), next); 28 | 29 | std::string digits; 30 | int exponent = 0; 31 | 32 | assert(next != last); 33 | assert(IsDigit(*next)); 34 | 35 | if (*next == '0') 36 | { 37 | // Number is of the form 0[.xxx][e+nnn]. 38 | // The leading zero here is not a significant digit. 39 | ++next; 40 | } 41 | else 42 | { 43 | for (;;) 44 | { 45 | digits += *next; 46 | ++next; 47 | if (next == last || !IsDigit(*next)) 48 | break; 49 | } 50 | } 51 | 52 | if (next != last && *next == '.') 53 | { 54 | ++next; 55 | assert(next != last); 56 | assert(IsDigit(*next)); 57 | 58 | const char* fraction_start = next; 59 | 60 | if (digits.empty()) 61 | { 62 | // Number is of the form 0.xxx[e+nnn]. 63 | // Skip leading zeros in the fractional part and adjust the exponent. 64 | while (*next == '0') 65 | { 66 | --exponent; 67 | ++next; 68 | if (next == last) 69 | return {"0", 0}; 70 | } 71 | } 72 | 73 | while (IsDigit(*next)) 74 | { 75 | digits += *next; 76 | --exponent; 77 | ++next; 78 | if (next == last) 79 | break; 80 | } 81 | 82 | const char* fraction_end = next; 83 | for (;;) 84 | { 85 | if (fraction_end == fraction_start) 86 | break; 87 | --fraction_end; 88 | if (*fraction_end == '0') 89 | return {digits + " --- trailing zeros detected", INT32_MIN}; 90 | break; 91 | } 92 | } 93 | 94 | if (next != last && (*next == 'e' || *next == 'E')) 95 | { 96 | if (digits.empty()) 97 | { 98 | // Number is of the form 0[.000]e+nnn. 99 | return {"0", 0}; 100 | } 101 | 102 | ++next; 103 | assert(next != last); 104 | 105 | bool const exp_is_neg = (*next == '-'); 106 | if (exp_is_neg || *next == '+') 107 | { 108 | ++next; 109 | assert(next != last); 110 | } 111 | 112 | // No overflow checks... 113 | int e = 0; 114 | while (next != last) 115 | { 116 | e = 10 * e + DigitValue(*next); 117 | ++next; 118 | } 119 | 120 | exponent += exp_is_neg ? -e : e; 121 | } 122 | 123 | // Move trailing zeros into the exponent 124 | while (!digits.empty() && digits.back() == '0') 125 | { 126 | digits.pop_back(); 127 | exponent++; 128 | } 129 | 130 | // Normalize "0.0" and "0" 131 | if (digits.empty()) 132 | { 133 | return {"0", 0}; 134 | } 135 | 136 | return {digits, exponent}; 137 | } 138 | 139 | inline ScanNumberResult ScanNumber(std::string const& str) 140 | { 141 | char const* next = str.c_str(); 142 | char const* last = str.c_str() + str.size(); 143 | 144 | return ScanNumber(next, last); 145 | } 146 | -------------------------------------------------------------------------------- /scripts/dtoa/dtoa_burger_dybvig.py: -------------------------------------------------------------------------------- 1 | PRECISION = 53 2 | EXPONENT_BITS = 11 3 | 4 | # PRECISION = 24 5 | # EXPONENT_BITS = 8 6 | 7 | HIDDEN_BIT = 2**(PRECISION - 1) 8 | BIAS = 2**(EXPONENT_BITS - 1) - 1 + (PRECISION - 1) 9 | MIN_EXPONENT = 1 - BIAS 10 | MAX_EXPONENT = 2**EXPONENT_BITS - 2 - BIAS 11 | 12 | #=================================================================================================== 13 | # Dtoa 14 | #=================================================================================================== 15 | 16 | # Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 17 | # Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 18 | # Design and Implementation, PLDI 1996 19 | 20 | def EffectivePrecision(f): 21 | """Returns the effective precision of the significand, aka. f.bit_length()""" 22 | 23 | assert f > 0 24 | assert f < 2**PRECISION 25 | 26 | p = PRECISION 27 | while f < 2**(PRECISION - 1): 28 | f *= 2 29 | p -= 1 30 | 31 | return p 32 | 33 | def CeilLog10Pow2(e): 34 | """Returns ceil(log_10(2^e))""" 35 | 36 | assert e >= -1650 37 | assert e <= 1650 38 | return (int(e) * 78913 + (2**18 - 1)) // 2**18 # floor-division (SAR) 39 | 40 | def DtoaBurgerDybvig(f, e): 41 | assert f > 0 42 | assert f < 2**PRECISION 43 | assert e >= MIN_EXPONENT 44 | assert e <= MAX_EXPONENT 45 | 46 | # 47 | # Init 48 | # 49 | 50 | isEven = (f % 2 == 0) 51 | acceptBounds = isEven 52 | lowerBoundaryIsCloser = (f == HIDDEN_BIT and e != MIN_EXPONENT) 53 | 54 | if e >= 0: 55 | r, s, mp, mm = f * 2 * 2**e, 2, 2**e, 2**e 56 | else: 57 | r, s, mp, mm = f * 2, 2**(-e) * 2, 1, 1 58 | 59 | # Could do after scaling to keep the numbers a tiny bit smaller?!?! 60 | if lowerBoundaryIsCloser: 61 | r, s, mp = r * 2, s * 2, mp * 2 62 | 63 | # 64 | # Scale into the range [0.1, 1.0) 65 | # aka: Find the smallest integer k, such that (r + m+) / s <= 10^k 66 | # aka: k = ceil(log_10((r + m+) / s)) 67 | # 68 | 69 | if False: 70 | k = 0 71 | while True: 72 | rp = r + mp 73 | if (rp >= s) if acceptBounds else (rp > s): 74 | s, k = s * 10, k + 1 75 | elif (rp * 10 < s) if acceptBounds else (rp * 10 <= s): 76 | r, mp, mm, k = r * 10, mp * 10, mm * 10, k - 1 77 | else: 78 | break 79 | else: 80 | # p = f.bit_length() # Effective precision 81 | p = EffectivePrecision(f) 82 | 83 | # Estimate: 84 | k = CeilLog10Pow2(e + (p - 1)) 85 | if k >= 0: 86 | s *= 10**k 87 | else: 88 | r, mp, mm = r * 10**(-k), mp * 10**(-k), mm * 10**(-k) 89 | 90 | # Fixup: 91 | if (r + mp >= s) if acceptBounds else (r + mp > s): 92 | s, k = s * 10, k + 1 93 | 94 | assert (r + mp < s) if acceptBounds else (r + mp <= s) 95 | assert ((r + mp) * 10 >= s) if acceptBounds else ((r + mp) * 10 > s) 96 | 97 | # 98 | # Generate 99 | # 100 | 101 | d = [] 102 | while True: 103 | assert r > 0 104 | 105 | r, mp, mm = r * 10, mp * 10, mm * 10 106 | q, r = divmod(r, s) 107 | assert q <= 9 108 | 109 | tc1 = (r <= mm) if acceptBounds else (r < mm) 110 | tc2 = (r + mp >= s) if acceptBounds else (r + mp > s) 111 | 112 | if tc1 and tc2: 113 | # Return the number closer to v. If the two are equidistant 114 | # from v, use **some** strategy to break the tie. 115 | if (r * 2 > s) or (r * 2 == s and q % 2 != 0): 116 | q += 1 117 | elif not tc1 and tc2: 118 | q += 1 119 | 120 | assert q >= 0 121 | assert q <= 9 122 | d.append(q) # d = 10 * d + q 123 | k -= 1 124 | 125 | if tc1 or tc2: 126 | break 127 | 128 | return long(''.join(map(str, d))), k 129 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: xenial 3 | 4 | language: cpp 5 | 6 | matrix: 7 | include: 8 | - os: linux 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - g++-6 15 | - lcov 16 | compiler: gcc 17 | env: 18 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 19 | - CONFIGURATION=Debug 20 | - CXXFLAGS="-std=c++11 -O0 -fprofile-arcs -ftest-coverage --coverage" 21 | - LINKFLAGS="--coverage" 22 | - GCOV=true 23 | after_success: 24 | - echo $PWD 25 | - lcov --version 26 | - lcov --directory . --capture --output-file coverage.info 27 | - lcov --remove coverage.info "test/*" "ext/*" "/usr/*" --output-file coverage.info 28 | # - lcov --extract coverage.info "$PWD/src/*" --output-file coverage.info 29 | - lcov --list coverage.info 30 | - bash <(curl -s https://codecov.io/bash) -X gcov 31 | # - bash <(curl -s https://codecov.io/bash) -f coverage.info || echo "no coverage reports" 32 | - os: linux 33 | addons: 34 | apt: 35 | sources: 36 | - ubuntu-toolchain-r-test 37 | packages: 38 | - g++-6 39 | compiler: gcc 40 | env: 41 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 42 | - CONFIGURATION=Release 43 | - CXXFLAGS="-std=c++11" 44 | - os: linux 45 | addons: 46 | apt: 47 | sources: 48 | - ubuntu-toolchain-r-test 49 | packages: 50 | - g++-6 51 | compiler: gcc 52 | env: 53 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 54 | - CONFIGURATION=Debug 55 | - CXXFLAGS="-std=c++11" 56 | - os: linux 57 | addons: 58 | apt: 59 | sources: 60 | - ubuntu-toolchain-r-test 61 | packages: 62 | - g++-6 63 | compiler: gcc 64 | env: 65 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 66 | - CONFIGURATION=Release 67 | - CXXFLAGS="-std=c++14" 68 | - os: linux 69 | addons: 70 | apt: 71 | sources: 72 | - ubuntu-toolchain-r-test 73 | packages: 74 | - g++-6 75 | compiler: gcc 76 | env: 77 | - MATRIX_EVAL="CC=gcc-6 && CXX=g++-6" 78 | - CONFIGURATION=Debug 79 | - CXXFLAGS="-std=c++14" 80 | - os: linux 81 | addons: 82 | apt: 83 | sources: 84 | - ubuntu-toolchain-r-test 85 | packages: 86 | - g++-7 87 | compiler: gcc 88 | env: 89 | - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" 90 | - CONFIGURATION=Release 91 | - CXXFLAGS="-std=c++17" 92 | - os: linux 93 | addons: 94 | apt: 95 | sources: 96 | - ubuntu-toolchain-r-test 97 | packages: 98 | - g++-7 99 | compiler: gcc 100 | env: 101 | - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" 102 | - CONFIGURATION=Debug 103 | - CXXFLAGS="-std=c++17" 104 | - os: osx 105 | compiler: clang 106 | env: 107 | - MATRIX_EVAL="CC=clang && CXX=clang++" 108 | - CONFIGURATION=Release 109 | - CXXFLAGS="-std=c++11 -stdlib=libc++" 110 | - os: osx 111 | compiler: clang 112 | env: 113 | - MATRIX_EVAL="CC=clang && CXX=clang++" 114 | - CONFIGURATION=Debug 115 | - CXXFLAGS="-std=c++11 -stdlib=libc++ -fsanitize=undefined" 116 | - LINKFLAGS="-fsanitize=undefined" 117 | - os: osx 118 | compiler: clang 119 | env: 120 | - MATRIX_EVAL="CC=clang && CXX=clang++" 121 | - CONFIGURATION=Release 122 | - CXXFLAGS="-std=c++14 -stdlib=libc++" 123 | - os: osx 124 | compiler: clang 125 | env: 126 | - MATRIX_EVAL="CC=clang && CXX=clang++" 127 | - CONFIGURATION=Debug 128 | - CXXFLAGS="-std=c++14 -stdlib=libc++" 129 | 130 | before_install: 131 | - eval "${MATRIX_EVAL}" 132 | 133 | install: 134 | - mkdir build 135 | - cd build 136 | - cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE="$CONFIGURATION" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_EXE_LINKER_FLAGS="$LINKFLAGS" .. 137 | 138 | script: 139 | - make test_all 140 | - ./test/test_all 141 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/abolz/Drachennest.svg?branch=master)](https://travis-ci.org/abolz/Drachennest) 2 | [![Build status](https://ci.appveyor.com/api/projects/status/py96h02xct0ycdqs?svg=true)](https://ci.appveyor.com/project/abolz/drachennest) 3 | [![codecov](https://codecov.io/gh/abolz/Drachennest/branch/master/graph/badge.svg)](https://codecov.io/gh/abolz/Drachennest) 4 | 5 | Converting binary floating-point to decimal floating-point numbers. 6 | 7 | --- 8 | 9 | Grisu / Dragon 10 | -------------------------------------------------------------------------------- 11 | 12 | Contains an implementation of the [Grisu2](https://github.com/abolz/Drachennest/blob/master/src/grisu2.h) 13 | and [Grisu3](https://github.com/abolz/Drachennest/blob/master/src/grisu3.h) algorithms as described in 14 | 15 | * Loitsch, [_Printing Floating-Point Numbers Quickly and Accurately with Integers_](https://dl.acm.org/citation.cfm?id=1806623), 16 | 17 | The Grisu3 implementation uses the [Dragon4](https://github.com/abolz/Drachennest/blob/master/src/dragon4.h) 18 | algorithm as a fallback. 19 | 20 | * Steele, White, [_How to Print FloatingPoint Numbers Accurately_](https://dl.acm.org/citation.cfm?id=93559), 21 | * Burger, Dybvig, [_Printing Floating-Point Numbers Quickly and Accurately_](https://dl.acm.org/citation.cfm?id=231397), 22 | 23 | Ryu 24 | -------------------------------------------------------------------------------- 25 | 26 | Contains an implementation of the [Ryu](https://github.com/abolz/Drachennest/blob/master/src/ryu_64.cc) 27 | algorithm as described in 28 | 29 | * Adams, [_Ryu: fast float-to-string conversion_](https://dl.acm.org/citation.cfm?id=3192369), 30 | 31 | The implemenation also contains a (fast!) `strtod` implementation, which can be 32 | used to convert decimal numbers with at most 17 significant decimal digits back 33 | into binary floating-point numbers. (Note that none of the algorithms here will 34 | ever produce more than 17 significant digits.) 35 | 36 | Schubfach 37 | -------------------------------------------------------------------------------- 38 | 39 | Contains an implementation of the [Schubfach](https://github.com/abolz/Drachennest/blob/master/src/schubfach_64.cc) 40 | algorithm as described in 41 | 42 | * Giulietti, [The Schubfach way to render doubles](https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN) 43 | 44 | The name of this algorithm "deliberately departs from a long lineage of fabulous drakes". 45 | 46 | Dragonbox 47 | -------------------------------------------------------------------------------- 48 | 49 | Contains a slightly modified version the reference implementation of 50 | Junekey Jeon's [Dragonbox](https://github.com/jk-jeon/dragonbox) algorithm. 51 | 52 | --- 53 | 54 | Grisu3, Ryu, Schubfach, and Dragonbox are optimal, i.e. the output string 55 | 1. rounds back to the input number when read in, 56 | 2. is as short as possible, 57 | 3. is as close to the input number as possible. 58 | 59 | These algorithms (currently) assume that the input rounding algorithm uses 60 | _round-to-nearest-even_ to break ties. Grisu2 only is optimal for ~99% of all 61 | floating point numbers, though it guarantees the first property for all of its 62 | inputs, _regardless of how the input rounding mode breaks ties_. 63 | 64 | --- 65 | 66 | Benchmarks 67 | -------------------------------------------------------------------------------- 68 | 69 | > Benchmarks were run on an Intel Core i7-9750H, using Visual Studio 2019 16.7.7, Clang 10.0, 64-bit. 70 | 71 | > Timings are in ns. 72 | 73 | --- 74 | 75 | For this benchmark uniformly distributed random `double`s in the 76 | range `[1,2]` have been generated. These numbers were then rounded to `N` 77 | significant digits and converted to decimal using the given algorithm. 78 | 79 | ![BenchDigits](/resources/bench_digits.png) 80 | 81 | --- 82 | 83 | Uniformly distributed random numbers in the range `[10^i, 10^(i+1)]` for 84 | `i=-12,...,12`. 85 | 86 | ![BenchUniform](/resources/bench_uniform.png) 87 | 88 | --- 89 | 90 | Uniformly distributed random numbers in the range `[0, 10^10]`. Each benchmark 91 | is run 10 times (using different numbers each run). 92 | 93 | ![BenchUniformE10](/resources/bench_uniform_e10.png) 94 | 95 | --- 96 | 97 | Random bit patterns. Each benchmark is run 10 times (using different numbers 98 | each run). 99 | 100 | ![BenchRandom](/resources/bench_random_bits.png) 101 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/re.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef BENCHMARK_RE_H_ 16 | #define BENCHMARK_RE_H_ 17 | 18 | #include "internal_macros.h" 19 | 20 | // clang-format off 21 | 22 | #if !defined(HAVE_STD_REGEX) && \ 23 | !defined(HAVE_GNU_POSIX_REGEX) && \ 24 | !defined(HAVE_POSIX_REGEX) 25 | // No explicit regex selection; detect based on builtin hints. 26 | #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE) 27 | #define HAVE_POSIX_REGEX 1 28 | #elif __cplusplus >= 199711L 29 | #define HAVE_STD_REGEX 1 30 | #endif 31 | #endif 32 | 33 | // Prefer C regex libraries when compiling w/o exceptions so that we can 34 | // correctly report errors. 35 | #if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \ 36 | defined(BENCHMARK_HAVE_STD_REGEX) && \ 37 | (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX)) 38 | #undef HAVE_STD_REGEX 39 | #endif 40 | 41 | #if defined(HAVE_STD_REGEX) 42 | #include 43 | #elif defined(HAVE_GNU_POSIX_REGEX) 44 | #include 45 | #elif defined(HAVE_POSIX_REGEX) 46 | #include 47 | #else 48 | #error No regular expression backend was found! 49 | #endif 50 | 51 | // clang-format on 52 | 53 | #include 54 | 55 | #include "check.h" 56 | 57 | namespace benchmark { 58 | 59 | // A wrapper around the POSIX regular expression API that provides automatic 60 | // cleanup 61 | class Regex { 62 | public: 63 | Regex() : init_(false) {} 64 | 65 | ~Regex(); 66 | 67 | // Compile a regular expression matcher from spec. Returns true on success. 68 | // 69 | // On failure (and if error is not nullptr), error is populated with a human 70 | // readable error message if an error occurs. 71 | bool Init(const std::string& spec, std::string* error); 72 | 73 | // Returns whether str matches the compiled regular expression. 74 | bool Match(const std::string& str); 75 | 76 | private: 77 | bool init_; 78 | // Underlying regular expression object 79 | #if defined(HAVE_STD_REGEX) 80 | std::regex re_; 81 | #elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX) 82 | regex_t re_; 83 | #else 84 | #error No regular expression backend implementation available 85 | #endif 86 | }; 87 | 88 | #if defined(HAVE_STD_REGEX) 89 | 90 | inline bool Regex::Init(const std::string& spec, std::string* error) { 91 | #ifdef BENCHMARK_HAS_NO_EXCEPTIONS 92 | ((void)error); // suppress unused warning 93 | #else 94 | try { 95 | #endif 96 | re_ = std::regex(spec, std::regex_constants::extended); 97 | init_ = true; 98 | #ifndef BENCHMARK_HAS_NO_EXCEPTIONS 99 | } 100 | catch (const std::regex_error& e) { 101 | if (error) { 102 | *error = e.what(); 103 | } 104 | } 105 | #endif 106 | return init_; 107 | } 108 | 109 | inline Regex::~Regex() {} 110 | 111 | inline bool Regex::Match(const std::string& str) { 112 | if (!init_) { 113 | return false; 114 | } 115 | return std::regex_search(str, re_); 116 | } 117 | 118 | #else 119 | inline bool Regex::Init(const std::string& spec, std::string* error) { 120 | int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB); 121 | if (ec != 0) { 122 | if (error) { 123 | size_t needed = regerror(ec, &re_, nullptr, 0); 124 | char* errbuf = new char[needed]; 125 | regerror(ec, &re_, errbuf, needed); 126 | 127 | // regerror returns the number of bytes necessary to null terminate 128 | // the string, so we move that when assigning to error. 129 | CHECK_NE(needed, 0); 130 | error->assign(errbuf, needed - 1); 131 | 132 | delete[] errbuf; 133 | } 134 | 135 | return false; 136 | } 137 | 138 | init_ = true; 139 | return true; 140 | } 141 | 142 | inline Regex::~Regex() { 143 | if (init_) { 144 | regfree(&re_); 145 | } 146 | } 147 | 148 | inline bool Regex::Match(const std::string& str) { 149 | if (!init_) { 150 | return false; 151 | } 152 | return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0; 153 | } 154 | #endif 155 | 156 | } // end namespace benchmark 157 | 158 | #endif // BENCHMARK_RE_H_ 159 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/csv_reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "complexity.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "check.h" 26 | #include "string_util.h" 27 | #include "timers.h" 28 | 29 | // File format reference: http://edoceo.com/utilitas/csv-file-format. 30 | 31 | namespace benchmark { 32 | 33 | namespace { 34 | std::vector elements = { 35 | "name", "iterations", "real_time", "cpu_time", 36 | "time_unit", "bytes_per_second", "items_per_second", "label", 37 | "error_occurred", "error_message"}; 38 | } // namespace 39 | 40 | std::string CsvEscape(const std::string & s) { 41 | std::string tmp; 42 | tmp.reserve(s.size() + 2); 43 | for (char c : s) { 44 | switch (c) { 45 | case '"' : tmp += "\"\""; break; 46 | default : tmp += c; break; 47 | } 48 | } 49 | return '"' + tmp + '"'; 50 | } 51 | 52 | bool CSVReporter::ReportContext(const Context& context) { 53 | PrintBasicContext(&GetErrorStream(), context); 54 | return true; 55 | } 56 | 57 | void CSVReporter::ReportRuns(const std::vector& reports) { 58 | std::ostream& Out = GetOutputStream(); 59 | 60 | if (!printed_header_) { 61 | // save the names of all the user counters 62 | for (const auto& run : reports) { 63 | for (const auto& cnt : run.counters) { 64 | if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 65 | continue; 66 | user_counter_names_.insert(cnt.first); 67 | } 68 | } 69 | 70 | // print the header 71 | for (auto B = elements.begin(); B != elements.end();) { 72 | Out << *B++; 73 | if (B != elements.end()) Out << ","; 74 | } 75 | for (auto B = user_counter_names_.begin(); 76 | B != user_counter_names_.end();) { 77 | Out << ",\"" << *B++ << "\""; 78 | } 79 | Out << "\n"; 80 | 81 | printed_header_ = true; 82 | } else { 83 | // check that all the current counters are saved in the name set 84 | for (const auto& run : reports) { 85 | for (const auto& cnt : run.counters) { 86 | if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 87 | continue; 88 | CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end()) 89 | << "All counters must be present in each run. " 90 | << "Counter named \"" << cnt.first 91 | << "\" was not in a run after being added to the header"; 92 | } 93 | } 94 | } 95 | 96 | // print results for each run 97 | for (const auto& run : reports) { 98 | PrintRunData(run); 99 | } 100 | } 101 | 102 | void CSVReporter::PrintRunData(const Run& run) { 103 | std::ostream& Out = GetOutputStream(); 104 | Out << CsvEscape(run.benchmark_name()) << ","; 105 | if (run.error_occurred) { 106 | Out << std::string(elements.size() - 3, ','); 107 | Out << "true,"; 108 | Out << CsvEscape(run.error_message) << "\n"; 109 | return; 110 | } 111 | 112 | // Do not print iteration on bigO and RMS report 113 | if (!run.report_big_o && !run.report_rms) { 114 | Out << run.iterations; 115 | } 116 | Out << ","; 117 | 118 | Out << run.GetAdjustedRealTime() << ","; 119 | Out << run.GetAdjustedCPUTime() << ","; 120 | 121 | // Do not print timeLabel on bigO and RMS report 122 | if (run.report_big_o) { 123 | Out << GetBigOString(run.complexity); 124 | } else if (!run.report_rms) { 125 | Out << GetTimeUnitString(run.time_unit); 126 | } 127 | Out << ","; 128 | 129 | if (run.counters.find("bytes_per_second") != run.counters.end()) { 130 | Out << run.counters.at("bytes_per_second"); 131 | } 132 | Out << ","; 133 | if (run.counters.find("items_per_second") != run.counters.end()) { 134 | Out << run.counters.at("items_per_second"); 135 | } 136 | Out << ","; 137 | if (!run.report_label.empty()) { 138 | Out << CsvEscape(run.report_label); 139 | } 140 | Out << ",,"; // for error_occurred and error_message 141 | 142 | // Print user counters 143 | for (const auto& ucn : user_counter_names_) { 144 | auto it = run.counters.find(ucn); 145 | if (it == run.counters.end()) { 146 | Out << ","; 147 | } else { 148 | Out << "," << it->second; 149 | } 150 | } 151 | Out << '\n'; 152 | } 153 | 154 | } // end namespace benchmark 155 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/mutex.h: -------------------------------------------------------------------------------- 1 | #ifndef BENCHMARK_MUTEX_H_ 2 | #define BENCHMARK_MUTEX_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "check.h" 8 | 9 | // Enable thread safety attributes only with clang. 10 | // The attributes can be safely erased when compiling with other compilers. 11 | #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) 12 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) 13 | #else 14 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op 15 | #endif 16 | 17 | #define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) 18 | 19 | #define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) 20 | 21 | #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) 22 | 23 | #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) 24 | 25 | #define ACQUIRED_BEFORE(...) \ 26 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) 27 | 28 | #define ACQUIRED_AFTER(...) \ 29 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) 30 | 31 | #define REQUIRES(...) \ 32 | THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) 33 | 34 | #define REQUIRES_SHARED(...) \ 35 | THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) 36 | 37 | #define ACQUIRE(...) \ 38 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) 39 | 40 | #define ACQUIRE_SHARED(...) \ 41 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) 42 | 43 | #define RELEASE(...) \ 44 | THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) 45 | 46 | #define RELEASE_SHARED(...) \ 47 | THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) 48 | 49 | #define TRY_ACQUIRE(...) \ 50 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) 51 | 52 | #define TRY_ACQUIRE_SHARED(...) \ 53 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) 54 | 55 | #define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) 56 | 57 | #define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) 58 | 59 | #define ASSERT_SHARED_CAPABILITY(x) \ 60 | THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) 61 | 62 | #define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) 63 | 64 | #define NO_THREAD_SAFETY_ANALYSIS \ 65 | THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) 66 | 67 | namespace benchmark { 68 | 69 | typedef std::condition_variable Condition; 70 | 71 | // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that 72 | // we can annotate them with thread safety attributes and use the 73 | // -Wthread-safety warning with clang. The standard library types cannot be 74 | // used directly because they do not provided the required annotations. 75 | class CAPABILITY("mutex") Mutex { 76 | public: 77 | Mutex() {} 78 | 79 | void lock() ACQUIRE() { mut_.lock(); } 80 | void unlock() RELEASE() { mut_.unlock(); } 81 | std::mutex& native_handle() { return mut_; } 82 | 83 | private: 84 | std::mutex mut_; 85 | }; 86 | 87 | class SCOPED_CAPABILITY MutexLock { 88 | typedef std::unique_lock MutexLockImp; 89 | 90 | public: 91 | MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {} 92 | ~MutexLock() RELEASE() {} 93 | MutexLockImp& native_handle() { return ml_; } 94 | 95 | private: 96 | MutexLockImp ml_; 97 | }; 98 | 99 | class Barrier { 100 | public: 101 | Barrier(int num_threads) : running_threads_(num_threads) {} 102 | 103 | // Called by each thread 104 | bool wait() EXCLUDES(lock_) { 105 | bool last_thread = false; 106 | { 107 | MutexLock ml(lock_); 108 | last_thread = createBarrier(ml); 109 | } 110 | if (last_thread) phase_condition_.notify_all(); 111 | return last_thread; 112 | } 113 | 114 | void removeThread() EXCLUDES(lock_) { 115 | MutexLock ml(lock_); 116 | --running_threads_; 117 | if (entered_ != 0) phase_condition_.notify_all(); 118 | } 119 | 120 | private: 121 | Mutex lock_; 122 | Condition phase_condition_; 123 | int running_threads_; 124 | 125 | // State for barrier management 126 | int phase_number_ = 0; 127 | int entered_ = 0; // Number of threads that have entered this barrier 128 | 129 | // Enter the barrier and wait until all other threads have also 130 | // entered the barrier. Returns iff this is the last thread to 131 | // enter the barrier. 132 | bool createBarrier(MutexLock& ml) REQUIRES(lock_) { 133 | CHECK_LT(entered_, running_threads_); 134 | entered_++; 135 | if (entered_ < running_threads_) { 136 | // Wait for all threads to enter 137 | int phase_number_cp = phase_number_; 138 | auto cb = [this, phase_number_cp]() { 139 | return this->phase_number_ > phase_number_cp || 140 | entered_ == running_threads_; // A thread has aborted in error 141 | }; 142 | phase_condition_.wait(ml.native_handle(), cb); 143 | if (phase_number_ > phase_number_cp) return false; 144 | // else (running_threads_ == entered_) and we are the last thread. 145 | } 146 | // Last thread has reached the barrier 147 | phase_number_++; 148 | entered_ = 0; 149 | return true; 150 | } 151 | }; 152 | 153 | } // end namespace benchmark 154 | 155 | #endif // BENCHMARK_MUTEX_H_ 156 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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 store only non-negative numbers and are not designed to contain special 40 | // doubles (NaN and Infinity). 41 | class DiyFp { 42 | public: 43 | static const int kSignificandSize = 64; 44 | 45 | DiyFp() : f_(0), e_(0) {} 46 | DiyFp(const uint64_t significand, const int32_t exponent) : f_(significand), e_(exponent) {} 47 | 48 | // this -= other. 49 | // The exponents of both numbers must be the same and the significand of this 50 | // must be greater or equal than the significand of other. 51 | // The result will not be normalized. 52 | void Subtract(const DiyFp& other) { 53 | DOUBLE_CONVERSION_ASSERT(e_ == other.e_); 54 | DOUBLE_CONVERSION_ASSERT(f_ >= other.f_); 55 | f_ -= other.f_; 56 | } 57 | 58 | // Returns a - b. 59 | // The exponents of both numbers must be the same and a must be greater 60 | // or equal than b. The result will not be normalized. 61 | static DiyFp Minus(const DiyFp& a, const DiyFp& b) { 62 | DiyFp result = a; 63 | result.Subtract(b); 64 | return result; 65 | } 66 | 67 | // this *= other. 68 | void Multiply(const DiyFp& other) { 69 | // Simply "emulates" a 128 bit multiplication. 70 | // However: the resulting number only contains 64 bits. The least 71 | // significant 64 bits are only used for rounding the most significant 64 72 | // bits. 73 | const uint64_t kM32 = 0xFFFFFFFFU; 74 | const uint64_t a = f_ >> 32; 75 | const uint64_t b = f_ & kM32; 76 | const uint64_t c = other.f_ >> 32; 77 | const uint64_t d = other.f_ & kM32; 78 | const uint64_t ac = a * c; 79 | const uint64_t bc = b * c; 80 | const uint64_t ad = a * d; 81 | const uint64_t bd = b * d; 82 | // By adding 1U << 31 to tmp we round the final result. 83 | // Halfway cases will be rounded up. 84 | const uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32) + (1U << 31); 85 | e_ += other.e_ + 64; 86 | f_ = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); 87 | } 88 | 89 | // returns a * b; 90 | static DiyFp Times(const DiyFp& a, const DiyFp& b) { 91 | DiyFp result = a; 92 | result.Multiply(b); 93 | return result; 94 | } 95 | 96 | void Normalize() { 97 | DOUBLE_CONVERSION_ASSERT(f_ != 0); 98 | uint64_t significand = f_; 99 | int32_t exponent = e_; 100 | 101 | // This method is mainly called for normalizing boundaries. In general, 102 | // boundaries need to be shifted by 10 bits, and we optimize for this case. 103 | const uint64_t k10MSBits = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFC00000, 00000000); 104 | while ((significand & k10MSBits) == 0) { 105 | significand <<= 10; 106 | exponent -= 10; 107 | } 108 | while ((significand & kUint64MSB) == 0) { 109 | significand <<= 1; 110 | exponent--; 111 | } 112 | f_ = significand; 113 | e_ = exponent; 114 | } 115 | 116 | static DiyFp Normalize(const DiyFp& a) { 117 | DiyFp result = a; 118 | result.Normalize(); 119 | return result; 120 | } 121 | 122 | uint64_t f() const { return f_; } 123 | int32_t e() const { return e_; } 124 | 125 | void set_f(uint64_t new_value) { f_ = new_value; } 126 | void set_e(int32_t new_value) { e_ = new_value; } 127 | 128 | private: 129 | static const uint64_t kUint64MSB = DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000); 130 | 131 | uint64_t f_; 132 | int32_t e_; 133 | }; 134 | 135 | } // namespace double_conversion 136 | 137 | #endif // DOUBLE_CONVERSION_DIY_FP_H_ 138 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/colorprint.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "colorprint.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "check.h" 25 | #include "internal_macros.h" 26 | 27 | #ifdef BENCHMARK_OS_WINDOWS 28 | #include 29 | #include 30 | #else 31 | #include 32 | #endif // BENCHMARK_OS_WINDOWS 33 | 34 | namespace benchmark { 35 | namespace { 36 | #ifdef BENCHMARK_OS_WINDOWS 37 | typedef WORD PlatformColorCode; 38 | #else 39 | typedef const char* PlatformColorCode; 40 | #endif 41 | 42 | PlatformColorCode GetPlatformColorCode(LogColor color) { 43 | #ifdef BENCHMARK_OS_WINDOWS 44 | switch (color) { 45 | case COLOR_RED: 46 | return FOREGROUND_RED; 47 | case COLOR_GREEN: 48 | return FOREGROUND_GREEN; 49 | case COLOR_YELLOW: 50 | return FOREGROUND_RED | FOREGROUND_GREEN; 51 | case COLOR_BLUE: 52 | return FOREGROUND_BLUE; 53 | case COLOR_MAGENTA: 54 | return FOREGROUND_BLUE | FOREGROUND_RED; 55 | case COLOR_CYAN: 56 | return FOREGROUND_BLUE | FOREGROUND_GREEN; 57 | case COLOR_WHITE: // fall through to default 58 | default: 59 | return 0; 60 | } 61 | #else 62 | switch (color) { 63 | case COLOR_RED: 64 | return "1"; 65 | case COLOR_GREEN: 66 | return "2"; 67 | case COLOR_YELLOW: 68 | return "3"; 69 | case COLOR_BLUE: 70 | return "4"; 71 | case COLOR_MAGENTA: 72 | return "5"; 73 | case COLOR_CYAN: 74 | return "6"; 75 | case COLOR_WHITE: 76 | return "7"; 77 | default: 78 | return nullptr; 79 | }; 80 | #endif 81 | } 82 | 83 | } // end namespace 84 | 85 | std::string FormatString(const char* msg, va_list args) { 86 | // we might need a second shot at this, so pre-emptivly make a copy 87 | va_list args_cp; 88 | va_copy(args_cp, args); 89 | 90 | std::size_t size = 256; 91 | char local_buff[256]; 92 | auto ret = vsnprintf(local_buff, size, msg, args_cp); 93 | 94 | va_end(args_cp); 95 | 96 | // currently there is no error handling for failure, so this is hack. 97 | CHECK(ret >= 0); 98 | 99 | if (ret == 0) // handle empty expansion 100 | return {}; 101 | else if (static_cast(ret) < size) 102 | return local_buff; 103 | else { 104 | // we did not provide a long enough buffer on our first attempt. 105 | size = (size_t)ret + 1; // + 1 for the null byte 106 | std::unique_ptr buff(new char[size]); 107 | ret = vsnprintf(buff.get(), size, msg, args); 108 | CHECK(ret > 0 && ((size_t)ret) < size); 109 | return buff.get(); 110 | } 111 | } 112 | 113 | std::string FormatString(const char* msg, ...) { 114 | va_list args; 115 | va_start(args, msg); 116 | auto tmp = FormatString(msg, args); 117 | va_end(args); 118 | return tmp; 119 | } 120 | 121 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) { 122 | va_list args; 123 | va_start(args, fmt); 124 | ColorPrintf(out, color, fmt, args); 125 | va_end(args); 126 | } 127 | 128 | void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, 129 | va_list args) { 130 | #ifdef BENCHMARK_OS_WINDOWS 131 | ((void)out); // suppress unused warning 132 | 133 | const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); 134 | 135 | // Gets the current text color. 136 | CONSOLE_SCREEN_BUFFER_INFO buffer_info; 137 | GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); 138 | const WORD old_color_attrs = buffer_info.wAttributes; 139 | 140 | // We need to flush the stream buffers into the console before each 141 | // SetConsoleTextAttribute call lest it affect the text that is already 142 | // printed but has not yet reached the console. 143 | fflush(stdout); 144 | SetConsoleTextAttribute(stdout_handle, 145 | GetPlatformColorCode(color) | FOREGROUND_INTENSITY); 146 | vprintf(fmt, args); 147 | 148 | fflush(stdout); 149 | // Restores the text color. 150 | SetConsoleTextAttribute(stdout_handle, old_color_attrs); 151 | #else 152 | const char* color_code = GetPlatformColorCode(color); 153 | if (color_code) out << FormatString("\033[0;3%sm", color_code); 154 | out << FormatString(fmt, args) << "\033[m"; 155 | #endif 156 | } 157 | 158 | bool IsColorTerminal() { 159 | #if BENCHMARK_OS_WINDOWS 160 | // On Windows the TERM variable is usually not set, but the 161 | // console there does support colors. 162 | return 0 != _isatty(_fileno(stdout)); 163 | #else 164 | // On non-Windows platforms, we rely on the TERM variable. This list of 165 | // supported TERM values is copied from Google Test: 166 | // . 167 | const char* const SUPPORTED_TERM_VALUES[] = { 168 | "xterm", "xterm-color", "xterm-256color", 169 | "screen", "screen-256color", "tmux", 170 | "tmux-256color", "rxvt-unicode", "rxvt-unicode-256color", 171 | "linux", "cygwin", 172 | }; 173 | 174 | const char* const term = getenv("TERM"); 175 | 176 | bool term_supports_color = false; 177 | for (const char* candidate : SUPPORTED_TERM_VALUES) { 178 | if (term && 0 == strcmp(term, candidate)) { 179 | term_supports_color = true; 180 | break; 181 | } 182 | } 183 | 184 | return 0 != isatty(fileno(stdout)) && term_supports_color; 185 | #endif // BENCHMARK_OS_WINDOWS 186 | } 187 | 188 | } // end namespace benchmark 189 | -------------------------------------------------------------------------------- /ext/google_double_conversion/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() : used_bigits_(0), exponent_(0) {} 43 | 44 | void AssignUInt16(const uint16_t value); 45 | void AssignUInt64(uint64_t value); 46 | void AssignBignum(const Bignum& other); 47 | 48 | void AssignDecimalString(const Vector value); 49 | void AssignHexString(const Vector value); 50 | 51 | void AssignPowerUInt16(uint16_t base, const int exponent); 52 | 53 | void AddUInt64(const 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(const int shift_amount); 60 | void MultiplyByUInt32(const uint32_t factor); 61 | void MultiplyByUInt64(const uint64_t factor); 62 | void MultiplyByPowerOfTen(const 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, const 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 | static void EnsureCapacity(const int size) { 115 | if (size > kBigitCapacity) { 116 | DOUBLE_CONVERSION_UNREACHABLE(); 117 | } 118 | } 119 | void Align(const Bignum& other); 120 | void Clamp(); 121 | bool IsClamped() const { 122 | return used_bigits_ == 0 || RawBigit(used_bigits_ - 1) != 0; 123 | } 124 | void Zero() { 125 | used_bigits_ = 0; 126 | exponent_ = 0; 127 | } 128 | // Requires this to have enough capacity (no tests done). 129 | // Updates used_bigits_ if necessary. 130 | // shift_amount must be < kBigitSize. 131 | void BigitsShiftLeft(const int shift_amount); 132 | // BigitLength includes the "hidden" bigits encoded in the exponent. 133 | int BigitLength() const { return used_bigits_ + exponent_; } 134 | Chunk& RawBigit(const int index); 135 | const Chunk& RawBigit(const int index) const; 136 | Chunk BigitOrZero(const int index) const; 137 | void SubtractTimes(const Bignum& other, const int factor); 138 | 139 | // The Bignum's value is value(bigits_buffer_) * 2^(exponent_ * kBigitSize), 140 | // where the value of the buffer consists of the lower kBigitSize bits of 141 | // the first used_bigits_ Chunks in bigits_buffer_, first chunk has lowest 142 | // significant bits. 143 | int16_t used_bigits_; 144 | int16_t exponent_; 145 | Chunk bigits_buffer_[kBigitCapacity]; 146 | 147 | DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Bignum); 148 | }; 149 | 150 | } // namespace double_conversion 151 | 152 | #endif // DOUBLE_CONVERSION_BIGNUM_H_ 153 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/console_reporter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "benchmark/benchmark.h" 16 | #include "complexity.h" 17 | #include "counter.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "check.h" 28 | #include "colorprint.h" 29 | #include "commandlineflags.h" 30 | #include "internal_macros.h" 31 | #include "string_util.h" 32 | #include "timers.h" 33 | 34 | namespace benchmark { 35 | 36 | bool ConsoleReporter::ReportContext(const Context& context) { 37 | name_field_width_ = context.name_field_width; 38 | printed_header_ = false; 39 | prev_counters_.clear(); 40 | 41 | PrintBasicContext(&GetErrorStream(), context); 42 | 43 | #ifdef BENCHMARK_OS_WINDOWS 44 | if ((output_options_ & OO_Color) && &std::cout != &GetOutputStream()) { 45 | GetErrorStream() 46 | << "Color printing is only supported for stdout on windows." 47 | " Disabling color printing\n"; 48 | output_options_ = static_cast< OutputOptions >(output_options_ & ~OO_Color); 49 | } 50 | #endif 51 | 52 | return true; 53 | } 54 | 55 | void ConsoleReporter::PrintHeader(const Run& run) { 56 | std::string str = FormatString("%-*s %13s %15s %12s", static_cast(name_field_width_), 57 | "Benchmark", "Time", "CPU", "Iterations"); 58 | if(!run.counters.empty()) { 59 | if(output_options_ & OO_Tabular) { 60 | for(auto const& c : run.counters) { 61 | str += FormatString(" %10s", c.first.c_str()); 62 | } 63 | } else { 64 | str += " UserCounters..."; 65 | } 66 | } 67 | std::string line = std::string(str.length(), '-'); 68 | GetOutputStream() << line << "\n" << str << "\n" << line << "\n"; 69 | } 70 | 71 | void ConsoleReporter::ReportRuns(const std::vector& reports) { 72 | for (const auto& run : reports) { 73 | // print the header: 74 | // --- if none was printed yet 75 | bool print_header = !printed_header_; 76 | // --- or if the format is tabular and this run 77 | // has different fields from the prev header 78 | print_header |= (output_options_ & OO_Tabular) && 79 | (!internal::SameNames(run.counters, prev_counters_)); 80 | if (print_header) { 81 | printed_header_ = true; 82 | prev_counters_ = run.counters; 83 | PrintHeader(run); 84 | } 85 | // As an alternative to printing the headers like this, we could sort 86 | // the benchmarks by header and then print. But this would require 87 | // waiting for the full results before printing, or printing twice. 88 | PrintRunData(run); 89 | } 90 | } 91 | 92 | static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt, 93 | ...) { 94 | va_list args; 95 | va_start(args, fmt); 96 | out << FormatString(fmt, args); 97 | va_end(args); 98 | } 99 | 100 | 101 | static std::string FormatTime(double time) { 102 | // Align decimal places... 103 | if (time < 1.0) { 104 | return FormatString("%10.3f", time); 105 | } 106 | if (time < 10.0) { 107 | return FormatString("%10.2f", time); 108 | } 109 | if (time < 100.0) { 110 | return FormatString("%10.1f", time); 111 | } 112 | return FormatString("%10.0f", time); 113 | } 114 | 115 | void ConsoleReporter::PrintRunData(const Run& result) { 116 | typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...); 117 | auto& Out = GetOutputStream(); 118 | PrinterFn* printer = (output_options_ & OO_Color) ? 119 | (PrinterFn*)ColorPrintf : IgnoreColorPrint; 120 | auto name_color = 121 | (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN; 122 | printer(Out, name_color, "%-*s ", name_field_width_, 123 | result.benchmark_name().c_str()); 124 | 125 | if (result.error_occurred) { 126 | printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'", 127 | result.error_message.c_str()); 128 | printer(Out, COLOR_DEFAULT, "\n"); 129 | return; 130 | } 131 | 132 | const double real_time = result.GetAdjustedRealTime(); 133 | const double cpu_time = result.GetAdjustedCPUTime(); 134 | const std::string real_time_str = FormatTime(real_time); 135 | const std::string cpu_time_str = FormatTime(cpu_time); 136 | 137 | 138 | if (result.report_big_o) { 139 | std::string big_o = GetBigOString(result.complexity); 140 | printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, big_o.c_str(), 141 | cpu_time, big_o.c_str()); 142 | } else if (result.report_rms) { 143 | printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%", 144 | cpu_time * 100, "%"); 145 | } else { 146 | const char* timeLabel = GetTimeUnitString(result.time_unit); 147 | printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), timeLabel, 148 | cpu_time_str.c_str(), timeLabel); 149 | } 150 | 151 | if (!result.report_big_o && !result.report_rms) { 152 | printer(Out, COLOR_CYAN, "%10lld", result.iterations); 153 | } 154 | 155 | for (auto& c : result.counters) { 156 | const std::size_t cNameLen = std::max(std::string::size_type(10), 157 | c.first.length()); 158 | auto const& s = HumanReadableNumber(c.second.value, c.second.oneK); 159 | if (output_options_ & OO_Tabular) { 160 | if (c.second.flags & Counter::kIsRate) { 161 | printer(Out, COLOR_DEFAULT, " %*s/s", cNameLen - 2, s.c_str()); 162 | } else { 163 | printer(Out, COLOR_DEFAULT, " %*s", cNameLen, s.c_str()); 164 | } 165 | } else { 166 | const char* unit = (c.second.flags & Counter::kIsRate) ? "/s" : ""; 167 | printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), 168 | unit); 169 | } 170 | } 171 | 172 | if (!result.report_label.empty()) { 173 | printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str()); 174 | } 175 | 176 | printer(Out, COLOR_DEFAULT, "\n"); 177 | } 178 | 179 | } // end namespace benchmark 180 | -------------------------------------------------------------------------------- /bench/bench_strtod.cc: -------------------------------------------------------------------------------- 1 | #include "benchmark/benchmark.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ryu_64.h" 10 | 11 | #define BENCH_RYU() 1 12 | #define BENCH_STD_STRTOD() 0 13 | #define BENCH_STD_CHARCONV() 0 14 | #define BENCH_DOUBLE_CONVERSION() 0 15 | 16 | static constexpr int NumFloats = 1 << 14; 17 | 18 | #if BENCH_RYU() 19 | struct S2DRyu 20 | { 21 | using value_type = double; 22 | 23 | value_type operator()(std::string const& str) const 24 | { 25 | value_type flt = 0; 26 | const auto res = ryu::Strtod(str.data(), str.data() + str.size(), flt); 27 | assert(res.status != ryu::StrtodStatus::invalid); 28 | return flt; 29 | } 30 | }; 31 | #endif 32 | 33 | #if BENCH_STD_STRTOD() 34 | struct S2DStdStrtod 35 | { 36 | using value_type = double; 37 | 38 | value_type operator()(std::string const& str) const 39 | { 40 | value_type flt = std::strtod(str.c_str(), nullptr); 41 | return flt; 42 | } 43 | }; 44 | #endif 45 | 46 | #if BENCH_STD_CHARCONV() 47 | #include 48 | struct S2DStdCharconv 49 | { 50 | using value_type = double; 51 | 52 | value_type operator()(std::string const& str) const 53 | { 54 | value_type flt = 0; 55 | const bool ok = std::from_chars(str.data(), str.data() + str.size(), flt).ec == std::errc{}; 56 | assert(ok); 57 | return flt; 58 | } 59 | }; 60 | #endif 61 | 62 | #if BENCH_DOUBLE_CONVERSION() 63 | #include "double-conversion/double-conversion.h" 64 | struct S2DDoubleConversion 65 | { 66 | using value_type = double; 67 | 68 | value_type operator()(std::string const& str) const 69 | { 70 | double_conversion::StringToDoubleConverter s2d(0, 0.0, 1.0, "inf", "nan"); 71 | int processed_characters_count = 0; 72 | return s2d.StringToDouble(str.data(), static_cast(str.size()), &processed_characters_count); 73 | } 74 | }; 75 | #endif 76 | 77 | template 78 | static void BenchIt(benchmark::State& state, std::vector const& numbers) 79 | { 80 | Converter convert; 81 | 82 | size_t index = 0; 83 | for (auto _ : state) 84 | { 85 | benchmark::DoNotOptimize( convert(numbers[index]) ); 86 | index = (index + 1) & (NumFloats - 1); 87 | } 88 | } 89 | 90 | template 91 | static void RegisterBenchmarks(char const* name, std::vector const& numbers) 92 | { 93 | auto* bench = benchmark::RegisterBenchmark(name, BenchIt, numbers); 94 | 95 | bench->ComputeStatistics("min", [](std::vector const& v) -> double { 96 | return *(std::min_element(std::begin(v), std::end(v))); 97 | }); 98 | //bench->Repetitions(3); 99 | bench->ReportAggregatesOnly(); 100 | } 101 | 102 | class JenkinsRandom 103 | { 104 | // A small noncryptographic PRNG 105 | // http://burtleburtle.net/bob/rand/smallprng.html 106 | 107 | uint32_t a; 108 | uint32_t b; 109 | uint32_t c; 110 | uint32_t d; 111 | 112 | static uint32_t Rotate(uint32_t value, int n) { 113 | return (value << n) | (value >> (32 - n)); 114 | } 115 | 116 | uint32_t Gen() { 117 | const uint32_t e = a - Rotate(b, 27); 118 | a = b ^ Rotate(c, 17); 119 | b = c + d; 120 | c = d + e; 121 | d = e + a; 122 | return d; 123 | } 124 | 125 | public: 126 | using result_type = uint32_t; 127 | 128 | static constexpr uint32_t min() { return 0; } 129 | static constexpr uint32_t max() { return UINT32_MAX; } 130 | 131 | explicit JenkinsRandom(uint32_t seed = 0) { 132 | a = 0xF1EA5EED; 133 | b = seed; 134 | c = seed; 135 | d = seed; 136 | for (int i = 0; i < 20; ++i) { 137 | static_cast(Gen()); 138 | } 139 | } 140 | 141 | uint32_t operator()() { return Gen(); } 142 | }; 143 | 144 | static JenkinsRandom random; 145 | 146 | template 147 | static inline char const* StrPrintf(char const* format, Args&&... args) 148 | { 149 | char buf[1024]; 150 | snprintf(buf, 1024, format, std::forward(args)...); 151 | #ifdef _MSC_VER 152 | return _strdup(buf); // leak... 153 | #else 154 | return strdup(buf); // leak... 155 | #endif 156 | } 157 | 158 | static inline void RegisterUniform_double(char const* name, double min, double max) 159 | { 160 | std::vector numbers(NumFloats); 161 | 162 | std::uniform_real_distribution gen(min, max); 163 | 164 | std::generate(numbers.begin(), numbers.end(), [&] { 165 | char buf[128]; 166 | 167 | char* const end = ryu::Dtoa(buf, gen(random)); 168 | //char* const end = buf + std::snprintf(buf, 128, "%.17g", gen(random)); 169 | //char* const end = buf + std::snprintf(buf, 128, "%.19g", gen(random)); 170 | //char* const end = buf + std::snprintf(buf, 128, "%.20g", gen(random)); 171 | 172 | return std::string(buf, end); 173 | }); 174 | 175 | #if BENCH_RYU() 176 | RegisterBenchmarks(StrPrintf("%s Ryu ", name), numbers); 177 | #endif 178 | #if BENCH_STD_STRTOD() 179 | RegisterBenchmarks(StrPrintf("%s std::strtod ", name), numbers); 180 | #endif 181 | #if BENCH_STD_CHARCONV() 182 | RegisterBenchmarks(StrPrintf("%s std::charconv ", name), numbers); 183 | #endif 184 | #if BENCH_DOUBLE_CONVERSION() 185 | RegisterBenchmarks(StrPrintf("%s double_conversion ", name), numbers); 186 | #endif 187 | } 188 | 189 | int main(int argc, char** argv) 190 | { 191 | #if defined(__clang__) 192 | printf("clang %d.%d\n", __clang_major__, __clang_minor__); 193 | #elif defined(__GNUC__) 194 | printf("gcc %s\n", __VERSION__); 195 | #elif defined(_MSC_VER) 196 | printf("msc %d\n", _MSC_FULL_VER); 197 | #endif 198 | 199 | RegisterUniform_double("warm up", 0, 1); 200 | RegisterUniform_double("warm up", 0, 1); 201 | RegisterUniform_double("warm up", 0, 1); 202 | 203 | RegisterUniform_double("uniform [0,1/2]", 0.0, 0.5); 204 | RegisterUniform_double("uniform [1/4,1/2]", 0.25, 0.5); 205 | RegisterUniform_double("uniform [1/2,1]", 0.5, 1.0); 206 | RegisterUniform_double("uniform [0,1]", 0.0, 1.0); 207 | RegisterUniform_double("uniform [1,2]", 1.0, 2.0); 208 | RegisterUniform_double("uniform [2,4]", 2.0, 4.0); 209 | RegisterUniform_double("uniform [4,8]", 4.0, 8.0); 210 | RegisterUniform_double("uniform [8,2^10]", 8.0, 1ll << 10); 211 | RegisterUniform_double("uniform [2^10,2^20]", 1ll << 10, 1ll << 20); 212 | RegisterUniform_double("uniform [2^20,2^50]", 1ll << 20, 1ll << 50); 213 | RegisterUniform_double("uniform [0,max]", 0.0, std::numeric_limits::max()); 214 | 215 | benchmark::Initialize(&argc, argv); 216 | benchmark::RunSpecifiedBenchmarks(); 217 | 218 | return 0; 219 | } 220 | -------------------------------------------------------------------------------- /bench/results/plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import pandas as pd 4 | import seaborn as sns 5 | 6 | data_digits = [ 7 | # gr3 ryu sf db std 8 | [ 9.23, 10.7, 7.25 , 7.36, 16.5], 9 | [ 24.4, 26.3, 17.3 , 13.9, 46.2], 10 | [ 25.3, 27.5, 17.8 , 14.6, 46.6], 11 | [ 23.6, 27.2, 17.1 , 14.1, 44.2], 12 | [ 22.8, 28.0, 20.0 , 16.1, 42.1], 13 | [ 23.1, 27.3, 19.1 , 15.4, 41.3], 14 | [ 25.1, 27.8, 18.9 , 15.3, 40.8], 15 | [ 26.6, 27.7, 19.3 , 15.3, 39.5], 16 | [ 28.2, 27.5, 20.6 , 17.5, 37.7], 17 | [ 28.9, 27.8, 20.0 , 17.1, 36.0], 18 | [ 31.2, 27.7, 20.0 , 16.7, 35.4], 19 | [ 31.7, 27.3, 20.4 , 17.1, 36.7], 20 | [ 34.5, 27.8, 21.4 , 17.9, 32.6], 21 | [ 34.9, 27.3, 21.2 , 17.7, 31.6], 22 | [ 38.0, 28.0, 21.2 , 17.3, 31.0], 23 | [ 39.1, 28.2, 21.2 , 17.5, 29.8], 24 | [ 43.0, 28.9, 25.8 , 23.0, 29.3], 25 | ] 26 | index_digits = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] 27 | 28 | df = pd.DataFrame(data_digits, index_digits, ["Grisu3", "Ryu", "Schubfach", "Dragonbox", "std::to_chars"]) 29 | ax = sns.lineplot(data=df, dashes=False) 30 | plt.savefig('bench_digits' + '.png') 31 | plt.close() 32 | 33 | data_uniform = [ 34 | # gr3 ryu sf db std 35 | # [ 43.4 , 28.8 , 25.7, 23.4 , 30.2 ], # -16 36 | # [ 42.8 , 29.6 , 28.7, 25.4 , 31.7 ], # -15 37 | # [ 41.8 , 29.2 , 28.6, 26.1 , 30.5 ], # -14 38 | # [ 39.3 , 28.8 , 27.4, 25.2 , 30.3 ], # -13 39 | [45.3, 30.1, 29.2, 26.4, 32.5], 40 | [48.9, 30.3, 29.5, 26.6, 32.0], 41 | [46.8, 29.9, 28.4, 26.2, 32.6], 42 | [46.6, 31.7, 28.7, 26.1, 32.9], 43 | [44.6, 30.7, 29.2, 26.9, 33.6], 44 | [42.0, 29.1, 26.8, 24.7, 33.0], 45 | [42.0, 29.3, 27.5, 24.6, 31.6], 46 | [40.5, 29.6, 28.3, 25.5, 32.2], 47 | [45.7, 29.1, 26.8, 25.0, 31.2], 48 | [49.9, 29.2, 27.3, 24.3, 31.3], 49 | [48.4, 29.6, 28.3, 25.5, 33.2], 50 | [45.0, 29.1, 26.7, 25.0, 32.9], 51 | [45.9, 30.1, 27.8, 24.4, 32.8], 52 | [43.5, 30.2, 28.8, 25.9, 33.7], 53 | [41.0, 29.8, 27.4, 25.6, 33.2], 54 | [40.9, 29.8, 27.4, 24.0, 32.1], 55 | [45.5, 30.2, 28.8, 25.8, 32.8], 56 | [48.2, 29.8, 27.7, 25.8, 32.0], 57 | [47.3, 29.8, 27.0, 23.5, 32.0], 58 | [46.8, 30.2, 28.7, 25.9, 32.5], 59 | [43.9, 29.8, 27.9, 25.8, 32.1], 60 | [42.9, 29.6, 26.7, 23.1, 31.7], 61 | [42.4, 30.2, 28.7, 25.7, 32.9], 62 | [39.8, 29.8, 28.2, 25.8, 32.2], 63 | [47.4, 29.9, 26.3, 22.7, 32.6], 64 | # [ 60.1 , 31.4 , 27.4, 25.2 , 36.0 ], # 13 65 | # [ 101 , 31.2 , 26.0, 25.3 , 32.7 ], # 14 66 | # [ 41.5 , 20.9 , 16.4, 17.2 , 23.1 ], # 15 67 | # [ 145 , 35.3 , 26.6, 25.8 , 47.3 ], # 16 68 | ] 69 | 70 | 71 | 72 | 73 | 74 | #index_uniform = [-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] 75 | index_uniform = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12] 76 | 77 | df = pd.DataFrame(data_uniform, index_uniform, ["Grisu3", "Ryu", "Schubfach", "Dragonbox", "std::to_chars"]) 78 | ax = sns.lineplot(data=df, dashes=False) 79 | plt.savefig('bench_uniform' + '.png') 80 | plt.close() 81 | 82 | 83 | 84 | 85 | 86 | 87 | data_uniform_e10 = [ 88 | # gr3 ryu sf db std 89 | [44.5, 29.6, 27.2, 23.7, 32.3], 90 | [44.5, 29.7, 27.2, 23.7, 32.3], 91 | [44.7, 29.7, 27.1, 23.8, 32.4], 92 | [44.4, 29.7, 27.1, 23.5, 32.3], 93 | [44.6, 29.7, 27.1, 23.6, 32.4], 94 | [44.6, 29.7, 27.1, 23.6, 32.3], 95 | [44.3, 29.6, 27.0, 23.6, 32.2], 96 | [44.8, 29.7, 27.1, 23.6, 32.2], 97 | [44.8, 29.7, 27.1, 23.6, 32.3], 98 | [44.3, 29.7, 27.1, 23.5, 32.3], 99 | ] 100 | index_uniform_e10 = [0,1,2,3,4,5,6,7,8,9] 101 | df = pd.DataFrame(data_uniform_e10, index_uniform_e10, ["Grisu3", "Ryu", "Schubfach", "Dragonbox", "std::to_chars"]) 102 | ax = sns.lineplot(data=df, dashes=False) 103 | plt.savefig('bench_uniform_e10' + '.png') 104 | plt.close() 105 | 106 | 107 | 108 | 109 | 110 | data_random_bits = [ 111 | # gr3 ryu sf db std 112 | [57.0, 36.7, 30.4, 28.7, 38.3], 113 | [56.4, 36.8, 30.4, 28.9, 38.3], 114 | [56.3, 36.9, 30.5, 28.7, 38.3], 115 | [57.3, 36.9, 30.4, 28.8, 38.3], 116 | [57.1, 36.8, 30.5, 28.8, 38.3], 117 | [56.8, 36.8, 30.5, 28.8, 38.3], 118 | [57.0, 36.9, 30.5, 28.8, 38.4], 119 | [57.6, 36.8, 30.4, 28.7, 38.3], 120 | [57.1, 36.8, 30.4, 28.7, 38.3], 121 | [57.7, 36.8, 30.4, 28.7, 38.4], 122 | ] 123 | index_random_bits = [0,1,2,3,4,5,6,7,8,9] 124 | df = pd.DataFrame(data_random_bits, index_random_bits, ["Grisu3", "Ryu", "Schubfach", "Dragonbox", "std::to_chars"]) 125 | ax = sns.lineplot(data=df, dashes=False) 126 | plt.savefig('bench_random_bits' + '.png') 127 | plt.close() 128 | 129 | 130 | 131 | 132 | 133 | data_random = [ 134 | # gr3 ryu sf db std 135 | [ 56.0, 36.5 , 30.9 , 27.8, 37.9 ], 136 | [ 56.3, 35.6 , 30.5 , 27.8, 37.3 ], 137 | [ 55.3, 35.5 , 30.8 , 28.3, 37.3 ], 138 | [ 56.0, 35.2 , 30.2 , 28.3, 37.4 ], 139 | [ 58.7, 35.5 , 30.3 , 28.0, 38.0 ], 140 | [ 54.4, 35.4 , 30.8 , 27.9, 37.8 ], 141 | [ 56.4, 35.7 , 30.7 , 28.4, 37.3 ], 142 | [ 56.4, 35.9 , 30.7 , 28.3, 37.3 ], 143 | [ 59.7, 35.8 , 30.4 , 28.4, 37.6 ], 144 | [ 55.6, 37.0 , 30.8 , 27.8, 38.0 ], 145 | [ 55.5, 35.9 , 30.4 , 28.3, 37.9 ], 146 | [ 54.8, 35.3 , 30.3 , 27.9, 37.9 ], 147 | ] 148 | index_random = [1,2,3,4,5,6,7,8,9,10,11,12] 149 | 150 | df = pd.DataFrame(data_random, index_random, ["Grisu3", "Ryu", "Schubfach", "Dragonbox", "std::to_chars"]) 151 | ax = sns.lineplot(data=df, dashes=False) 152 | plt.savefig('bench_random' + '.png') 153 | plt.close() 154 | 155 | 156 | 157 | 158 | 159 | 160 | # names = [ 161 | # "charconv", 162 | # "charconv-general", 163 | # "grisu2", 164 | # "grisu3", 165 | # "ryu", 166 | # ] 167 | 168 | # for name in names: 169 | # data = pd.read_csv(name + '.csv') 170 | # data = data.pivot('len(N)', 'E', 'ns') 171 | # data = data.transpose() 172 | # ax = sns.heatmap(data, vmin=0.0, vmax=150.0, cmap="inferno") 173 | # plt.savefig(name + '.png') 174 | # plt.close() 175 | -------------------------------------------------------------------------------- /ext/ryu/ryu/d2s_intrinsics.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Ulf Adams 2 | // 3 | // The contents of this file may be used under the terms of the Apache License, 4 | // Version 2.0. 5 | // 6 | // (See accompanying file LICENSE-Apache or copy at 7 | // http://www.apache.org/licenses/LICENSE-2.0) 8 | // 9 | // Alternatively, the contents of this file may be used under the terms of 10 | // the Boost Software License, Version 1.0. 11 | // (See accompanying file LICENSE-Boost or copy at 12 | // https://www.boost.org/LICENSE_1_0.txt) 13 | // 14 | // Unless required by applicable law or agreed to in writing, this software 15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. 17 | #ifndef RYU_D2S_INTRINSICS_H 18 | #define RYU_D2S_INTRINSICS_H 19 | 20 | #include 21 | #include 22 | 23 | // This sets RYU_32_BIT_PLATFORM as a side effect if applicable. 24 | #include "ryu/common.h" 25 | 26 | #if defined(HAS_64_BIT_INTRINSICS) 27 | 28 | #include 29 | 30 | static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) { 31 | return _umul128(a, b, productHi); 32 | } 33 | 34 | static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) { 35 | // For the __shiftright128 intrinsic, the shift value is always 36 | // modulo 64. 37 | // In the current implementation of the double-precision version 38 | // of Ryu, the shift value is always < 64. (In the case 39 | // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [49, 58]. 40 | // Otherwise in the range [2, 59].) 41 | // Check this here in case a future change requires larger shift 42 | // values. In this case this function needs to be adjusted. 43 | assert(dist < 64); 44 | return __shiftright128(lo, hi, (unsigned char) dist); 45 | } 46 | 47 | #else // defined(HAS_64_BIT_INTRINSICS) 48 | 49 | static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) { 50 | // The casts here help MSVC to avoid calls to the __allmul library function. 51 | const uint32_t aLo = (uint32_t)a; 52 | const uint32_t aHi = (uint32_t)(a >> 32); 53 | const uint32_t bLo = (uint32_t)b; 54 | const uint32_t bHi = (uint32_t)(b >> 32); 55 | 56 | const uint64_t b00 = (uint64_t)aLo * bLo; 57 | const uint64_t b01 = (uint64_t)aLo * bHi; 58 | const uint64_t b10 = (uint64_t)aHi * bLo; 59 | const uint64_t b11 = (uint64_t)aHi * bHi; 60 | 61 | const uint32_t b00Lo = (uint32_t)b00; 62 | const uint32_t b00Hi = (uint32_t)(b00 >> 32); 63 | 64 | const uint64_t mid1 = b10 + b00Hi; 65 | const uint32_t mid1Lo = (uint32_t)(mid1); 66 | const uint32_t mid1Hi = (uint32_t)(mid1 >> 32); 67 | 68 | const uint64_t mid2 = b01 + mid1Lo; 69 | const uint32_t mid2Lo = (uint32_t)(mid2); 70 | const uint32_t mid2Hi = (uint32_t)(mid2 >> 32); 71 | 72 | const uint64_t pHi = b11 + mid1Hi + mid2Hi; 73 | const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo; 74 | 75 | *productHi = pHi; 76 | return pLo; 77 | } 78 | 79 | static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) { 80 | // We don't need to handle the case dist >= 64 here (see above). 81 | assert(dist < 64); 82 | #if defined(RYU_OPTIMIZE_SIZE) || !defined(RYU_32_BIT_PLATFORM) 83 | assert(dist > 0); 84 | return (hi << (64 - dist)) | (lo >> dist); 85 | #else 86 | // Avoid a 64-bit shift by taking advantage of the range of shift values. 87 | assert(dist >= 32); 88 | return (hi << (64 - dist)) | ((uint32_t)(lo >> 32) >> (dist - 32)); 89 | #endif 90 | } 91 | 92 | #endif // defined(HAS_64_BIT_INTRINSICS) 93 | 94 | #ifdef RYU_32_BIT_PLATFORM 95 | 96 | // Returns the high 64 bits of the 128-bit product of a and b. 97 | static inline uint64_t umulh(const uint64_t a, const uint64_t b) { 98 | // Reuse the umul128 implementation. 99 | // Optimizers will likely eliminate the instructions used to compute the 100 | // low part of the product. 101 | uint64_t hi; 102 | umul128(a, b, &hi); 103 | return hi; 104 | } 105 | 106 | // On 32-bit platforms, compilers typically generate calls to library 107 | // functions for 64-bit divisions, even if the divisor is a constant. 108 | // 109 | // E.g.: 110 | // https://bugs.llvm.org/show_bug.cgi?id=37932 111 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958 112 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443 113 | // 114 | // The functions here perform division-by-constant using multiplications 115 | // in the same way as 64-bit compilers would do. 116 | // 117 | // NB: 118 | // The multipliers and shift values are the ones generated by clang x64 119 | // for expressions like x/5, x/10, etc. 120 | 121 | static inline uint64_t div5(const uint64_t x) { 122 | return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2; 123 | } 124 | 125 | static inline uint64_t div10(const uint64_t x) { 126 | return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3; 127 | } 128 | 129 | static inline uint64_t div100(const uint64_t x) { 130 | return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2; 131 | } 132 | 133 | static inline uint64_t div1e8(const uint64_t x) { 134 | return umulh(x, 0xABCC77118461CEFDu) >> 26; 135 | } 136 | 137 | static inline uint64_t div1e9(const uint64_t x) { 138 | return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11; 139 | } 140 | 141 | static inline uint32_t mod1e9(const uint64_t x) { 142 | // Avoid 64-bit math as much as possible. 143 | // Returning (uint32_t) (x - 1000000000 * div1e9(x)) would 144 | // perform 32x64-bit multiplication and 64-bit subtraction. 145 | // x and 1000000000 * div1e9(x) are guaranteed to differ by 146 | // less than 10^9, so their highest 32 bits must be identical, 147 | // so we can truncate both sides to uint32_t before subtracting. 148 | // We can also simplify (uint32_t) (1000000000 * div1e9(x)). 149 | // We can truncate before multiplying instead of after, as multiplying 150 | // the highest 32 bits of div1e9(x) can't affect the lowest 32 bits. 151 | return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x)); 152 | } 153 | 154 | #else // RYU_32_BIT_PLATFORM 155 | 156 | static inline uint64_t div5(const uint64_t x) { 157 | return x / 5; 158 | } 159 | 160 | static inline uint64_t div10(const uint64_t x) { 161 | return x / 10; 162 | } 163 | 164 | static inline uint64_t div100(const uint64_t x) { 165 | return x / 100; 166 | } 167 | 168 | static inline uint64_t div1e8(const uint64_t x) { 169 | return x / 100000000; 170 | } 171 | 172 | static inline uint64_t div1e9(const uint64_t x) { 173 | return x / 1000000000; 174 | } 175 | 176 | static inline uint32_t mod1e9(const uint64_t x) { 177 | return (uint32_t) (x - 1000000000 * div1e9(x)); 178 | } 179 | 180 | #endif // RYU_32_BIT_PLATFORM 181 | 182 | static inline uint32_t pow5Factor(uint64_t value) { 183 | uint32_t count = 0; 184 | for (;;) { 185 | assert(value != 0); 186 | const uint64_t q = div5(value); 187 | const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q); 188 | if (r != 0) { 189 | break; 190 | } 191 | value = q; 192 | ++count; 193 | } 194 | return count; 195 | } 196 | 197 | // Returns true if value is divisible by 5^p. 198 | static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) { 199 | // I tried a case distinction on p, but there was no performance difference. 200 | return pow5Factor(value) >= p; 201 | } 202 | 203 | // Returns true if value is divisible by 2^p. 204 | static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) { 205 | assert(value != 0); 206 | // return __builtin_ctzll(value) >= p; 207 | return (value & ((1ull << p) - 1)) == 0; 208 | } 209 | 210 | #endif // RYU_D2S_INTRINSICS_H 211 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/statistics.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Ismael Jimenez Martinez. All rights reserved. 2 | // Copyright 2017 Roman Lebedev. All rights reserved. 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 | #include "benchmark/benchmark.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "check.h" 24 | #include "statistics.h" 25 | 26 | namespace benchmark { 27 | 28 | auto StatisticsSum = [](const std::vector& v) { 29 | return std::accumulate(v.begin(), v.end(), 0.0); 30 | }; 31 | 32 | double StatisticsMean(const std::vector& v) { 33 | if (v.empty()) return 0.0; 34 | return StatisticsSum(v) * (1.0 / v.size()); 35 | } 36 | 37 | double StatisticsMedian(const std::vector& v) { 38 | if (v.size() < 3) return StatisticsMean(v); 39 | std::vector copy(v); 40 | 41 | auto center = copy.begin() + v.size() / 2; 42 | std::nth_element(copy.begin(), center, copy.end()); 43 | 44 | // did we have an odd number of samples? 45 | // if yes, then center is the median 46 | // it no, then we are looking for the average between center and the value 47 | // before 48 | if (v.size() % 2 == 1) return *center; 49 | auto center2 = copy.begin() + v.size() / 2 - 1; 50 | std::nth_element(copy.begin(), center2, copy.end()); 51 | return (*center + *center2) / 2.0; 52 | } 53 | 54 | // Return the sum of the squares of this sample set 55 | auto SumSquares = [](const std::vector& v) { 56 | return std::inner_product(v.begin(), v.end(), v.begin(), 0.0); 57 | }; 58 | 59 | auto Sqr = [](const double dat) { return dat * dat; }; 60 | auto Sqrt = [](const double dat) { 61 | // Avoid NaN due to imprecision in the calculations 62 | if (dat < 0.0) return 0.0; 63 | return std::sqrt(dat); 64 | }; 65 | 66 | double StatisticsStdDev(const std::vector& v) { 67 | const auto mean = StatisticsMean(v); 68 | if (v.empty()) return mean; 69 | 70 | // Sample standard deviation is undefined for n = 1 71 | if (v.size() == 1) return 0.0; 72 | 73 | const double avg_squares = SumSquares(v) * (1.0 / v.size()); 74 | return Sqrt(v.size() / (v.size() - 1.0) * (avg_squares - Sqr(mean))); 75 | } 76 | 77 | std::vector ComputeStats( 78 | const std::vector& reports) { 79 | typedef BenchmarkReporter::Run Run; 80 | std::vector results; 81 | 82 | auto error_count = 83 | std::count_if(reports.begin(), reports.end(), 84 | [](Run const& run) { return run.error_occurred; }); 85 | 86 | if (reports.size() - error_count < 2) { 87 | // We don't report aggregated data if there was a single run. 88 | return results; 89 | } 90 | 91 | // Accumulators. 92 | std::vector real_accumulated_time_stat; 93 | std::vector cpu_accumulated_time_stat; 94 | 95 | real_accumulated_time_stat.reserve(reports.size()); 96 | cpu_accumulated_time_stat.reserve(reports.size()); 97 | 98 | // All repetitions should be run with the same number of iterations so we 99 | // can take this information from the first benchmark. 100 | const IterationCount run_iterations = reports.front().iterations; 101 | // create stats for user counters 102 | struct CounterStat { 103 | Counter c; 104 | std::vector s; 105 | }; 106 | std::map counter_stats; 107 | for (Run const& r : reports) { 108 | for (auto const& cnt : r.counters) { 109 | auto it = counter_stats.find(cnt.first); 110 | if (it == counter_stats.end()) { 111 | counter_stats.insert({cnt.first, {cnt.second, std::vector{}}}); 112 | it = counter_stats.find(cnt.first); 113 | it->second.s.reserve(reports.size()); 114 | } else { 115 | CHECK_EQ(counter_stats[cnt.first].c.flags, cnt.second.flags); 116 | } 117 | } 118 | } 119 | 120 | // Populate the accumulators. 121 | for (Run const& run : reports) { 122 | CHECK_EQ(reports[0].benchmark_name(), run.benchmark_name()); 123 | CHECK_EQ(run_iterations, run.iterations); 124 | if (run.error_occurred) continue; 125 | real_accumulated_time_stat.emplace_back(run.real_accumulated_time); 126 | cpu_accumulated_time_stat.emplace_back(run.cpu_accumulated_time); 127 | // user counters 128 | for (auto const& cnt : run.counters) { 129 | auto it = counter_stats.find(cnt.first); 130 | CHECK_NE(it, counter_stats.end()); 131 | it->second.s.emplace_back(cnt.second); 132 | } 133 | } 134 | 135 | // Only add label if it is same for all runs 136 | std::string report_label = reports[0].report_label; 137 | for (std::size_t i = 1; i < reports.size(); i++) { 138 | if (reports[i].report_label != report_label) { 139 | report_label = ""; 140 | break; 141 | } 142 | } 143 | 144 | const double iteration_rescale_factor = 145 | double(reports.size()) / double(run_iterations); 146 | 147 | for (const auto& Stat : *reports[0].statistics) { 148 | // Get the data from the accumulator to BenchmarkReporter::Run's. 149 | Run data; 150 | data.run_name = reports[0].run_name; 151 | data.run_type = BenchmarkReporter::Run::RT_Aggregate; 152 | data.threads = reports[0].threads; 153 | data.repetitions = reports[0].repetitions; 154 | data.repetition_index = Run::no_repetition_index; 155 | data.aggregate_name = Stat.name_; 156 | data.report_label = report_label; 157 | 158 | // It is incorrect to say that an aggregate is computed over 159 | // run's iterations, because those iterations already got averaged. 160 | // Similarly, if there are N repetitions with 1 iterations each, 161 | // an aggregate will be computed over N measurements, not 1. 162 | // Thus it is best to simply use the count of separate reports. 163 | data.iterations = reports.size(); 164 | 165 | data.real_accumulated_time = Stat.compute_(real_accumulated_time_stat); 166 | data.cpu_accumulated_time = Stat.compute_(cpu_accumulated_time_stat); 167 | 168 | // We will divide these times by data.iterations when reporting, but the 169 | // data.iterations is not nessesairly the scale of these measurements, 170 | // because in each repetition, these timers are sum over all the iterations. 171 | // And if we want to say that the stats are over N repetitions and not 172 | // M iterations, we need to multiply these by (N/M). 173 | data.real_accumulated_time *= iteration_rescale_factor; 174 | data.cpu_accumulated_time *= iteration_rescale_factor; 175 | 176 | data.time_unit = reports[0].time_unit; 177 | 178 | // user counters 179 | for (auto const& kv : counter_stats) { 180 | // Do *NOT* rescale the custom counters. They are already properly scaled. 181 | const auto uc_stat = Stat.compute_(kv.second.s); 182 | auto c = Counter(uc_stat, counter_stats[kv.first].c.flags, 183 | counter_stats[kv.first].c.oneK); 184 | data.counters[kv.first] = c; 185 | } 186 | 187 | results.push_back(data); 188 | } 189 | 190 | return results; 191 | } 192 | 193 | } // end namespace benchmark 194 | -------------------------------------------------------------------------------- /ext/ryu/README.md: -------------------------------------------------------------------------------- 1 | # Ryu [![Build Status](https://travis-ci.org/ulfjack/ryu.svg?branch=master)](https://travis-ci.org/ulfjack/ryu) 2 | 3 | This project contains a C and a Java implementation of Ryu, an algorithm to 4 | quickly convert floating point numbers to decimal strings. We have tested the 5 | code on Ubuntu 17.10, MacOS High Sierra, and Windows 10. 6 | 7 | The Java implementations are RyuFloat and RyuDouble under src/main/java/. The 8 | C implementation is in the ryu/ directory. Both cover 32 and 64-bit floating 9 | point numbers. 10 | 11 | *Note*: The Java implementation differs from the output of ```Double.toString``` 12 | in some cases: sometimes the output is shorter (which is arguably more accurate) 13 | and sometimes the output may differ in the precise digits output (e.g., see 14 | https://github.com/ulfjack/ryu/issues/83). 15 | 16 | *Note*: While the Java specification requires outputting at least 2 digits, 17 | other specifications, such as for JavaScript, always require the shortest output. 18 | We may change the Java implementation in the future to support both. 19 | 20 | There is an experimental C low-level API and 128-bit implementation in ryu/. 21 | These are still subject to change. 22 | 23 | All code outside of third_party/ is Copyright Ulf Adams, and may be used in 24 | accordance with the Apache 2.0 license. Alternatively, the files in the ryu/ 25 | directory may be used in accordance with the Boost 1.0 license. 26 | 27 | My PLDI'18 paper includes a complete correctness proof of the algorithm: 28 | https://dl.acm.org/citation.cfm?id=3192369, available under the creative commons 29 | CC-BY-SA license. 30 | 31 | Other implementations: 32 | 33 | | Language | Author | Link | 34 | |------------------|--------------------|-----------------------------------------------| 35 | | Scala | Andriy Plokhotnyuk | https://github.com/plokhotnyuk/jsoniter-scala | 36 | | Rust | David Tolnay | https://github.com/dtolnay/ryu | 37 | | Julia | Jacob Quinn | https://github.com/quinnj/Ryu.jl | 38 | | Factor | Alexander Iljin | https://github.com/AlexIljin/ryu | 39 | | Go | Caleb Spare | https://github.com/cespare/ryu | 40 | 41 | [1] https://docs.oracle.com/javase/10/docs/api/java/lang/Double.html#toString(double) 42 | 43 | ## Building, Testing, Running 44 | 45 | We use the Bazel build system (https://bazel.build). We recommend using the 46 | latest release, but it should also work with earlier versions. You also need 47 | to install Jdk 8 and a C/C++ compiler (gcc or clang on Ubuntu, XCode on 48 | MacOS, or MSVC on Windows). 49 | 50 | ### Building with a Custom Compiler 51 | You can select a custom C++ compiler by setting the CC environment variable 52 | (e.g., on Ubuntu, run `export CC=clang-3.9`). 53 | 54 | For example, use these steps to build with clang-4.0: 55 | ``` 56 | $ export CC=clang-4.0 57 | $ bazel build //ryu 58 | ``` 59 | Note that older Bazel versions (< 0.14) did not work with all compilers 60 | (https://github.com/bazelbuild/bazel/issues/3977). 61 | 62 | ### Tests 63 | You can run both C and Java tests with 64 | ``` 65 | $ bazel test //ryu/... //src/... 66 | ``` 67 | 68 | ### Big-Endian Architectures 69 | The C implementation of Ryu should work on big-endian architectures provided 70 | that the floating point type and the corresponding integer type use the same 71 | endianness. 72 | 73 | There are no concerns around endianness for the Java implementation. 74 | 75 | ### Computing Required Lookup Table Sizes 76 | You can compute the required lookup table sizes with: 77 | ``` 78 | $ bazel run //src/main/java/info/adams/ryu/analysis:ComputeTableSizes -- 79 | ``` 80 | 81 | Add `-v` to get slightly more verbose output. 82 | 83 | ### Computing Required Bit Sizes 84 | You can compute the required bit sizes with: 85 | ``` 86 | $ bazel run //src/main/java/info/adams/ryu/analysis:ComputeRequiredBitSizes -- 87 | ``` 88 | 89 | Add the `-128` and `-256` flags to also cover 128- and 256-bit numbers. This 90 | could take a while - 128-bit takes ~20 seconds on my machine while 256-bit takes 91 | a few hours. Add `-v` to get very verbose output. 92 | 93 | ### Java: Comparing All Possible 32-bit Values Exhaustively 94 | You can check the slow vs. the fast implementation for all 32-bit floating point 95 | numbers using: 96 | ``` 97 | $ bazel run //src/main/java/info/adams/ryu/analysis:ExhaustiveFloatComparison 98 | ``` 99 | 100 | This takes ~60 hours to run to completion on an 101 | Intel(R) Core(TM) i7-4770K with 3.50GHz. 102 | 103 | ### Java: Comparing All Possible 64-bit Values Exhaustively 104 | You can check the slow vs. the fast implementation for all 64-bit floating point 105 | numbers using: 106 | ``` 107 | $ bazel run //src/main/java/info/adams/ryu/analysis:ExtensiveDoubleComparison 108 | ``` 109 | 110 | However, this takes approximately forever, so you will need to interrupt the 111 | program. 112 | 113 | ### Benchmarks 114 | We provide both C and Java benchmark programs. 115 | 116 | Enable optimization by adding "-c opt" on the command line: 117 | ``` 118 | $ bazel run -c opt //ryu/benchmark -- 119 | Average & Stddev Ryu Average & Stddev Grisu3 120 | 32: 22.515 1.578 90.981 41.455 121 | 64: 27.545 1.677 98.981 80.797 122 | 123 | $ bazel run //src/main/java/info/adams/ryu/benchmark -- 124 | Average & Stddev Ryu Average & Stddev Jdk Average & Stddev Jaffer 125 | 32: 56.680 9.127 254.903 170.099 126 | 64: 89.751 13.442 1085.596 302.371 1089.535 309.245 127 | ``` 128 | 129 | Additional parameters can be passed to the benchmark after the `--` parameter: 130 | ``` 131 | -32 only run the 32-bit benchmark 132 | -64 only run the 64-bit benchmark 133 | -samples=n run n pseudo-randomly selected numbers 134 | -iterations=n run each number n times 135 | -v generate verbose output in CSV format 136 | ``` 137 | 138 | If you have gnuplot installed, you can generate plots from the benchmark data 139 | with: 140 | ``` 141 | $ bazel build --jobs=1 //scripts:{c,java}-{float,double}.pdf 142 | ``` 143 | 144 | The resulting files are `bazel-genfiles/scripts/{c,java}-{float,double}.pdf`. 145 | 146 | ### Building without Bazel on Linux / MacOS 147 | You can build and run the C benchmark without using Bazel with the following shell 148 | command: 149 | ``` 150 | $ gcc -o benchmark -I. -O2 -l m -l stdc++ ryu/*.c ryu/benchmark/benchmark.cc \ 151 | third_party/double-conversion/double-conversion/*.cc 152 | $ ./benchmark 153 | ``` 154 | 155 | You can build and run the Java benchmark with the following shell command: 156 | ``` 157 | $ mkdir out 158 | $ javac -d out \ 159 | -sourcepath src/main/java/:third_party/mersenne_java/java/:third_party/jaffer/java/ \ 160 | src/main/java/info/adams/ryu/benchmark/BenchmarkMain.java 161 | $ java -cp out info.adams.ryu.benchmark.BenchmarkMain 162 | ``` 163 | 164 | ## Comparison with Other Implementations 165 | 166 | ### Grisu3 167 | 168 | Ryu's output should exactly match Grisu3's output. Our benchmark verifies that 169 | the generated numbers are identical. 170 | ``` 171 | $ bazel run -c opt //ryu/benchmark -- -64 172 | Average & Stddev Ryu Average & Stddev Grisu3 173 | 64: 29.806 3.182 103.060 98.717 174 | ``` 175 | 176 | ### Jaffer's Implementation 177 | The code given by Jaffer in the original paper does not come with a license 178 | declaration. Instead, we're using code found on GitHub, which contains a 179 | license declaration by Jaffer. Compared to the original code, this 180 | implementation no longer outputs incorrect values for negative numbers. 181 | 182 | ### Differences between Ryu and Jaffer / Jdk implementations 183 | We provide a binary to find differences between Ryu and the Jaffer / Jdk 184 | implementations: 185 | ``` 186 | $ bazel run //src/main/java/info/adams/ryu/analysis:FindDifferences -- 187 | ``` 188 | 189 | Add the `-mode=csv` option to get all the discovered differences as a CSV. Use 190 | `-mode=latex` instead to get a latex snippet of the first 20. Use 191 | `-mode=summary` to only print the number of discovered differences (this is the 192 | default mode). 193 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/timers.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "timers.h" 16 | #include "internal_macros.h" 17 | 18 | #ifdef BENCHMARK_OS_WINDOWS 19 | #include 20 | #undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA 21 | #include 22 | #include 23 | #else 24 | #include 25 | #ifndef BENCHMARK_OS_FUCHSIA 26 | #include 27 | #endif 28 | #include 29 | #include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD 30 | #include 31 | #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX 32 | #include 33 | #endif 34 | #if defined(BENCHMARK_OS_MACOSX) 35 | #include 36 | #include 37 | #include 38 | #endif 39 | #endif 40 | 41 | #ifdef BENCHMARK_OS_EMSCRIPTEN 42 | #include 43 | #endif 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #include "check.h" 56 | #include "log.h" 57 | #include "sleep.h" 58 | #include "string_util.h" 59 | 60 | namespace benchmark { 61 | 62 | // Suppress unused warnings on helper functions. 63 | #if defined(__GNUC__) 64 | #pragma GCC diagnostic ignored "-Wunused-function" 65 | #endif 66 | 67 | namespace { 68 | #if defined(BENCHMARK_OS_WINDOWS) 69 | double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) { 70 | ULARGE_INTEGER kernel; 71 | ULARGE_INTEGER user; 72 | kernel.HighPart = kernel_time.dwHighDateTime; 73 | kernel.LowPart = kernel_time.dwLowDateTime; 74 | user.HighPart = user_time.dwHighDateTime; 75 | user.LowPart = user_time.dwLowDateTime; 76 | return (static_cast(kernel.QuadPart) + 77 | static_cast(user.QuadPart)) * 78 | 1e-7; 79 | } 80 | #elif !defined(BENCHMARK_OS_FUCHSIA) 81 | double MakeTime(struct rusage const& ru) { 82 | return (static_cast(ru.ru_utime.tv_sec) + 83 | static_cast(ru.ru_utime.tv_usec) * 1e-6 + 84 | static_cast(ru.ru_stime.tv_sec) + 85 | static_cast(ru.ru_stime.tv_usec) * 1e-6); 86 | } 87 | #endif 88 | #if defined(BENCHMARK_OS_MACOSX) 89 | double MakeTime(thread_basic_info_data_t const& info) { 90 | return (static_cast(info.user_time.seconds) + 91 | static_cast(info.user_time.microseconds) * 1e-6 + 92 | static_cast(info.system_time.seconds) + 93 | static_cast(info.system_time.microseconds) * 1e-6); 94 | } 95 | #endif 96 | #if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID) 97 | double MakeTime(struct timespec const& ts) { 98 | return ts.tv_sec + (static_cast(ts.tv_nsec) * 1e-9); 99 | } 100 | #endif 101 | 102 | BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) { 103 | std::cerr << "ERROR: " << msg << std::endl; 104 | std::exit(EXIT_FAILURE); 105 | } 106 | 107 | } // end namespace 108 | 109 | double ProcessCPUUsage() { 110 | #if defined(BENCHMARK_OS_WINDOWS) 111 | HANDLE proc = GetCurrentProcess(); 112 | FILETIME creation_time; 113 | FILETIME exit_time; 114 | FILETIME kernel_time; 115 | FILETIME user_time; 116 | if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time, 117 | &user_time)) 118 | return MakeTime(kernel_time, user_time); 119 | DiagnoseAndExit("GetProccessTimes() failed"); 120 | #elif defined(BENCHMARK_OS_EMSCRIPTEN) 121 | // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten. 122 | // Use Emscripten-specific API. Reported CPU time would be exactly the 123 | // same as total time, but this is ok because there aren't long-latency 124 | // syncronous system calls in Emscripten. 125 | return emscripten_get_now() * 1e-3; 126 | #elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX) 127 | // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See 128 | // https://github.com/google/benchmark/pull/292 129 | struct timespec spec; 130 | if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0) 131 | return MakeTime(spec); 132 | DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed"); 133 | #else 134 | struct rusage ru; 135 | if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru); 136 | DiagnoseAndExit("getrusage(RUSAGE_SELF, ...) failed"); 137 | #endif 138 | } 139 | 140 | double ThreadCPUUsage() { 141 | #if defined(BENCHMARK_OS_WINDOWS) 142 | HANDLE this_thread = GetCurrentThread(); 143 | FILETIME creation_time; 144 | FILETIME exit_time; 145 | FILETIME kernel_time; 146 | FILETIME user_time; 147 | GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time, 148 | &user_time); 149 | return MakeTime(kernel_time, user_time); 150 | #elif defined(BENCHMARK_OS_MACOSX) 151 | // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See 152 | // https://github.com/google/benchmark/pull/292 153 | mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; 154 | thread_basic_info_data_t info; 155 | mach_port_t thread = pthread_mach_thread_np(pthread_self()); 156 | if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count) == 157 | KERN_SUCCESS) { 158 | return MakeTime(info); 159 | } 160 | DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info"); 161 | #elif defined(BENCHMARK_OS_EMSCRIPTEN) 162 | // Emscripten doesn't support traditional threads 163 | return ProcessCPUUsage(); 164 | #elif defined(BENCHMARK_OS_RTEMS) 165 | // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See 166 | // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c 167 | return ProcessCPUUsage(); 168 | #elif defined(BENCHMARK_OS_SOLARIS) 169 | struct rusage ru; 170 | if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru); 171 | DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed"); 172 | #elif defined(CLOCK_THREAD_CPUTIME_ID) 173 | struct timespec ts; 174 | if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts); 175 | DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed"); 176 | #else 177 | #error Per-thread timing is not available on your system. 178 | #endif 179 | } 180 | 181 | namespace { 182 | 183 | std::string DateTimeString(bool local) { 184 | typedef std::chrono::system_clock Clock; 185 | std::time_t now = Clock::to_time_t(Clock::now()); 186 | const std::size_t kStorageSize = 128; 187 | char storage[kStorageSize]; 188 | std::size_t written; 189 | 190 | if (local) { 191 | #if defined(BENCHMARK_OS_WINDOWS) 192 | written = 193 | std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now)); 194 | #else 195 | std::tm timeinfo; 196 | ::localtime_r(&now, &timeinfo); 197 | written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); 198 | #endif 199 | } else { 200 | #if defined(BENCHMARK_OS_WINDOWS) 201 | written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now)); 202 | #else 203 | std::tm timeinfo; 204 | ::gmtime_r(&now, &timeinfo); 205 | written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); 206 | #endif 207 | } 208 | CHECK(written < kStorageSize); 209 | ((void)written); // prevent unused variable in optimized mode. 210 | return std::string(storage); 211 | } 212 | 213 | } // end namespace 214 | 215 | std::string LocalDateTimeString() { return DateTimeString(true); } 216 | 217 | } // end namespace benchmark 218 | -------------------------------------------------------------------------------- /ext/google_benchmark/src/cycleclock.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | // CycleClock 3 | // A CycleClock tells you the current time in Cycles. The "time" 4 | // is actually time since power-on. This is like time() but doesn't 5 | // involve a system call and is much more precise. 6 | // 7 | // NOTE: Not all cpu/platform/kernel combinations guarantee that this 8 | // clock increments at a constant rate or is synchronized across all logical 9 | // cpus in a system. 10 | // 11 | // If you need the above guarantees, please consider using a different 12 | // API. There are efforts to provide an interface which provides a millisecond 13 | // granularity and implemented as a memory read. A memory read is generally 14 | // cheaper than the CycleClock for many architectures. 15 | // 16 | // Also, in some out of order CPU implementations, the CycleClock is not 17 | // serializing. So if you're trying to count at cycles granularity, your 18 | // data might be inaccurate due to out of order instruction execution. 19 | // ---------------------------------------------------------------------- 20 | 21 | #ifndef BENCHMARK_CYCLECLOCK_H_ 22 | #define BENCHMARK_CYCLECLOCK_H_ 23 | 24 | #include 25 | 26 | #include "benchmark/benchmark.h" 27 | #include "internal_macros.h" 28 | 29 | #if defined(BENCHMARK_OS_MACOSX) 30 | #include 31 | #endif 32 | // For MSVC, we want to use '_asm rdtsc' when possible (since it works 33 | // with even ancient MSVC compilers), and when not possible the 34 | // __rdtsc intrinsic, declared in . Unfortunately, in some 35 | // environments, and have conflicting 36 | // declarations of some other intrinsics, breaking compilation. 37 | // Therefore, we simply declare __rdtsc ourselves. See also 38 | // http://connect.microsoft.com/VisualStudio/feedback/details/262047 39 | #if defined(COMPILER_MSVC) && !defined(_M_IX86) 40 | extern "C" uint64_t __rdtsc(); 41 | #pragma intrinsic(__rdtsc) 42 | #endif 43 | 44 | #if !defined(BENCHMARK_OS_WINDOWS) || defined(BENCHMARK_OS_MINGW) 45 | #include 46 | #include 47 | #endif 48 | 49 | #ifdef BENCHMARK_OS_EMSCRIPTEN 50 | #include 51 | #endif 52 | 53 | namespace benchmark { 54 | // NOTE: only i386 and x86_64 have been well tested. 55 | // PPC, sparc, alpha, and ia64 are based on 56 | // http://peter.kuscsik.com/wordpress/?p=14 57 | // with modifications by m3b. See also 58 | // https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h 59 | namespace cycleclock { 60 | // This should return the number of cycles since power-on. Thread-safe. 61 | inline BENCHMARK_ALWAYS_INLINE int64_t Now() { 62 | #if defined(BENCHMARK_OS_MACOSX) 63 | // this goes at the top because we need ALL Macs, regardless of 64 | // architecture, to return the number of "mach time units" that 65 | // have passed since startup. See sysinfo.cc where 66 | // InitializeSystemInfo() sets the supposed cpu clock frequency of 67 | // macs to the number of mach time units per second, not actual 68 | // CPU clock frequency (which can change in the face of CPU 69 | // frequency scaling). Also note that when the Mac sleeps, this 70 | // counter pauses; it does not continue counting, nor does it 71 | // reset to zero. 72 | return mach_absolute_time(); 73 | #elif defined(BENCHMARK_OS_EMSCRIPTEN) 74 | // this goes above x86-specific code because old versions of Emscripten 75 | // define __x86_64__, although they have nothing to do with it. 76 | return static_cast(emscripten_get_now() * 1e+6); 77 | #elif defined(__i386__) 78 | int64_t ret; 79 | __asm__ volatile("rdtsc" : "=A"(ret)); 80 | return ret; 81 | #elif defined(__x86_64__) || defined(__amd64__) 82 | uint64_t low, high; 83 | __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); 84 | return (high << 32) | low; 85 | #elif defined(__powerpc__) || defined(__ppc__) 86 | // This returns a time-base, which is not always precisely a cycle-count. 87 | int64_t tbl, tbu0, tbu1; 88 | asm("mftbu %0" : "=r"(tbu0)); 89 | asm("mftb %0" : "=r"(tbl)); 90 | asm("mftbu %0" : "=r"(tbu1)); 91 | tbl &= -static_cast(tbu0 == tbu1); 92 | // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage) 93 | return (tbu1 << 32) | tbl; 94 | #elif defined(__sparc__) 95 | int64_t tick; 96 | asm(".byte 0x83, 0x41, 0x00, 0x00"); 97 | asm("mov %%g1, %0" : "=r"(tick)); 98 | return tick; 99 | #elif defined(__ia64__) 100 | int64_t itc; 101 | asm("mov %0 = ar.itc" : "=r"(itc)); 102 | return itc; 103 | #elif defined(COMPILER_MSVC) && defined(_M_IX86) 104 | // Older MSVC compilers (like 7.x) don't seem to support the 105 | // __rdtsc intrinsic properly, so I prefer to use _asm instead 106 | // when I know it will work. Otherwise, I'll use __rdtsc and hope 107 | // the code is being compiled with a non-ancient compiler. 108 | _asm rdtsc 109 | #elif defined(COMPILER_MSVC) 110 | return __rdtsc(); 111 | #elif defined(BENCHMARK_OS_NACL) 112 | // Native Client validator on x86/x86-64 allows RDTSC instructions, 113 | // and this case is handled above. Native Client validator on ARM 114 | // rejects MRC instructions (used in the ARM-specific sequence below), 115 | // so we handle it here. Portable Native Client compiles to 116 | // architecture-agnostic bytecode, which doesn't provide any 117 | // cycle counter access mnemonics. 118 | 119 | // Native Client does not provide any API to access cycle counter. 120 | // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday 121 | // because is provides nanosecond resolution (which is noticable at 122 | // least for PNaCl modules running on x86 Mac & Linux). 123 | // Initialize to always return 0 if clock_gettime fails. 124 | struct timespec ts = {0, 0}; 125 | clock_gettime(CLOCK_MONOTONIC, &ts); 126 | return static_cast(ts.tv_sec) * 1000000000 + ts.tv_nsec; 127 | #elif defined(__aarch64__) 128 | // System timer of ARMv8 runs at a different frequency than the CPU's. 129 | // The frequency is fixed, typically in the range 1-50MHz. It can be 130 | // read at CNTFRQ special register. We assume the OS has set up 131 | // the virtual timer properly. 132 | int64_t virtual_timer_value; 133 | asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); 134 | return virtual_timer_value; 135 | #elif defined(__ARM_ARCH) 136 | // V6 is the earliest arch that has a standard cyclecount 137 | // Native Client validator doesn't allow MRC instructions. 138 | #if (__ARM_ARCH >= 6) 139 | uint32_t pmccntr; 140 | uint32_t pmuseren; 141 | uint32_t pmcntenset; 142 | // Read the user mode perf monitor counter access permissions. 143 | asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren)); 144 | if (pmuseren & 1) { // Allows reading perfmon counters for user mode code. 145 | asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset)); 146 | if (pmcntenset & 0x80000000ul) { // Is it counting? 147 | asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); 148 | // The counter is set up to count every 64th cycle 149 | return static_cast(pmccntr) * 64; // Should optimize to << 6 150 | } 151 | } 152 | #endif 153 | struct timeval tv; 154 | gettimeofday(&tv, nullptr); 155 | return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; 156 | #elif defined(__mips__) 157 | // mips apparently only allows rdtsc for superusers, so we fall 158 | // back to gettimeofday. It's possible clock_gettime would be better. 159 | struct timeval tv; 160 | gettimeofday(&tv, nullptr); 161 | return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; 162 | #elif defined(__s390__) // Covers both s390 and s390x. 163 | // Return the CPU clock. 164 | uint64_t tsc; 165 | asm("stck %0" : "=Q"(tsc) : : "cc"); 166 | return tsc; 167 | #else 168 | // The soft failover to a generic implementation is automatic only for ARM. 169 | // For other platforms the developer is expected to make an attempt to create 170 | // a fast implementation and use generic version if nothing better is available. 171 | #error You need to define CycleTimer for your OS and CPU 172 | #endif 173 | } 174 | } // end namespace cycleclock 175 | } // end namespace benchmark 176 | 177 | #endif // BENCHMARK_CYCLECLOCK_H_ 178 | --------------------------------------------------------------------------------