From 38b5900fd2e9bac9f53fb36d6bb33748ce476d33 Mon Sep 17 00:00:00 2001 From: Samuel Longchamps Date: Mon, 18 Oct 2021 22:41:57 -0400 Subject: [PATCH 01/84] Added dual license option, proper copyright Fixed #115 --- LICENSE-APACHE | 4 ++-- LICENSE-MIT | 4 ++++ script/amalgamate.py | 50 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 79e5913..261eeb9 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -178,7 +178,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2020 The fast_float authors + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/LICENSE-MIT b/LICENSE-MIT index 31aa793..2fb2a37 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,3 +1,7 @@ +MIT License + +Copyright (c) 2021 The fast_float authors + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the diff --git a/script/amalgamate.py b/script/amalgamate.py index b360d99..c203b52 100644 --- a/script/amalgamate.py +++ b/script/amalgamate.py @@ -10,15 +10,25 @@ for filename in ['AUTHORS', 'CONTRIBUTORS']: text += '// fast_float by ' + line if filename == 'CONTRIBUTORS': text += '// with contributions from ' + line - processed_files[filename] = text + processed_files[filename] = text + '//\n' # licenses for filename in ['LICENSE-MIT', 'LICENSE-APACHE']: + lines = [] with open(filename) as f: - text = '' - for line in f: - text += '// ' + line - processed_files[filename] = text + lines = f.readlines() + + # Retrieve subset required for inclusion in source + if filename == 'LICENSE-APACHE': + lines = [ + ' Copyright 2021 The fast_float authors\n', + *lines[189:-1] + ] + + text = '' + for line in lines: + text += '// ' + line.strip() + '\n' + processed_files[filename] = text # code for filename in [ 'fast_float.h', 'float_common.h', 'ascii_number.h', @@ -29,20 +39,42 @@ for filename in [ 'fast_float.h', 'float_common.h', 'ascii_number.h', for line in f: if line.startswith('#include "'): continue text += line - processed_files[filename] = text + processed_files[filename] = '\n' + text # command line import argparse parser = argparse.ArgumentParser(description='Amalgamate fast_float.') -parser.add_argument('--license', default='MIT', help='choose license') +parser.add_argument('--license', default='DUAL', choices=['DUAL', 'MIT', 'APACHE'], help='choose license') parser.add_argument('--output', default='', help='output file (stdout if none') args = parser.parse_args() -text = '\n\n'.join([ +def license_content(license_arg): + result = [] + + if license_arg == 'DUAL': + result += [ + '// Licensed under the Apache License, Version 2.0, or the\n', + '// MIT License at your option. This file may not be copied,\n', + '// modified, or distributed except according to those terms.\n', + '//\n' + ] + + if license_arg in ('DUAL', 'MIT'): + result.append('// MIT License Notice\n//\n') + result.append(processed_files['LICENSE-MIT']) + result.append('//\n') + if license_arg in ('DUAL', 'APACHE'): + result.append('// Apache License (Version 2.0) Notice\n//\n') + result.append(processed_files['LICENSE-APACHE']) + result.append('//\n') + + return result + +text = ''.join([ processed_files['AUTHORS'], processed_files['CONTRIBUTORS'], - processed_files['LICENSE-' + args.license], + *license_content(args.license), processed_files['fast_float.h'], processed_files['float_common.h'], processed_files['ascii_number.h'], processed_files['fast_table.h'], processed_files['decimal_to_binary.h'], processed_files['bigint.h'], From b9861e419025698879d39936358d2c61a051603b Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 19 Oct 2021 14:45:19 -0400 Subject: [PATCH 02/84] Version 3.3 --- CMakeLists.txt | 2 +- LICENSE-APACHE | 13 +------------ script/amalgamate.py | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 819df4f..468f3ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.2.0 LANGUAGES CXX) +project(fast_float VERSION 3.3.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used") set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 261eeb9..26f4398 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -175,18 +175,7 @@ END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] + Copyright 2021 The fast_float authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/script/amalgamate.py b/script/amalgamate.py index c203b52..e18ead9 100644 --- a/script/amalgamate.py +++ b/script/amalgamate.py @@ -22,7 +22,7 @@ for filename in ['LICENSE-MIT', 'LICENSE-APACHE']: if filename == 'LICENSE-APACHE': lines = [ ' Copyright 2021 The fast_float authors\n', - *lines[189:-1] + *lines[179:-1] ] text = '' From d35368cae610b4edeec61cd41e4d2367a4d33f58 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 23 Oct 2021 18:04:22 -0400 Subject: [PATCH 03/84] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 059b9da..1e1c06d 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,8 @@ int main() { ## Relation With Other Work +The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). + The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). ## Users From 133099ab4e2b72173a7396e2c58505533ac0b643 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 30 Nov 2021 20:35:09 +0100 Subject: [PATCH 04/84] Fix #117: compilation warning with gcc 6.3.0 Fix the following warning: ``` /arrow/cpp/src/arrow/vendored/fast_float/digit_comparison.h:62:50: error: right shift count >= width of type [-Werror=shift-count-overflow] am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` --- include/fast_float/digit_comparison.h | 46 +++++++++------------------ include/fast_float/float_common.h | 33 +++++++++++++++++++ 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 7ffe874..3202718 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -44,40 +44,24 @@ fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) n // this converts a native floating-point number to an extended-precision float. template fastfloat_really_inline adjusted_mantissa to_extended(T value) noexcept { + using equiv_uint = typename binary_format::equiv_uint; + constexpr equiv_uint exponent_mask = binary_format::exponent_mask(); + constexpr equiv_uint mantissa_mask = binary_format::mantissa_mask(); + constexpr equiv_uint hidden_bit_mask = binary_format::hidden_bit_mask(); + adjusted_mantissa am; int32_t bias = binary_format::mantissa_explicit_bits() - binary_format::minimum_exponent(); - if (std::is_same::value) { - constexpr uint32_t exponent_mask = 0x7F800000; - constexpr uint32_t mantissa_mask = 0x007FFFFF; - constexpr uint64_t hidden_bit_mask = 0x00800000; - uint32_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } + equiv_uint bits; + ::memcpy(&bits, &value, sizeof(T)); + if ((bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = bits & mantissa_mask; } else { - constexpr uint64_t exponent_mask = 0x7FF0000000000000; - constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF; - constexpr uint64_t hidden_bit_mask = 0x0010000000000000; - uint64_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } + // normal + am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); + am.power2 -= bias; + am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; } return am; diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index c8e7e4f..9374cdf 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -5,6 +5,7 @@ #include #include #include +#include #if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \ @@ -219,6 +220,8 @@ constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}; template struct binary_format { + using equiv_uint = typename std::conditional::type; + static inline constexpr int mantissa_explicit_bits(); static inline constexpr int minimum_exponent(); static inline constexpr int infinite_power(); @@ -232,6 +235,9 @@ template struct binary_format { static inline constexpr int smallest_power_of_ten(); static inline constexpr T exact_power_of_ten(int64_t power); static inline constexpr size_t max_digits(); + static inline constexpr equiv_uint exponent_mask(); + static inline constexpr equiv_uint mantissa_mask(); + static inline constexpr equiv_uint hidden_bit_mask(); }; template <> inline constexpr int binary_format::mantissa_explicit_bits() { @@ -339,6 +345,33 @@ template <> inline constexpr size_t binary_format::max_digits() { return 114; } +template <> inline constexpr binary_format::equiv_uint + binary_format::exponent_mask() { + return 0x7F800000; +} +template <> inline constexpr binary_format::equiv_uint + binary_format::exponent_mask() { + return 0x7FF0000000000000; +} + +template <> inline constexpr binary_format::equiv_uint + binary_format::mantissa_mask() { + return 0x007FFFFF; +} +template <> inline constexpr binary_format::equiv_uint + binary_format::mantissa_mask() { + return 0x000FFFFFFFFFFFFF; +} + +template <> inline constexpr binary_format::equiv_uint + binary_format::hidden_bit_mask() { + return 0x00800000; +} +template <> inline constexpr binary_format::equiv_uint + binary_format::hidden_bit_mask() { + return 0x0010000000000000; +} + template fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) { uint64_t word = am.mantissa; From b7f9d6ca3980de0f47251921f307e88c894f6daa Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 30 Nov 2021 15:53:33 -0500 Subject: [PATCH 05/84] Version 3.4.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 468f3ea..d2c40bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.3.0 LANGUAGES CXX) +project(fast_float VERSION 3.4.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used") set(CMAKE_CXX_STANDARD_REQUIRED ON) From b15abc92382bc9c7e318d12d35ab8e17d4a941f7 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sun, 16 Jan 2022 21:04:50 -0500 Subject: [PATCH 06/84] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e1c06d..6fb947d 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ the command line help. You may directly download automatically generated single-header files: -https://github.com/fastfloat/fast_float/releases/download/v1.1.2/fast_float.h +https://github.com/fastfloat/fast_float/releases/download/v3.4.0/fast_float.h ## Credit From 1ccabed64ccbcc40cfa5bac41f9d6af818cc3217 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 18 Jan 2022 10:11:21 +0000 Subject: [PATCH 07/84] Fix deduction failure for std::min call This assumes that the literal `64` of type `int` has the same type as the `int32_t` typedef, which is never true for targets with 16-bit `int`, and isn't guaranteed to be true even with 32-bit `int`. --- include/fast_float/digit_comparison.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 3202718..77c710f 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -86,7 +86,7 @@ fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept if (-am.power2 >= mantissa_shift) { // have a denormal float int32_t shift = -am.power2 + 1; - cb(am, std::min(shift, 64)); + cb(am, std::min(shift, 64)); // check for round-up: if rounding-nearest carried us to the hidden bit. am.power2 = (am.mantissa < (uint64_t(1) << binary_format::mantissa_explicit_bits())) ? 0 : 1; return; From 61f48401886e3ef15cad09461d53318285870ca2 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 18 Jan 2022 10:17:01 +0000 Subject: [PATCH 08/84] Make endianness detection more portable The current check for endianness fails on platforms using newlib as the C library, because it provides not . This could be fixed by adding `|| defined(__NEWLIB__)` to the check for targets that provide (i.e. BSD-like targets). A more portable solution is to just check if the compiler has already defined the necessary macros (which is true for GCC and Clang and Intel, at least). Then no header is needed, and it works for platforms that aren't explicitly listed in the conditionals. --- include/fast_float/float_common.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 9374cdf..bb8580e 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -41,7 +41,9 @@ #define FASTFLOAT_VISUAL_STUDIO 1 #endif -#ifdef _WIN32 +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 #define FASTFLOAT_IS_BIG_ENDIAN 0 #else #if defined(__APPLE__) || defined(__FreeBSD__) From ca9be545c3e31676c019bbf0329c75a0f0bff267 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 2 Mar 2022 22:39:54 -0500 Subject: [PATCH 09/84] Trying to upgrade to vs17 --- .github/workflows/{vs16-arm-ci.yml => vs17-arm-ci.yml} | 4 ++-- .github/workflows/{vs16-ci.yml => vs17-ci.yml} | 8 ++++---- .../workflows/{vs16-clang-ci.yml => vs17-clang-ci.yml} | 8 ++++---- .github/workflows/{vs16-cxx20.yml => vs17-cxx20.yml} | 8 ++++---- 4 files changed, 14 insertions(+), 14 deletions(-) rename .github/workflows/{vs16-arm-ci.yml => vs17-arm-ci.yml} (91%) rename .github/workflows/{vs16-ci.yml => vs17-ci.yml} (85%) rename .github/workflows/{vs16-clang-ci.yml => vs17-clang-ci.yml} (79%) rename .github/workflows/{vs16-cxx20.yml => vs17-cxx20.yml} (77%) diff --git a/.github/workflows/vs16-arm-ci.yml b/.github/workflows/vs17-arm-ci.yml similarity index 91% rename from .github/workflows/vs16-arm-ci.yml rename to .github/workflows/vs17-arm-ci.yml index 7c69e38..956e280 100644 --- a/.github/workflows/vs16-arm-ci.yml +++ b/.github/workflows/vs17-arm-ci.yml @@ -1,10 +1,10 @@ -name: VS16-ARM-CI +name: VS17-ARM-CI on: [push, pull_request] jobs: ci: - name: windows-vs16 + name: windows-vs17 runs-on: windows-latest strategy: fail-fast: false diff --git a/.github/workflows/vs16-ci.yml b/.github/workflows/vs17-ci.yml similarity index 85% rename from .github/workflows/vs16-ci.yml rename to .github/workflows/vs17-ci.yml index fe40ddd..a10600f 100644 --- a/.github/workflows/vs16-ci.yml +++ b/.github/workflows/vs17-ci.yml @@ -1,17 +1,17 @@ -name: VS16-CI +name: VS17-CI on: [push, pull_request] jobs: ci: - name: windows-vs16 + name: windows-vs17 runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32} + - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout uses: actions/checkout@v2 diff --git a/.github/workflows/vs16-clang-ci.yml b/.github/workflows/vs17-clang-ci.yml similarity index 79% rename from .github/workflows/vs16-clang-ci.yml rename to .github/workflows/vs17-clang-ci.yml index a32c6b8..c5d5fa7 100644 --- a/.github/workflows/vs16-clang-ci.yml +++ b/.github/workflows/vs17-clang-ci.yml @@ -1,17 +1,17 @@ -name: VS16-CLANG-CI +name: VS17-CLANG-CI on: [push, pull_request] jobs: ci: - name: windows-vs16 + name: windows-vs17 runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32} + - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout uses: actions/checkout@v2 diff --git a/.github/workflows/vs16-cxx20.yml b/.github/workflows/vs17-cxx20.yml similarity index 77% rename from .github/workflows/vs16-cxx20.yml rename to .github/workflows/vs17-cxx20.yml index 3a77093..b2d747d 100644 --- a/.github/workflows/vs16-cxx20.yml +++ b/.github/workflows/vs17-cxx20.yml @@ -1,17 +1,17 @@ -name: VS16-CI C++20 +name: VS17-CI C++20 on: [push, pull_request] jobs: ci: - name: windows-vs16 + name: windows-vs17 runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32} + - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout uses: actions/checkout@v2 From 78edcbb9e22307bd17350d32cea8e7517b304843 Mon Sep 17 00:00:00 2001 From: Fargier Sylvain Date: Mon, 28 Feb 2022 18:37:58 +0100 Subject: [PATCH 10/84] python: set file encoding - on some containers LC_ALL is not set, python fallsback on ascii encoder, which fails on AUTHORS file --- script/amalgamate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/script/amalgamate.py b/script/amalgamate.py index e18ead9..a5377d7 100644 --- a/script/amalgamate.py +++ b/script/amalgamate.py @@ -3,7 +3,7 @@ processed_files = { } # authors for filename in ['AUTHORS', 'CONTRIBUTORS']: - with open(filename) as f: + with open(filename, encoding='utf8') as f: text = '' for line in f: if filename == 'AUTHORS': @@ -15,7 +15,7 @@ for filename in ['AUTHORS', 'CONTRIBUTORS']: # licenses for filename in ['LICENSE-MIT', 'LICENSE-APACHE']: lines = [] - with open(filename) as f: + with open(filename, encoding='utf8') as f: lines = f.readlines() # Retrieve subset required for inclusion in source @@ -34,7 +34,7 @@ for filename in ['LICENSE-MIT', 'LICENSE-APACHE']: for filename in [ 'fast_float.h', 'float_common.h', 'ascii_number.h', 'fast_table.h', 'decimal_to_binary.h', 'bigint.h', 'ascii_number.h', 'digit_comparison.h', 'parse_number.h']: - with open('include/fast_float/' + filename) as f: + with open('include/fast_float/' + filename, encoding='utf8') as f: text = '' for line in f: if line.startswith('#include "'): continue @@ -82,7 +82,7 @@ text = ''.join([ processed_files['parse_number.h']]) if args.output: - with open(args.output, 'wt') as f: + with open(args.output, 'wt', encoding='utf8') as f: f.write(text) else: print(text) From 17bcdcef02153bb0475d2bfceab583b5a09c72f8 Mon Sep 17 00:00:00 2001 From: Vitaly Zaitsev Date: Tue, 1 Mar 2022 17:08:03 +0100 Subject: [PATCH 11/84] Fixed installation on other than Ubuntu GNU/Linux distributions. Signed-off-by: Vitaly Zaitsev --- CMakeLists.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2c40bc..6c8f502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,24 +42,25 @@ if(MSVC_VERSION GREATER 1910) endif() +include(GNUInstallDirs) include(CMakePackageConfigHelpers) set(FASTFLOAT_VERSION_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfigVersion.cmake") set(FASTFLOAT_PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfig.cmake") -set(FASTFLOAT_INSTALL_DIR "share/FastFloat") +set(FASTFLOAT_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/FastFloat") write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) configure_package_config_file("cmake/config.cmake.in" "${FASTFLOAT_PROJECT_CONFIG}" - INSTALL_DESTINATION "${FASTFLOAT_INSTALL_DIR}") + INSTALL_DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") -install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/fast_float" DESTINATION "include") -install(FILES "${FASTFLOAT_PROJECT_CONFIG}" "${FASTFLOAT_VERSION_CONFIG}" DESTINATION "${FASTFLOAT_INSTALL_DIR}") -install(EXPORT ${PROJECT_NAME}-targets NAMESPACE FastFloat:: DESTINATION "${FASTFLOAT_INSTALL_DIR}") +install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/fast_float" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") +install(FILES "${FASTFLOAT_PROJECT_CONFIG}" "${FASTFLOAT_VERSION_CONFIG}" DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") +install(EXPORT ${PROJECT_NAME}-targets NAMESPACE FastFloat:: DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") install(TARGETS fast_float EXPORT ${PROJECT_NAME}-targets - RUNTIME DESTINATION bin - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) From 5738f189529c4064b113bf7eb61f09be6a48efe7 Mon Sep 17 00:00:00 2001 From: Vitaly Zaitsev Date: Sat, 5 Mar 2022 15:49:54 +0100 Subject: [PATCH 12/84] Export CMake targets as architecture independent. Signed-off-by: Vitaly Zaitsev --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c8f502..f3ab1be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,11 @@ set(FASTFLOAT_VERSION_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfig set(FASTFLOAT_PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfig.cmake") set(FASTFLOAT_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/FastFloat") -write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +if(${CMAKE_VERSION} VERSION_LESS "3.14") + write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +else() + write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) +endif() configure_package_config_file("cmake/config.cmake.in" "${FASTFLOAT_PROJECT_CONFIG}" INSTALL_DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") From b467215b4dae81db89afac8015f7d16fc1911862 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 19 Mar 2022 00:14:13 -0400 Subject: [PATCH 13/84] Update README.md --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 6fb947d..d0f86b5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,5 @@ ## fast_float number parsing library: 4x faster than strtod -![Ubuntu 20.04 CI (GCC 9)](https://github.com/lemire/fast_float/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg) -![Ubuntu 18.04 CI (GCC 7)](https://github.com/lemire/fast_float/workflows/Ubuntu%2018.04%20CI%20(GCC%207)/badge.svg) -![Alpine Linux](https://github.com/lemire/fast_float/workflows/Alpine%20Linux/badge.svg) -![MSYS2-CI](https://github.com/lemire/fast_float/workflows/MSYS2-CI/badge.svg) -![VS16-CLANG-CI](https://github.com/lemire/fast_float/workflows/VS16-CLANG-CI/badge.svg) -[![VS16-CI](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml/badge.svg)](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml) - The fast_float library provides fast header-only implementations for the C++ from_chars functions for `float` and `double` types. These functions convert ASCII strings representing decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including From 708224bc3eecd31b3cddb31556de6ce5f56a8340 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 19 Mar 2022 00:28:06 -0400 Subject: [PATCH 14/84] Dropping Windows 2016. --- .github/workflows/vs15-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/vs15-ci.yml b/.github/workflows/vs15-ci.yml index a6207a7..b611eed 100644 --- a/.github/workflows/vs15-ci.yml +++ b/.github/workflows/vs15-ci.yml @@ -8,7 +8,7 @@ jobs: ! contains(toJSON(github.event.commits.*.message), '[skip ci]') && ! contains(toJSON(github.event.commits.*.message), '[skip github]') name: windows-vs15 - runs-on: windows-2016 + runs-on: windows-latest strategy: fail-fast: false matrix: From 7a17c54269171fa858ae1e137b6218a2a12f6616 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 19 Mar 2022 00:29:57 -0400 Subject: [PATCH 15/84] Dropping it. --- .github/workflows/vs15-ci.yml | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 .github/workflows/vs15-ci.yml diff --git a/.github/workflows/vs15-ci.yml b/.github/workflows/vs15-ci.yml deleted file mode 100644 index b611eed..0000000 --- a/.github/workflows/vs15-ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: VS15-CI - -on: [push, pull_request] - -jobs: - ci: - if: >- - ! contains(toJSON(github.event.commits.*.message), '[skip ci]') && - ! contains(toJSON(github.event.commits.*.message), '[skip github]') - name: windows-vs15 - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - include: - - {gen: Visual Studio 15 2017, arch: Win32} - - {gen: Visual Studio 15 2017, arch: x64} - steps: - - uses: actions/checkout@v2 - - name: Configure - run: | - mkdir build - cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build --verbose --config Release --parallel - - name: 'Run CTest' - run: | - cd build - ctest -C Release --output-on-failure -R basictest \ No newline at end of file From f2082bf747eabc0873f2fdceb05f9451931b96dc Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 31 Mar 2022 10:18:12 -0400 Subject: [PATCH 16/84] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d0f86b5..7fe6bdd 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ The fastfloat algorithm is part of the [LLVM standard libraries](https://github. The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). +There is a [derived implementation part of AdaCore](https://github.com/AdaCore/VSS). + ## Users The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [Yandex ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet). From cfb44c259226086b5a9580a1cf4b0c3e8158b6d7 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 29 Jun 2022 14:05:21 -0400 Subject: [PATCH 17/84] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7fe6bdd..6337993 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,8 @@ int main() { ## Relation With Other Work +The fast_float library is part of GCC (as of version 12): the `from_chars` function in GCC relies on fast_float. + The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). From d797a3a05d2ef6a493145199728a5a365edc7b01 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 29 Jul 2022 11:42:20 -0400 Subject: [PATCH 18/84] Adding example. --- README.md | 72 ++++++++++++++++++++++++++++-------------- tests/basictest.cpp | 27 ++++++++++++++++ tests/example_test.cpp | 25 ++++++++++++++- 3 files changed, 100 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 6337993..92eb3a4 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ struct from_chars_result { ``` It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting -a locale-independent format equivalent to the C++17 from_chars function. -The resulting floating-point value is the closest floating-point values (using either float or double), +a locale-independent format equivalent to the C++17 from_chars function. +The resulting floating-point value is the closest floating-point values (using either float or double), using the "round to even" convention for values that would otherwise fall right in-between two values. That is, we provide exact parsing according to the IEEE standard. @@ -40,7 +40,7 @@ Example: ``` C++ #include "fast_float/fast_float.h" #include - + int main() { const std::string input = "3.1416 xyz "; double result; @@ -53,15 +53,15 @@ int main() { Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of -the type `fast_float::chars_format`. It is a bitset value: we check whether +the type `fast_float::chars_format`. It is a bitset value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set to determine whether we allow the fixed point and scientific notation respectively. The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. -The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification. +The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification. * The `from_chars` function does not skip leading white-space characters. * [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden. -* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers. +* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers. Furthermore, we have the following restrictions: * We only support `float` and `double` types at this time. @@ -76,16 +76,16 @@ We support Visual Studio, macOS, Linux, freeBSD. We support big and little endia The C++ standard stipulate that `from_chars` has to be locale-independent. In -particular, the decimal separator has to be the period (`.`). However, -some users still want to use the `fast_float` library with in a locale-dependent +particular, the decimal separator has to be the period (`.`). However, +some users still want to use the `fast_float` library with in a locale-dependent manner. Using a separate function called `from_chars_advanced`, we allow the users -to pass a `parse_options` instance which contains a custom decimal separator (e.g., +to pass a `parse_options` instance which contains a custom decimal separator (e.g., the comma). You may use it as follows. ```C++ #include "fast_float/fast_float.h" #include - + int main() { const std::string input = "3,1416 xyz "; double result; @@ -97,6 +97,32 @@ int main() { } ``` +You can parse delimited numbers: +```C++ + const std::string input = "234532.3426362,7869234.9823,324562.645"; + double result; + auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); + if(answer.ec != std::errc()) { + // check error + } + // we have result == 234532.3426362. + if(answer.ptr[0] != ',') { + // unexpected delimiter + } + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + if(answer.ec != std::errc()) { + // check error + } + // we have result == 7869234.9823. + if(answer.ptr[0] != ',') { + // unexpected delimiter + } + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + if(answer.ec != std::errc()) { + // check error + } + // we have result == 324562.645. +``` ## Reference @@ -114,7 +140,7 @@ int main() { The fast_float library is part of GCC (as of version 12): the `from_chars` function in GCC relies on fast_float. -The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). +The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). @@ -132,14 +158,14 @@ It can parse random floating-point numbers at a speed of 1 GB/s on some systems. ``` -$ ./build/benchmarks/benchmark +$ ./build/benchmarks/benchmark # parsing random integers in the range [0,1) -volume = 2.09808 MB -netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s -doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s -strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s -abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s -fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s +volume = 2.09808 MB +netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s +doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s +strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s +abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s +fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s ``` See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code. @@ -180,9 +206,9 @@ You should change the `GIT_TAG` line so that you recover the version you wish to ## Using as single header -The script `script/amalgamate.py` may be used to generate a single header +The script `script/amalgamate.py` may be used to generate a single header version of the library if so desired. -Just run the script from the root directory of this repository. +Just run the script from the root directory of this repository. You can customize the license type and output file if desired as described in the command line help. @@ -192,11 +218,11 @@ https://github.com/fastfloat/fast_float/releases/download/v3.4.0/fast_float.h ## Credit -Though this work is inspired by many different people, this work benefited especially from exchanges with -Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided +Though this work is inspired by many different people, this work benefited especially from exchanges with +Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits. -The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published +The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published under the Apache 2.0 license. ## License diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 1dd924e..d422aeb 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -224,6 +224,33 @@ TEST_CASE("decimal_point_parsing") { } } +TEST_CASE("issue19") { + const std::string input = "234532.3426362,7869234.9823,324562.645"; + double result; + auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); + CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 234532.3426362\n"); + CHECK_MESSAGE(answer.ptr == input.data() + 14, + "Parsed the number " << result + << " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters"); + CHECK_MESSAGE(result == 234532.3426362, "We want to parse234532.3426362\n"); + CHECK_MESSAGE(answer.ptr[0] == ',', "We want to parse up to the comma\n"); + + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse 7869234.9823\n"); + CHECK_MESSAGE(answer.ptr == input.data() + 27, + "Parsed the number " << result + << " and stopped at the wrong character " << (answer.ptr - input.data())); + CHECK_MESSAGE(answer.ptr[0] == ',', "We want to parse up to the comma\n"); + CHECK_MESSAGE(result == 7869234.9823, "We want to parse up 7869234.9823\n"); + + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse 324562.645\n"); + CHECK_MESSAGE(answer.ptr == input.data() + 38, + "Parsed the number " << result + << " and stopped at the wrong character " << (answer.ptr - input.data())); + CHECK_MESSAGE(result == 324562.645, "We want to parse up 7869234.9823\n"); +} + TEST_CASE("issue19") { const std::string input = "3.14e"; double result; diff --git a/tests/example_test.cpp b/tests/example_test.cpp index db1bae8..ab2556c 100644 --- a/tests/example_test.cpp +++ b/tests/example_test.cpp @@ -3,12 +3,35 @@ #include #include #include - + + +bool many() { + const std::string input = "234532.3426362,7869234.9823,324562.645"; + double result; + auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); + if(answer.ec != std::errc()) { return false; } + if(result != 234532.3426362) { return false; } + if(answer.ptr[0] != ',') { return false; } + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + if(answer.ec != std::errc()) { return false; } + if(result != 7869234.9823) { return false; } + if(answer.ptr[0] != ',') { return false; } + answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result); + if(answer.ec != std::errc()) { return false; } + if(result != 324562.645) { return false; } + return true; +} + int main() { const std::string input = "3.1416 xyz "; double result; auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } std::cout << "parsed the number " << result << std::endl; + + if(!many()) { + printf("Bug\n"); + return EXIT_FAILURE; + } return EXIT_SUCCESS; } From a332ec1ca7826d727af9c01568803a054865bc0a Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 29 Jul 2022 11:54:19 -0400 Subject: [PATCH 19/84] Saving. --- tests/example_test.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/example_test.cpp b/tests/example_test.cpp index ab2556c..f2a0bce 100644 --- a/tests/example_test.cpp +++ b/tests/example_test.cpp @@ -22,6 +22,27 @@ bool many() { return true; } + +void many_loop() { + const std::string input = "234532.3426362,7869234.9823,324562.645"; + double result; + const char* pointer = input.data(); + const char* end_pointer = input.data() + input.size(); + + while(pointer < end_pointer) { + auto answer = fast_float::from_chars(pointer, end_pointer, result); + if(answer.ec != std::errc()) { + std::cerr << "error while parsing" << std::endl; + break; + } + std::cout << "parsed: " << result << std::endl; + pointer = answer.ptr; + if ((answer.ptr < end_pointer) && (*pointer == ',')) { + pointer++; + } + } +} + int main() { const std::string input = "3.1416 xyz "; double result; @@ -33,5 +54,6 @@ int main() { printf("Bug\n"); return EXIT_FAILURE; } + many_loop(); return EXIT_SUCCESS; } From ac81b016967970dddf0419eb65f1ab50a5d6d79b Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 4 Aug 2022 13:58:48 -0400 Subject: [PATCH 20/84] Added __EMSCRIPTEN__ patch --- include/fast_float/float_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index bb8580e..d11a3fa 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -16,7 +16,7 @@ #define FASTFLOAT_64BIT #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ || defined(__arm__) || defined(_M_ARM) \ - || defined(__MINGW32__)) + || defined(__MINGW32__) || defined(__EMSCRIPTEN__)) #define FASTFLOAT_32BIT #else // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. From 6876616f0f6e69534b42ff0524fd616b56116736 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 4 Aug 2022 15:05:22 -0400 Subject: [PATCH 21/84] Update float_common.h --- include/fast_float/float_common.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index d11a3fa..55a2e4c 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -11,8 +11,7 @@ || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \ || defined(__MINGW64__) \ || defined(__s390x__) \ - || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) \ - || defined(__EMSCRIPTEN__)) + || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) ) #define FASTFLOAT_64BIT #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ || defined(__arm__) || defined(_M_ARM) \ From d4dd12f8cfd92bff0837304bf26132fe19b66236 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 12 Aug 2022 11:36:35 -0400 Subject: [PATCH 22/84] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92eb3a4..5e6cd91 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ You can parse delimited numbers: - [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called `rcppfastfloat`. - [There is a Rust port of the fast_float library](https://github.com/aldanor/fast-float-rust/) called `fast-float-rust`. -- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`. +- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`. It used for important systems such as [Jackson](https://github.com/FasterXML/jackson-core). - [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`. From 3fddb895081368748545be14901941220c81f60d Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 30 Aug 2022 22:55:34 +0200 Subject: [PATCH 23/84] Fix some typos --- README.md | 2 +- include/fast_float/fast_float.h | 2 +- tests/basictest.cpp | 2 +- tests/exhaustive32_midpoint.cpp | 2 +- tests/string_test.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5e6cd91..7a2ded5 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ You can parse delimited numbers: ## Reference -- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Pratice and Experience 51 (8), 2021. +- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021. ## Other programming languages diff --git a/include/fast_float/fast_float.h b/include/fast_float/fast_float.h index 3c48380..ad3093e 100644 --- a/include/fast_float/fast_float.h +++ b/include/fast_float/fast_float.h @@ -44,7 +44,7 @@ struct parse_options { * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of * the type `fast_float::chars_format`. It is a bitset value: we check whether * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set - * to determine whether we allowe the fixed point and scientific notation respectively. + * to determine whether we allow the fixed point and scientific notation respectively. * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. */ template diff --git a/tests/basictest.cpp b/tests/basictest.cpp index d422aeb..cef34db 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -50,7 +50,7 @@ #include #include -// return true on succcess +// return true on success bool check_file(std::string file_name) { std::cout << "Checking " << file_name << std::endl; size_t number{0}; diff --git a/tests/exhaustive32_midpoint.cpp b/tests/exhaustive32_midpoint.cpp index f64f4e4..fdfd25d 100644 --- a/tests/exhaustive32_midpoint.cpp +++ b/tests/exhaustive32_midpoint.cpp @@ -132,7 +132,7 @@ bool allvalues() { inline void Assert(bool Assertion) { #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; } + if (!Assertion) { std::cerr << "Omitting hard failure on msys/cygwin/sun systems."; } #else if (!Assertion) { throw std::runtime_error("bug"); } #endif diff --git a/tests/string_test.cpp b/tests/string_test.cpp index 05871db..78da51e 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -44,8 +44,8 @@ float cygwin_strtof_l(const char* start, char** end) { inline void Assert(bool Assertion) { #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; } -#else + if (!Assertion) { std::cerr << "Omitting hard failure on msys/cygwin/sun systems."; } +#else if (!Assertion) { throw std::runtime_error("bug"); } #endif } From 3aaf22e14ddc02f2a0984e8452c679033f78d187 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 30 Aug 2022 23:03:10 +0200 Subject: [PATCH 24/84] update actions/checkout in GitHub Actions to v3 --- .github/workflows/alpine.yml | 4 ++-- .github/workflows/amalgamate-ubuntu20.yml | 2 +- .github/workflows/msys2-clang.yml | 2 +- .github/workflows/msys2.yml | 2 +- .github/workflows/ubuntu18.yml | 2 +- .github/workflows/ubuntu20-cxx20.yml | 2 +- .github/workflows/ubuntu20.yml | 2 +- .github/workflows/vs17-arm-ci.yml | 4 ++-- .github/workflows/vs17-ci.yml | 4 ++-- .github/workflows/vs17-clang-ci.yml | 2 +- .github/workflows/vs17-cxx20.yml | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/alpine.yml b/.github/workflows/alpine.yml index 8259376..459008a 100644 --- a/.github/workflows/alpine.yml +++ b/.github/workflows/alpine.yml @@ -6,7 +6,7 @@ jobs: ubuntu-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: start docker run: | docker run -w /src -dit --name alpine -v $PWD:/src alpine:latest @@ -24,4 +24,4 @@ jobs: ./alpine.sh cmake --build build_for_alpine - name: test run: | - ./alpine.sh bash -c "cd build_for_alpine && ctest -R basictest" \ No newline at end of file + ./alpine.sh bash -c "cd build_for_alpine && ctest -R basictest" diff --git a/.github/workflows/amalgamate-ubuntu20.yml b/.github/workflows/amalgamate-ubuntu20.yml index 3d47714..14b8902 100644 --- a/.github/workflows/amalgamate-ubuntu20.yml +++ b/.github/workflows/amalgamate-ubuntu20.yml @@ -14,7 +14,7 @@ jobs: - {cxx: , arch: } # default=gcc9 #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Compile with amalgamation run: | mkdir build && diff --git a/.github/workflows/msys2-clang.yml b/.github/workflows/msys2-clang.yml index ba16f43..19772cc 100644 --- a/.github/workflows/msys2-clang.yml +++ b/.github/workflows/msys2-clang.yml @@ -23,7 +23,7 @@ jobs: CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: update: true diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 665c539..a44cfe2 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -29,7 +29,7 @@ jobs: CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: msys2/setup-msys2@v2 with: update: true diff --git a/.github/workflows/ubuntu18.yml b/.github/workflows/ubuntu18.yml index dbdaa7a..63a1455 100644 --- a/.github/workflows/ubuntu18.yml +++ b/.github/workflows/ubuntu18.yml @@ -15,7 +15,7 @@ jobs: - {cxx: , arch: } # default=gcc7 #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc7 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup cmake uses: jwlawson/actions-setup-cmake@v1.4 with: diff --git a/.github/workflows/ubuntu20-cxx20.yml b/.github/workflows/ubuntu20-cxx20.yml index a8b9acb..debb13b 100644 --- a/.github/workflows/ubuntu20-cxx20.yml +++ b/.github/workflows/ubuntu20-cxx20.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use cmake run: | mkdir build && diff --git a/.github/workflows/ubuntu20.yml b/.github/workflows/ubuntu20.yml index ebd8b23..2704c85 100644 --- a/.github/workflows/ubuntu20.yml +++ b/.github/workflows/ubuntu20.yml @@ -14,7 +14,7 @@ jobs: - {cxx: , arch: } # default=gcc9 #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use cmake run: | mkdir build && diff --git a/.github/workflows/vs17-arm-ci.yml b/.github/workflows/vs17-arm-ci.yml index 956e280..7e0ec0b 100644 --- a/.github/workflows/vs17-arm-ci.yml +++ b/.github/workflows/vs17-arm-ci.yml @@ -14,8 +14,8 @@ jobs: - {arch: ARM64} steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Use cmake run: | cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DFASTFLOAT_TEST=ON -B build && - cmake --build build --verbose \ No newline at end of file + cmake --build build --verbose diff --git a/.github/workflows/vs17-ci.yml b/.github/workflows/vs17-ci.yml index a10600f..68e5ce1 100644 --- a/.github/workflows/vs17-ci.yml +++ b/.github/workflows/vs17-ci.yml @@ -14,7 +14,7 @@ jobs: - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Use cmake run: | mkdir build && @@ -26,4 +26,4 @@ jobs: cd ../tests/installation_tests/find && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose cd ../../issue72_installation && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose \ No newline at end of file + mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose diff --git a/.github/workflows/vs17-clang-ci.yml b/.github/workflows/vs17-clang-ci.yml index c5d5fa7..e116e72 100644 --- a/.github/workflows/vs17-clang-ci.yml +++ b/.github/workflows/vs17-clang-ci.yml @@ -14,7 +14,7 @@ jobs: - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Configure run: | mkdir build diff --git a/.github/workflows/vs17-cxx20.yml b/.github/workflows/vs17-cxx20.yml index b2d747d..8eca7db 100644 --- a/.github/workflows/vs17-cxx20.yml +++ b/.github/workflows/vs17-cxx20.yml @@ -14,7 +14,7 @@ jobs: - {gen: Visual Studio 17 2022, arch: x64} steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Use cmake run: | mkdir build && From 3c1190cd85bc3ef2143941cca7e5e3cfddf46b03 Mon Sep 17 00:00:00 2001 From: Olivier Le Doeuff Date: Mon, 26 Sep 2022 11:34:30 +0200 Subject: [PATCH 25/84] =?UTF-8?q?=F0=9F=94=A8=20Introduce=20FASTFLOAT=5FIN?= =?UTF-8?q?STALL=20to=20make=20install=20optional?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using fast_float as a PRIVATE dependency, it is not required to install it. This flag give user using fastfloat with add_subdirectory the opportunity to disable install target Default behavior is conserved since FASTFLOAT_INSTALL is ON --- CMakeLists.txt | 54 ++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3ab1be..d56c4d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,13 +22,18 @@ if (NOT CMAKE_BUILD_TYPE) endif() endif() +option(FASTFLOAT_INSTALL "Enable install" ON) + +if(FASTFLOAT_INSTALL) + include(GNUInstallDirs) +endif() add_library(fast_float INTERFACE) target_include_directories( fast_float INTERFACE $ - $ + $ ) if(FASTFLOAT_SANITIZE) target_compile_options(fast_float INTERFACE -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all) @@ -42,29 +47,30 @@ if(MSVC_VERSION GREATER 1910) endif() -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) +if(FASTFLOAT_INSTALL) + include(CMakePackageConfigHelpers) -set(FASTFLOAT_VERSION_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfigVersion.cmake") -set(FASTFLOAT_PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfig.cmake") -set(FASTFLOAT_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/FastFloat") + set(FASTFLOAT_VERSION_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfigVersion.cmake") + set(FASTFLOAT_PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/module/FastFloatConfig.cmake") + set(FASTFLOAT_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/FastFloat") -if(${CMAKE_VERSION} VERSION_LESS "3.14") - write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) -else() - write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) + if(${CMAKE_VERSION} VERSION_LESS "3.14") + write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) + else() + write_basic_package_version_file("${FASTFLOAT_VERSION_CONFIG}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) + endif() + configure_package_config_file("cmake/config.cmake.in" + "${FASTFLOAT_PROJECT_CONFIG}" + INSTALL_DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") + + install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/fast_float" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(FILES "${FASTFLOAT_PROJECT_CONFIG}" "${FASTFLOAT_VERSION_CONFIG}" DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") + install(EXPORT ${PROJECT_NAME}-targets NAMESPACE FastFloat:: DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") + + install(TARGETS fast_float + EXPORT ${PROJECT_NAME}-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) endif() -configure_package_config_file("cmake/config.cmake.in" - "${FASTFLOAT_PROJECT_CONFIG}" - INSTALL_DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") - -install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/fast_float" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") -install(FILES "${FASTFLOAT_PROJECT_CONFIG}" "${FASTFLOAT_VERSION_CONFIG}" DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") -install(EXPORT ${PROJECT_NAME}-targets NAMESPACE FastFloat:: DESTINATION "${FASTFLOAT_CONFIG_INSTALL_DIR}") - -install(TARGETS fast_float - EXPORT ${PROJECT_NAME}-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) From 696f5299f02f76dee42fc796b94bb0ec3b63c941 Mon Sep 17 00:00:00 2001 From: Olivier Le Doeuff Date: Mon, 26 Sep 2022 11:39:13 +0200 Subject: [PATCH 26/84] =?UTF-8?q?=F0=9F=94=A8=20Don't=20write=20to=20globa?= =?UTF-8?q?l=20CMAKE=5FCXX=5FSTANDARD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead use modern target_compile_features with cxx_std_11 --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3ab1be..c5dff77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.9) project(fast_float VERSION 3.4.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) -set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used") -set(CMAKE_CXX_STANDARD_REQUIRED ON) if(FASTFLOAT_TEST) enable_testing() add_subdirectory(tests) @@ -30,6 +28,7 @@ target_include_directories( $ $ ) +target_compile_features(fast_float INTERFACE cxx_std_11) if(FASTFLOAT_SANITIZE) target_compile_options(fast_float INTERFACE -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all) target_link_libraries(fast_float INTERFACE -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all) From ab406c7c0b6346afdeb831f01562bd21260967b5 Mon Sep 17 00:00:00 2001 From: Olivier Le Doeuff Date: Mon, 26 Sep 2022 11:44:15 +0200 Subject: [PATCH 27/84] =?UTF-8?q?=F0=9F=94=A8=20add=20library=20ALIAS=20Fa?= =?UTF-8?q?stFloat::fast=5Ffloat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This give same target name if library is found with find_package, or added via add_subdirectory --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3ab1be..c09620b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ endif() add_library(fast_float INTERFACE) +add_library(FastFloat::fast_float ALIAS fast_float) target_include_directories( fast_float INTERFACE From b4d7cceb9322972ab1c53095d195d096b2e335d0 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sun, 2 Oct 2022 11:09:08 -0400 Subject: [PATCH 28/84] Added a couple of tests. --- tests/basictest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/basictest.cpp b/tests/basictest.cpp index cef34db..273c2c6 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -481,6 +481,7 @@ TEST_CASE("64bit.inf") { } TEST_CASE("64bit.general") { + verify("-1e-999",-0.0); verify("-2.2222222222223e-322",-0x1.68p-1069); verify("9007199254740993.0", 0x1p+53); verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328); @@ -615,6 +616,7 @@ TEST_CASE("32bit.inf") { } TEST_CASE("32bit.general") { + verify("-1e-999",-0.0f); verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f); verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f); verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f); From 5a71e5bc40b1faf6fdde57078faef0c8f120d7cd Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Fri, 28 Oct 2022 15:33:37 +0900 Subject: [PATCH 29/84] Don't use __umulh() with MinGW on ARM64 --- include/fast_float/float_common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 55a2e4c..2272518 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -183,8 +183,9 @@ fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd, fastfloat_really_inline value128 full_multiplication(uint64_t a, uint64_t b) { value128 answer; -#ifdef _M_ARM64 +#if defined(_M_ARM64) && !defined(__MINGW32__) // ARM64 has native support for 64-bit multiplications, no need to emulate + // But MinGW on ARM64 doesn't have native support for 64-bit multiplications answer.high = __umulh(a, b); answer.low = a * b; #elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__)) From c56e5954385109dfa69cdbb48443a4da83d138e1 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 2 Nov 2022 12:40:09 -0400 Subject: [PATCH 30/84] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a2ded5..d6ae279 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Furthermore, we have the following restrictions: We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems. - +We assume that the rounding mode is set to nearest (`std::fegetround() == FE_TONEAREST`). ## Using commas as decimal separator From e958ff4269ab0f0223f4fe2fe17d9a563e1c469c Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 3 Nov 2022 18:51:37 -0400 Subject: [PATCH 31/84] Simplified clinger. --- include/fast_float/float_common.h | 81 ++++++++++++++----- include/fast_float/parse_number.h | 7 +- .../fast_float/simple_decimal_conversion.h | 4 +- tests/CMakeLists.txt | 2 + 4 files changed, 67 insertions(+), 27 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 2272518..7f14914 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -221,6 +221,55 @@ constexpr static double powers_of_ten_double[] = { constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}; +// Largest integer value v so that (5**index * v) <= 1<<53. +// 0x10000000000000 == 1 << 53 +constexpr static uint64_t max_mantissa_double[] = { + 0x10000000000000, + 0x10000000000000 / 5, + 0x10000000000000 / (5 * 5), + 0x10000000000000 / (5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5 * 5 * 5 * 5 * 5), + 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * + 5 * 5 * 5 * 5 * 5 * 5)}; + // Largest integer value v so that (5**index * v) <= 1<<24. + // 0x1000000 == 1<<24 + constexpr static uint64_t max_mantissa_float[] = { + 0x1000000, + 0x1000000 / 5, + 0x1000000 / (5 * 5), + 0x1000000 / (5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5)}; + template struct binary_format { using equiv_uint = typename std::conditional::type; @@ -228,11 +277,10 @@ template struct binary_format { static inline constexpr int minimum_exponent(); static inline constexpr int infinite_power(); static inline constexpr int sign_index(); - static inline constexpr int min_exponent_fast_path(); static inline constexpr int max_exponent_fast_path(); static inline constexpr int max_exponent_round_to_even(); static inline constexpr int min_exponent_round_to_even(); - static inline constexpr uint64_t max_mantissa_fast_path(); + static inline constexpr uint64_t max_mantissa_fast_path(int64_t power); static inline constexpr int largest_power_of_ten(); static inline constexpr int smallest_power_of_ten(); static inline constexpr T exact_power_of_ten(int64_t power); @@ -282,21 +330,6 @@ template <> inline constexpr int binary_format::infinite_power() { template <> inline constexpr int binary_format::sign_index() { return 63; } template <> inline constexpr int binary_format::sign_index() { return 31; } -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -22; -#endif -} -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -10; -#endif -} - template <> inline constexpr int binary_format::max_exponent_fast_path() { return 22; } @@ -304,11 +337,17 @@ template <> inline constexpr int binary_format::max_exponent_fast_path() return 10; } -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); +template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 22 + // + return max_mantissa_double[power]; } -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); +template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 10 + // + return max_mantissa_float[power]; } template <> diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 62ae3b0..8789475 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -87,11 +87,10 @@ from_chars_result from_chars_advanced(const char *first, const char *last, } answer.ec = std::errc(); // be optimistic answer.ptr = pns.lastmatch; - // Next is Clinger's fast path. - if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal + if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { value = T(pns.mantissa); - if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } - else { value = value * binary_format::exact_power_of_ten(pns.exponent); } + value = value * binary_format::exact_power_of_ten(pns.exponent); if (pns.negative) { value = -value; } return answer; } diff --git a/include/fast_float/simple_decimal_conversion.h b/include/fast_float/simple_decimal_conversion.h index e878014..0484d74 100644 --- a/include/fast_float/simple_decimal_conversion.h +++ b/include/fast_float/simple_decimal_conversion.h @@ -137,7 +137,7 @@ inline uint64_t round(decimal &h) { } bool round_up = false; if (dp < h.num_digits) { - round_up = h.digits[dp] >= 5; // normally, we round up + round_up = h.digits[dp] >= 5; // normally, we round up // but we may need to round to even! if ((h.digits[dp] == 5) && (dp + 1 == h.num_digits)) { round_up = h.truncated || ((dp > 0) && (1 & h.digits[dp - 1])); @@ -266,7 +266,7 @@ adjusted_mantissa compute_float(decimal &d) { return answer; } else if(d.decimal_point >= 310) { // We have something at least as large as 0.1e310 which is - // always infinite. + // always infinite. answer.power2 = binary::infinite_power(); answer.mantissa = 0; return answer; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9704aa2..dfeec75 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,6 +56,8 @@ endfunction(fast_float_add_cpp_test) fast_float_add_cpp_test(example_test) fast_float_add_cpp_test(example_comma_test) fast_float_add_cpp_test(basictest) +target_compile_features(basictest PRIVATE cxx_std_17) + fast_float_add_cpp_test(long_test) fast_float_add_cpp_test(powersoffive_hardround) fast_float_add_cpp_test(string_test) From 3e29bf78c79155f39d4d27d570e700998c89a0b6 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 3 Nov 2022 19:40:05 -0400 Subject: [PATCH 32/84] Nicer constants. --- include/fast_float/float_common.h | 61 ++++++++++++++----------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 7f14914..f051667 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -220,7 +220,8 @@ constexpr static double powers_of_ten_double[] = { 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}; - +// used for max_mantissa_double and max_mantissa_float +constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; // Largest integer value v so that (5**index * v) <= 1<<53. // 0x10000000000000 == 1 << 53 constexpr static uint64_t max_mantissa_double[] = { @@ -229,31 +230,25 @@ constexpr static uint64_t max_mantissa_double[] = { 0x10000000000000 / (5 * 5), 0x10000000000000 / (5 * 5 * 5), 0x10000000000000 / (5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5 * 5 * 5 * 5 * 5), - 0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * - 5 * 5 * 5 * 5 * 5 * 5)}; + 0x10000000000000 / (constant_55555), + 0x10000000000000 / (constant_55555 * 5), + 0x10000000000000 / (constant_55555 * 5 * 5), + 0x10000000000000 / (constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555), + 0x10000000000000 / (constant_55555 * constant_55555 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5)}; // Largest integer value v so that (5**index * v) <= 1<<24. // 0x1000000 == 1<<24 constexpr static uint64_t max_mantissa_float[] = { @@ -262,13 +257,13 @@ constexpr static uint64_t max_mantissa_double[] = { 0x1000000 / (5 * 5), 0x1000000 / (5 * 5 * 5), 0x1000000 / (5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5), - 0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5)}; + 0x1000000 / (constant_55555), + 0x1000000 / (constant_55555 * 5), + 0x1000000 / (constant_55555 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * constant_55555), + 0x1000000 / (constant_55555 * constant_55555 * 5)}; template struct binary_format { using equiv_uint = typename std::conditional::type; From a2cf502395e3041a4176b5b32971b9995c6cbea2 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 3 Nov 2022 19:41:30 -0400 Subject: [PATCH 33/84] Typo. --- include/fast_float/float_common.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index f051667..f99371c 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -239,16 +239,16 @@ constexpr static uint64_t max_mantissa_double[] = { 0x10000000000000 / (constant_55555 * constant_55555 * 5), 0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5), 0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * 5 * 5 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), - 0x10000000000000 / (constant_5555constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5)}; + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5)}; // Largest integer value v so that (5**index * v) <= 1<<24. // 0x1000000 == 1<<24 constexpr static uint64_t max_mantissa_float[] = { From 6484c7369632d2a069d44c72f1dc086e4ad4f25a Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 15 Nov 2022 11:38:06 -0500 Subject: [PATCH 34/84] Trimming out one eight-digit optimization. --- CMakeLists.txt | 2 +- include/fast_float/ascii_number.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6db0004..721a29f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.4.0 LANGUAGES CXX) +project(fast_float VERSION 3.6.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 3e6bb3e..1783bd4 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -106,10 +106,6 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_ uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } while ((p != pend) && is_integer(*p)) { // a multiplication by 10 is cheaper than an arbitrary integer // multiplication From dac641ee13c6c1e8da490e996791e687017033e5 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 15 Nov 2022 12:07:56 -0500 Subject: [PATCH 35/84] Preparing release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 721a29f..4909110 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.6.0 LANGUAGES CXX) +project(fast_float VERSION 3.7.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From 6ceb29a7e48db8ac5f441ce0a23e3e4f205d07a8 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 16:21:34 +0000 Subject: [PATCH 36/84] We might reenable clinger. --- include/fast_float/float_common.h | 25 ++++++++++++++++++++++- include/fast_float/parse_number.h | 34 +++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index f99371c..a19a817 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -272,10 +272,12 @@ template struct binary_format { static inline constexpr int minimum_exponent(); static inline constexpr int infinite_power(); static inline constexpr int sign_index(); + static inline constexpr int min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST static inline constexpr int max_exponent_fast_path(); static inline constexpr int max_exponent_round_to_even(); static inline constexpr int min_exponent_round_to_even(); static inline constexpr uint64_t max_mantissa_fast_path(int64_t power); + static inline constexpr uint64_t max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST static inline constexpr int largest_power_of_ten(); static inline constexpr int smallest_power_of_ten(); static inline constexpr T exact_power_of_ten(int64_t power); @@ -285,6 +287,22 @@ template struct binary_format { static inline constexpr equiv_uint hidden_bit_mask(); }; +template <> inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -22; +#endif +} + +template <> inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -10; +#endif +} + template <> inline constexpr int binary_format::mantissa_explicit_bits() { return 52; } @@ -331,13 +349,18 @@ template <> inline constexpr int binary_format::max_exponent_fast_path() template <> inline constexpr int binary_format::max_exponent_fast_path() { return 10; } - +template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path(int64_t power) { // caller is responsible to ensure that // power >= 0 && power <= 22 // return max_mantissa_double[power]; } +template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path(int64_t power) { // caller is responsible to ensure that // power >= 0 && power <= 10 diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 8789475..89e1b5d 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -60,6 +60,15 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n return answer; } +fastfloat_really_inline bool rounds_nearest() { + // This function is meant to be equivalent to : + // prior: #include + // return fegetround() == FE_TONEAREST; + // volatile prevents the compiler from computing the function at compile-time + static volatile float fmin = std::numeric_limits::min(); + return (fmin + 1.0f == 1.0f - fmin); +} + } // namespace detail template @@ -87,12 +96,25 @@ from_chars_result from_chars_advanced(const char *first, const char *last, } answer.ec = std::errc(); // be optimistic answer.ptr = pns.lastmatch; - // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal - if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { - value = T(pns.mantissa); - value = value * binary_format::exact_power_of_ten(pns.exponent); - if (pns.negative) { value = -value; } - return answer; + if(detail::rounds_nearest()) { + // We have that fegetround() == FE_TONEAREST. + // Next is Clinger's fast path. + if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { + value = T(pns.mantissa); + if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } + else { value = value * binary_format::exact_power_of_ten(pns.exponent); } + if (pns.negative) { value = -value; } + return answer; + } + } else { + // We do not have that fegetround() == FE_TONEAREST. + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal + if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { + value = T(pns.mantissa); + value = value * binary_format::exact_power_of_ten(pns.exponent); + if (pns.negative) { value = -value; } + return answer; + } } adjusted_mantissa am = compute_float>(pns.exponent, pns.mantissa); if(pns.too_many_digits && am.power2 >= 0) { From 2c8e73895062198bedca9597fd44f8e8d32c7212 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 12:06:33 -0500 Subject: [PATCH 37/84] Cleaning. --- include/fast_float/parse_number.h | 29 +++++- tests/basictest.cpp | 149 ++++++++++++++++++++---------- 2 files changed, 129 insertions(+), 49 deletions(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 89e1b5d..1340a0d 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -60,12 +60,35 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n return answer; } -fastfloat_really_inline bool rounds_nearest() { +fastfloat_really_inline bool rounds_to_nearest() noexcept { // This function is meant to be equivalent to : // prior: #include // return fegetround() == FE_TONEAREST; + // However, it is expected to be much faster than the fegetround() + // function call. + // // volatile prevents the compiler from computing the function at compile-time static volatile float fmin = std::numeric_limits::min(); + // + // Explanation: + // Only when fegetround() == FE_TONEAREST do we have that + // fmin + 1.0f == 1.0f - fmin. + // + // FE_UPWARD: + // fmin + 1.0f = 0x1.00001 (1.00001) + // 1.0f - fmin = 0x1 (1) + // + // FE_DOWNWARD or FE_TOWARDZERO: + // fmin + 1.0f = 0x1 (1) + // 1.0f - fmin = 0x0.999999 (0.999999) + // + // fmin + 1.0f = 0x1 (1) + // 1.0f - fmin = 0x0.999999 (0.999999) + // + // FE_TONEAREST: + // fmin + 1.0f = 0x1 (1) + // 1.0f - fmin = 0x1 (1) + // return (fmin + 1.0f == 1.0f - fmin); } @@ -96,7 +119,9 @@ from_chars_result from_chars_advanced(const char *first, const char *last, } answer.ec = std::errc(); // be optimistic answer.ptr = pns.lastmatch; - if(detail::rounds_nearest()) { + // Unfortunately, the conventional Clinger's fast path is only possible + // when the system rounds to the nearest float. + if(detail::rounds_to_nearest()) { // We have that fegetround() == FE_TONEAREST. // Next is Clinger's fast path. if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 273c2c6..251e609 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef SUPPLEMENTAL_TEST_DATA_DIR #define SUPPLEMENTAL_TEST_DATA_DIR "data/" @@ -42,6 +43,11 @@ #define FASTFLOAT_ODDPLATFORM 1 #endif + +#define iHexAndDec(v) std::hex << "0x" << (v) << " (" << std::dec << (v) << ")" +#define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")" + + // C++ 17 because it is otherwise annoying to browse all files in a directory. // We also only run these tests on little endian systems. #if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM) @@ -50,59 +56,111 @@ #include #include +TEST_CASE("rounds_to_nearest") { + // + // If this function fails, we may be left in a non-standard rounding state. + // + static volatile float fmin = std::numeric_limits::min(); + fesetround(FE_UPWARD); + std::cout << "FE_UPWARD: fmin + 1.0f = " << iHexAndDec(fmin + 1.0f) << " 1.0f - fmin = " << iHexAndDec(1.0f - fmin) << std::endl; + CHECK(fegetround() == FE_UPWARD); + CHECK(fast_float::detail::rounds_to_nearest() == false); + + fesetround(FE_DOWNWARD); + std::cout << "FE_DOWNWARD: fmin + 1.0f = " << iHexAndDec(fmin + 1.0f) << " 1.0f - fmin = " << iHexAndDec(1.0f - fmin) << std::endl; + CHECK(fegetround() == FE_DOWNWARD); + CHECK(fast_float::detail::rounds_to_nearest() == false); + + fesetround(FE_TOWARDZERO); + std::cout << "FE_TOWARDZERO: fmin + 1.0f = " << iHexAndDec(fmin + 1.0f) << " 1.0f - fmin = " << iHexAndDec(1.0f - fmin) << std::endl; + CHECK(fegetround() == FE_TOWARDZERO); + CHECK(fast_float::detail::rounds_to_nearest() == false); + + fesetround(FE_TONEAREST); + std::cout << "FE_TONEAREST: fmin + 1.0f = " << iHexAndDec(fmin + 1.0f) << " 1.0f - fmin = " << iHexAndDec(1.0f - fmin) << std::endl; + CHECK(fegetround() == FE_TONEAREST); + CHECK(fast_float::detail::rounds_to_nearest() == true); +} + +const char * round_name(int d) { + switch(d) { + case FE_UPWARD: + return "FE_UPWARD"; + case FE_DOWNWARD: + return "FE_DOWNWARD"; + case FE_TOWARDZERO: + return "FE_TOWARDZERO"; + case FE_TONEAREST: + return "FE_TONEAREST"; + default: + return "UNKNOWN"; + } + +} + // return true on success bool check_file(std::string file_name) { std::cout << "Checking " << file_name << std::endl; - size_t number{0}; - std::fstream newfile(file_name, std::ios::in); - if (newfile.is_open()) { - std::string str; - while (std::getline(newfile, str)) { - if (str.size() > 0) { - // Read 32-bit hex - uint32_t float32; - auto r32 = std::from_chars(str.data() + 5, str.data() + str.size(), + // We check all rounding directions, for each file. + std::vector directions = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}; + for (int d : directions) { + std::cout << "fesetround to " << round_name(d) << std::endl; + fesetround(d); + size_t number{0}; + std::fstream newfile(file_name, std::ios::in); + if (newfile.is_open()) { + std::string str; + while (std::getline(newfile, str)) { + if (str.size() > 0) { + // Read 32-bit hex + uint32_t float32; + auto r32 = std::from_chars(str.data() + 5, str.data() + str.size(), float32, 16); - if(r32.ec != std::errc()) { std::cerr << "32-bit parsing failure\n"; return false; } - // Read 64-bit hex - uint64_t float64; - auto r64 = std::from_chars(str.data() + 14, str.data() + str.size(), + if(r32.ec != std::errc()) { std::cerr << "32-bit parsing failure\n"; return false; } + // Read 64-bit hex + uint64_t float64; + auto r64 = std::from_chars(str.data() + 14, str.data() + str.size(), float64, 16); - if(r64.ec != std::errc()) { std::cerr << "64-bit parsing failure\n"; return false; } - // The string to parse: - const char *number_string = str.data() + 31; - const char *end_of_string = str.data() + str.size(); - // Parse as 32-bit float - float parsed_32; - auto fast_float_r32 = fast_float::from_chars(number_string, end_of_string, parsed_32); - if(fast_float_r32.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } - // Parse as 64-bit float - double parsed_64; - auto fast_float_r64 = fast_float::from_chars(number_string, end_of_string, parsed_64); - if(fast_float_r64.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } - // Convert the floats to unsigned ints. - uint32_t float32_parsed; - uint64_t float64_parsed; - ::memcpy(&float32_parsed, &parsed_32, sizeof(parsed_32)); - ::memcpy(&float64_parsed, &parsed_64, sizeof(parsed_64)); - // Compare with expected results - if (float32_parsed != float32) { - std::cout << "bad 32 " << str << std::endl; - return false; + if(r64.ec != std::errc()) { std::cerr << "64-bit parsing failure\n"; return false; } + // The string to parse: + const char *number_string = str.data() + 31; + const char *end_of_string = str.data() + str.size(); + // Parse as 32-bit float + float parsed_32; + auto fast_float_r32 = fast_float::from_chars(number_string, end_of_string, parsed_32); + if(fast_float_r32.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } + // Parse as 64-bit float + double parsed_64; + auto fast_float_r64 = fast_float::from_chars(number_string, end_of_string, parsed_64); + if(fast_float_r64.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } + // Convert the floats to unsigned ints. + uint32_t float32_parsed; + uint64_t float64_parsed; + ::memcpy(&float32_parsed, &parsed_32, sizeof(parsed_32)); + ::memcpy(&float64_parsed, &parsed_64, sizeof(parsed_64)); + // Compare with expected results + if (float32_parsed != float32) { + std::cout << "bad 32 " << str << std::endl; + fesetround(FE_TONEAREST); + return false; + } + if (float64_parsed != float64) { + std::cout << "bad 64 " << str << std::endl; + fesetround(FE_TONEAREST); + return false; + } + number++; } - if (float64_parsed != float64) { - std::cout << "bad 64 " << str << std::endl; - return false; - } - number++; } + std::cout << "checked " << std::defaultfloat << number << " values" << std::endl; + newfile.close(); // close the file object + } else { + std::cout << "Could not read " << file_name << std::endl; + fesetround(FE_TONEAREST); + return false; } - std::cout << "checked " << std::defaultfloat << number << " values" << std::endl; - newfile.close(); // close the file object - } else { - std::cout << "Could not read " << file_name << std::endl; - return false; } + fesetround(FE_TONEAREST); return true; } @@ -125,9 +183,6 @@ TEST_CASE("leading_zeroes") { CHECK(fast_float::leading_zeroes(bit << 63) == 0); } -#define iHexAndDec(v) std::hex << "0x" << (v) << " (" << std::dec << (v) << ")" -#define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")" - void test_full_multiplication(uint64_t lhs, uint64_t rhs, uint64_t expected_lo, uint64_t expected_hi) { fast_float::value128 v; v = fast_float::full_multiplication(lhs, rhs); From 95321767eebd207c23cb67a21e48db6affb0ffbd Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 12:29:46 -0500 Subject: [PATCH 38/84] More verbose error report. --- tests/basictest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 251e609..d79fb82 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -141,11 +141,15 @@ bool check_file(std::string file_name) { // Compare with expected results if (float32_parsed != float32) { std::cout << "bad 32 " << str << std::endl; + std::cout << "parsed = " << iHexAndDec(float32_parsed) << ", expectd = " << iHexAndDec(float32) << std::endl; + std::cout << "fesetround: " << round_name(d) << std::endl; fesetround(FE_TONEAREST); return false; } if (float64_parsed != float64) { std::cout << "bad 64 " << str << std::endl; + std::cout << "parsed = " << iHexAndDec(float64_parsed) << ", expectd = " << iHexAndDec(float64) << std::endl; + std::cout << "fesetround: " << round_name(d) << std::endl; fesetround(FE_TONEAREST); return false; } From d2250598737dbb87289ee3fa137c49ad3b79528f Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 14:35:31 -0500 Subject: [PATCH 39/84] Fix for Win32+ClangCL --- include/fast_float/parse_number.h | 5 +++++ tests/basictest.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 1340a0d..b5f92ce 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -135,7 +135,12 @@ from_chars_result from_chars_advanced(const char *first, const char *last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { +#if (defined(_WIN32) && defined(__clang__)) + // 32-bit ClangCL maps 0 to -0.0 when fegetround() == FE_DOWNWARD + value = pns.mantissa ? T(pns.mantissa) : 0.0; +#else value = T(pns.mantissa); +#endif value = value * binary_format::exact_power_of_ten(pns.exponent); if (pns.negative) { value = -value; } return answer; diff --git a/tests/basictest.cpp b/tests/basictest.cpp index d79fb82..980ead1 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -98,6 +98,36 @@ const char * round_name(int d) { } + +TEST_CASE("parse_zero") { + // + // If this function fails, we may be left in a non-standard rounding state. + // + const char * zero = "0"; + double f = 0; + fesetround(FE_UPWARD); + auto r1 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r1.ec == std::errc()); + std::cout << "FE_UPWARD parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_TOWARDZERO); + auto r2 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r2.ec == std::errc()); + std::cout << "FE_TOWARDZERO parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_DOWNWARD); + auto r3 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r3.ec == std::errc()); + std::cout << "FE_DOWNWARD parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); + fesetround(FE_TONEAREST); + auto r4 = fast_float::from_chars(zero, zero + 1, f); + CHECK(r4.ec == std::errc()); + std::cout << "FE_TONEAREST parsed zero as " << iHexAndDec(f) << std::endl; + CHECK(f == 0); +} + + // return true on success bool check_file(std::string file_name) { std::cout << "Checking " << file_name << std::endl; From 559b89d34d48a8559437d48fceb939eb0fc0b8af Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 14:59:03 -0500 Subject: [PATCH 40/84] 32-bit clangcl appears to be ridiculous. --- tests/basictest.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 980ead1..1c07256 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -104,27 +104,46 @@ TEST_CASE("parse_zero") { // If this function fails, we may be left in a non-standard rounding state. // const char * zero = "0"; + uint64_t float64_parsed; double f = 0; + ::memcpy(&float64_parsed, &f, sizeof(f)); + CHECK(float64_parsed == 0); + fesetround(FE_UPWARD); auto r1 = fast_float::from_chars(zero, zero + 1, f); CHECK(r1.ec == std::errc()); std::cout << "FE_UPWARD parsed zero as " << iHexAndDec(f) << std::endl; CHECK(f == 0); + ::memcpy(&float64_parsed, &f, sizeof(f)); + std::cout << "double as uint64_t is " << float64_parsed << std::endl; + CHECK(float64_parsed == 0); + fesetround(FE_TOWARDZERO); auto r2 = fast_float::from_chars(zero, zero + 1, f); CHECK(r2.ec == std::errc()); std::cout << "FE_TOWARDZERO parsed zero as " << iHexAndDec(f) << std::endl; CHECK(f == 0); + ::memcpy(&float64_parsed, &f, sizeof(f)); + std::cout << "double as uint64_t is " << float64_parsed << std::endl; + CHECK(float64_parsed == 0); + fesetround(FE_DOWNWARD); auto r3 = fast_float::from_chars(zero, zero + 1, f); CHECK(r3.ec == std::errc()); std::cout << "FE_DOWNWARD parsed zero as " << iHexAndDec(f) << std::endl; CHECK(f == 0); + ::memcpy(&float64_parsed, &f, sizeof(f)); + std::cout << "double as uint64_t is " << float64_parsed << std::endl; + CHECK(float64_parsed == 0); + fesetround(FE_TONEAREST); auto r4 = fast_float::from_chars(zero, zero + 1, f); CHECK(r4.ec == std::errc()); std::cout << "FE_TONEAREST parsed zero as " << iHexAndDec(f) << std::endl; CHECK(f == 0); + ::memcpy(&float64_parsed, &f, sizeof(f)); + std::cout << "double as uint64_t is " << float64_parsed << std::endl; + CHECK(float64_parsed == 0); } @@ -171,14 +190,16 @@ bool check_file(std::string file_name) { // Compare with expected results if (float32_parsed != float32) { std::cout << "bad 32 " << str << std::endl; - std::cout << "parsed = " << iHexAndDec(float32_parsed) << ", expectd = " << iHexAndDec(float32) << std::endl; + std::cout << "parsed as " << iHexAndDec(parsed_32) << std::endl; + std::cout << "as raw uint32_t, parsed = " << float32_parsed << ", expected = " << float32 << std::endl; std::cout << "fesetround: " << round_name(d) << std::endl; fesetround(FE_TONEAREST); return false; } if (float64_parsed != float64) { std::cout << "bad 64 " << str << std::endl; - std::cout << "parsed = " << iHexAndDec(float64_parsed) << ", expectd = " << iHexAndDec(float64) << std::endl; + std::cout << "parsed as " << iHexAndDec(parsed_64) << std::endl; + std::cout << "as raw uint64_t, parsed = " << float64_parsed << ", expected = " << float64 << std::endl; std::cout << "fesetround: " << round_name(d) << std::endl; fesetround(FE_TONEAREST); return false; From fd9d9effda91bdba9b9135ef8b66f14bb576dc25 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 15:25:03 -0500 Subject: [PATCH 41/84] More tweaking around clangcl --- include/fast_float/parse_number.h | 13 +++-- tests/basictest.cpp | 91 +++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index b5f92ce..2b3b935 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -135,13 +135,14 @@ from_chars_result from_chars_advanced(const char *first, const char *last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { -#if (defined(_WIN32) && defined(__clang__)) - // 32-bit ClangCL maps 0 to -0.0 when fegetround() == FE_DOWNWARD - value = pns.mantissa ? T(pns.mantissa) : 0.0; -#else - value = T(pns.mantissa); +#if (defined(_MSC_VER) && defined(__clang__)) + // ClangCL may map 0 to -0.0 when fegetround() == FE_DOWNWARD + if(pns.mantissa == 0) { + value = 0; + return answer; + } #endif - value = value * binary_format::exact_power_of_ten(pns.exponent); + value = T(pns.mantissa) * binary_format::exact_power_of_ten(pns.exponent); if (pns.negative) { value = -value; } return answer; } diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 1c07256..fec51de 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -48,13 +48,66 @@ #define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")" -// C++ 17 because it is otherwise annoying to browse all files in a directory. -// We also only run these tests on little endian systems. -#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM) +const char * round_name(int d) { + switch(d) { + case FE_UPWARD: + return "FE_UPWARD"; + case FE_DOWNWARD: + return "FE_DOWNWARD"; + case FE_TOWARDZERO: + return "FE_TOWARDZERO"; + case FE_TONEAREST: + return "FE_TONEAREST"; + default: + return "UNKNOWN"; + } +} + + +#define FASTFLOAT_STR(x) #x +#define SHOW_DEFINE(x) printf("%s='%s'\n", #x, FASTFLOAT_STR(x)) + +TEST_CASE("system_info") { + std::cout << "system info:" << std::endl; +#ifdef _MSC_VER + SHOW_DEFINE(_MSC_VER); +#endif +#ifdef FASTFLOAT_64BIT_LIMB + SHOW_DEFINE(FASTFLOAT_64BIT_LIMB); +#endif +#ifdef __clang__ + SHOW_DEFINE(__clang__); +#endif +#ifdef FASTFLOAT_VISUAL_STUDIO + SHOW_DEFINE(FASTFLOAT_VISUAL_STUDIO); +#endif +#ifdef FASTFLOAT_IS_BIG_ENDIAN + #if FASTFLOAT_IS_BIG_ENDIAN + printf("big endian\n"); + #else + printf("little endian\n"); + #endif +#endif +#ifdef FASTFLOAT_32BIT + SHOW_DEFINE(FASTFLOAT_32BIT); +#endif +#ifdef FASTFLOAT_64BIT + SHOW_DEFINE(FASTFLOAT_64BIT); +#endif +#ifdef FLT_EVAL_METHOD + SHOW_DEFINE(FLT_EVAL_METHOD); +#endif +#ifdef _WIN32 + SHOW_DEFINE(_WIN32); +#endif +#ifdef _WIN64 + SHOW_DEFINE(_WIN64); +#endif + std::cout << "fegetround() = " << round_name(fegetround()) << std::endl; + std::cout << std::endl; + +} -#include -#include -#include TEST_CASE("rounds_to_nearest") { // @@ -82,23 +135,6 @@ TEST_CASE("rounds_to_nearest") { CHECK(fast_float::detail::rounds_to_nearest() == true); } -const char * round_name(int d) { - switch(d) { - case FE_UPWARD: - return "FE_UPWARD"; - case FE_DOWNWARD: - return "FE_DOWNWARD"; - case FE_TOWARDZERO: - return "FE_TOWARDZERO"; - case FE_TONEAREST: - return "FE_TONEAREST"; - default: - return "UNKNOWN"; - } - -} - - TEST_CASE("parse_zero") { // // If this function fails, we may be left in a non-standard rounding state. @@ -146,6 +182,15 @@ TEST_CASE("parse_zero") { CHECK(float64_parsed == 0); } +// C++ 17 because it is otherwise annoying to browse all files in a directory. +// We also only run these tests on little endian systems. +#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM) + +#include +#include +#include + + // return true on success bool check_file(std::string file_name) { From 8f27b7e9210b31f5966f5a3ef9517d478ad28b2e Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 15:42:56 -0500 Subject: [PATCH 42/84] More tuning. --- include/fast_float/bigint.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_float/bigint.h b/include/fast_float/bigint.h index b56cb9b..220e057 100644 --- a/include/fast_float/bigint.h +++ b/include/fast_float/bigint.h @@ -17,7 +17,7 @@ namespace fast_float { // we might have platforms where `CHAR_BIT` is not 8, so let's avoid // doing `8 * sizeof(limb)`. #if defined(FASTFLOAT_64BIT) && !defined(__sparc) -#define FASTFLOAT_64BIT_LIMB +#define FASTFLOAT_64BIT_LIMB 1 typedef uint64_t limb; constexpr size_t limb_bits = 64; #else From 29b1a03d5be3e250e70c8892b360b01da0cad9c9 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 15:49:09 -0500 Subject: [PATCH 43/84] Make sure that macros have actual values when defined (makes debugging easier) --- include/fast_float/float_common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index a19a817..c2084e0 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -12,11 +12,11 @@ || defined(__MINGW64__) \ || defined(__s390x__) \ || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) ) -#define FASTFLOAT_64BIT +#define FASTFLOAT_64BIT 1 #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ || defined(__arm__) || defined(_M_ARM) \ || defined(__MINGW32__) || defined(__EMSCRIPTEN__)) -#define FASTFLOAT_32BIT +#define FASTFLOAT_32BIT 1 #else // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. // We can never tell the register width, but the SIZE_MAX is a good approximation. @@ -24,9 +24,9 @@ #if SIZE_MAX == 0xffff #error Unknown platform (16-bit, unsupported) #elif SIZE_MAX == 0xffffffff - #define FASTFLOAT_32BIT + #define FASTFLOAT_32BIT 1 #elif SIZE_MAX == 0xffffffffffffffff - #define FASTFLOAT_64BIT + #define FASTFLOAT_64BIT 1 #else #error Unknown platform (not 32-bit, not 64-bit?) #endif From bfc0478feb213241c22d45340975c5690327e84c Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 16 Nov 2022 16:45:01 -0500 Subject: [PATCH 44/84] More tweaks. --- include/fast_float/parse_number.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 2b3b935..d1f3bce 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -60,7 +60,16 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n return answer; } +/** + * Returns true if the floating-pointing rounding mode is to 'nearest'. + * It is the default on most system. This function is meant to be inexpensive. + * Credit : @mwalcott3 + */ fastfloat_really_inline bool rounds_to_nearest() noexcept { + // See + // A fast function to check your floating-point rounding mode + // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/ + // // This function is meant to be equivalent to : // prior: #include // return fegetround() == FE_TONEAREST; @@ -68,6 +77,8 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // function call. // // volatile prevents the compiler from computing the function at compile-time + // It does not need to be std::numeric_limits::min(), any small + // value so that 1 + x should round to 1 would do. static volatile float fmin = std::numeric_limits::min(); // // Explanation: @@ -135,7 +146,7 @@ from_chars_result from_chars_advanced(const char *first, const char *last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { -#if (defined(_MSC_VER) && defined(__clang__)) +#if (defined(_WIN32) && defined(__clang__)) // ClangCL may map 0 to -0.0 when fegetround() == FE_DOWNWARD if(pns.mantissa == 0) { value = 0; From 39ea41b84a4e7e9a8239ac07c9006af5eb59b15e Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 18 Nov 2022 11:28:34 -0500 Subject: [PATCH 45/84] Adopting proposal. --- include/fast_float/parse_number.h | 66 +++++++++++++++++++------------ 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index d1f3bce..a1f4c5d 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -76,8 +76,10 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // However, it is expected to be much faster than the fegetround() // function call. // - // volatile prevents the compiler from computing the function at compile-time - // It does not need to be std::numeric_limits::min(), any small + // The volatile keywoard prevents the compiler from computing the function + // at compile-time. + // There might be other ways to prevent compile-time optimizations (e.g., asm). + // The value does not need to be std::numeric_limits::min(), any small // value so that 1 + x should round to 1 would do. static volatile float fmin = std::numeric_limits::min(); // @@ -100,6 +102,8 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // fmin + 1.0f = 0x1 (1) // 1.0f - fmin = 0x1 (1) // + // Note: This may fail to be accurate if fast-math has been + // enabled, as rounding conventions may not apply. return (fmin + 1.0f == 1.0f - fmin); } @@ -130,32 +134,44 @@ from_chars_result from_chars_advanced(const char *first, const char *last, } answer.ec = std::errc(); // be optimistic answer.ptr = pns.lastmatch; - // Unfortunately, the conventional Clinger's fast path is only possible - // when the system rounds to the nearest float. - if(detail::rounds_to_nearest()) { - // We have that fegetround() == FE_TONEAREST. - // Next is Clinger's fast path. - if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { - value = T(pns.mantissa); - if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } - else { value = value * binary_format::exact_power_of_ten(pns.exponent); } - if (pns.negative) { value = -value; } - return answer; - } - } else { - // We do not have that fegetround() == FE_TONEAREST. - // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal - if (pns.exponent >= 0 && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) { -#if (defined(_WIN32) && defined(__clang__)) - // ClangCL may map 0 to -0.0 when fegetround() == FE_DOWNWARD - if(pns.mantissa == 0) { - value = 0; + // The implementation of the Clinger's fast path is convoluted because + // we want round-to-nearest in all cases, irrespective of the rounding mode + // selected on the thread. + // We proceed optimistically, assuming that detail::rounds_to_nearest() returns + // true. + if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && !pns.too_many_digits) { + // Unfortunately, the conventional Clinger's fast path is only possible + // when the system rounds to the nearest float. + // + // We expect the next branch to almost always be selected. + // We could check it first (before the previous branch), but + // there might be performance advantages at having the check + // be last. + if(detail::rounds_to_nearest()) { + // We have that fegetround() == FE_TONEAREST. + // Next is Clinger's fast path. + if (pns.mantissa <=binary_format::max_mantissa_fast_path()) { + value = T(pns.mantissa); + if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } + else { value = value * binary_format::exact_power_of_ten(pns.exponent); } + if (pns.negative) { value = -value; } return answer; } + } else { + // We do not have that fegetround() == FE_TONEAREST. + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal + if (pns.exponent >= 0 && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent)) { +#if (defined(_WIN32) && defined(__clang__)) + // ClangCL may map 0 to -0.0 when fegetround() == FE_DOWNWARD + if(pns.mantissa == 0) { + value = 0; + return answer; + } #endif - value = T(pns.mantissa) * binary_format::exact_power_of_ten(pns.exponent); - if (pns.negative) { value = -value; } - return answer; + value = T(pns.mantissa) * binary_format::exact_power_of_ten(pns.exponent); + if (pns.negative) { value = -value; } + return answer; + } } } adjusted_mantissa am = compute_float>(pns.exponent, pns.mantissa); From 3d0e448940ba40760b1abae03f82100a6dccad51 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 18 Nov 2022 12:27:38 -0500 Subject: [PATCH 46/84] Added a remark. --- include/fast_float/parse_number.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index a1f4c5d..0a8092f 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -80,7 +80,8 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // at compile-time. // There might be other ways to prevent compile-time optimizations (e.g., asm). // The value does not need to be std::numeric_limits::min(), any small - // value so that 1 + x should round to 1 would do. + // value so that 1 + x should round to 1 would do (after accounting for excess + // precision, as in 387). static volatile float fmin = std::numeric_limits::min(); // // Explanation: From 8b7a55a03cb38fa4ab4e9309d38f0fd24a51814a Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 18 Nov 2022 15:33:44 -0500 Subject: [PATCH 47/84] Minor optimization. --- include/fast_float/parse_number.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 0a8092f..0e22afc 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -83,6 +83,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // value so that 1 + x should round to 1 would do (after accounting for excess // precision, as in 387). static volatile float fmin = std::numeric_limits::min(); + float fmini = fmin; // we copy it so that it gets loaded at most once. // // Explanation: // Only when fegetround() == FE_TONEAREST do we have that @@ -105,7 +106,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // // Note: This may fail to be accurate if fast-math has been // enabled, as rounding conventions may not apply. - return (fmin + 1.0f == 1.0f - fmin); + return (fmini + 1.0f == 1.0f - fmini); } } // namespace detail From 003a98318876f5376fe18cc745440ea6ef2f387a Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 18 Nov 2022 15:38:21 -0500 Subject: [PATCH 48/84] Simplifying the justification. --- include/fast_float/parse_number.h | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 0e22afc..bd0ab43 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -81,7 +81,7 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // There might be other ways to prevent compile-time optimizations (e.g., asm). // The value does not need to be std::numeric_limits::min(), any small // value so that 1 + x should round to 1 would do (after accounting for excess - // precision, as in 387). + // precision, as in 387 instructions). static volatile float fmin = std::numeric_limits::min(); float fmini = fmin; // we copy it so that it gets loaded at most once. // @@ -90,19 +90,12 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // fmin + 1.0f == 1.0f - fmin. // // FE_UPWARD: - // fmin + 1.0f = 0x1.00001 (1.00001) - // 1.0f - fmin = 0x1 (1) + // fmin + 1.0f > 1 + // 1.0f - fmin == 1 // // FE_DOWNWARD or FE_TOWARDZERO: - // fmin + 1.0f = 0x1 (1) - // 1.0f - fmin = 0x0.999999 (0.999999) - // - // fmin + 1.0f = 0x1 (1) - // 1.0f - fmin = 0x0.999999 (0.999999) - // - // FE_TONEAREST: - // fmin + 1.0f = 0x1 (1) - // 1.0f - fmin = 0x1 (1) + // fmin + 1.0f == 1 + // 1.0f - fmin < 1 // // Note: This may fail to be accurate if fast-math has been // enabled, as rounding conventions may not apply. From eec504ae0360d39af3350f449d33159cbb7279a9 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 21 Nov 2022 09:53:49 -0500 Subject: [PATCH 49/84] Adding a fast-math test. --- .github/workflows/ubuntu20-fastmath.yml | 18 ++++++++++++++++++ tests/CMakeLists.txt | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ubuntu20-fastmath.yml diff --git a/.github/workflows/ubuntu20-fastmath.yml b/.github/workflows/ubuntu20-fastmath.yml new file mode 100644 index 0000000..389f4ed --- /dev/null +++ b/.github/workflows/ubuntu20-fastmath.yml @@ -0,0 +1,18 @@ +name: Ubuntu 20.04 CI (GCC 9) + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v3 + - name: Use cmake + run: | + mkdir build && + cd build && + cmake -DCMAKE_CXX_FLAGS="-ffast-math" -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index dfeec75..6534217 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,7 +9,7 @@ option(SYSTEM_DOCTEST "Use system copy of doctest" OFF) if (NOT SYSTEM_DOCTEST) FetchContent_Declare(doctest GIT_REPOSITORY https://github.com/onqtam/doctest.git - GIT_TAG 2.4.6) + GIT_TAG v2.4.9) endif() FetchContent_Declare(supplemental_test_files GIT_REPOSITORY https://github.com/fastfloat/supplemental_test_files.git From 968bd9d86eccb7c16ffadeb1c8d936309849bbfe Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 21 Nov 2022 09:56:21 -0500 Subject: [PATCH 50/84] Renaming the test. --- .github/workflows/ubuntu20-fastmath.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu20-fastmath.yml b/.github/workflows/ubuntu20-fastmath.yml index 389f4ed..eda488a 100644 --- a/.github/workflows/ubuntu20-fastmath.yml +++ b/.github/workflows/ubuntu20-fastmath.yml @@ -1,4 +1,4 @@ -name: Ubuntu 20.04 CI (GCC 9) +name: Ubuntu 20.04 CI (GCC 9, fast-math) on: [push, pull_request] From 9e868b3d1a84342db57689275ff2f8562cad5cf7 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 23 Nov 2022 10:51:27 -0500 Subject: [PATCH 51/84] Preparing release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4909110..2c4e403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.7.0 LANGUAGES CXX) +project(fast_float VERSION 3.8.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From b6f1567d0b09b694d65e3b6c235bb3cf6ff61fac Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 25 Nov 2022 15:53:50 -0500 Subject: [PATCH 52/84] Adding two new runners --- .github/workflows/ubuntu22-clang.yml | 18 ++++++++++++++++++ .github/workflows/ubuntu22.yml | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .github/workflows/ubuntu22-clang.yml create mode 100644 .github/workflows/ubuntu22.yml diff --git a/.github/workflows/ubuntu22-clang.yml b/.github/workflows/ubuntu22-clang.yml new file mode 100644 index 0000000..8db9bda --- /dev/null +++ b/.github/workflows/ubuntu22-clang.yml @@ -0,0 +1,18 @@ +name: Ubuntu 22.04 CI (clang 14) + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Install clang++-14 + run: sudo apt-get install -y clang++-14 + - name: Use cmake + run: | + mkdir build && + cd build && + CXX=clang++-14 cmake -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure \ No newline at end of file diff --git a/.github/workflows/ubuntu22.yml b/.github/workflows/ubuntu22.yml new file mode 100644 index 0000000..3951dbc --- /dev/null +++ b/.github/workflows/ubuntu22.yml @@ -0,0 +1,16 @@ +name: Ubuntu 22.04 CI + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Use cmake + run: | + mkdir build && + cd build && + cmake -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure \ No newline at end of file From 76537e16953ac5172458fdc281742631bbf244ce Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 25 Nov 2022 15:58:54 -0500 Subject: [PATCH 53/84] Fixing issue 154. --- include/fast_float/parse_number.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index bd0ab43..4772881 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -156,8 +156,8 @@ from_chars_result from_chars_advanced(const char *first, const char *last, // We do not have that fegetround() == FE_TONEAREST. // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal if (pns.exponent >= 0 && pns.mantissa <=binary_format::max_mantissa_fast_path(pns.exponent)) { -#if (defined(_WIN32) && defined(__clang__)) - // ClangCL may map 0 to -0.0 when fegetround() == FE_DOWNWARD +#if defined(__clang__) + // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD if(pns.mantissa == 0) { value = 0; return answer; From 08c47edf570aedfffc7dc1fbbed5cad9be691840 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 25 Nov 2022 22:22:14 -0500 Subject: [PATCH 54/84] Preparing release --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c4e403..1ddbff9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.8.0 LANGUAGES CXX) +project(fast_float VERSION 3.8.1 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From ff5855813f4a83b1738451994fe7c6da4cbe4408 Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Fri, 2 Dec 2022 11:42:38 +0900 Subject: [PATCH 55/84] Add missing namespace end comments Other files have it. --- include/fast_float/fast_float.h | 2 +- include/fast_float/fast_table.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_float/fast_float.h b/include/fast_float/fast_float.h index ad3093e..d3497fd 100644 --- a/include/fast_float/fast_float.h +++ b/include/fast_float/fast_float.h @@ -58,6 +58,6 @@ template from_chars_result from_chars_advanced(const char *first, const char *last, T &value, parse_options options) noexcept; -} +} // namespace fast_float #include "parse_number.h" #endif // FASTFLOAT_FAST_FLOAT_H diff --git a/include/fast_float/fast_table.h b/include/fast_float/fast_table.h index 5766274..46ee965 100644 --- a/include/fast_float/fast_table.h +++ b/include/fast_float/fast_table.h @@ -694,6 +694,6 @@ const uint64_t powers_template::power_of_five_128[number_of_entries] = { 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,}; using powers = powers_template<>; -} +} // namespace fast_float #endif From ae028f1aea6d8ecc4b43280c9ee227c396227818 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sun, 11 Dec 2022 14:53:00 -0500 Subject: [PATCH 56/84] Update README.md --- README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d6ae279..7b3166a 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,22 @@ You can parse delimited numbers: // we have result == 324562.645. ``` + +## Relation With Other Work + +The fast_float library is part of: + +- GCC (as of version 12): the `from_chars` function in GCC relies on fast_float. +- [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's web browser) + + +The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). + +There is a [derived implementation part of AdaCore](https://github.com/AdaCore/VSS). + + +The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). + ## Reference - Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021. @@ -136,16 +152,6 @@ You can parse delimited numbers: - [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`. -## Relation With Other Work - -The fast_float library is part of GCC (as of version 12): the `from_chars` function in GCC relies on fast_float. - -The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba). - -The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). - -There is a [derived implementation part of AdaCore](https://github.com/AdaCore/VSS). - ## Users The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [Yandex ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet). From 6f9da45af3c75cfab269495046b29dcb275a6da3 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 13 Dec 2022 17:05:04 -0500 Subject: [PATCH 57/84] Cleaning our CI a bit. --- .github/workflows/amalgamate-ubuntu20.yml | 10 +--------- .github/workflows/ubuntu18.yml | 11 +---------- .github/workflows/ubuntu20-fastmath.yml | 2 -- .github/workflows/ubuntu20.yml | 10 +--------- 4 files changed, 3 insertions(+), 30 deletions(-) diff --git a/.github/workflows/amalgamate-ubuntu20.yml b/.github/workflows/amalgamate-ubuntu20.yml index 14b8902..0611e84 100644 --- a/.github/workflows/amalgamate-ubuntu20.yml +++ b/.github/workflows/amalgamate-ubuntu20.yml @@ -1,18 +1,10 @@ -name: Amalgamate Ubuntu 20.04 CI (GCC 9, 8) +name: Amalgamate Ubuntu 20.04 CI (GCC 9) on: [push, pull_request] jobs: ubuntu-build: runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: } - - {cxx: , arch: } # default=gcc9 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 steps: - uses: actions/checkout@v3 - name: Compile with amalgamation diff --git a/.github/workflows/ubuntu18.yml b/.github/workflows/ubuntu18.yml index 63a1455..791582d 100644 --- a/.github/workflows/ubuntu18.yml +++ b/.github/workflows/ubuntu18.yml @@ -1,19 +1,10 @@ -name: Ubuntu 18.04 CI (GCC 7, 6, 5) +name: Ubuntu 18.04 CI (GCC 7) on: [push, pull_request] jobs: ubuntu-build: runs-on: ubuntu-18.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-5, arch: } - #- {cxx: -DCMAKE_CXX_COMPILER=g++-6, arch: } - - {cxx: , arch: } # default=gcc7 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc7 steps: - uses: actions/checkout@v3 - name: Setup cmake diff --git a/.github/workflows/ubuntu20-fastmath.yml b/.github/workflows/ubuntu20-fastmath.yml index eda488a..90f5347 100644 --- a/.github/workflows/ubuntu20-fastmath.yml +++ b/.github/workflows/ubuntu20-fastmath.yml @@ -5,8 +5,6 @@ on: [push, pull_request] jobs: ubuntu-build: runs-on: ubuntu-20.04 - strategy: - fail-fast: false steps: - uses: actions/checkout@v3 - name: Use cmake diff --git a/.github/workflows/ubuntu20.yml b/.github/workflows/ubuntu20.yml index 2704c85..2bbd973 100644 --- a/.github/workflows/ubuntu20.yml +++ b/.github/workflows/ubuntu20.yml @@ -4,15 +4,7 @@ on: [push, pull_request] jobs: ubuntu-build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: } - - {cxx: , arch: } # default=gcc9 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 + runs-on: ubuntu-20.04 , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 steps: - uses: actions/checkout@v3 - name: Use cmake From 9c4c20dd7f353a59fbe8d93a7b2c4bc38fd0eec4 Mon Sep 17 00:00:00 2001 From: huangqinjin Date: Sun, 18 Dec 2022 11:03:23 +0800 Subject: [PATCH 58/84] Replace utf8 chars. --- include/fast_float/fast_table.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_float/fast_table.h b/include/fast_float/fast_table.h index 46ee965..aa7804b 100644 --- a/include/fast_float/fast_table.h +++ b/include/fast_float/fast_table.h @@ -17,11 +17,11 @@ namespace fast_float { */ /** - * The smallest non-zero float (binary64) is 2^−1074. + * The smallest non-zero float (binary64) is 2^-1074. * We take as input numbers of the form w x 10^q where w < 2^64. * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. * However, we have that - * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^−1074. + * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^-1074. * Thus it is possible for a number of the form w * 10^-342 where * w is a 64-bit value to be a non-zero floating-point number. ********* From 293ca61c76d90f92119e0d45b796b0c1564efc7a Mon Sep 17 00:00:00 2001 From: huangqinjin Date: Fri, 23 Dec 2022 19:20:28 +0800 Subject: [PATCH 59/84] Fix compile warning of unit64_t to bool --- include/fast_float/digit_comparison.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 77c710f..4c43433 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -125,8 +125,8 @@ void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) n halfway = uint64_t(1) << (shift - 1); } uint64_t truncated_bits = am.mantissa & mask; - uint64_t is_above = truncated_bits > halfway; - uint64_t is_halfway = truncated_bits == halfway; + bool is_above = truncated_bits > halfway; + bool is_halfway = truncated_bits == halfway; // shift digits into position if (shift == 64) { From 7040160143e3876266cbff540ed2a8e6ba297be4 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Fri, 23 Dec 2022 10:37:04 -0500 Subject: [PATCH 60/84] Adding GCC 12 --- .github/workflows/ubuntu22-gcc12.yml | 16 ++++++++++++++++ .github/workflows/ubuntu22.yml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ubuntu22-gcc12.yml diff --git a/.github/workflows/ubuntu22-gcc12.yml b/.github/workflows/ubuntu22-gcc12.yml new file mode 100644 index 0000000..fb3f859 --- /dev/null +++ b/.github/workflows/ubuntu22-gcc12.yml @@ -0,0 +1,16 @@ +name: Ubuntu 22.04 CI (GCC 12) + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - name: Use cmake + run: | + mkdir build && + cd build && + CXX=g++-12 CXXFLAGS=-Werror cmake -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure \ No newline at end of file diff --git a/.github/workflows/ubuntu22.yml b/.github/workflows/ubuntu22.yml index 3951dbc..367cb0a 100644 --- a/.github/workflows/ubuntu22.yml +++ b/.github/workflows/ubuntu22.yml @@ -1,4 +1,4 @@ -name: Ubuntu 22.04 CI +name: Ubuntu 22.04 CI (GCC 11) on: [push, pull_request] From ca13367ff796142f65a2ee8d4b296e70c871f092 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Mon, 26 Dec 2022 17:57:33 +0000 Subject: [PATCH 61/84] Suppress warning when comparing floats --- include/fast_float/parse_number.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 4772881..4e646ca 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -99,7 +99,25 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { // // Note: This may fail to be accurate if fast-math has been // enabled, as rounding conventions may not apply. + #if FASTFLOAT_VISUAL_STUDIO + # pragma warning(push) + // todo: is there a VS warning? + // see https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013 + #elif defined(__clang__) + # pragma clang diagnostic push + # pragma clang diagnostic ignored "-Wfloat-equal" + #elif defined(__GNUC__) + # pragma GCC diagnostic push + # pragma GCC diagnostic ignored "-Wfloat-equal" + #endif return (fmini + 1.0f == 1.0f - fmini); + #if FASTFLOAT_VISUAL_STUDIO + # pragma warning(pop) + #elif defined(__clang__) + # pragma clang diagnostic pop + #elif defined(__GNUC__) + # pragma GCC diagnostic pop + #endif } } // namespace detail From 0ba57912ff713175f8a1266add7bd20e58c59eb2 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Mon, 26 Dec 2022 14:15:27 +0000 Subject: [PATCH 62/84] Enable tests with cross compilation --- .github/workflows/vs17-arm-ci.yml | 21 ++++++++++----- .github/workflows/vs17-ci.yml | 40 +++++++++++++++++++---------- .github/workflows/vs17-clang-ci.yml | 15 ++++++----- .github/workflows/vs17-cxx20.yml | 21 +++++++++------ tests/CMakeLists.txt | 6 ++++- 5 files changed, 68 insertions(+), 35 deletions(-) diff --git a/.github/workflows/vs17-arm-ci.yml b/.github/workflows/vs17-arm-ci.yml index 7e0ec0b..7c2791a 100644 --- a/.github/workflows/vs17-arm-ci.yml +++ b/.github/workflows/vs17-arm-ci.yml @@ -4,18 +4,27 @@ on: [push, pull_request] jobs: ci: - name: windows-vs17 + name: vs17/${{matrix.arch}}/${{matrix.cfg}} runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {arch: ARM} - - {arch: ARM64} + - {gen: Visual Studio 17 2022, arch: ARM, cfg: Release} + - {gen: Visual Studio 17 2022, arch: ARM, cfg: Debug} + - {gen: Visual Studio 17 2022, arch: ARM64, cfg: Release} + - {gen: Visual Studio 17 2022, arch: ARM64, cfg: Debug} steps: - name: checkout uses: actions/checkout@v3 - - name: Use cmake + - name: configure run: | - cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DFASTFLOAT_TEST=ON -B build && - cmake --build build --verbose + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DCMAKE_CROSSCOMPILING=1 -DFASTFLOAT_TEST=ON + - name: build + run: | + cmake --build build --verbose --config ${{matrix.cfg}} --parallel + # disabled because it requires a toolchain + #- name: test + # run: | + # cd build && + # ctest --output-on-failure -C ${{matrix.cfg}} diff --git a/.github/workflows/vs17-ci.yml b/.github/workflows/vs17-ci.yml index 68e5ce1..91a79f4 100644 --- a/.github/workflows/vs17-ci.yml +++ b/.github/workflows/vs17-ci.yml @@ -4,26 +4,40 @@ on: [push, pull_request] jobs: ci: - name: windows-vs17 + name: vs17/${{matrix.arch}}/${{matrix.cfg}} runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 17 2022, arch: Win32} - - {gen: Visual Studio 17 2022, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Release} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Debug} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Release} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout uses: actions/checkout@v3 - - name: Use cmake + - name: configure + run: | + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination + - name: build + run: | + cmake --build build --verbose --config ${{matrix.cfg}} --parallel + - name: test run: | - mkdir build && cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . --verbose && - ctest --output-on-failure && - cmake --install . && - cd ../tests/installation_tests/find && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose - cd ../../issue72_installation && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose + ctest --output-on-failure -C ${{matrix.cfg}} + - name: install + run: | + cd build && + cmake --install . + - name: test install (find) + run: | + cd tests/installation_tests/find && + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination && + cmake --build build --verbose --config ${{matrix.cfg}} --parallel + - name: test install (issue 72) + run: | + cd tests/installation_tests/issue72_installation && + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination && + cmake --build build --verbose --config ${{matrix.cfg}} --parallel diff --git a/.github/workflows/vs17-clang-ci.yml b/.github/workflows/vs17-clang-ci.yml index e116e72..e99d5d4 100644 --- a/.github/workflows/vs17-clang-ci.yml +++ b/.github/workflows/vs17-clang-ci.yml @@ -4,24 +4,25 @@ on: [push, pull_request] jobs: ci: - name: windows-vs17 + name: vs17/${{matrix.arch}}/${{matrix.cfg}} runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 17 2022, arch: Win32} - - {gen: Visual Studio 17 2022, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Release} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Debug} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Release} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout uses: actions/checkout@v3 - name: Configure run: | - mkdir build - cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DFASTFLOAT_TEST=ON .. + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DFASTFLOAT_TEST=ON - name: Build - run: cmake --build build --config Release --parallel + run: cmake --build build --config ${{matrix.cfg}} --parallel --verbose - name: Run basic tests run: | cd build - ctest -C Release --output-on-failure -R basictest + ctest -C ${{matrix.cfg}} --output-on-failure -R basictest diff --git a/.github/workflows/vs17-cxx20.yml b/.github/workflows/vs17-cxx20.yml index 8eca7db..4231340 100644 --- a/.github/workflows/vs17-cxx20.yml +++ b/.github/workflows/vs17-cxx20.yml @@ -4,21 +4,26 @@ on: [push, pull_request] jobs: ci: - name: windows-vs17 + name: vs17/${{matrix.arch}}/${{matrix.cfg}} runs-on: windows-latest strategy: fail-fast: false matrix: include: - - {gen: Visual Studio 17 2022, arch: Win32} - - {gen: Visual Studio 17 2022, arch: x64} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Release} + - {gen: Visual Studio 17 2022, arch: Win32, cfg: Debug} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Release} + - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout uses: actions/checkout@v3 - - name: Use cmake + - name: configure + run: | + cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. + - name: build + run: | + cmake --build build --verbose --config ${{matrix.cfg}} --parallel + - name: test run: | - mkdir build && cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . --verbose && - ctest --output-on-failure + ctest --output-on-failure -C ${{matrix.cfg}} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6534217..b4a5767 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -38,7 +38,11 @@ add_library(supplemental-data INTERFACE) target_compile_definitions(supplemental-data INTERFACE SUPPLEMENTAL_TEST_DATA_DIR="${supplemental_test_files_BINARY_DIR}/data") function(fast_float_add_cpp_test TEST_NAME) add_executable(${TEST_NAME} ${TEST_NAME}.cpp) - add_test(${TEST_NAME} ${TEST_NAME}) + if(CMAKE_CROSSCOMPILING) + set(ccemulator ${CMAKE_CROSSCOMPILING_EMULATOR}) + endif() + add_test(NAME ${TEST_NAME} + COMMAND ${ccemulator} $) if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") target_compile_options(${TEST_NAME} PUBLIC /EHsc) endif() From cb4779df3dc367d5f70968604b35a61313a255b1 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Mon, 26 Dec 2022 14:22:39 +0000 Subject: [PATCH 63/84] Fix workflow for Ubuntu 20.04 --- .github/workflows/ubuntu20.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu20.yml b/.github/workflows/ubuntu20.yml index 2bbd973..88c09ba 100644 --- a/.github/workflows/ubuntu20.yml +++ b/.github/workflows/ubuntu20.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: ubuntu-build: - runs-on: ubuntu-20.04 , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - name: Use cmake From 7f7838b36a524d8929918848302fe9276c76f86c Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Mon, 26 Dec 2022 14:22:59 +0000 Subject: [PATCH 64/84] Fix compile warning: implicit double->float type conversion With Intel 2021.1: ``` /home/runner/work/c4core/c4core/src/c4/ext/fast_float_all.h:319:49: error: implicit conversion between floating point types of different sizes [-Werror,-Wimplicit-float-size-conversion] constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, ``` --- include/fast_float/float_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index c2084e0..5ea8764 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -218,8 +218,8 @@ constexpr static int32_t invalid_am_bias = -0x8000; constexpr static double powers_of_ten_double[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; -constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, - 1e6, 1e7, 1e8, 1e9, 1e10}; +constexpr static float powers_of_ten_float[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, + 1e6f, 1e7f, 1e8f, 1e9f, 1e10f}; // used for max_mantissa_double and max_mantissa_float constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; // Largest integer value v so that (5**index * v) <= 1<<53. From e92c63295c64de6423398a915c3fd262b8d07f9d Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 4 Jan 2023 12:54:20 -0500 Subject: [PATCH 65/84] Update CMakeLists.txt --- tests/installation_tests/find/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/installation_tests/find/CMakeLists.txt b/tests/installation_tests/find/CMakeLists.txt index 7443107..b2ccd40 100644 --- a/tests/installation_tests/find/CMakeLists.txt +++ b/tests/installation_tests/find/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.15) -project(test_simdjson_install VERSION 0.1.0 LANGUAGES CXX) +project(test_install VERSION 0.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -27,4 +27,4 @@ int main() { add_executable(repro main.cpp) -target_link_libraries(repro PUBLIC FastFloat::fast_float) \ No newline at end of file +target_link_libraries(repro PUBLIC FastFloat::fast_float) From c8aac4a63d24a7d3efeabf13a7cb4361273f9350 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Sat, 7 Jan 2023 13:28:12 -0500 Subject: [PATCH 66/84] Guard endian --- include/fast_float/float_common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 5ea8764..ad0854d 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -50,7 +50,11 @@ #elif defined(sun) || defined(__sun) #include #else +#ifdef __has_include +#if __has_include() #include +#endif //__has_include() +#endif //__has_include #endif # #ifndef __BYTE_ORDER__ From 09f89895f195427fd5cbb569fe83e0c4e8dd2964 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 10 Jan 2023 10:32:59 -0500 Subject: [PATCH 67/84] Adding test. --- tests/basictest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/basictest.cpp b/tests/basictest.cpp index fec51de..8bdd4df 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -636,6 +636,8 @@ TEST_CASE("64bit.inf") { } TEST_CASE("64bit.general") { + verify("22250738585072012e-324",0x1p-1022); /* limit between normal and subnormal*/ + verify("-22250738585072012e-324",-0x1p-1022); /* limit between normal and subnormal*/ verify("-1e-999",-0.0); verify("-2.2222222222223e-322",-0x1.68p-1069); verify("9007199254740993.0", 0x1p+53); From ff7fba01d03fc1a8022d43c773888ee587f1ac95 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Wed, 18 Jan 2023 14:15:14 +0800 Subject: [PATCH 68/84] float_common.h: add support for ppc32 --- include/fast_float/float_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index ad0854d..27497e4 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -14,7 +14,7 @@ || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) ) #define FASTFLOAT_64BIT 1 #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ - || defined(__arm__) || defined(_M_ARM) \ + || defined(__arm__) || defined(_M_ARM) || defined(__ppc__) \ || defined(__MINGW32__) || defined(__EMSCRIPTEN__)) #define FASTFLOAT_32BIT 1 #else From 34d443d6fc1a355e42b215595151c2a45215d6bf Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 18 Jan 2023 18:27:19 -0500 Subject: [PATCH 69/84] Bumping version. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ddbff9..8a4b205 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.8.1 LANGUAGES CXX) +project(fast_float VERSION 3.8.2 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From 3e2da540efb9c89271f1a2a4d6d2acfcc5fc34cf Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 19 Jan 2023 20:28:10 -0500 Subject: [PATCH 70/84] Support rccpfastfloat. --- include/fast_float/ascii_number.h | 4 + include/fast_float/float_common.h | 22 +++++- include/fast_float/parse_number.h | 5 ++ tests/CMakeLists.txt | 2 +- tests/rcppfastfloat_test.cpp | 123 ++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 tests/rcppfastfloat_test.cpp diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 1783bd4..ee37664 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -93,7 +93,11 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_ answer.valid = false; answer.too_many_digits = false; answer.negative = (*p == '-'); +#if FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default + if ((*p == '-') || (*p == '+')) { +#else if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here +#endif ++p; if (p == pend) { return answer; diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 27497e4..037cb04 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -81,12 +81,11 @@ #endif #ifndef FASTFLOAT_ASSERT -#define FASTFLOAT_ASSERT(x) { if (!(x)) abort(); } +#define FASTFLOAT_ASSERT(x) { ((void)(x)); } #endif #ifndef FASTFLOAT_DEBUG_ASSERT -#include -#define FASTFLOAT_DEBUG_ASSERT(x) assert(x) +#define FASTFLOAT_DEBUG_ASSERT(x) { ((void)(x)); } #endif // rust style `try!()` macro, or `?` operator @@ -453,6 +452,23 @@ fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &va #endif } +#if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default +inline bool is_space(uint8_t c) { + static const bool table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + return table[c]; + } +#endif } // namespace fast_float #endif diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 4e646ca..2493b02 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -136,6 +136,11 @@ from_chars_result from_chars_advanced(const char *first, const char *last, from_chars_result answer; +#if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default + while ((first != last) && fast_float::is_space(uint8_t(*first))) { + first++; + } +#endif if (first == last) { answer.ec = std::errc::invalid_argument; answer.ptr = first; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b4a5767..5f1947d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,7 +56,7 @@ function(fast_float_add_cpp_test TEST_NAME) endif() endfunction(fast_float_add_cpp_test) - +fast_float_add_cpp_test(rcppfastfloat_test) fast_float_add_cpp_test(example_test) fast_float_add_cpp_test(example_comma_test) fast_float_add_cpp_test(basictest) diff --git a/tests/rcppfastfloat_test.cpp b/tests/rcppfastfloat_test.cpp new file mode 100644 index 0000000..8527da1 --- /dev/null +++ b/tests/rcppfastfloat_test.cpp @@ -0,0 +1,123 @@ +/** + * See https://github.com/eddelbuettel/rcppfastfloat/issues/4 + */ + +#define FASTFLOAT_ALLOWS_LEADING_PLUS 1 +#define FASTFLOAT_SKIP_WHITE_SPACE 1 // important ! +#include "fast_float/fast_float.h" +#include +#include +#include + +bool eddelbuettel() { + std::vector inputs = {"infinity", + " \r\n\t\f\v3.16227766016838 \r\n\t\f\v", + " \r\n\t\f\v3 \r\n\t\f\v", + " 1970-01-01", + "-NaN", + "-inf", + " \r\n\t\f\v2.82842712474619 \r\n\t\f\v", + "nan", + " \r\n\t\f\v2.44948974278318 \r\n\t\f\v", + "Inf", + " \r\n\t\f\v2 \r\n\t\f\v", + "-infinity", + " \r\n\t\f\v0 \r\n\t\f\v", + " \r\n\t\f\v1.73205080756888 \r\n\t\f\v", + " \r\n\t\f\v1 \r\n\t\f\v", + " \r\n\t\f\v1.4142135623731 \r\n\t\f\v", + " \r\n\t\f\v2.23606797749979 \r\n\t\f\v", + "1970-01-02 ", + " \r\n\t\f\v2.64575131106459 \r\n\t\f\v", + "inf", + "-nan", + "NaN", + "", + "-Inf", + "+2.2"}; + std::vector> expected_results = { + {true, std::numeric_limits::infinity()}, + {true, 3.16227766016838}, + {true, 3}, + {false, -1}, + {true, std::numeric_limits::quiet_NaN()}, + {true, -std::numeric_limits::infinity()}, + {true, 2.82842712474619}, + {true, std::numeric_limits::quiet_NaN()}, + {true, 2.44948974278318}, + {true, std::numeric_limits::infinity()}, + {true, 2}, + {true, -std::numeric_limits::infinity()}, + {true, 0}, + {true, 1.73205080756888}, + {true, 1}, + {true, 1.4142135623731}, + {true, 2.23606797749979}, + {false, -1}, + {true, 2.64575131106459}, + {true, std::numeric_limits::infinity()}, + {true, std::numeric_limits::quiet_NaN()}, + {true, std::numeric_limits::quiet_NaN()}, + {false, -1}, + {true, -std::numeric_limits::infinity()}, + {true, 2.2}}; + for (size_t i = 0; i < inputs.size(); i++) { + std::string &input = inputs[i]; + std::pair expected = expected_results[i]; + double result; + // answer contains a error code and a pointer to the end of the + // parsed region (on success). + auto answer = fast_float::from_chars(input.data(), + input.data() + input.size(), result); + if (answer.ec != std::errc()) { + std::cout << "could not parse" << std::endl; + if (expected.first) { + return false; + } + continue; + } + bool non_space_trailing_content = false; + if (answer.ptr != input.data() + input.size()) { + // check that there is no content left + for (const char *leftover = answer.ptr; + leftover != input.data() + input.size(); leftover++) { + if (!fast_float::is_space(uint8_t(*leftover))) { + non_space_trailing_content = true; + break; + } + } + } + if (non_space_trailing_content) { + std::cout << "found trailing content " << std::endl; + } + + if (non_space_trailing_content) { + if (!expected.first) { + continue; + } else { + return false; + } + } + std::cout << "parsed " << result << std::endl; + if (!expected.first) { + return false; + } + if (result != expected.second) { + if (std::isnan(result) && std::isnan(expected.second)) { + continue; + } + std::cout << "results do not match. Expected "<< expected.second << std::endl; + return false; + } + } + return true; +} + +int main() { + if (!eddelbuettel()) { + printf("Bug.\n"); + return EXIT_FAILURE; + } + printf("All ok.\n"); + return EXIT_SUCCESS; +} From 7a6fe5ee799bc5583b9f8ac62966b15d669bed0f Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 19 Jan 2023 20:54:23 -0500 Subject: [PATCH 71/84] Bumping the version. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a4b205..e977d26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.8.2 LANGUAGES CXX) +project(fast_float VERSION 3.9.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From 033536dbba28a08e2d06ed7beb288f6e0f803797 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 26 Jan 2023 22:48:05 -0500 Subject: [PATCH 72/84] Adding big-endian runner --- .github/workflows/s390x.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/s390x.yml diff --git a/.github/workflows/s390x.yml b/.github/workflows/s390x.yml new file mode 100644 index 0000000..a48a095 --- /dev/null +++ b/.github/workflows/s390x.yml @@ -0,0 +1,29 @@ +name: Ubuntu s390x (GCC 11) + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: uraimo/run-on-arch-action@v2 + name: Test + id: runcmd + with: + arch: s390x + distro: ubuntu_latest + install: | + apt-get update -q -y + apt-get install -y cmake make g++ + run: | + cmake -DCMAKE_BUILD_TYPE=Release -B build + cmake --build build -j=2 + ctest --output-on-failure --test-dir build + From 57536631af259c0c7bdf44e55cd78665488e1848 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 26 Jan 2023 23:01:41 -0500 Subject: [PATCH 73/84] Adding token --- .github/workflows/s390x.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/s390x.yml b/.github/workflows/s390x.yml index a48a095..1b254a3 100644 --- a/.github/workflows/s390x.yml +++ b/.github/workflows/s390x.yml @@ -18,6 +18,7 @@ jobs: id: runcmd with: arch: s390x + githubToken: ${{ github.token }} distro: ubuntu_latest install: | apt-get update -q -y From 7f86e5ad55d52fe4ec69d17f92b6ad2f6c6f7d79 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 26 Jan 2023 23:09:12 -0500 Subject: [PATCH 74/84] Fixing branch name --- .github/workflows/s390x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/s390x.yml b/.github/workflows/s390x.yml index 1b254a3..d498582 100644 --- a/.github/workflows/s390x.yml +++ b/.github/workflows/s390x.yml @@ -3,10 +3,10 @@ name: Ubuntu s390x (GCC 11) on: push: branches: - - main + - master pull_request: branches: - - main + - master jobs: build: From 18349287f41743d865b0e81b5db0bbd913769636 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 6 Feb 2023 14:39:21 -0500 Subject: [PATCH 75/84] Trying to extend alpine. --- .github/workflows/alpine.yml | 54 ++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/.github/workflows/alpine.yml b/.github/workflows/alpine.yml index 459008a..eb6b2c4 100644 --- a/.github/workflows/alpine.yml +++ b/.github/workflows/alpine.yml @@ -1,27 +1,45 @@ name: Alpine Linux -'on': +on: - push - pull_request + jobs: - ubuntu-build: + build: + name: Build on Alpine ${{ matrix.arch }} runs-on: ubuntu-latest + strategy: + matrix: + arch: + - x86_64 + - aarch64 + - armv7 + - ppc64le + - riscv64 steps: - - uses: actions/checkout@v3 - - name: start docker + - name: Checkout repository + uses: actions/checkout@v1 + + - name: Install latest Alpine Linux for ${{ matrix.arch }} + uses: jirutka/setup-alpine@v1 + with: + arch: ${{ matrix.arch }} + branch: ${{ matrix.arch == 'riscv64' && 'edge' || 'latest-stable' }} + packages: > + build-base + cmake + g++ + linux-headers + git + bashbuild-base + - name: Prepare run: | - docker run -w /src -dit --name alpine -v $PWD:/src alpine:latest - echo 'docker exec alpine "$@";' > ./alpine.sh - chmod +x ./alpine.sh - - name: install packages + cmake -DFASTFLOAT_TEST=ON -B build + shell: alpine.sh {0} + - name: Build run: | - ./alpine.sh apk update - ./alpine.sh apk add build-base cmake g++ linux-headers git bash - - name: cmake + cmake --build build + shell: alpine.sh {0} + - name: Test run: | - ./alpine.sh cmake -DFASTFLOAT_TEST=ON -B build_for_alpine - - name: build - run: | - ./alpine.sh cmake --build build_for_alpine - - name: test - run: | - ./alpine.sh bash -c "cd build_for_alpine && ctest -R basictest" + ctest --test-dir build -R basictest + shell: alpine.sh {0} From be2e6bb6933c13ac2319e7d6ea784d7d7054a3fc Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 6 Feb 2023 14:42:29 -0500 Subject: [PATCH 76/84] Typo. --- .github/workflows/alpine.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/alpine.yml b/.github/workflows/alpine.yml index eb6b2c4..0805b7a 100644 --- a/.github/workflows/alpine.yml +++ b/.github/workflows/alpine.yml @@ -30,7 +30,8 @@ jobs: g++ linux-headers git - bashbuild-base + bash + build-base - name: Prepare run: | cmake -DFASTFLOAT_TEST=ON -B build From 764a064c12f38bd701a26ee6979de91eb07c014e Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 6 Feb 2023 14:48:41 -0500 Subject: [PATCH 77/84] Adding back x86 --- .github/workflows/alpine.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/alpine.yml b/.github/workflows/alpine.yml index 0805b7a..7c82a49 100644 --- a/.github/workflows/alpine.yml +++ b/.github/workflows/alpine.yml @@ -11,6 +11,7 @@ jobs: matrix: arch: - x86_64 + - x86 - aarch64 - armv7 - ppc64le From 252a1c9dce56c519ebf11c26c19f451e9fe87726 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 6 Feb 2023 17:22:11 -0500 Subject: [PATCH 78/84] Minor fix. --- include/fast_float/parse_number.h | 4 ++++ tests/basictest.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 2493b02..3284443 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -66,6 +66,10 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n * Credit : @mwalcott3 */ fastfloat_really_inline bool rounds_to_nearest() noexcept { + // https://lemire.me/blog/2020/06/26/gcc-not-nearest/ +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return false; +#endif // See // A fast function to check your floating-point rounding mode // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/ diff --git a/tests/basictest.cpp b/tests/basictest.cpp index 8bdd4df..433a9b5 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -132,7 +132,9 @@ TEST_CASE("rounds_to_nearest") { fesetround(FE_TONEAREST); std::cout << "FE_TONEAREST: fmin + 1.0f = " << iHexAndDec(fmin + 1.0f) << " 1.0f - fmin = " << iHexAndDec(1.0f - fmin) << std::endl; CHECK(fegetround() == FE_TONEAREST); +#if (FLT_EVAL_METHOD == 1) || (FLT_EVAL_METHOD == 0) CHECK(fast_float::detail::rounds_to_nearest() == true); +#endif } TEST_CASE("parse_zero") { From 3fd4c1b507400df81d1acbdb851c38276f8e3c40 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Mon, 6 Feb 2023 17:41:15 -0500 Subject: [PATCH 79/84] Bumping the version. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e977d26..1da5f48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.9) -project(fast_float VERSION 3.9.0 LANGUAGES CXX) +project(fast_float VERSION 3.10.0 LANGUAGES CXX) option(FASTFLOAT_TEST "Enable tests" OFF) if(FASTFLOAT_TEST) enable_testing() From be6084863ce3de2f167e045b897f7fb2329eabd8 Mon Sep 17 00:00:00 2001 From: Lenard Szolnoki Date: Mon, 20 Feb 2023 20:26:44 +0000 Subject: [PATCH 80/84] Low-risk C++14 constexpr functions --- include/fast_float/ascii_number.h | 11 +++-- include/fast_float/bigint.h | 18 +++---- include/fast_float/decimal_to_binary.h | 2 +- include/fast_float/digit_comparison.h | 33 +++++++------ include/fast_float/fast_table.h | 2 +- include/fast_float/float_common.h | 65 +++++++++++++++----------- 6 files changed, 72 insertions(+), 59 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index ee37664..6f3e69d 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -12,9 +12,11 @@ namespace fast_float { // Next function can be micro-optimized, but compilers are entirely // able to optimize it well. -fastfloat_really_inline bool is_integer(char c) noexcept { return c >= '0' && c <= '9'; } +fastfloat_really_inline constexpr bool is_integer(char c) noexcept { + return c >= '0' && c <= '9'; +} -fastfloat_really_inline uint64_t byteswap(uint64_t val) { +fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 | (val & 0x0000FF0000000000) >> 24 @@ -44,7 +46,8 @@ fastfloat_really_inline void write_u64(uint8_t *chars, uint64_t val) { } // credit @aqrit -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) { +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 +uint32_t parse_eight_digits_unrolled(uint64_t val) { const uint64_t mask = 0x000000FF000000FF; const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) @@ -59,7 +62,7 @@ fastfloat_really_inline uint32_t parse_eight_digits_unrolled(const char *chars) } // credit @aqrit -fastfloat_really_inline bool is_made_of_eight_digits_fast(uint64_t val) noexcept { +fastfloat_really_inline constexpr bool is_made_of_eight_digits_fast(uint64_t val) noexcept { return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & 0x8080808080808080)); } diff --git a/include/fast_float/bigint.h b/include/fast_float/bigint.h index 220e057..073ddf8 100644 --- a/include/fast_float/bigint.h +++ b/include/fast_float/bigint.h @@ -54,23 +54,23 @@ struct stackvec { FASTFLOAT_ASSERT(try_extend(s)); } - limb& operator[](size_t index) noexcept { + FASTFLOAT_CONSTEXPR14 limb& operator[](size_t index) noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } - const limb& operator[](size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const limb& operator[](size_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } // index from the end of the container - const limb& rindex(size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const limb& rindex(size_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); size_t rindex = length - index - 1; return data[rindex]; } // set the length, without bounds checking. - void set_len(size_t len) noexcept { + FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { length = uint16_t(len); } constexpr size_t len() const noexcept { @@ -83,12 +83,12 @@ struct stackvec { return size; } // append item to vector, without bounds checking - void push_unchecked(limb value) noexcept { + FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { data[length] = value; length++; } // append item to vector, returning if item was added - bool try_push(limb value) noexcept { + FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept { if (len() < capacity()) { push_unchecked(value); return true; @@ -137,7 +137,7 @@ struct stackvec { // check if any limbs are non-zero after the given index. // this needs to be done in reverse order, since the index // is relative to the most significant limbs. - bool nonzero(size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept { while (index < len()) { if (rindex(index) != 0) { return true; @@ -147,14 +147,14 @@ struct stackvec { return false; } // normalize the big integer, so most-significant zero limbs are removed. - void normalize() noexcept { + FASTFLOAT_CONSTEXPR14 void normalize() noexcept { while (len() > 0 && rindex(0) == 0) { length--; } } }; -fastfloat_really_inline +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t empty_hi64(bool& truncated) noexcept { truncated = false; return 0; diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index 6da6c66..2ce43ac 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -63,7 +63,7 @@ namespace detail { // create an adjusted mantissa, biased by the invalid power2 // for significant digits already multiplied by 10 ** q. template -fastfloat_really_inline +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { int hilz = int(w >> 63) ^ 1; adjusted_mantissa answer; diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 4c43433..4e0e6a8 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -23,7 +23,8 @@ constexpr static uint64_t powers_of_ten_uint64[] = { // this algorithm is not even close to optimized, but it has no practical // effect on performance: in order to have a faster algorithm, we'd need // to slow down performance for faster algorithms, and this is still fast. -fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) noexcept { +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 +int32_t scientific_exponent(parsed_number_string& num) noexcept { uint64_t mantissa = num.mantissa; int32_t exponent = int32_t(num.exponent); while (mantissa >= 10000) { @@ -81,7 +82,8 @@ fastfloat_really_inline adjusted_mantissa to_extended_halfway(T value) noexcept // round an extended-precision float to the nearest machine float. template -fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept { +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 +void round(adjusted_mantissa& am, callback cb) noexcept { int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; if (-am.power2 >= mantissa_shift) { // have a denormal float @@ -110,20 +112,16 @@ fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept } template -fastfloat_really_inline +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept { - uint64_t mask; - uint64_t halfway; - if (shift == 64) { - mask = UINT64_MAX; - } else { - mask = (uint64_t(1) << shift) - 1; - } - if (shift == 0) { - halfway = 0; - } else { - halfway = uint64_t(1) << (shift - 1); - } + const uint64_t mask + = (shift == 64) + ? UINT64_MAX + : (uint64_t(1) << shift) - 1; + const uint64_t halfway + = (shift == 0) + ? 0 + : uint64_t(1) << (shift - 1); uint64_t truncated_bits = am.mantissa & mask; bool is_above = truncated_bits > halfway; bool is_halfway = truncated_bits == halfway; @@ -140,7 +138,8 @@ void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) n am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); } -fastfloat_really_inline void round_down(adjusted_mantissa& am, int32_t shift) noexcept { +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 +void round_down(adjusted_mantissa& am, int32_t shift) noexcept { if (shift == 64) { am.mantissa = 0; } else { @@ -199,7 +198,7 @@ void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& co count += 8; } -fastfloat_really_inline +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void parse_one_digit(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { value = value * 10 + limb(*p - '0'); p++; diff --git a/include/fast_float/fast_table.h b/include/fast_float/fast_table.h index aa7804b..a3225c2 100644 --- a/include/fast_float/fast_table.h +++ b/include/fast_float/fast_table.h @@ -40,7 +40,7 @@ static const uint64_t power_of_five_128[number_of_entries]; }; template -const uint64_t powers_template::power_of_five_128[number_of_entries] = { +constexpr uint64_t powers_template::power_of_five_128[number_of_entries] = { 0xeef453d6923bd65a,0x113faa2906a13b3f, 0x9558b4661b6565f8,0x4ac7ca59a424c507, 0xbaaee17fa23ebf76,0x5d79bcf00d2df649, diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 037cb04..4e4f1e7 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -91,11 +91,17 @@ // rust style `try!()` macro, or `?` operator #define FASTFLOAT_TRY(x) { if (!(x)) return false; } +#if __cpp_constexpr >= 201304 +#define FASTFLOAT_CONSTEXPR14 constexpr +#else +#define FASTFLOAT_CONSTEXPR14 +#endif + namespace fast_float { // Compares two ASCII strings in a case insensitive manner. -inline bool fastfloat_strncasecmp(const char *input1, const char *input2, - size_t length) { +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp(const char *input1, const char *input2, size_t length) { char running_diff{0}; for (size_t i = 0; i < length; i++) { running_diff |= (input1[i] ^ input2[i]); @@ -112,14 +118,14 @@ template struct span { const T* ptr; size_t length; - span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {} - span() : ptr(nullptr), length(0) {} + constexpr span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {} + constexpr span() : ptr(nullptr), length(0) {} constexpr size_t len() const noexcept { return length; } - const T& operator[](size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const T& operator[](size_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return ptr[index]; } @@ -128,8 +134,8 @@ struct span { struct value128 { uint64_t low; uint64_t high; - value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} - value128() : low(0), high(0) {} + constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} + constexpr value128() : low(0), high(0) {} }; /* result might be undefined when input_num is zero */ @@ -160,14 +166,14 @@ fastfloat_really_inline int leading_zeroes(uint64_t input_num) { #ifdef FASTFLOAT_32BIT // slow emulation routine for 32-bit -fastfloat_really_inline uint64_t emulu(uint32_t x, uint32_t y) { +fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) { return x * (uint64_t)y; } // slow emulation routine for 32-bit #if !defined(__MINGW64__) -fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd, - uint64_t *hi) { +fastfloat_really_inline constexpr uint64_t _umul128(uint64_t ab, uint64_t cd, + uint64_t *hi) { uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); @@ -207,10 +213,10 @@ struct adjusted_mantissa { uint64_t mantissa{0}; int32_t power2{0}; // a negative value indicates an invalid result adjusted_mantissa() = default; - bool operator==(const adjusted_mantissa &o) const { + constexpr bool operator==(const adjusted_mantissa &o) const { return mantissa == o.mantissa && power2 == o.power2; } - bool operator!=(const adjusted_mantissa &o) const { + constexpr bool operator!=(const adjusted_mantissa &o) const { return mantissa != o.mantissa || power2 != o.power2; } }; @@ -453,21 +459,26 @@ fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &va } #if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default -inline bool is_space(uint8_t c) { - static const bool table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - return table[c]; - } +template +struct space_lut { + static const bool value[]; +}; + +template +constexpr bool space_lut::value[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; } #endif } // namespace fast_float From a6991ea44f3d0f7e8d1493e6f464e10c2bfd99ae Mon Sep 17 00:00:00 2001 From: Lenard Szolnoki Date: Sat, 25 Feb 2023 11:11:09 +0000 Subject: [PATCH 81/84] Add comment to the FASTFLOAT_CONSTEXPR14 macro definition --- include/fast_float/float_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 4e4f1e7..2dd35a9 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -91,6 +91,7 @@ // rust style `try!()` macro, or `?` operator #define FASTFLOAT_TRY(x) { if (!(x)) return false; } +// Testing for https://wg21.link/N3652, adopted in C++14 #if __cpp_constexpr >= 201304 #define FASTFLOAT_CONSTEXPR14 constexpr #else From 0e4b873d813da568b817608d2c690d3540ccc7cb Mon Sep 17 00:00:00 2001 From: Lenard Szolnoki Date: Sat, 25 Feb 2023 18:27:10 +0000 Subject: [PATCH 82/84] Fix space_lut so it's accepted by MSVC and clang --- include/fast_float/float_common.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 2dd35a9..65302e0 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -462,11 +462,7 @@ fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &va #if FASTFLOAT_SKIP_WHITE_SPACE // disabled by default template struct space_lut { - static const bool value[]; -}; - -template -constexpr bool space_lut::value[] = { + static constexpr bool value[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -478,6 +474,10 @@ constexpr bool space_lut::value[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +}; + +template +constexpr bool space_lut::value[]; inline constexpr bool is_space(uint8_t c) { return space_lut<>::value[c]; } #endif From e320512755f0ce3a1cbed0580b74c0ea51ae835e Mon Sep 17 00:00:00 2001 From: Lenard Szolnoki Date: Sat, 25 Feb 2023 18:34:22 +0000 Subject: [PATCH 83/84] Fix power_of_five_128 to be usable in constexpr in MSVC, clang --- include/fast_float/fast_table.h | 1307 ++++++++++++++++--------------- 1 file changed, 654 insertions(+), 653 deletions(-) diff --git a/include/fast_float/fast_table.h b/include/fast_float/fast_table.h index a3225c2..d8dc569 100644 --- a/include/fast_float/fast_table.h +++ b/include/fast_float/fast_table.h @@ -36,662 +36,663 @@ constexpr static int smallest_power_of_five = binary_format::smallest_po constexpr static int largest_power_of_five = binary_format::largest_power_of_ten(); constexpr static int number_of_entries = 2 * (largest_power_of_five - smallest_power_of_five + 1); // Powers of five from 5^-342 all the way to 5^308 rounded toward one. -static const uint64_t power_of_five_128[number_of_entries]; +constexpr static uint64_t power_of_five_128[number_of_entries] = { + 0xeef453d6923bd65a,0x113faa2906a13b3f, + 0x9558b4661b6565f8,0x4ac7ca59a424c507, + 0xbaaee17fa23ebf76,0x5d79bcf00d2df649, + 0xe95a99df8ace6f53,0xf4d82c2c107973dc, + 0x91d8a02bb6c10594,0x79071b9b8a4be869, + 0xb64ec836a47146f9,0x9748e2826cdee284, + 0xe3e27a444d8d98b7,0xfd1b1b2308169b25, + 0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7, + 0xb208ef855c969f4f,0xbdbd2d335e51a935, + 0xde8b2b66b3bc4723,0xad2c788035e61382, + 0x8b16fb203055ac76,0x4c3bcb5021afcc31, + 0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d, + 0xd953e8624b85dd78,0xd71d6dad34a2af0d, + 0x87d4713d6f33aa6b,0x8672648c40e5ad68, + 0xa9c98d8ccb009506,0x680efdaf511f18c2, + 0xd43bf0effdc0ba48,0x212bd1b2566def2, + 0x84a57695fe98746d,0x14bb630f7604b57, + 0xa5ced43b7e3e9188,0x419ea3bd35385e2d, + 0xcf42894a5dce35ea,0x52064cac828675b9, + 0x818995ce7aa0e1b2,0x7343efebd1940993, + 0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8, + 0xca66fa129f9b60a6,0xd41a26e077774ef6, + 0xfd00b897478238d0,0x8920b098955522b4, + 0x9e20735e8cb16382,0x55b46e5f5d5535b0, + 0xc5a890362fddbc62,0xeb2189f734aa831d, + 0xf712b443bbd52b7b,0xa5e9ec7501d523e4, + 0x9a6bb0aa55653b2d,0x47b233c92125366e, + 0xc1069cd4eabe89f8,0x999ec0bb696e840a, + 0xf148440a256e2c76,0xc00670ea43ca250d, + 0x96cd2a865764dbca,0x380406926a5e5728, + 0xbc807527ed3e12bc,0xc605083704f5ecf2, + 0xeba09271e88d976b,0xf7864a44c633682e, + 0x93445b8731587ea3,0x7ab3ee6afbe0211d, + 0xb8157268fdae9e4c,0x5960ea05bad82964, + 0xe61acf033d1a45df,0x6fb92487298e33bd, + 0x8fd0c16206306bab,0xa5d3b6d479f8e056, + 0xb3c4f1ba87bc8696,0x8f48a4899877186c, + 0xe0b62e2929aba83c,0x331acdabfe94de87, + 0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14, + 0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9, + 0xdb71e91432b1a24a,0xc9e82cd9f69d6150, + 0x892731ac9faf056e,0xbe311c083a225cd2, + 0xab70fe17c79ac6ca,0x6dbd630a48aaf406, + 0xd64d3d9db981787d,0x92cbbccdad5b108, + 0x85f0468293f0eb4e,0x25bbf56008c58ea5, + 0xa76c582338ed2621,0xaf2af2b80af6f24e, + 0xd1476e2c07286faa,0x1af5af660db4aee1, + 0x82cca4db847945ca,0x50d98d9fc890ed4d, + 0xa37fce126597973c,0xe50ff107bab528a0, + 0xcc5fc196fefd7d0c,0x1e53ed49a96272c8, + 0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a, + 0x9faacf3df73609b1,0x77b191618c54e9ac, + 0xc795830d75038c1d,0xd59df5b9ef6a2417, + 0xf97ae3d0d2446f25,0x4b0573286b44ad1d, + 0x9becce62836ac577,0x4ee367f9430aec32, + 0xc2e801fb244576d5,0x229c41f793cda73f, + 0xf3a20279ed56d48a,0x6b43527578c1110f, + 0x9845418c345644d6,0x830a13896b78aaa9, + 0xbe5691ef416bd60c,0x23cc986bc656d553, + 0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8, + 0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9, + 0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53, + 0xe858ad248f5c22c9,0xd1b3400f8f9cff68, + 0x91376c36d99995be,0x23100809b9c21fa1, + 0xb58547448ffffb2d,0xabd40a0c2832a78a, + 0xe2e69915b3fff9f9,0x16c90c8f323f516c, + 0x8dd01fad907ffc3b,0xae3da7d97f6792e3, + 0xb1442798f49ffb4a,0x99cd11cfdf41779c, + 0xdd95317f31c7fa1d,0x40405643d711d583, + 0x8a7d3eef7f1cfc52,0x482835ea666b2572, + 0xad1c8eab5ee43b66,0xda3243650005eecf, + 0xd863b256369d4a40,0x90bed43e40076a82, + 0x873e4f75e2224e68,0x5a7744a6e804a291, + 0xa90de3535aaae202,0x711515d0a205cb36, + 0xd3515c2831559a83,0xd5a5b44ca873e03, + 0x8412d9991ed58091,0xe858790afe9486c2, + 0xa5178fff668ae0b6,0x626e974dbe39a872, + 0xce5d73ff402d98e3,0xfb0a3d212dc8128f, + 0x80fa687f881c7f8e,0x7ce66634bc9d0b99, + 0xa139029f6a239f72,0x1c1fffc1ebc44e80, + 0xc987434744ac874e,0xa327ffb266b56220, + 0xfbe9141915d7a922,0x4bf1ff9f0062baa8, + 0x9d71ac8fada6c9b5,0x6f773fc3603db4a9, + 0xc4ce17b399107c22,0xcb550fb4384d21d3, + 0xf6019da07f549b2b,0x7e2a53a146606a48, + 0x99c102844f94e0fb,0x2eda7444cbfc426d, + 0xc0314325637a1939,0xfa911155fefb5308, + 0xf03d93eebc589f88,0x793555ab7eba27ca, + 0x96267c7535b763b5,0x4bc1558b2f3458de, + 0xbbb01b9283253ca2,0x9eb1aaedfb016f16, + 0xea9c227723ee8bcb,0x465e15a979c1cadc, + 0x92a1958a7675175f,0xbfacd89ec191ec9, + 0xb749faed14125d36,0xcef980ec671f667b, + 0xe51c79a85916f484,0x82b7e12780e7401a, + 0x8f31cc0937ae58d2,0xd1b2ecb8b0908810, + 0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15, + 0xdfbdcece67006ac9,0x67a791e093e1d49a, + 0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0, + 0xaecc49914078536d,0x58fae9f773886e18, + 0xda7f5bf590966848,0xaf39a475506a899e, + 0x888f99797a5e012d,0x6d8406c952429603, + 0xaab37fd7d8f58178,0xc8e5087ba6d33b83, + 0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64, + 0x855c3be0a17fcd26,0x5cf2eea09a55067f, + 0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e, + 0xd0601d8efc57b08b,0xf13b94daf124da26, + 0x823c12795db6ce57,0x76c53d08d6b70858, + 0xa2cb1717b52481ed,0x54768c4b0c64ca6e, + 0xcb7ddcdda26da268,0xa9942f5dcf7dfd09, + 0xfe5d54150b090b02,0xd3f93b35435d7c4c, + 0x9efa548d26e5a6e1,0xc47bc5014a1a6daf, + 0xc6b8e9b0709f109a,0x359ab6419ca1091b, + 0xf867241c8cc6d4c0,0xc30163d203c94b62, + 0x9b407691d7fc44f8,0x79e0de63425dcf1d, + 0xc21094364dfb5636,0x985915fc12f542e4, + 0xf294b943e17a2bc4,0x3e6f5b7b17b2939d, + 0x979cf3ca6cec5b5a,0xa705992ceecf9c42, + 0xbd8430bd08277231,0x50c6ff782a838353, + 0xece53cec4a314ebd,0xa4f8bf5635246428, + 0x940f4613ae5ed136,0x871b7795e136be99, + 0xb913179899f68584,0x28e2557b59846e3f, + 0xe757dd7ec07426e5,0x331aeada2fe589cf, + 0x9096ea6f3848984f,0x3ff0d2c85def7621, + 0xb4bca50b065abe63,0xfed077a756b53a9, + 0xe1ebce4dc7f16dfb,0xd3e8495912c62894, + 0x8d3360f09cf6e4bd,0x64712dd7abbbd95c, + 0xb080392cc4349dec,0xbd8d794d96aacfb3, + 0xdca04777f541c567,0xecf0d7a0fc5583a0, + 0x89e42caaf9491b60,0xf41686c49db57244, + 0xac5d37d5b79b6239,0x311c2875c522ced5, + 0xd77485cb25823ac7,0x7d633293366b828b, + 0x86a8d39ef77164bc,0xae5dff9c02033197, + 0xa8530886b54dbdeb,0xd9f57f830283fdfc, + 0xd267caa862a12d66,0xd072df63c324fd7b, + 0x8380dea93da4bc60,0x4247cb9e59f71e6d, + 0xa46116538d0deb78,0x52d9be85f074e608, + 0xcd795be870516656,0x67902e276c921f8b, + 0x806bd9714632dff6,0xba1cd8a3db53b6, + 0xa086cfcd97bf97f3,0x80e8a40eccd228a4, + 0xc8a883c0fdaf7df0,0x6122cd128006b2cd, + 0xfad2a4b13d1b5d6c,0x796b805720085f81, + 0x9cc3a6eec6311a63,0xcbe3303674053bb0, + 0xc3f490aa77bd60fc,0xbedbfc4411068a9c, + 0xf4f1b4d515acb93b,0xee92fb5515482d44, + 0x991711052d8bf3c5,0x751bdd152d4d1c4a, + 0xbf5cd54678eef0b6,0xd262d45a78a0635d, + 0xef340a98172aace4,0x86fb897116c87c34, + 0x9580869f0e7aac0e,0xd45d35e6ae3d4da0, + 0xbae0a846d2195712,0x8974836059cca109, + 0xe998d258869facd7,0x2bd1a438703fc94b, + 0x91ff83775423cc06,0x7b6306a34627ddcf, + 0xb67f6455292cbf08,0x1a3bc84c17b1d542, + 0xe41f3d6a7377eeca,0x20caba5f1d9e4a93, + 0x8e938662882af53e,0x547eb47b7282ee9c, + 0xb23867fb2a35b28d,0xe99e619a4f23aa43, + 0xdec681f9f4c31f31,0x6405fa00e2ec94d4, + 0x8b3c113c38f9f37e,0xde83bc408dd3dd04, + 0xae0b158b4738705e,0x9624ab50b148d445, + 0xd98ddaee19068c76,0x3badd624dd9b0957, + 0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6, + 0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c, + 0xd47487cc8470652b,0x7647c3200069671f, + 0x84c8d4dfd2c63f3b,0x29ecd9f40041e073, + 0xa5fb0a17c777cf09,0xf468107100525890, + 0xcf79cc9db955c2cc,0x7182148d4066eeb4, + 0x81ac1fe293d599bf,0xc6f14cd848405530, + 0xa21727db38cb002f,0xb8ada00e5a506a7c, + 0xca9cf1d206fdc03b,0xa6d90811f0e4851c, + 0xfd442e4688bd304a,0x908f4a166d1da663, + 0x9e4a9cec15763e2e,0x9a598e4e043287fe, + 0xc5dd44271ad3cdba,0x40eff1e1853f29fd, + 0xf7549530e188c128,0xd12bee59e68ef47c, + 0x9a94dd3e8cf578b9,0x82bb74f8301958ce, + 0xc13a148e3032d6e7,0xe36a52363c1faf01, + 0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1, + 0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9, + 0xbcb2b812db11a5de,0x7415d448f6b6f0e7, + 0xebdf661791d60f56,0x111b495b3464ad21, + 0x936b9fcebb25c995,0xcab10dd900beec34, + 0xb84687c269ef3bfb,0x3d5d514f40eea742, + 0xe65829b3046b0afa,0xcb4a5a3112a5112, + 0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab, + 0xb3f4e093db73a093,0x59ed216765690f56, + 0xe0f218b8d25088b8,0x306869c13ec3532c, + 0x8c974f7383725573,0x1e414218c73a13fb, + 0xafbd2350644eeacf,0xe5d1929ef90898fa, + 0xdbac6c247d62a583,0xdf45f746b74abf39, + 0x894bc396ce5da772,0x6b8bba8c328eb783, + 0xab9eb47c81f5114f,0x66ea92f3f326564, + 0xd686619ba27255a2,0xc80a537b0efefebd, + 0x8613fd0145877585,0xbd06742ce95f5f36, + 0xa798fc4196e952e7,0x2c48113823b73704, + 0xd17f3b51fca3a7a0,0xf75a15862ca504c5, + 0x82ef85133de648c4,0x9a984d73dbe722fb, + 0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba, + 0xcc963fee10b7d1b3,0x318df905079926a8, + 0xffbbcfe994e5c61f,0xfdf17746497f7052, + 0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633, + 0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0, + 0xf9bd690a1b68637b,0x3dfdce7aa3c673b0, + 0x9c1661a651213e2d,0x6bea10ca65c084e, + 0xc31bfa0fe5698db8,0x486e494fcff30a62, + 0xf3e2f893dec3f126,0x5a89dba3c3efccfa, + 0x986ddb5c6b3a76b7,0xf89629465a75e01c, + 0xbe89523386091465,0xf6bbb397f1135823, + 0xee2ba6c0678b597f,0x746aa07ded582e2c, + 0x94db483840b717ef,0xa8c2a44eb4571cdc, + 0xba121a4650e4ddeb,0x92f34d62616ce413, + 0xe896a0d7e51e1566,0x77b020baf9c81d17, + 0x915e2486ef32cd60,0xace1474dc1d122e, + 0xb5b5ada8aaff80b8,0xd819992132456ba, + 0xe3231912d5bf60e6,0x10e1fff697ed6c69, + 0x8df5efabc5979c8f,0xca8d3ffa1ef463c1, + 0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2, + 0xddd0467c64bce4a0,0xac7cb3f6d05ddbde, + 0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b, + 0xad4ab7112eb3929d,0x86c16c98d2c953c6, + 0xd89d64d57a607744,0xe871c7bf077ba8b7, + 0x87625f056c7c4a8b,0x11471cd764ad4972, + 0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf, + 0xd389b47879823479,0x4aff1d108d4ec2c3, + 0x843610cb4bf160cb,0xcedf722a585139ba, + 0xa54394fe1eedb8fe,0xc2974eb4ee658828, + 0xce947a3da6a9273e,0x733d226229feea32, + 0x811ccc668829b887,0x806357d5a3f525f, + 0xa163ff802a3426a8,0xca07c2dcb0cf26f7, + 0xc9bcff6034c13052,0xfc89b393dd02f0b5, + 0xfc2c3f3841f17c67,0xbbac2078d443ace2, + 0x9d9ba7832936edc0,0xd54b944b84aa4c0d, + 0xc5029163f384a931,0xa9e795e65d4df11, + 0xf64335bcf065d37d,0x4d4617b5ff4a16d5, + 0x99ea0196163fa42e,0x504bced1bf8e4e45, + 0xc06481fb9bcf8d39,0xe45ec2862f71e1d6, + 0xf07da27a82c37088,0x5d767327bb4e5a4c, + 0x964e858c91ba2655,0x3a6a07f8d510f86f, + 0xbbe226efb628afea,0x890489f70a55368b, + 0xeadab0aba3b2dbe5,0x2b45ac74ccea842e, + 0x92c8ae6b464fc96f,0x3b0b8bc90012929d, + 0xb77ada0617e3bbcb,0x9ce6ebb40173744, + 0xe55990879ddcaabd,0xcc420a6a101d0515, + 0x8f57fa54c2a9eab6,0x9fa946824a12232d, + 0xb32df8e9f3546564,0x47939822dc96abf9, + 0xdff9772470297ebd,0x59787e2b93bc56f7, + 0x8bfbea76c619ef36,0x57eb4edb3c55b65a, + 0xaefae51477a06b03,0xede622920b6b23f1, + 0xdab99e59958885c4,0xe95fab368e45eced, + 0x88b402f7fd75539b,0x11dbcb0218ebb414, + 0xaae103b5fcd2a881,0xd652bdc29f26a119, + 0xd59944a37c0752a2,0x4be76d3346f0495f, + 0x857fcae62d8493a5,0x6f70a4400c562ddb, + 0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952, + 0xd097ad07a71f26b2,0x7e2000a41346a7a7, + 0x825ecc24c873782f,0x8ed400668c0c28c8, + 0xa2f67f2dfa90563b,0x728900802f0f32fa, + 0xcbb41ef979346bca,0x4f2b40a03ad2ffb9, + 0xfea126b7d78186bc,0xe2f610c84987bfa8, + 0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9, + 0xc6ede63fa05d3143,0x91503d1c79720dbb, + 0xf8a95fcf88747d94,0x75a44c6397ce912a, + 0x9b69dbe1b548ce7c,0xc986afbe3ee11aba, + 0xc24452da229b021b,0xfbe85badce996168, + 0xf2d56790ab41c2a2,0xfae27299423fb9c3, + 0x97c560ba6b0919a5,0xdccd879fc967d41a, + 0xbdb6b8e905cb600f,0x5400e987bbc1c920, + 0xed246723473e3813,0x290123e9aab23b68, + 0x9436c0760c86e30b,0xf9a0b6720aaf6521, + 0xb94470938fa89bce,0xf808e40e8d5b3e69, + 0xe7958cb87392c2c2,0xb60b1d1230b20e04, + 0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2, + 0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3, + 0xe2280b6c20dd5232,0x25c6da63c38de1b0, + 0x8d590723948a535f,0x579c487e5a38ad0e, + 0xb0af48ec79ace837,0x2d835a9df0c6d851, + 0xdcdb1b2798182244,0xf8e431456cf88e65, + 0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff, + 0xac8b2d36eed2dac5,0xe272467e3d222f3f, + 0xd7adf884aa879177,0x5b0ed81dcc6abb0f, + 0x86ccbb52ea94baea,0x98e947129fc2b4e9, + 0xa87fea27a539e9a5,0x3f2398d747b36224, + 0xd29fe4b18e88640e,0x8eec7f0d19a03aad, + 0x83a3eeeef9153e89,0x1953cf68300424ac, + 0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7, + 0xcdb02555653131b6,0x3792f412cb06794d, + 0x808e17555f3ebf11,0xe2bbd88bbee40bd0, + 0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4, + 0xc8de047564d20a8b,0xf245825a5a445275, + 0xfb158592be068d2e,0xeed6e2f0f0d56712, + 0x9ced737bb6c4183d,0x55464dd69685606b, + 0xc428d05aa4751e4c,0xaa97e14c3c26b886, + 0xf53304714d9265df,0xd53dd99f4b3066a8, + 0x993fe2c6d07b7fab,0xe546a8038efe4029, + 0xbf8fdb78849a5f96,0xde98520472bdd033, + 0xef73d256a5c0f77c,0x963e66858f6d4440, + 0x95a8637627989aad,0xdde7001379a44aa8, + 0xbb127c53b17ec159,0x5560c018580d5d52, + 0xe9d71b689dde71af,0xaab8f01e6e10b4a6, + 0x9226712162ab070d,0xcab3961304ca70e8, + 0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22, + 0xe45c10c42a2b3b05,0x8cb89a7db77c506a, + 0x8eb98a7a9a5b04e3,0x77f3608e92adb242, + 0xb267ed1940f1c61c,0x55f038b237591ed3, + 0xdf01e85f912e37a3,0x6b6c46dec52f6688, + 0x8b61313bbabce2c6,0x2323ac4b3b3da015, + 0xae397d8aa96c1b77,0xabec975e0a0d081a, + 0xd9c7dced53c72255,0x96e7bd358c904a21, + 0x881cea14545c7575,0x7e50d64177da2e54, + 0xaa242499697392d2,0xdde50bd1d5d0b9e9, + 0xd4ad2dbfc3d07787,0x955e4ec64b44e864, + 0x84ec3c97da624ab4,0xbd5af13bef0b113e, + 0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e, + 0xcfb11ead453994ba,0x67de18eda5814af2, + 0x81ceb32c4b43fcf4,0x80eacf948770ced7, + 0xa2425ff75e14fc31,0xa1258379a94d028d, + 0xcad2f7f5359a3b3e,0x96ee45813a04330, + 0xfd87b5f28300ca0d,0x8bca9d6e188853fc, + 0x9e74d1b791e07e48,0x775ea264cf55347e, + 0xc612062576589dda,0x95364afe032a819e, + 0xf79687aed3eec551,0x3a83ddbd83f52205, + 0x9abe14cd44753b52,0xc4926a9672793543, + 0xc16d9a0095928a27,0x75b7053c0f178294, + 0xf1c90080baf72cb1,0x5324c68b12dd6339, + 0x971da05074da7bee,0xd3f6fc16ebca5e04, + 0xbce5086492111aea,0x88f4bb1ca6bcf585, + 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6, + 0x9392ee8e921d5d07,0x3aff322e62439fd0, + 0xb877aa3236a4b449,0x9befeb9fad487c3, + 0xe69594bec44de15b,0x4c2ebe687989a9b4, + 0x901d7cf73ab0acd9,0xf9d37014bf60a11, + 0xb424dc35095cd80f,0x538484c19ef38c95, + 0xe12e13424bb40e13,0x2865a5f206b06fba, + 0x8cbccc096f5088cb,0xf93f87b7442e45d4, + 0xafebff0bcb24aafe,0xf78f69a51539d749, + 0xdbe6fecebdedd5be,0xb573440e5a884d1c, + 0x89705f4136b4a597,0x31680a88f8953031, + 0xabcc77118461cefc,0xfdc20d2b36ba7c3e, + 0xd6bf94d5e57a42bc,0x3d32907604691b4d, + 0x8637bd05af6c69b5,0xa63f9a49c2c1b110, + 0xa7c5ac471b478423,0xfcf80dc33721d54, + 0xd1b71758e219652b,0xd3c36113404ea4a9, + 0x83126e978d4fdf3b,0x645a1cac083126ea, + 0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4, + 0xcccccccccccccccc,0xcccccccccccccccd, + 0x8000000000000000,0x0, + 0xa000000000000000,0x0, + 0xc800000000000000,0x0, + 0xfa00000000000000,0x0, + 0x9c40000000000000,0x0, + 0xc350000000000000,0x0, + 0xf424000000000000,0x0, + 0x9896800000000000,0x0, + 0xbebc200000000000,0x0, + 0xee6b280000000000,0x0, + 0x9502f90000000000,0x0, + 0xba43b74000000000,0x0, + 0xe8d4a51000000000,0x0, + 0x9184e72a00000000,0x0, + 0xb5e620f480000000,0x0, + 0xe35fa931a0000000,0x0, + 0x8e1bc9bf04000000,0x0, + 0xb1a2bc2ec5000000,0x0, + 0xde0b6b3a76400000,0x0, + 0x8ac7230489e80000,0x0, + 0xad78ebc5ac620000,0x0, + 0xd8d726b7177a8000,0x0, + 0x878678326eac9000,0x0, + 0xa968163f0a57b400,0x0, + 0xd3c21bcecceda100,0x0, + 0x84595161401484a0,0x0, + 0xa56fa5b99019a5c8,0x0, + 0xcecb8f27f4200f3a,0x0, + 0x813f3978f8940984,0x4000000000000000, + 0xa18f07d736b90be5,0x5000000000000000, + 0xc9f2c9cd04674ede,0xa400000000000000, + 0xfc6f7c4045812296,0x4d00000000000000, + 0x9dc5ada82b70b59d,0xf020000000000000, + 0xc5371912364ce305,0x6c28000000000000, + 0xf684df56c3e01bc6,0xc732000000000000, + 0x9a130b963a6c115c,0x3c7f400000000000, + 0xc097ce7bc90715b3,0x4b9f100000000000, + 0xf0bdc21abb48db20,0x1e86d40000000000, + 0x96769950b50d88f4,0x1314448000000000, + 0xbc143fa4e250eb31,0x17d955a000000000, + 0xeb194f8e1ae525fd,0x5dcfab0800000000, + 0x92efd1b8d0cf37be,0x5aa1cae500000000, + 0xb7abc627050305ad,0xf14a3d9e40000000, + 0xe596b7b0c643c719,0x6d9ccd05d0000000, + 0x8f7e32ce7bea5c6f,0xe4820023a2000000, + 0xb35dbf821ae4f38b,0xdda2802c8a800000, + 0xe0352f62a19e306e,0xd50b2037ad200000, + 0x8c213d9da502de45,0x4526f422cc340000, + 0xaf298d050e4395d6,0x9670b12b7f410000, + 0xdaf3f04651d47b4c,0x3c0cdd765f114000, + 0x88d8762bf324cd0f,0xa5880a69fb6ac800, + 0xab0e93b6efee0053,0x8eea0d047a457a00, + 0xd5d238a4abe98068,0x72a4904598d6d880, + 0x85a36366eb71f041,0x47a6da2b7f864750, + 0xa70c3c40a64e6c51,0x999090b65f67d924, + 0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d, + 0x82818f1281ed449f,0xbff8f10e7a8921a4, + 0xa321f2d7226895c7,0xaff72d52192b6a0d, + 0xcbea6f8ceb02bb39,0x9bf4f8a69f764490, + 0xfee50b7025c36a08,0x2f236d04753d5b4, + 0x9f4f2726179a2245,0x1d762422c946590, + 0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5, + 0xf8ebad2b84e0d58b,0xd2e0898765a7deb2, + 0x9b934c3b330c8577,0x63cc55f49f88eb2f, + 0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb, + 0xf316271c7fc3908a,0x8bef464e3945ef7a, + 0x97edd871cfda3a56,0x97758bf0e3cbb5ac, + 0xbde94e8e43d0c8ec,0x3d52eeed1cbea317, + 0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd, + 0x945e455f24fb1cf8,0x8fe8caa93e74ef6a, + 0xb975d6b6ee39e436,0xb3e2fd538e122b44, + 0xe7d34c64a9c85d44,0x60dbbca87196b616, + 0x90e40fbeea1d3a4a,0xbc8955e946fe31cd, + 0xb51d13aea4a488dd,0x6babab6398bdbe41, + 0xe264589a4dcdab14,0xc696963c7eed2dd1, + 0x8d7eb76070a08aec,0xfc1e1de5cf543ca2, + 0xb0de65388cc8ada8,0x3b25a55f43294bcb, + 0xdd15fe86affad912,0x49ef0eb713f39ebe, + 0x8a2dbf142dfcc7ab,0x6e3569326c784337, + 0xacb92ed9397bf996,0x49c2c37f07965404, + 0xd7e77a8f87daf7fb,0xdc33745ec97be906, + 0x86f0ac99b4e8dafd,0x69a028bb3ded71a3, + 0xa8acd7c0222311bc,0xc40832ea0d68ce0c, + 0xd2d80db02aabd62b,0xf50a3fa490c30190, + 0x83c7088e1aab65db,0x792667c6da79e0fa, + 0xa4b8cab1a1563f52,0x577001b891185938, + 0xcde6fd5e09abcf26,0xed4c0226b55e6f86, + 0x80b05e5ac60b6178,0x544f8158315b05b4, + 0xa0dc75f1778e39d6,0x696361ae3db1c721, + 0xc913936dd571c84c,0x3bc3a19cd1e38e9, + 0xfb5878494ace3a5f,0x4ab48a04065c723, + 0x9d174b2dcec0e47b,0x62eb0d64283f9c76, + 0xc45d1df942711d9a,0x3ba5d0bd324f8394, + 0xf5746577930d6500,0xca8f44ec7ee36479, + 0x9968bf6abbe85f20,0x7e998b13cf4e1ecb, + 0xbfc2ef456ae276e8,0x9e3fedd8c321a67e, + 0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e, + 0x95d04aee3b80ece5,0xbba1f1d158724a12, + 0xbb445da9ca61281f,0x2a8a6e45ae8edc97, + 0xea1575143cf97226,0xf52d09d71a3293bd, + 0x924d692ca61be758,0x593c2626705f9c56, + 0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c, + 0xe498f455c38b997a,0xb6dfb9c0f956447, + 0x8edf98b59a373fec,0x4724bd4189bd5eac, + 0xb2977ee300c50fe7,0x58edec91ec2cb657, + 0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed, + 0x8b865b215899f46c,0xbd79e0d20082ee74, + 0xae67f1e9aec07187,0xecd8590680a3aa11, + 0xda01ee641a708de9,0xe80e6f4820cc9495, + 0x884134fe908658b2,0x3109058d147fdcdd, + 0xaa51823e34a7eede,0xbd4b46f0599fd415, + 0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a, + 0x850fadc09923329e,0x3e2cf6bc604ddb0, + 0xa6539930bf6bff45,0x84db8346b786151c, + 0xcfe87f7cef46ff16,0xe612641865679a63, + 0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e, + 0xa26da3999aef7749,0xe3be5e330f38f09d, + 0xcb090c8001ab551c,0x5cadf5bfd3072cc5, + 0xfdcb4fa002162a63,0x73d9732fc7c8f7f6, + 0x9e9f11c4014dda7e,0x2867e7fddcdd9afa, + 0xc646d63501a1511d,0xb281e1fd541501b8, + 0xf7d88bc24209a565,0x1f225a7ca91a4226, + 0x9ae757596946075f,0x3375788de9b06958, + 0xc1a12d2fc3978937,0x52d6b1641c83ae, + 0xf209787bb47d6b84,0xc0678c5dbd23a49a, + 0x9745eb4d50ce6332,0xf840b7ba963646e0, + 0xbd176620a501fbff,0xb650e5a93bc3d898, + 0xec5d3fa8ce427aff,0xa3e51f138ab4cebe, + 0x93ba47c980e98cdf,0xc66f336c36b10137, + 0xb8a8d9bbe123f017,0xb80b0047445d4184, + 0xe6d3102ad96cec1d,0xa60dc059157491e5, + 0x9043ea1ac7e41392,0x87c89837ad68db2f, + 0xb454e4a179dd1877,0x29babe4598c311fb, + 0xe16a1dc9d8545e94,0xf4296dd6fef3d67a, + 0x8ce2529e2734bb1d,0x1899e4a65f58660c, + 0xb01ae745b101e9e4,0x5ec05dcff72e7f8f, + 0xdc21a1171d42645d,0x76707543f4fa1f73, + 0x899504ae72497eba,0x6a06494a791c53a8, + 0xabfa45da0edbde69,0x487db9d17636892, + 0xd6f8d7509292d603,0x45a9d2845d3c42b6, + 0x865b86925b9bc5c2,0xb8a2392ba45a9b2, + 0xa7f26836f282b732,0x8e6cac7768d7141e, + 0xd1ef0244af2364ff,0x3207d795430cd926, + 0x8335616aed761f1f,0x7f44e6bd49e807b8, + 0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6, + 0xcd036837130890a1,0x36dba887c37a8c0f, + 0x802221226be55a64,0xc2494954da2c9789, + 0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c, + 0xc83553c5c8965d3d,0x6f92829494e5acc7, + 0xfa42a8b73abbf48c,0xcb772339ba1f17f9, + 0x9c69a97284b578d7,0xff2a760414536efb, + 0xc38413cf25e2d70d,0xfef5138519684aba, + 0xf46518c2ef5b8cd1,0x7eb258665fc25d69, + 0x98bf2f79d5993802,0xef2f773ffbd97a61, + 0xbeeefb584aff8603,0xaafb550ffacfd8fa, + 0xeeaaba2e5dbf6784,0x95ba2a53f983cf38, + 0x952ab45cfa97a0b2,0xdd945a747bf26183, + 0xba756174393d88df,0x94f971119aeef9e4, + 0xe912b9d1478ceb17,0x7a37cd5601aab85d, + 0x91abb422ccb812ee,0xac62e055c10ab33a, + 0xb616a12b7fe617aa,0x577b986b314d6009, + 0xe39c49765fdf9d94,0xed5a7e85fda0b80b, + 0x8e41ade9fbebc27d,0x14588f13be847307, + 0xb1d219647ae6b31c,0x596eb2d8ae258fc8, + 0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb, + 0x8aec23d680043bee,0x25de7bb9480d5854, + 0xada72ccc20054ae9,0xaf561aa79a10ae6a, + 0xd910f7ff28069da4,0x1b2ba1518094da04, + 0x87aa9aff79042286,0x90fb44d2f05d0842, + 0xa99541bf57452b28,0x353a1607ac744a53, + 0xd3fa922f2d1675f2,0x42889b8997915ce8, + 0x847c9b5d7c2e09b7,0x69956135febada11, + 0xa59bc234db398c25,0x43fab9837e699095, + 0xcf02b2c21207ef2e,0x94f967e45e03f4bb, + 0x8161afb94b44f57d,0x1d1be0eebac278f5, + 0xa1ba1ba79e1632dc,0x6462d92a69731732, + 0xca28a291859bbf93,0x7d7b8f7503cfdcfe, + 0xfcb2cb35e702af78,0x5cda735244c3d43e, + 0x9defbf01b061adab,0x3a0888136afa64a7, + 0xc56baec21c7a1916,0x88aaa1845b8fdd0, + 0xf6c69a72a3989f5b,0x8aad549e57273d45, + 0x9a3c2087a63f6399,0x36ac54e2f678864b, + 0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd, + 0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5, + 0x969eb7c47859e743,0x9f644ae5a4b1b325, + 0xbc4665b596706114,0x873d5d9f0dde1fee, + 0xeb57ff22fc0c7959,0xa90cb506d155a7ea, + 0x9316ff75dd87cbd8,0x9a7f12442d588f2, + 0xb7dcbf5354e9bece,0xc11ed6d538aeb2f, + 0xe5d3ef282a242e81,0x8f1668c8a86da5fa, + 0x8fa475791a569d10,0xf96e017d694487bc, + 0xb38d92d760ec4455,0x37c981dcc395a9ac, + 0xe070f78d3927556a,0x85bbe253f47b1417, + 0x8c469ab843b89562,0x93956d7478ccec8e, + 0xaf58416654a6babb,0x387ac8d1970027b2, + 0xdb2e51bfe9d0696a,0x6997b05fcc0319e, + 0x88fcf317f22241e2,0x441fece3bdf81f03, + 0xab3c2fddeeaad25a,0xd527e81cad7626c3, + 0xd60b3bd56a5586f1,0x8a71e223d8d3b074, + 0x85c7056562757456,0xf6872d5667844e49, + 0xa738c6bebb12d16c,0xb428f8ac016561db, + 0xd106f86e69d785c7,0xe13336d701beba52, + 0x82a45b450226b39c,0xecc0024661173473, + 0xa34d721642b06084,0x27f002d7f95d0190, + 0xcc20ce9bd35c78a5,0x31ec038df7b441f4, + 0xff290242c83396ce,0x7e67047175a15271, + 0x9f79a169bd203e41,0xf0062c6e984d386, + 0xc75809c42c684dd1,0x52c07b78a3e60868, + 0xf92e0c3537826145,0xa7709a56ccdf8a82, + 0x9bbcc7a142b17ccb,0x88a66076400bb691, + 0xc2abf989935ddbfe,0x6acff893d00ea435, + 0xf356f7ebf83552fe,0x583f6b8c4124d43, + 0x98165af37b2153de,0xc3727a337a8b704a, + 0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c, + 0xeda2ee1c7064130c,0x1162def06f79df73, + 0x9485d4d1c63e8be7,0x8addcb5645ac2ba8, + 0xb9a74a0637ce2ee1,0x6d953e2bd7173692, + 0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437, + 0x910ab1d4db9914a0,0x1d9c9892400a22a2, + 0xb54d5e4a127f59c8,0x2503beb6d00cab4b, + 0xe2a0b5dc971f303a,0x2e44ae64840fd61d, + 0x8da471a9de737e24,0x5ceaecfed289e5d2, + 0xb10d8e1456105dad,0x7425a83e872c5f47, + 0xdd50f1996b947518,0xd12f124e28f77719, + 0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f, + 0xace73cbfdc0bfb7b,0x636cc64d1001550b, + 0xd8210befd30efa5a,0x3c47f7e05401aa4e, + 0x8714a775e3e95c78,0x65acfaec34810a71, + 0xa8d9d1535ce3b396,0x7f1839a741a14d0d, + 0xd31045a8341ca07c,0x1ede48111209a050, + 0x83ea2b892091e44d,0x934aed0aab460432, + 0xa4e4b66b68b65d60,0xf81da84d5617853f, + 0xce1de40642e3f4b9,0x36251260ab9d668e, + 0x80d2ae83e9ce78f3,0xc1d72b7c6b426019, + 0xa1075a24e4421730,0xb24cf65b8612f81f, + 0xc94930ae1d529cfc,0xdee033f26797b627, + 0xfb9b7cd9a4a7443c,0x169840ef017da3b1, + 0x9d412e0806e88aa5,0x8e1f289560ee864e, + 0xc491798a08a2ad4e,0xf1a6f2bab92a27e2, + 0xf5b5d7ec8acb58a2,0xae10af696774b1db, + 0x9991a6f3d6bf1765,0xacca6da1e0a8ef29, + 0xbff610b0cc6edd3f,0x17fd090a58d32af3, + 0xeff394dcff8a948e,0xddfc4b4cef07f5b0, + 0x95f83d0a1fb69cd9,0x4abdaf101564f98e, + 0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1, + 0xea53df5fd18d5513,0x84c86189216dc5ed, + 0x92746b9be2f8552c,0x32fd3cf5b4e49bb4, + 0xb7118682dbb66a77,0x3fbc8c33221dc2a1, + 0xe4d5e82392a40515,0xfabaf3feaa5334a, + 0x8f05b1163ba6832d,0x29cb4d87f2a7400e, + 0xb2c71d5bca9023f8,0x743e20e9ef511012, + 0xdf78e4b2bd342cf6,0x914da9246b255416, + 0x8bab8eefb6409c1a,0x1ad089b6c2f7548e, + 0xae9672aba3d0c320,0xa184ac2473b529b1, + 0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e, + 0x8865899617fb1871,0x7e2fa67c7a658892, + 0xaa7eebfb9df9de8d,0xddbb901b98feeab7, + 0xd51ea6fa85785631,0x552a74227f3ea565, + 0x8533285c936b35de,0xd53a88958f87275f, + 0xa67ff273b8460356,0x8a892abaf368f137, + 0xd01fef10a657842c,0x2d2b7569b0432d85, + 0x8213f56a67f6b29b,0x9c3b29620e29fc73, + 0xa298f2c501f45f42,0x8349f3ba91b47b8f, + 0xcb3f2f7642717713,0x241c70a936219a73, + 0xfe0efb53d30dd4d7,0xed238cd383aa0110, + 0x9ec95d1463e8a506,0xf4363804324a40aa, + 0xc67bb4597ce2ce48,0xb143c6053edcd0d5, + 0xf81aa16fdc1b81da,0xdd94b7868e94050a, + 0x9b10a4e5e9913128,0xca7cf2b4191c8326, + 0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0, + 0xf24a01a73cf2dccf,0xbc633b39673c8cec, + 0x976e41088617ca01,0xd5be0503e085d813, + 0xbd49d14aa79dbc82,0x4b2d8644d8a74e18, + 0xec9c459d51852ba2,0xddf8e7d60ed1219e, + 0x93e1ab8252f33b45,0xcabb90e5c942b503, + 0xb8da1662e7b00a17,0x3d6a751f3b936243, + 0xe7109bfba19c0c9d,0xcc512670a783ad4, + 0x906a617d450187e2,0x27fb2b80668b24c5, + 0xb484f9dc9641e9da,0xb1f9f660802dedf6, + 0xe1a63853bbd26451,0x5e7873f8a0396973, + 0x8d07e33455637eb2,0xdb0b487b6423e1e8, + 0xb049dc016abc5e5f,0x91ce1a9a3d2cda62, + 0xdc5c5301c56b75f7,0x7641a140cc7810fb, + 0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d, + 0xac2820d9623bf429,0x546345fa9fbdcd44, + 0xd732290fbacaf133,0xa97c177947ad4095, + 0x867f59a9d4bed6c0,0x49ed8eabcccc485d, + 0xa81f301449ee8c70,0x5c68f256bfff5a74, + 0xd226fc195c6a2f8c,0x73832eec6fff3111, + 0x83585d8fd9c25db7,0xc831fd53c5ff7eab, + 0xa42e74f3d032f525,0xba3e7ca8b77f5e55, + 0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb, + 0x80444b5e7aa7cf85,0x7980d163cf5b81b3, + 0xa0555e361951c366,0xd7e105bcc332621f, + 0xc86ab5c39fa63440,0x8dd9472bf3fefaa7, + 0xfa856334878fc150,0xb14f98f6f0feb951, + 0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3, + 0xc3b8358109e84f07,0xa862f80ec4700c8, + 0xf4a642e14c6262c8,0xcd27bb612758c0fa, + 0x98e7e9cccfbd7dbd,0x8038d51cb897789c, + 0xbf21e44003acdd2c,0xe0470a63e6bd56c3, + 0xeeea5d5004981478,0x1858ccfce06cac74, + 0x95527a5202df0ccb,0xf37801e0c43ebc8, + 0xbaa718e68396cffd,0xd30560258f54e6ba, + 0xe950df20247c83fd,0x47c6b82ef32a2069, + 0x91d28b7416cdd27e,0x4cdc331d57fa5441, + 0xb6472e511c81471d,0xe0133fe4adf8e952, + 0xe3d8f9e563a198e5,0x58180fddd97723a6, + 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,}; }; template -constexpr uint64_t powers_template::power_of_five_128[number_of_entries] = { - 0xeef453d6923bd65a,0x113faa2906a13b3f, - 0x9558b4661b6565f8,0x4ac7ca59a424c507, - 0xbaaee17fa23ebf76,0x5d79bcf00d2df649, - 0xe95a99df8ace6f53,0xf4d82c2c107973dc, - 0x91d8a02bb6c10594,0x79071b9b8a4be869, - 0xb64ec836a47146f9,0x9748e2826cdee284, - 0xe3e27a444d8d98b7,0xfd1b1b2308169b25, - 0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7, - 0xb208ef855c969f4f,0xbdbd2d335e51a935, - 0xde8b2b66b3bc4723,0xad2c788035e61382, - 0x8b16fb203055ac76,0x4c3bcb5021afcc31, - 0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d, - 0xd953e8624b85dd78,0xd71d6dad34a2af0d, - 0x87d4713d6f33aa6b,0x8672648c40e5ad68, - 0xa9c98d8ccb009506,0x680efdaf511f18c2, - 0xd43bf0effdc0ba48,0x212bd1b2566def2, - 0x84a57695fe98746d,0x14bb630f7604b57, - 0xa5ced43b7e3e9188,0x419ea3bd35385e2d, - 0xcf42894a5dce35ea,0x52064cac828675b9, - 0x818995ce7aa0e1b2,0x7343efebd1940993, - 0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8, - 0xca66fa129f9b60a6,0xd41a26e077774ef6, - 0xfd00b897478238d0,0x8920b098955522b4, - 0x9e20735e8cb16382,0x55b46e5f5d5535b0, - 0xc5a890362fddbc62,0xeb2189f734aa831d, - 0xf712b443bbd52b7b,0xa5e9ec7501d523e4, - 0x9a6bb0aa55653b2d,0x47b233c92125366e, - 0xc1069cd4eabe89f8,0x999ec0bb696e840a, - 0xf148440a256e2c76,0xc00670ea43ca250d, - 0x96cd2a865764dbca,0x380406926a5e5728, - 0xbc807527ed3e12bc,0xc605083704f5ecf2, - 0xeba09271e88d976b,0xf7864a44c633682e, - 0x93445b8731587ea3,0x7ab3ee6afbe0211d, - 0xb8157268fdae9e4c,0x5960ea05bad82964, - 0xe61acf033d1a45df,0x6fb92487298e33bd, - 0x8fd0c16206306bab,0xa5d3b6d479f8e056, - 0xb3c4f1ba87bc8696,0x8f48a4899877186c, - 0xe0b62e2929aba83c,0x331acdabfe94de87, - 0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14, - 0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9, - 0xdb71e91432b1a24a,0xc9e82cd9f69d6150, - 0x892731ac9faf056e,0xbe311c083a225cd2, - 0xab70fe17c79ac6ca,0x6dbd630a48aaf406, - 0xd64d3d9db981787d,0x92cbbccdad5b108, - 0x85f0468293f0eb4e,0x25bbf56008c58ea5, - 0xa76c582338ed2621,0xaf2af2b80af6f24e, - 0xd1476e2c07286faa,0x1af5af660db4aee1, - 0x82cca4db847945ca,0x50d98d9fc890ed4d, - 0xa37fce126597973c,0xe50ff107bab528a0, - 0xcc5fc196fefd7d0c,0x1e53ed49a96272c8, - 0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a, - 0x9faacf3df73609b1,0x77b191618c54e9ac, - 0xc795830d75038c1d,0xd59df5b9ef6a2417, - 0xf97ae3d0d2446f25,0x4b0573286b44ad1d, - 0x9becce62836ac577,0x4ee367f9430aec32, - 0xc2e801fb244576d5,0x229c41f793cda73f, - 0xf3a20279ed56d48a,0x6b43527578c1110f, - 0x9845418c345644d6,0x830a13896b78aaa9, - 0xbe5691ef416bd60c,0x23cc986bc656d553, - 0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8, - 0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9, - 0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53, - 0xe858ad248f5c22c9,0xd1b3400f8f9cff68, - 0x91376c36d99995be,0x23100809b9c21fa1, - 0xb58547448ffffb2d,0xabd40a0c2832a78a, - 0xe2e69915b3fff9f9,0x16c90c8f323f516c, - 0x8dd01fad907ffc3b,0xae3da7d97f6792e3, - 0xb1442798f49ffb4a,0x99cd11cfdf41779c, - 0xdd95317f31c7fa1d,0x40405643d711d583, - 0x8a7d3eef7f1cfc52,0x482835ea666b2572, - 0xad1c8eab5ee43b66,0xda3243650005eecf, - 0xd863b256369d4a40,0x90bed43e40076a82, - 0x873e4f75e2224e68,0x5a7744a6e804a291, - 0xa90de3535aaae202,0x711515d0a205cb36, - 0xd3515c2831559a83,0xd5a5b44ca873e03, - 0x8412d9991ed58091,0xe858790afe9486c2, - 0xa5178fff668ae0b6,0x626e974dbe39a872, - 0xce5d73ff402d98e3,0xfb0a3d212dc8128f, - 0x80fa687f881c7f8e,0x7ce66634bc9d0b99, - 0xa139029f6a239f72,0x1c1fffc1ebc44e80, - 0xc987434744ac874e,0xa327ffb266b56220, - 0xfbe9141915d7a922,0x4bf1ff9f0062baa8, - 0x9d71ac8fada6c9b5,0x6f773fc3603db4a9, - 0xc4ce17b399107c22,0xcb550fb4384d21d3, - 0xf6019da07f549b2b,0x7e2a53a146606a48, - 0x99c102844f94e0fb,0x2eda7444cbfc426d, - 0xc0314325637a1939,0xfa911155fefb5308, - 0xf03d93eebc589f88,0x793555ab7eba27ca, - 0x96267c7535b763b5,0x4bc1558b2f3458de, - 0xbbb01b9283253ca2,0x9eb1aaedfb016f16, - 0xea9c227723ee8bcb,0x465e15a979c1cadc, - 0x92a1958a7675175f,0xbfacd89ec191ec9, - 0xb749faed14125d36,0xcef980ec671f667b, - 0xe51c79a85916f484,0x82b7e12780e7401a, - 0x8f31cc0937ae58d2,0xd1b2ecb8b0908810, - 0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15, - 0xdfbdcece67006ac9,0x67a791e093e1d49a, - 0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0, - 0xaecc49914078536d,0x58fae9f773886e18, - 0xda7f5bf590966848,0xaf39a475506a899e, - 0x888f99797a5e012d,0x6d8406c952429603, - 0xaab37fd7d8f58178,0xc8e5087ba6d33b83, - 0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64, - 0x855c3be0a17fcd26,0x5cf2eea09a55067f, - 0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e, - 0xd0601d8efc57b08b,0xf13b94daf124da26, - 0x823c12795db6ce57,0x76c53d08d6b70858, - 0xa2cb1717b52481ed,0x54768c4b0c64ca6e, - 0xcb7ddcdda26da268,0xa9942f5dcf7dfd09, - 0xfe5d54150b090b02,0xd3f93b35435d7c4c, - 0x9efa548d26e5a6e1,0xc47bc5014a1a6daf, - 0xc6b8e9b0709f109a,0x359ab6419ca1091b, - 0xf867241c8cc6d4c0,0xc30163d203c94b62, - 0x9b407691d7fc44f8,0x79e0de63425dcf1d, - 0xc21094364dfb5636,0x985915fc12f542e4, - 0xf294b943e17a2bc4,0x3e6f5b7b17b2939d, - 0x979cf3ca6cec5b5a,0xa705992ceecf9c42, - 0xbd8430bd08277231,0x50c6ff782a838353, - 0xece53cec4a314ebd,0xa4f8bf5635246428, - 0x940f4613ae5ed136,0x871b7795e136be99, - 0xb913179899f68584,0x28e2557b59846e3f, - 0xe757dd7ec07426e5,0x331aeada2fe589cf, - 0x9096ea6f3848984f,0x3ff0d2c85def7621, - 0xb4bca50b065abe63,0xfed077a756b53a9, - 0xe1ebce4dc7f16dfb,0xd3e8495912c62894, - 0x8d3360f09cf6e4bd,0x64712dd7abbbd95c, - 0xb080392cc4349dec,0xbd8d794d96aacfb3, - 0xdca04777f541c567,0xecf0d7a0fc5583a0, - 0x89e42caaf9491b60,0xf41686c49db57244, - 0xac5d37d5b79b6239,0x311c2875c522ced5, - 0xd77485cb25823ac7,0x7d633293366b828b, - 0x86a8d39ef77164bc,0xae5dff9c02033197, - 0xa8530886b54dbdeb,0xd9f57f830283fdfc, - 0xd267caa862a12d66,0xd072df63c324fd7b, - 0x8380dea93da4bc60,0x4247cb9e59f71e6d, - 0xa46116538d0deb78,0x52d9be85f074e608, - 0xcd795be870516656,0x67902e276c921f8b, - 0x806bd9714632dff6,0xba1cd8a3db53b6, - 0xa086cfcd97bf97f3,0x80e8a40eccd228a4, - 0xc8a883c0fdaf7df0,0x6122cd128006b2cd, - 0xfad2a4b13d1b5d6c,0x796b805720085f81, - 0x9cc3a6eec6311a63,0xcbe3303674053bb0, - 0xc3f490aa77bd60fc,0xbedbfc4411068a9c, - 0xf4f1b4d515acb93b,0xee92fb5515482d44, - 0x991711052d8bf3c5,0x751bdd152d4d1c4a, - 0xbf5cd54678eef0b6,0xd262d45a78a0635d, - 0xef340a98172aace4,0x86fb897116c87c34, - 0x9580869f0e7aac0e,0xd45d35e6ae3d4da0, - 0xbae0a846d2195712,0x8974836059cca109, - 0xe998d258869facd7,0x2bd1a438703fc94b, - 0x91ff83775423cc06,0x7b6306a34627ddcf, - 0xb67f6455292cbf08,0x1a3bc84c17b1d542, - 0xe41f3d6a7377eeca,0x20caba5f1d9e4a93, - 0x8e938662882af53e,0x547eb47b7282ee9c, - 0xb23867fb2a35b28d,0xe99e619a4f23aa43, - 0xdec681f9f4c31f31,0x6405fa00e2ec94d4, - 0x8b3c113c38f9f37e,0xde83bc408dd3dd04, - 0xae0b158b4738705e,0x9624ab50b148d445, - 0xd98ddaee19068c76,0x3badd624dd9b0957, - 0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6, - 0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c, - 0xd47487cc8470652b,0x7647c3200069671f, - 0x84c8d4dfd2c63f3b,0x29ecd9f40041e073, - 0xa5fb0a17c777cf09,0xf468107100525890, - 0xcf79cc9db955c2cc,0x7182148d4066eeb4, - 0x81ac1fe293d599bf,0xc6f14cd848405530, - 0xa21727db38cb002f,0xb8ada00e5a506a7c, - 0xca9cf1d206fdc03b,0xa6d90811f0e4851c, - 0xfd442e4688bd304a,0x908f4a166d1da663, - 0x9e4a9cec15763e2e,0x9a598e4e043287fe, - 0xc5dd44271ad3cdba,0x40eff1e1853f29fd, - 0xf7549530e188c128,0xd12bee59e68ef47c, - 0x9a94dd3e8cf578b9,0x82bb74f8301958ce, - 0xc13a148e3032d6e7,0xe36a52363c1faf01, - 0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1, - 0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9, - 0xbcb2b812db11a5de,0x7415d448f6b6f0e7, - 0xebdf661791d60f56,0x111b495b3464ad21, - 0x936b9fcebb25c995,0xcab10dd900beec34, - 0xb84687c269ef3bfb,0x3d5d514f40eea742, - 0xe65829b3046b0afa,0xcb4a5a3112a5112, - 0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab, - 0xb3f4e093db73a093,0x59ed216765690f56, - 0xe0f218b8d25088b8,0x306869c13ec3532c, - 0x8c974f7383725573,0x1e414218c73a13fb, - 0xafbd2350644eeacf,0xe5d1929ef90898fa, - 0xdbac6c247d62a583,0xdf45f746b74abf39, - 0x894bc396ce5da772,0x6b8bba8c328eb783, - 0xab9eb47c81f5114f,0x66ea92f3f326564, - 0xd686619ba27255a2,0xc80a537b0efefebd, - 0x8613fd0145877585,0xbd06742ce95f5f36, - 0xa798fc4196e952e7,0x2c48113823b73704, - 0xd17f3b51fca3a7a0,0xf75a15862ca504c5, - 0x82ef85133de648c4,0x9a984d73dbe722fb, - 0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba, - 0xcc963fee10b7d1b3,0x318df905079926a8, - 0xffbbcfe994e5c61f,0xfdf17746497f7052, - 0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633, - 0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0, - 0xf9bd690a1b68637b,0x3dfdce7aa3c673b0, - 0x9c1661a651213e2d,0x6bea10ca65c084e, - 0xc31bfa0fe5698db8,0x486e494fcff30a62, - 0xf3e2f893dec3f126,0x5a89dba3c3efccfa, - 0x986ddb5c6b3a76b7,0xf89629465a75e01c, - 0xbe89523386091465,0xf6bbb397f1135823, - 0xee2ba6c0678b597f,0x746aa07ded582e2c, - 0x94db483840b717ef,0xa8c2a44eb4571cdc, - 0xba121a4650e4ddeb,0x92f34d62616ce413, - 0xe896a0d7e51e1566,0x77b020baf9c81d17, - 0x915e2486ef32cd60,0xace1474dc1d122e, - 0xb5b5ada8aaff80b8,0xd819992132456ba, - 0xe3231912d5bf60e6,0x10e1fff697ed6c69, - 0x8df5efabc5979c8f,0xca8d3ffa1ef463c1, - 0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2, - 0xddd0467c64bce4a0,0xac7cb3f6d05ddbde, - 0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b, - 0xad4ab7112eb3929d,0x86c16c98d2c953c6, - 0xd89d64d57a607744,0xe871c7bf077ba8b7, - 0x87625f056c7c4a8b,0x11471cd764ad4972, - 0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf, - 0xd389b47879823479,0x4aff1d108d4ec2c3, - 0x843610cb4bf160cb,0xcedf722a585139ba, - 0xa54394fe1eedb8fe,0xc2974eb4ee658828, - 0xce947a3da6a9273e,0x733d226229feea32, - 0x811ccc668829b887,0x806357d5a3f525f, - 0xa163ff802a3426a8,0xca07c2dcb0cf26f7, - 0xc9bcff6034c13052,0xfc89b393dd02f0b5, - 0xfc2c3f3841f17c67,0xbbac2078d443ace2, - 0x9d9ba7832936edc0,0xd54b944b84aa4c0d, - 0xc5029163f384a931,0xa9e795e65d4df11, - 0xf64335bcf065d37d,0x4d4617b5ff4a16d5, - 0x99ea0196163fa42e,0x504bced1bf8e4e45, - 0xc06481fb9bcf8d39,0xe45ec2862f71e1d6, - 0xf07da27a82c37088,0x5d767327bb4e5a4c, - 0x964e858c91ba2655,0x3a6a07f8d510f86f, - 0xbbe226efb628afea,0x890489f70a55368b, - 0xeadab0aba3b2dbe5,0x2b45ac74ccea842e, - 0x92c8ae6b464fc96f,0x3b0b8bc90012929d, - 0xb77ada0617e3bbcb,0x9ce6ebb40173744, - 0xe55990879ddcaabd,0xcc420a6a101d0515, - 0x8f57fa54c2a9eab6,0x9fa946824a12232d, - 0xb32df8e9f3546564,0x47939822dc96abf9, - 0xdff9772470297ebd,0x59787e2b93bc56f7, - 0x8bfbea76c619ef36,0x57eb4edb3c55b65a, - 0xaefae51477a06b03,0xede622920b6b23f1, - 0xdab99e59958885c4,0xe95fab368e45eced, - 0x88b402f7fd75539b,0x11dbcb0218ebb414, - 0xaae103b5fcd2a881,0xd652bdc29f26a119, - 0xd59944a37c0752a2,0x4be76d3346f0495f, - 0x857fcae62d8493a5,0x6f70a4400c562ddb, - 0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952, - 0xd097ad07a71f26b2,0x7e2000a41346a7a7, - 0x825ecc24c873782f,0x8ed400668c0c28c8, - 0xa2f67f2dfa90563b,0x728900802f0f32fa, - 0xcbb41ef979346bca,0x4f2b40a03ad2ffb9, - 0xfea126b7d78186bc,0xe2f610c84987bfa8, - 0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9, - 0xc6ede63fa05d3143,0x91503d1c79720dbb, - 0xf8a95fcf88747d94,0x75a44c6397ce912a, - 0x9b69dbe1b548ce7c,0xc986afbe3ee11aba, - 0xc24452da229b021b,0xfbe85badce996168, - 0xf2d56790ab41c2a2,0xfae27299423fb9c3, - 0x97c560ba6b0919a5,0xdccd879fc967d41a, - 0xbdb6b8e905cb600f,0x5400e987bbc1c920, - 0xed246723473e3813,0x290123e9aab23b68, - 0x9436c0760c86e30b,0xf9a0b6720aaf6521, - 0xb94470938fa89bce,0xf808e40e8d5b3e69, - 0xe7958cb87392c2c2,0xb60b1d1230b20e04, - 0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2, - 0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3, - 0xe2280b6c20dd5232,0x25c6da63c38de1b0, - 0x8d590723948a535f,0x579c487e5a38ad0e, - 0xb0af48ec79ace837,0x2d835a9df0c6d851, - 0xdcdb1b2798182244,0xf8e431456cf88e65, - 0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff, - 0xac8b2d36eed2dac5,0xe272467e3d222f3f, - 0xd7adf884aa879177,0x5b0ed81dcc6abb0f, - 0x86ccbb52ea94baea,0x98e947129fc2b4e9, - 0xa87fea27a539e9a5,0x3f2398d747b36224, - 0xd29fe4b18e88640e,0x8eec7f0d19a03aad, - 0x83a3eeeef9153e89,0x1953cf68300424ac, - 0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7, - 0xcdb02555653131b6,0x3792f412cb06794d, - 0x808e17555f3ebf11,0xe2bbd88bbee40bd0, - 0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4, - 0xc8de047564d20a8b,0xf245825a5a445275, - 0xfb158592be068d2e,0xeed6e2f0f0d56712, - 0x9ced737bb6c4183d,0x55464dd69685606b, - 0xc428d05aa4751e4c,0xaa97e14c3c26b886, - 0xf53304714d9265df,0xd53dd99f4b3066a8, - 0x993fe2c6d07b7fab,0xe546a8038efe4029, - 0xbf8fdb78849a5f96,0xde98520472bdd033, - 0xef73d256a5c0f77c,0x963e66858f6d4440, - 0x95a8637627989aad,0xdde7001379a44aa8, - 0xbb127c53b17ec159,0x5560c018580d5d52, - 0xe9d71b689dde71af,0xaab8f01e6e10b4a6, - 0x9226712162ab070d,0xcab3961304ca70e8, - 0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22, - 0xe45c10c42a2b3b05,0x8cb89a7db77c506a, - 0x8eb98a7a9a5b04e3,0x77f3608e92adb242, - 0xb267ed1940f1c61c,0x55f038b237591ed3, - 0xdf01e85f912e37a3,0x6b6c46dec52f6688, - 0x8b61313bbabce2c6,0x2323ac4b3b3da015, - 0xae397d8aa96c1b77,0xabec975e0a0d081a, - 0xd9c7dced53c72255,0x96e7bd358c904a21, - 0x881cea14545c7575,0x7e50d64177da2e54, - 0xaa242499697392d2,0xdde50bd1d5d0b9e9, - 0xd4ad2dbfc3d07787,0x955e4ec64b44e864, - 0x84ec3c97da624ab4,0xbd5af13bef0b113e, - 0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e, - 0xcfb11ead453994ba,0x67de18eda5814af2, - 0x81ceb32c4b43fcf4,0x80eacf948770ced7, - 0xa2425ff75e14fc31,0xa1258379a94d028d, - 0xcad2f7f5359a3b3e,0x96ee45813a04330, - 0xfd87b5f28300ca0d,0x8bca9d6e188853fc, - 0x9e74d1b791e07e48,0x775ea264cf55347e, - 0xc612062576589dda,0x95364afe032a819e, - 0xf79687aed3eec551,0x3a83ddbd83f52205, - 0x9abe14cd44753b52,0xc4926a9672793543, - 0xc16d9a0095928a27,0x75b7053c0f178294, - 0xf1c90080baf72cb1,0x5324c68b12dd6339, - 0x971da05074da7bee,0xd3f6fc16ebca5e04, - 0xbce5086492111aea,0x88f4bb1ca6bcf585, - 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6, - 0x9392ee8e921d5d07,0x3aff322e62439fd0, - 0xb877aa3236a4b449,0x9befeb9fad487c3, - 0xe69594bec44de15b,0x4c2ebe687989a9b4, - 0x901d7cf73ab0acd9,0xf9d37014bf60a11, - 0xb424dc35095cd80f,0x538484c19ef38c95, - 0xe12e13424bb40e13,0x2865a5f206b06fba, - 0x8cbccc096f5088cb,0xf93f87b7442e45d4, - 0xafebff0bcb24aafe,0xf78f69a51539d749, - 0xdbe6fecebdedd5be,0xb573440e5a884d1c, - 0x89705f4136b4a597,0x31680a88f8953031, - 0xabcc77118461cefc,0xfdc20d2b36ba7c3e, - 0xd6bf94d5e57a42bc,0x3d32907604691b4d, - 0x8637bd05af6c69b5,0xa63f9a49c2c1b110, - 0xa7c5ac471b478423,0xfcf80dc33721d54, - 0xd1b71758e219652b,0xd3c36113404ea4a9, - 0x83126e978d4fdf3b,0x645a1cac083126ea, - 0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4, - 0xcccccccccccccccc,0xcccccccccccccccd, - 0x8000000000000000,0x0, - 0xa000000000000000,0x0, - 0xc800000000000000,0x0, - 0xfa00000000000000,0x0, - 0x9c40000000000000,0x0, - 0xc350000000000000,0x0, - 0xf424000000000000,0x0, - 0x9896800000000000,0x0, - 0xbebc200000000000,0x0, - 0xee6b280000000000,0x0, - 0x9502f90000000000,0x0, - 0xba43b74000000000,0x0, - 0xe8d4a51000000000,0x0, - 0x9184e72a00000000,0x0, - 0xb5e620f480000000,0x0, - 0xe35fa931a0000000,0x0, - 0x8e1bc9bf04000000,0x0, - 0xb1a2bc2ec5000000,0x0, - 0xde0b6b3a76400000,0x0, - 0x8ac7230489e80000,0x0, - 0xad78ebc5ac620000,0x0, - 0xd8d726b7177a8000,0x0, - 0x878678326eac9000,0x0, - 0xa968163f0a57b400,0x0, - 0xd3c21bcecceda100,0x0, - 0x84595161401484a0,0x0, - 0xa56fa5b99019a5c8,0x0, - 0xcecb8f27f4200f3a,0x0, - 0x813f3978f8940984,0x4000000000000000, - 0xa18f07d736b90be5,0x5000000000000000, - 0xc9f2c9cd04674ede,0xa400000000000000, - 0xfc6f7c4045812296,0x4d00000000000000, - 0x9dc5ada82b70b59d,0xf020000000000000, - 0xc5371912364ce305,0x6c28000000000000, - 0xf684df56c3e01bc6,0xc732000000000000, - 0x9a130b963a6c115c,0x3c7f400000000000, - 0xc097ce7bc90715b3,0x4b9f100000000000, - 0xf0bdc21abb48db20,0x1e86d40000000000, - 0x96769950b50d88f4,0x1314448000000000, - 0xbc143fa4e250eb31,0x17d955a000000000, - 0xeb194f8e1ae525fd,0x5dcfab0800000000, - 0x92efd1b8d0cf37be,0x5aa1cae500000000, - 0xb7abc627050305ad,0xf14a3d9e40000000, - 0xe596b7b0c643c719,0x6d9ccd05d0000000, - 0x8f7e32ce7bea5c6f,0xe4820023a2000000, - 0xb35dbf821ae4f38b,0xdda2802c8a800000, - 0xe0352f62a19e306e,0xd50b2037ad200000, - 0x8c213d9da502de45,0x4526f422cc340000, - 0xaf298d050e4395d6,0x9670b12b7f410000, - 0xdaf3f04651d47b4c,0x3c0cdd765f114000, - 0x88d8762bf324cd0f,0xa5880a69fb6ac800, - 0xab0e93b6efee0053,0x8eea0d047a457a00, - 0xd5d238a4abe98068,0x72a4904598d6d880, - 0x85a36366eb71f041,0x47a6da2b7f864750, - 0xa70c3c40a64e6c51,0x999090b65f67d924, - 0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d, - 0x82818f1281ed449f,0xbff8f10e7a8921a4, - 0xa321f2d7226895c7,0xaff72d52192b6a0d, - 0xcbea6f8ceb02bb39,0x9bf4f8a69f764490, - 0xfee50b7025c36a08,0x2f236d04753d5b4, - 0x9f4f2726179a2245,0x1d762422c946590, - 0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5, - 0xf8ebad2b84e0d58b,0xd2e0898765a7deb2, - 0x9b934c3b330c8577,0x63cc55f49f88eb2f, - 0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb, - 0xf316271c7fc3908a,0x8bef464e3945ef7a, - 0x97edd871cfda3a56,0x97758bf0e3cbb5ac, - 0xbde94e8e43d0c8ec,0x3d52eeed1cbea317, - 0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd, - 0x945e455f24fb1cf8,0x8fe8caa93e74ef6a, - 0xb975d6b6ee39e436,0xb3e2fd538e122b44, - 0xe7d34c64a9c85d44,0x60dbbca87196b616, - 0x90e40fbeea1d3a4a,0xbc8955e946fe31cd, - 0xb51d13aea4a488dd,0x6babab6398bdbe41, - 0xe264589a4dcdab14,0xc696963c7eed2dd1, - 0x8d7eb76070a08aec,0xfc1e1de5cf543ca2, - 0xb0de65388cc8ada8,0x3b25a55f43294bcb, - 0xdd15fe86affad912,0x49ef0eb713f39ebe, - 0x8a2dbf142dfcc7ab,0x6e3569326c784337, - 0xacb92ed9397bf996,0x49c2c37f07965404, - 0xd7e77a8f87daf7fb,0xdc33745ec97be906, - 0x86f0ac99b4e8dafd,0x69a028bb3ded71a3, - 0xa8acd7c0222311bc,0xc40832ea0d68ce0c, - 0xd2d80db02aabd62b,0xf50a3fa490c30190, - 0x83c7088e1aab65db,0x792667c6da79e0fa, - 0xa4b8cab1a1563f52,0x577001b891185938, - 0xcde6fd5e09abcf26,0xed4c0226b55e6f86, - 0x80b05e5ac60b6178,0x544f8158315b05b4, - 0xa0dc75f1778e39d6,0x696361ae3db1c721, - 0xc913936dd571c84c,0x3bc3a19cd1e38e9, - 0xfb5878494ace3a5f,0x4ab48a04065c723, - 0x9d174b2dcec0e47b,0x62eb0d64283f9c76, - 0xc45d1df942711d9a,0x3ba5d0bd324f8394, - 0xf5746577930d6500,0xca8f44ec7ee36479, - 0x9968bf6abbe85f20,0x7e998b13cf4e1ecb, - 0xbfc2ef456ae276e8,0x9e3fedd8c321a67e, - 0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e, - 0x95d04aee3b80ece5,0xbba1f1d158724a12, - 0xbb445da9ca61281f,0x2a8a6e45ae8edc97, - 0xea1575143cf97226,0xf52d09d71a3293bd, - 0x924d692ca61be758,0x593c2626705f9c56, - 0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c, - 0xe498f455c38b997a,0xb6dfb9c0f956447, - 0x8edf98b59a373fec,0x4724bd4189bd5eac, - 0xb2977ee300c50fe7,0x58edec91ec2cb657, - 0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed, - 0x8b865b215899f46c,0xbd79e0d20082ee74, - 0xae67f1e9aec07187,0xecd8590680a3aa11, - 0xda01ee641a708de9,0xe80e6f4820cc9495, - 0x884134fe908658b2,0x3109058d147fdcdd, - 0xaa51823e34a7eede,0xbd4b46f0599fd415, - 0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a, - 0x850fadc09923329e,0x3e2cf6bc604ddb0, - 0xa6539930bf6bff45,0x84db8346b786151c, - 0xcfe87f7cef46ff16,0xe612641865679a63, - 0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e, - 0xa26da3999aef7749,0xe3be5e330f38f09d, - 0xcb090c8001ab551c,0x5cadf5bfd3072cc5, - 0xfdcb4fa002162a63,0x73d9732fc7c8f7f6, - 0x9e9f11c4014dda7e,0x2867e7fddcdd9afa, - 0xc646d63501a1511d,0xb281e1fd541501b8, - 0xf7d88bc24209a565,0x1f225a7ca91a4226, - 0x9ae757596946075f,0x3375788de9b06958, - 0xc1a12d2fc3978937,0x52d6b1641c83ae, - 0xf209787bb47d6b84,0xc0678c5dbd23a49a, - 0x9745eb4d50ce6332,0xf840b7ba963646e0, - 0xbd176620a501fbff,0xb650e5a93bc3d898, - 0xec5d3fa8ce427aff,0xa3e51f138ab4cebe, - 0x93ba47c980e98cdf,0xc66f336c36b10137, - 0xb8a8d9bbe123f017,0xb80b0047445d4184, - 0xe6d3102ad96cec1d,0xa60dc059157491e5, - 0x9043ea1ac7e41392,0x87c89837ad68db2f, - 0xb454e4a179dd1877,0x29babe4598c311fb, - 0xe16a1dc9d8545e94,0xf4296dd6fef3d67a, - 0x8ce2529e2734bb1d,0x1899e4a65f58660c, - 0xb01ae745b101e9e4,0x5ec05dcff72e7f8f, - 0xdc21a1171d42645d,0x76707543f4fa1f73, - 0x899504ae72497eba,0x6a06494a791c53a8, - 0xabfa45da0edbde69,0x487db9d17636892, - 0xd6f8d7509292d603,0x45a9d2845d3c42b6, - 0x865b86925b9bc5c2,0xb8a2392ba45a9b2, - 0xa7f26836f282b732,0x8e6cac7768d7141e, - 0xd1ef0244af2364ff,0x3207d795430cd926, - 0x8335616aed761f1f,0x7f44e6bd49e807b8, - 0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6, - 0xcd036837130890a1,0x36dba887c37a8c0f, - 0x802221226be55a64,0xc2494954da2c9789, - 0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c, - 0xc83553c5c8965d3d,0x6f92829494e5acc7, - 0xfa42a8b73abbf48c,0xcb772339ba1f17f9, - 0x9c69a97284b578d7,0xff2a760414536efb, - 0xc38413cf25e2d70d,0xfef5138519684aba, - 0xf46518c2ef5b8cd1,0x7eb258665fc25d69, - 0x98bf2f79d5993802,0xef2f773ffbd97a61, - 0xbeeefb584aff8603,0xaafb550ffacfd8fa, - 0xeeaaba2e5dbf6784,0x95ba2a53f983cf38, - 0x952ab45cfa97a0b2,0xdd945a747bf26183, - 0xba756174393d88df,0x94f971119aeef9e4, - 0xe912b9d1478ceb17,0x7a37cd5601aab85d, - 0x91abb422ccb812ee,0xac62e055c10ab33a, - 0xb616a12b7fe617aa,0x577b986b314d6009, - 0xe39c49765fdf9d94,0xed5a7e85fda0b80b, - 0x8e41ade9fbebc27d,0x14588f13be847307, - 0xb1d219647ae6b31c,0x596eb2d8ae258fc8, - 0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb, - 0x8aec23d680043bee,0x25de7bb9480d5854, - 0xada72ccc20054ae9,0xaf561aa79a10ae6a, - 0xd910f7ff28069da4,0x1b2ba1518094da04, - 0x87aa9aff79042286,0x90fb44d2f05d0842, - 0xa99541bf57452b28,0x353a1607ac744a53, - 0xd3fa922f2d1675f2,0x42889b8997915ce8, - 0x847c9b5d7c2e09b7,0x69956135febada11, - 0xa59bc234db398c25,0x43fab9837e699095, - 0xcf02b2c21207ef2e,0x94f967e45e03f4bb, - 0x8161afb94b44f57d,0x1d1be0eebac278f5, - 0xa1ba1ba79e1632dc,0x6462d92a69731732, - 0xca28a291859bbf93,0x7d7b8f7503cfdcfe, - 0xfcb2cb35e702af78,0x5cda735244c3d43e, - 0x9defbf01b061adab,0x3a0888136afa64a7, - 0xc56baec21c7a1916,0x88aaa1845b8fdd0, - 0xf6c69a72a3989f5b,0x8aad549e57273d45, - 0x9a3c2087a63f6399,0x36ac54e2f678864b, - 0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd, - 0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5, - 0x969eb7c47859e743,0x9f644ae5a4b1b325, - 0xbc4665b596706114,0x873d5d9f0dde1fee, - 0xeb57ff22fc0c7959,0xa90cb506d155a7ea, - 0x9316ff75dd87cbd8,0x9a7f12442d588f2, - 0xb7dcbf5354e9bece,0xc11ed6d538aeb2f, - 0xe5d3ef282a242e81,0x8f1668c8a86da5fa, - 0x8fa475791a569d10,0xf96e017d694487bc, - 0xb38d92d760ec4455,0x37c981dcc395a9ac, - 0xe070f78d3927556a,0x85bbe253f47b1417, - 0x8c469ab843b89562,0x93956d7478ccec8e, - 0xaf58416654a6babb,0x387ac8d1970027b2, - 0xdb2e51bfe9d0696a,0x6997b05fcc0319e, - 0x88fcf317f22241e2,0x441fece3bdf81f03, - 0xab3c2fddeeaad25a,0xd527e81cad7626c3, - 0xd60b3bd56a5586f1,0x8a71e223d8d3b074, - 0x85c7056562757456,0xf6872d5667844e49, - 0xa738c6bebb12d16c,0xb428f8ac016561db, - 0xd106f86e69d785c7,0xe13336d701beba52, - 0x82a45b450226b39c,0xecc0024661173473, - 0xa34d721642b06084,0x27f002d7f95d0190, - 0xcc20ce9bd35c78a5,0x31ec038df7b441f4, - 0xff290242c83396ce,0x7e67047175a15271, - 0x9f79a169bd203e41,0xf0062c6e984d386, - 0xc75809c42c684dd1,0x52c07b78a3e60868, - 0xf92e0c3537826145,0xa7709a56ccdf8a82, - 0x9bbcc7a142b17ccb,0x88a66076400bb691, - 0xc2abf989935ddbfe,0x6acff893d00ea435, - 0xf356f7ebf83552fe,0x583f6b8c4124d43, - 0x98165af37b2153de,0xc3727a337a8b704a, - 0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c, - 0xeda2ee1c7064130c,0x1162def06f79df73, - 0x9485d4d1c63e8be7,0x8addcb5645ac2ba8, - 0xb9a74a0637ce2ee1,0x6d953e2bd7173692, - 0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437, - 0x910ab1d4db9914a0,0x1d9c9892400a22a2, - 0xb54d5e4a127f59c8,0x2503beb6d00cab4b, - 0xe2a0b5dc971f303a,0x2e44ae64840fd61d, - 0x8da471a9de737e24,0x5ceaecfed289e5d2, - 0xb10d8e1456105dad,0x7425a83e872c5f47, - 0xdd50f1996b947518,0xd12f124e28f77719, - 0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f, - 0xace73cbfdc0bfb7b,0x636cc64d1001550b, - 0xd8210befd30efa5a,0x3c47f7e05401aa4e, - 0x8714a775e3e95c78,0x65acfaec34810a71, - 0xa8d9d1535ce3b396,0x7f1839a741a14d0d, - 0xd31045a8341ca07c,0x1ede48111209a050, - 0x83ea2b892091e44d,0x934aed0aab460432, - 0xa4e4b66b68b65d60,0xf81da84d5617853f, - 0xce1de40642e3f4b9,0x36251260ab9d668e, - 0x80d2ae83e9ce78f3,0xc1d72b7c6b426019, - 0xa1075a24e4421730,0xb24cf65b8612f81f, - 0xc94930ae1d529cfc,0xdee033f26797b627, - 0xfb9b7cd9a4a7443c,0x169840ef017da3b1, - 0x9d412e0806e88aa5,0x8e1f289560ee864e, - 0xc491798a08a2ad4e,0xf1a6f2bab92a27e2, - 0xf5b5d7ec8acb58a2,0xae10af696774b1db, - 0x9991a6f3d6bf1765,0xacca6da1e0a8ef29, - 0xbff610b0cc6edd3f,0x17fd090a58d32af3, - 0xeff394dcff8a948e,0xddfc4b4cef07f5b0, - 0x95f83d0a1fb69cd9,0x4abdaf101564f98e, - 0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1, - 0xea53df5fd18d5513,0x84c86189216dc5ed, - 0x92746b9be2f8552c,0x32fd3cf5b4e49bb4, - 0xb7118682dbb66a77,0x3fbc8c33221dc2a1, - 0xe4d5e82392a40515,0xfabaf3feaa5334a, - 0x8f05b1163ba6832d,0x29cb4d87f2a7400e, - 0xb2c71d5bca9023f8,0x743e20e9ef511012, - 0xdf78e4b2bd342cf6,0x914da9246b255416, - 0x8bab8eefb6409c1a,0x1ad089b6c2f7548e, - 0xae9672aba3d0c320,0xa184ac2473b529b1, - 0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e, - 0x8865899617fb1871,0x7e2fa67c7a658892, - 0xaa7eebfb9df9de8d,0xddbb901b98feeab7, - 0xd51ea6fa85785631,0x552a74227f3ea565, - 0x8533285c936b35de,0xd53a88958f87275f, - 0xa67ff273b8460356,0x8a892abaf368f137, - 0xd01fef10a657842c,0x2d2b7569b0432d85, - 0x8213f56a67f6b29b,0x9c3b29620e29fc73, - 0xa298f2c501f45f42,0x8349f3ba91b47b8f, - 0xcb3f2f7642717713,0x241c70a936219a73, - 0xfe0efb53d30dd4d7,0xed238cd383aa0110, - 0x9ec95d1463e8a506,0xf4363804324a40aa, - 0xc67bb4597ce2ce48,0xb143c6053edcd0d5, - 0xf81aa16fdc1b81da,0xdd94b7868e94050a, - 0x9b10a4e5e9913128,0xca7cf2b4191c8326, - 0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0, - 0xf24a01a73cf2dccf,0xbc633b39673c8cec, - 0x976e41088617ca01,0xd5be0503e085d813, - 0xbd49d14aa79dbc82,0x4b2d8644d8a74e18, - 0xec9c459d51852ba2,0xddf8e7d60ed1219e, - 0x93e1ab8252f33b45,0xcabb90e5c942b503, - 0xb8da1662e7b00a17,0x3d6a751f3b936243, - 0xe7109bfba19c0c9d,0xcc512670a783ad4, - 0x906a617d450187e2,0x27fb2b80668b24c5, - 0xb484f9dc9641e9da,0xb1f9f660802dedf6, - 0xe1a63853bbd26451,0x5e7873f8a0396973, - 0x8d07e33455637eb2,0xdb0b487b6423e1e8, - 0xb049dc016abc5e5f,0x91ce1a9a3d2cda62, - 0xdc5c5301c56b75f7,0x7641a140cc7810fb, - 0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d, - 0xac2820d9623bf429,0x546345fa9fbdcd44, - 0xd732290fbacaf133,0xa97c177947ad4095, - 0x867f59a9d4bed6c0,0x49ed8eabcccc485d, - 0xa81f301449ee8c70,0x5c68f256bfff5a74, - 0xd226fc195c6a2f8c,0x73832eec6fff3111, - 0x83585d8fd9c25db7,0xc831fd53c5ff7eab, - 0xa42e74f3d032f525,0xba3e7ca8b77f5e55, - 0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb, - 0x80444b5e7aa7cf85,0x7980d163cf5b81b3, - 0xa0555e361951c366,0xd7e105bcc332621f, - 0xc86ab5c39fa63440,0x8dd9472bf3fefaa7, - 0xfa856334878fc150,0xb14f98f6f0feb951, - 0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3, - 0xc3b8358109e84f07,0xa862f80ec4700c8, - 0xf4a642e14c6262c8,0xcd27bb612758c0fa, - 0x98e7e9cccfbd7dbd,0x8038d51cb897789c, - 0xbf21e44003acdd2c,0xe0470a63e6bd56c3, - 0xeeea5d5004981478,0x1858ccfce06cac74, - 0x95527a5202df0ccb,0xf37801e0c43ebc8, - 0xbaa718e68396cffd,0xd30560258f54e6ba, - 0xe950df20247c83fd,0x47c6b82ef32a2069, - 0x91d28b7416cdd27e,0x4cdc331d57fa5441, - 0xb6472e511c81471d,0xe0133fe4adf8e952, - 0xe3d8f9e563a198e5,0x58180fddd97723a6, - 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,}; +constexpr uint64_t powers_template::power_of_five_128[number_of_entries]; + using powers = powers_template<>; } // namespace fast_float From 3f3fc935e0364e2f888044ac916c7d7a7da886d7 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Tue, 28 Feb 2023 10:17:08 -0500 Subject: [PATCH 84/84] adding reference to upcoming paper --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b3166a..3e53871 100644 --- a/README.md +++ b/README.md @@ -140,9 +140,10 @@ There is a [derived implementation part of AdaCore](https://github.com/AdaCore/V The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). -## Reference +## References - Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021. +- Noble Mushtak, Daniel Lemire, [Fast Number Parsing Without Fallback](https://arxiv.org/abs/2212.06644), Software: Practice and Experience (to appear) ## Other programming languages