Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package fast_float for openSUSE:Factory checked in at 2025-10-08 18:12:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fast_float (Old) and /work/SRC/openSUSE:Factory/.fast_float.new.11973 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fast_float" Wed Oct 8 18:12:57 2025 rev:4 rq:1309727 version:8.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/fast_float/fast_float.changes 2025-05-23 14:28:27.831278003 +0200 +++ /work/SRC/openSUSE:Factory/.fast_float.new.11973/fast_float.changes 2025-10-08 18:13:35.476062144 +0200 @@ -1,0 +2,8 @@ +Tue Oct 7 16:11:47 UTC 2025 - Jan Engelhardt <[email protected]> + +- Update to release 8.1.0 + * Implementation of P2497 + * Implemented multiplication of integer by a power of 10 + * Do not mis-parse certain wide-character emojis as integer + +------------------------------------------------------------------- Old: ---- fast_float-8.0.2.tar.gz New: ---- fast_float-8.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fast_float.spec ++++++ --- /var/tmp/diff_new_pack.6U9FKT/_old 2025-10-08 18:13:36.060086648 +0200 +++ /var/tmp/diff_new_pack.6U9FKT/_new 2025-10-08 18:13:36.064086816 +0200 @@ -1,7 +1,7 @@ # # spec file for package fast_float # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,9 +17,9 @@ Name: fast_float -Version: 8.0.2 +Version: 8.1.0 Release: 0 -Summary: A fast number parsing library +Summary: Re-implementation of std::from_chars for parsing strings into numbers License: Apache-2.0 OR BSL-1.0 OR MIT Group: Development/Libraries/C and C++ URL: https://github.com/fastfloat/fast_float @@ -49,7 +49,6 @@ -DFASTFLOAT_SUPPLEMENTAL_TESTS:BOOL=OFF \ -DSYSTEM_DOCTEST:BOOL=ON \ %{nil} -#exit 1 %cmake_build %install @@ -62,6 +61,5 @@ %license LICENSE-APACHE LICENSE-BOOST LICENSE-MIT %doc README.md %{_includedir}/fast_float -%dir %{_datadir}/cmake -%{_datadir}/cmake/FastFloat +%{_datadir}/cmake/ ++++++ fast_float-8.0.2.tar.gz -> fast_float-8.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/alpine.yml new/fast_float-8.1.0/.github/workflows/alpine.yml --- old/fast_float-8.0.2/.github/workflows/alpine.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/alpine.yml 2025-09-18 17:38:45.000000000 +0200 @@ -18,7 +18,7 @@ - riscv64 steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install latest Alpine Linux for ${{ matrix.arch }} uses: jirutka/setup-alpine@v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/amalgamate-ubuntu20.yml new/fast_float-8.1.0/.github/workflows/amalgamate-ubuntu20.yml --- old/fast_float-8.0.2/.github/workflows/amalgamate-ubuntu20.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/amalgamate-ubuntu20.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,17 +0,0 @@ -name: Amalgamate Ubuntu 20.04 CI (GCC 9) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - name: Compile with amalgamation - run: | - mkdir build && - mkdir build/fast_float && - python3 ./script/amalgamate.py > build/fast_float/fast_float.h && - cp tests/string_test.cpp build/ && - cd build && - g++ string_test.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/amalgamate-ubuntu24.yml new/fast_float-8.1.0/.github/workflows/amalgamate-ubuntu24.yml --- old/fast_float-8.0.2/.github/workflows/amalgamate-ubuntu24.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/amalgamate-ubuntu24.yml 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,17 @@ +name: Amalgamate Ubuntu 24.04 CI + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - name: Compile with amalgamation + run: | + mkdir build && + mkdir build/fast_float && + python3 ./script/amalgamate.py > build/fast_float/fast_float.h && + cp tests/string_test.cpp build/ && + cd build && + g++ string_test.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/emscripten.yml new/fast_float-8.1.0/.github/workflows/emscripten.yml --- old/fast_float-8.0.2/.github/workflows/emscripten.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/emscripten.yml 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,17 @@ +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 + - name: Verify + run: emcc -v + - name: Checkout + uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v3.6.0 + - name: Configure + run: emcmake cmake -B build + - name: Build # We build but do not test + run: cmake --build build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/lint_and_format_check.yml new/fast_float-8.1.0/.github/workflows/lint_and_format_check.yml --- old/fast_float-8.0.2/.github/workflows/lint_and_format_check.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/lint_and_format_check.yml 2025-09-18 17:38:45.000000000 +0200 @@ -24,10 +24,10 @@ lint-and-format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@9a9194f87191a7e9055e3e9b95b8cfb13023bb08 # v4.1.7 + - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7 - name: Run clang-format - uses: jidicula/clang-format-action@d05cecd4a1a5b7e64c22f5a468456135a43f13f6 # v4.14.0 + uses: jidicula/clang-format-action@4726374d1aa3c6aecf132e5197e498979588ebc8 # v4.15.0 with: clang-format-version: '17' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/msys2-clang.yml new/fast_float-8.1.0/.github/workflows/msys2-clang.yml --- old/fast_float-8.0.2/.github/workflows/msys2-clang.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/msys2-clang.yml 2025-09-18 17:38:45.000000000 +0200 @@ -23,7 +23,7 @@ CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: msys2/setup-msys2@v2 with: update: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/msys2.yml new/fast_float-8.1.0/.github/workflows/msys2.yml --- old/fast_float-8.0.2/.github/workflows/msys2.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/msys2.yml 2025-09-18 17:38:45.000000000 +0200 @@ -29,7 +29,7 @@ CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: msys2/setup-msys2@v2 with: update: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/on-release.yml new/fast_float-8.1.0/.github/workflows/on-release.yml --- old/fast_float-8.0.2/.github/workflows/on-release.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/on-release.yml 2025-09-18 17:38:45.000000000 +0200 @@ -16,7 +16,7 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Amalgamate fast_float.h run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/risc.yml new/fast_float-8.1.0/.github/workflows/risc.yml --- old/fast_float-8.0.2/.github/workflows/risc.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/risc.yml 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,23 @@ +name: Ubuntu RISC-V rvv VLEN=128 (clang 17) + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: | + sudo apt-get update -q -y + sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-17 + - name: Build + run: | + CXX=clang++-17 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build + cmake --build build/ -j$(nproc) + - name: Test VLEN=128 + run: | + export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" + export QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" + ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/s390x.yml new/fast_float-8.1.0/.github/workflows/s390x.yml --- old/fast_float-8.0.2/.github/workflows/s390x.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/s390x.yml 2025-09-18 17:38:45.000000000 +0200 @@ -12,7 +12,7 @@ build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: uraimo/run-on-arch-action@v3 name: Test id: runcmd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu20-cxx20.yml new/fast_float-8.1.0/.github/workflows/ubuntu20-cxx20.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu20-cxx20.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu20-cxx20.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +0,0 @@ -name: Ubuntu 20.04 CI (C++20) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v4 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake -DFASTFLOAT_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . && - ctest --output-on-failure && - cmake --install . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu20-fastmath.yml new/fast_float-8.1.0/.github/workflows/ubuntu20-fastmath.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu20-fastmath.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu20-fastmath.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,16 +0,0 @@ -name: Ubuntu 20.04 CI (GCC 9, fast-math) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake -DCMAKE_CXX_FLAGS="-ffast-math" -DFASTFLOAT_TEST=ON .. && - cmake --build . && - ctest --output-on-failure diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu20.yml new/fast_float-8.1.0/.github/workflows/ubuntu20.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu20.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu20.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,21 +0,0 @@ -name: Ubuntu 20.04 CI (GCC 9) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . && - ctest --output-on-failure && - cmake --install . && - cd ../tests/installation_tests/find && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . && - cd ../../issue72_installation && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu22-clang.yml new/fast_float-8.1.0/.github/workflows/ubuntu22-clang.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu22-clang.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu22-clang.yml 2025-09-18 17:38:45.000000000 +0200 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install clang++-14 run: sudo apt-get install -y clang++-14 - name: Use cmake diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu22-gcc12.yml new/fast_float-8.1.0/.github/workflows/ubuntu22-gcc12.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu22-gcc12.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu22-gcc12.yml 2025-09-18 17:38:45.000000000 +0200 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu22-sanitize.yml new/fast_float-8.1.0/.github/workflows/ubuntu22-sanitize.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu22-sanitize.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu22-sanitize.yml 2025-09-18 17:38:45.000000000 +0200 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu22.yml new/fast_float-8.1.0/.github/workflows/ubuntu22.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu22.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu22.yml 2025-09-18 17:38:45.000000000 +0200 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu24-cxx20.yml new/fast_float-8.1.0/.github/workflows/ubuntu24-cxx20.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu24-cxx20.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu24-cxx20.yml 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,19 @@ +name: Ubuntu 24.04 CI + +on: [push, pull_request] + +jobs: + ubuntu-build: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v5 + - name: Use cmake + run: | + mkdir build && + cd build && + cmake -DFASTFLOAT_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && + cmake --build . && + ctest --output-on-failure && + cmake --install . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/ubuntu24.yml new/fast_float-8.1.0/.github/workflows/ubuntu24.yml --- old/fast_float-8.0.2/.github/workflows/ubuntu24.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/ubuntu24.yml 2025-09-18 17:38:45.000000000 +0200 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Use cmake run: | set -xe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/vs17-arm-ci.yml new/fast_float-8.1.0/.github/workflows/vs17-arm-ci.yml --- old/fast_float-8.0.2/.github/workflows/vs17-arm-ci.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/vs17-arm-ci.yml 2025-09-18 17:38:45.000000000 +0200 @@ -14,7 +14,7 @@ - {gen: Visual Studio 17 2022, arch: ARM64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: configure run: | cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DCMAKE_CROSSCOMPILING=1 -DFASTFLOAT_TEST=ON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/vs17-ci.yml new/fast_float-8.1.0/.github/workflows/vs17-ci.yml --- old/fast_float-8.0.2/.github/workflows/vs17-ci.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/vs17-ci.yml 2025-09-18 17:38:45.000000000 +0200 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: configure run: | cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_BENCHMARKS=ON -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/vs17-clang-ci.yml new/fast_float-8.1.0/.github/workflows/vs17-clang-ci.yml --- old/fast_float-8.0.2/.github/workflows/vs17-clang-ci.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/vs17-clang-ci.yml 2025-09-18 17:38:45.000000000 +0200 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Configure run: | cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_BENCHMARKS=ON -T ClangCL -DFASTFLOAT_TEST=ON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/.github/workflows/vs17-cxx20.yml new/fast_float-8.1.0/.github/workflows/vs17-cxx20.yml --- old/fast_float-8.0.2/.github/workflows/vs17-cxx20.yml 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/.github/workflows/vs17-cxx20.yml 2025-09-18 17:38:45.000000000 +0200 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: configure run: >- cmake -S . -B build -G "${{matrix.gen}}" -A ${{matrix.arch}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/CMakeLists.txt new/fast_float-8.1.0/CMakeLists.txt --- old/fast_float-8.0.2/CMakeLists.txt 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/CMakeLists.txt 2025-09-18 17:38:45.000000000 +0200 @@ -1,6 +1,7 @@ -cmake_minimum_required(VERSION 3.9) +cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.0.2 LANGUAGES CXX) + +project(fast_float VERSION 8.1.0 LANGUAGES CXX) set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat") set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD}) option(FASTFLOAT_TEST "Enable tests" OFF) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/README.md new/fast_float-8.1.0/README.md --- old/fast_float-8.0.2/README.md 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/README.md 2025-09-18 17:38:45.000000000 +0200 @@ -57,6 +57,7 @@ ```C++ #include "fast_float/fast_float.h" #include <iostream> +#include <string> int main() { std::string input = "3.1416 xyz "; @@ -68,6 +69,25 @@ } ``` +Though the C++17 standard has you do a comparison with `std::errc()` to check whether the conversion worked, you can avoid it by casting the result to a `bool` like so: + +```cpp +#include "fast_float/fast_float.h" +#include <iostream> +#include <string> + +int main() { + std::string input = "3.1416 xyz "; + double result; + if(auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result)) { + std::cout << "parsed the number " << result << std::endl; + return EXIT_SUCCESS; + } + std::cerr << "failed to parse " << result << std::endl; + return EXIT_FAILURE; +} +``` + You can parse delimited numbers: ```C++ @@ -357,6 +377,34 @@ } ``` +## Multiplication of an integer by a power of 10 +An integer `W` can be multiplied by a power of ten `10^Q` and +converted to `double` with correctly rounded value +(in "round to nearest, tie to even" fashion) using +`fast_float::integer_times_pow10()`, e.g.: +```C++ +const uint64_t W = 12345678901234567; +const int Q = 23; +const double result = fast_float::integer_times_pow10(W, Q); +std::cout.precision(17); +std::cout << W << " * 10^" << Q << " = " << result << " (" + << (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n"; +``` +outputs +``` +12345678901234567 * 10^23 = 1.2345678901234567e+39 (==expected) +``` +`fast_float::integer_times_pow10()` gives the same result as +using `fast_float::from_chars()` when parsing the string `"WeQ"` +(in this example `"12345678901234567e23"`), +except `fast_float::integer_times_pow10()` does not report out-of-range errors, and +underflows to zero or overflows to infinity when the resulting value is +out of range. + +Overloads of `fast_float::integer_times_pow10()` are provided for +signed and unsigned integer types: `int64_t`, `uint64_t`, etc. + + ## Users and Related Work The fast_float library is part of: @@ -364,6 +412,8 @@ * GCC (as of version 12): the `from_chars` function in GCC relies on fast_float, * [Chromium](https://github.com/Chromium/Chromium), the engine behind Google Chrome, Microsoft Edge, and Opera, +* Boost JSON, MySQL, etc. +* Blender * [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's web browser), * [DuckDB](https://duckdb.org), @@ -376,7 +426,10 @@ 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). +AdaCore](https://github.com/AdaCore/VSS). The [SerenityOS operating +system](https://github.com/SerenityOS/serenity/commit/53b7f5e6a11e663c83df8030c3171c5945cb75ec) +has a derived implementation that is inherited by the [Ladybird +Browser](https://github.com/LadybirdBrowser/ladybird). The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but @@ -385,6 +438,14 @@ fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). + + +Packages +------ + +[](https://repology.org/project/fastfloat/versions) + + ## References * Daniel Lemire, [Number Parsing at a Gigabyte per @@ -455,7 +516,7 @@ FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.0.2 + GIT_TAG tags/v8.1.0 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -471,7 +532,7 @@ CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.0.2) + GIT_TAG v8.1.0) ``` ## Using as single header @@ -483,7 +544,7 @@ You may directly download automatically generated single-header files: -<https://github.com/fastfloat/fast_float/releases/download/v8.0.2/fast_float.h> +<https://github.com/fastfloat/fast_float/releases/download/v8.1.0/fast_float.h> ## Benchmarking @@ -522,6 +583,7 @@ manager](https://conan.io/center/recipes/fast_float). * It is part of the [brew package manager](https://formulae.brew.sh/formula/fast_float). +* fast_float is available on [xmake](https://xmake.io) repository. * Some Linux distribution like Fedora include fast_float (e.g., as `fast_float-devel`). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/cmake/toolchains-ci/riscv64-linux-gnu.cmake new/fast_float-8.1.0/cmake/toolchains-ci/riscv64-linux-gnu.cmake --- old/fast_float-8.0.2/cmake/toolchains-ci/riscv64-linux-gnu.cmake 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/cmake/toolchains-ci/riscv64-linux-gnu.cmake 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,4 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR riscv64) + +set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-riscv64-static") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/include/fast_float/ascii_number.h new/fast_float-8.1.0/include/fast_float/ascii_number.h --- old/fast_float-8.0.2/include/fast_float/ascii_number.h 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/include/fast_float/ascii_number.h 2025-09-18 17:38:45.000000000 +0200 @@ -441,7 +441,7 @@ if (digit_count > 19) { answer.too_many_digits = true; // Let us start again, this time, avoiding overflows. - // We don't need to check if is_integer, since we use the + // We don't need to call if is_integer, since we use the // pre-tokenized spans from above. i = 0; p = answer.integer.ptr; @@ -451,7 +451,7 @@ i = i * 10 + uint64_t(*p - UC('0')); ++p; } - if (i >= minimal_nineteen_digit_integer) { // We have a big integers + if (i >= minimal_nineteen_digit_integer) { // We have a big integer exponent = end_of_integer_part - p + exp_number; } else { // We have a value with a fractional component. p = answer.fraction.ptr; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/include/fast_float/fast_float.h new/fast_float-8.1.0/include/fast_float/fast_float.h --- old/fast_float-8.0.2/include/fast_float/fast_float.h 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/include/fast_float/fast_float.h 2025-09-18 17:38:45.000000000 +0200 @@ -46,6 +46,24 @@ parse_options_t<UC> options) noexcept; /** + * This function multiplies an integer number by a power of 10 and returns + * the result as a double precision floating-point value that is correctly + * rounded. The resulting floating-point value is the closest floating-point + * value, using the "round to nearest, tie to even" convention for values that + * would otherwise fall right in-between two values. That is, we provide exact + * conversion according to the IEEE standard. + * + * On overflow infinity is returned, on underflow 0 is returned. + * + * The implementation does not throw and does not allocate memory (e.g., with + * `new` or `malloc`). + */ +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept; +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept; + +/** * from_chars for integer types. */ template <typename T, typename UC = char, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/include/fast_float/float_common.h new/fast_float-8.1.0/include/fast_float/float_common.h --- old/fast_float-8.0.2/include/fast_float/float_common.h 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/include/fast_float/float_common.h 2025-09-18 17:38:45.000000000 +0200 @@ -16,8 +16,8 @@ #include "constexpr_feature_detect.h" #define FASTFLOAT_VERSION_MAJOR 8 -#define FASTFLOAT_VERSION_MINOR 0 -#define FASTFLOAT_VERSION_PATCH 2 +#define FASTFLOAT_VERSION_MINOR 1 +#define FASTFLOAT_VERSION_PATCH 0 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) @@ -58,6 +58,11 @@ template <typename UC> struct from_chars_result_t { UC const *ptr; std::errc ec; + + // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2497r0.html + constexpr explicit operator bool() const noexcept { + return ec == std::errc(); + } }; using from_chars_result = from_chars_result_t<char>; @@ -88,11 +93,12 @@ defined(__MINGW64__) || defined(__s390x__) || \ (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \ defined(__PPC64LE__)) || \ - defined(__loongarch64)) + defined(__loongarch64) || (defined(__riscv) && __riscv_xlen == 64)) #define FASTFLOAT_64BIT 1 #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \ - defined(__MINGW32__) || defined(__EMSCRIPTEN__)) + defined(__MINGW32__) || defined(__EMSCRIPTEN__) || \ + (defined(__riscv) && __riscv_xlen == 32)) #define FASTFLOAT_32BIT 1 #else // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. @@ -1126,7 +1132,12 @@ template <typename UC> fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) { - return int_luts<>::chdigit[static_cast<unsigned char>(c)]; + // wchar_t and char can be signed, so we need to be careful. + using UnsignedUC = typename std::make_unsigned<UC>::type; + return int_luts<>::chdigit[static_cast<unsigned char>( + static_cast<UnsignedUC>(c) & + static_cast<UnsignedUC>( + -((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))]; } fastfloat_really_inline constexpr size_t max_digits_u64(int base) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/include/fast_float/parse_number.h new/fast_float-8.1.0/include/fast_float/parse_number.h --- old/fast_float-8.0.2/include/fast_float/parse_number.h 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/include/fast_float/parse_number.h 2025-09-18 17:38:45.000000000 +0200 @@ -188,32 +188,17 @@ parse_options_t<UC>(fmt)); } -/** - * This function overload takes parsed_number_string_t structure that is created - * and populated either by from_chars_advanced function taking chars range and - * parsing options or other parsing custom function implemented by user. - */ -template <typename T, typename UC> -FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> -from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept { - - static_assert(is_supported_float_type<T>::value, - "only some floating-point types are supported"); - static_assert(is_supported_char_type<UC>::value, - "only char, wchar_t, char16_t and char32_t are supported"); - - from_chars_result_t<UC> answer; - - answer.ec = std::errc(); // be optimistic - answer.ptr = pns.lastmatch; +template <typename T> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative, + T &value) noexcept { // 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<T>::min_exponent_fast_path() <= pns.exponent && - pns.exponent <= binary_format<T>::max_exponent_fast_path() && - !pns.too_many_digits) { + if (binary_format<T>::min_exponent_fast_path() <= exponent && + exponent <= binary_format<T>::max_exponent_fast_path()) { // Unfortunately, the conventional Clinger's fast path is only possible // when the system rounds to the nearest float. // @@ -224,41 +209,64 @@ if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) { // We have that fegetround() == FE_TONEAREST. // Next is Clinger's fast path. - if (pns.mantissa <= binary_format<T>::max_mantissa_fast_path()) { - value = T(pns.mantissa); - if (pns.exponent < 0) { - value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); + if (mantissa <= binary_format<T>::max_mantissa_fast_path()) { + value = T(mantissa); + if (exponent < 0) { + value = value / binary_format<T>::exact_power_of_ten(-exponent); } else { - value = value * binary_format<T>::exact_power_of_ten(pns.exponent); + value = value * binary_format<T>::exact_power_of_ten(exponent); } - if (pns.negative) { + if (is_negative) { value = -value; } - return answer; + return true; } } 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<T>::max_mantissa_fast_path(pns.exponent)) { + if (exponent >= 0 && + mantissa <= binary_format<T>::max_mantissa_fast_path(exponent)) { #if defined(__clang__) || defined(FASTFLOAT_32BIT) // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD - if (pns.mantissa == 0) { - value = pns.negative ? T(-0.) : T(0.); - return answer; + if (mantissa == 0) { + value = is_negative ? T(-0.) : T(0.); + return true; } #endif - value = T(pns.mantissa) * - binary_format<T>::exact_power_of_ten(pns.exponent); - if (pns.negative) { + value = T(mantissa) * binary_format<T>::exact_power_of_ten(exponent); + if (is_negative) { value = -value; } - return answer; + return true; } } } + return false; +} + +/** + * This function overload takes parsed_number_string_t structure that is created + * and populated either by from_chars_advanced function taking chars range and + * parsing options or other parsing custom function implemented by user. + */ +template <typename T, typename UC> +FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> +from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept { + static_assert(is_supported_float_type<T>::value, + "only some floating-point types are supported"); + static_assert(is_supported_char_type<UC>::value, + "only char, wchar_t, char16_t and char32_t are supported"); + + from_chars_result_t<UC> answer; + + answer.ec = std::errc(); // be optimistic + answer.ptr = pns.lastmatch; + + if (!pns.too_many_digits && + clinger_fast_path_impl(pns.mantissa, pns.exponent, pns.negative, value)) + return answer; + adjusted_mantissa am = compute_float<binary_format<T>>(pns.exponent, pns.mantissa); if (pns.too_many_digits && am.power2 >= 0) { @@ -336,6 +344,49 @@ return from_chars_advanced(first, last, value, options); } +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept { + double value; + if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value)) + return value; + + adjusted_mantissa am = + compute_float<binary_format<double>>(decimal_exponent, mantissa); + to_float(false, am, value); + return value; +} + +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept { + const bool is_negative = mantissa < 0; + const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa); + + double value; + if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value)) + return value; + + adjusted_mantissa am = + compute_float<binary_format<double>>(decimal_exponent, m); + to_float(is_negative, am, value); + return value; +} + +// the following overloads are here to avoid surprising ambiguity for int, +// unsigned, etc. +template <typename Int> +FASTFLOAT_CONSTEXPR20 inline typename std::enable_if< + std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type +integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent); +} + +template <typename Int> +FASTFLOAT_CONSTEXPR20 inline typename std::enable_if< + std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type +integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent); +} + template <typename T, typename UC> FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_int_advanced(UC const *first, UC const *last, T &value, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/tests/CMakeLists.txt new/fast_float-8.1.0/tests/CMakeLists.txt --- old/fast_float-8.0.2/tests/CMakeLists.txt 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/tests/CMakeLists.txt 2025-09-18 17:38:45.000000000 +0200 @@ -9,8 +9,7 @@ if (NOT SYSTEM_DOCTEST) FetchContent_Declare(doctest - GIT_REPOSITORY https://github.com/onqtam/doctest.git - GIT_TAG v2.4.11) + GIT_REPOSITORY https://github.com/lemire/doctest.git) else () find_package(doctest REQUIRED) endif() @@ -23,24 +22,15 @@ # FetchContent_MakeAvailable() was only introduced in 3.14 # https://cmake.org/cmake/help/v3.14/release/3.14.html#modules -# FetchContent_MakeAvailable(doctest) if (NOT SYSTEM_DOCTEST) - FetchContent_GetProperties(doctest) - if(NOT doctest_POPULATED) - FetchContent_Populate(doctest) - add_subdirectory(${doctest_SOURCE_DIR} ${doctest_BINARY_DIR}) - endif() + FetchContent_MakeAvailable(doctest) endif() add_library(supplemental-data INTERFACE) if (FASTFLOAT_SUPPLEMENTAL_TESTS) - FetchContent_GetProperties(supplemental_test_files) - if(NOT supplemental_test_files_POPULATED) - message(STATUS "Supplemental tests enabled. Retrieving test files.") - FetchContent_Populate(supplemental_test_files) - message(STATUS "Supplemental test files retrieved.") - add_subdirectory(${supplemental_test_files_SOURCE_DIR} ${supplemental_test_files_BINARY_DIR}) - endif() + message(STATUS "Supplemental tests enabled. Retrieving test files.") + FetchContent_MakeAvailable(supplemental_test_files) + message(STATUS "Supplemental test files retrieved.") target_compile_definitions(supplemental-data INTERFACE SUPPLEMENTAL_TEST_DATA_DIR="${supplemental_test_files_BINARY_DIR}/data") endif() @@ -71,6 +61,7 @@ fast_float_add_cpp_test(supported_chars_test) fast_float_add_cpp_test(example_test) fast_float_add_cpp_test(example_comma_test) +fast_float_add_cpp_test(example_integer_times_pow10) fast_float_add_cpp_test(basictest) option(FASTFLOAT_CONSTEXPR_TESTS "Require constexpr tests (build will fail if the compiler won't support it)" OFF) if (FASTFLOAT_CONSTEXPR_TESTS) @@ -82,7 +73,7 @@ if (FASTFLOAT_SUPPLEMENTAL_TESTS) target_compile_definitions(basictest PRIVATE FASTFLOAT_SUPPLEMENTAL_TESTS) endif() - +fast_float_add_cpp_test(p2497) fast_float_add_cpp_test(long_test) fast_float_add_cpp_test(powersoffive_hardround) fast_float_add_cpp_test(string_test) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/tests/basictest.cpp new/fast_float-8.1.0/tests/basictest.cpp --- old/fast_float-8.0.2/tests/basictest.cpp 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/tests/basictest.cpp 2025-09-18 17:38:45.000000000 +0200 @@ -1134,6 +1134,14 @@ std::errc::result_out_of_range); verify("1.9e308", std::numeric_limits<double>::infinity(), std::errc::result_out_of_range); + + // DBL_MAX + 0.00000000000000001e308 + verify("1.79769313486231581e308", std::numeric_limits<double>::infinity(), + std::errc::result_out_of_range); + + // DBL_MAX + 0.0000000000000001e308 + verify("1.7976931348623159e308", std::numeric_limits<double>::infinity(), + std::errc::result_out_of_range); } TEST_CASE("double.general") { @@ -1143,6 +1151,13 @@ verify("-22250738585072012e-324", -0x1p-1022); /* limit between normal and subnormal*/ verify("-1e-999", -0.0, std::errc::result_out_of_range); + + // DBL_TRUE_MIN / 2 + verify("2.4703282292062327e-324", 0.0, std::errc::result_out_of_range); + + // DBL_TRUE_MIN / 2 + 0.0000000000000001e-324 + verify("2.4703282292062328e-324", 0x0.0000000000001p-1022); + verify("-2.2222222222223e-322", -0x1.68p-1069); verify("9007199254740993.0", 0x1p+53); verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328); @@ -2070,3 +2085,155 @@ // 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875bf16); } #endif + +template <typename Int> +void verify_integer_multiplication_by_power_of_10(Int mantissa, + int decimal_exponent, + double expected) { + const double actual = + fast_float::integer_times_pow10(mantissa, decimal_exponent); + + INFO("m * 10^e=" << mantissa << " * 10^" << decimal_exponent + << "\n" + " expected=" + << fHexAndDec(expected) << "\n" + << " ..actual=" << fHexAndDec(actual) << "\n" + << " expected mantissa=" + << iHexAndDec(get_mantissa(expected)) << "\n" + << " ..actual mantissa=" << iHexAndDec(get_mantissa(actual)) + << "\n"); + CHECK_EQ(actual, expected); +} + +template <typename Int> +void verify_integer_multiplication_by_power_of_10(Int mantissa, + int decimal_exponent) { + std::string constructed_string = + std::to_string(mantissa) + "e" + std::to_string(decimal_exponent); + double expected_result; + const auto result = fast_float::from_chars( + constructed_string.data(), + constructed_string.data() + constructed_string.size(), expected_result); + if (result.ec != std::errc()) + INFO("Failed to parse: " << constructed_string); + verify_integer_multiplication_by_power_of_10(mantissa, decimal_exponent, + expected_result); +} + +TEST_CASE("integer_times_pow10") { + // explicitly verifying API with different types of integers + verify_integer_multiplication_by_power_of_10<int8_t>(31, -1, 3.1); + verify_integer_multiplication_by_power_of_10<int8_t>(-31, -1, -3.1); + verify_integer_multiplication_by_power_of_10<uint8_t>(31, -1, 3.1); + verify_integer_multiplication_by_power_of_10<int16_t>(31415, -4, 3.1415); + verify_integer_multiplication_by_power_of_10<int16_t>(-31415, -4, -3.1415); + verify_integer_multiplication_by_power_of_10<uint16_t>(31415, -4, 3.1415); + verify_integer_multiplication_by_power_of_10<int32_t>(314159265, -8, + 3.14159265); + verify_integer_multiplication_by_power_of_10<int32_t>(-314159265, -8, + -3.14159265); + verify_integer_multiplication_by_power_of_10<uint32_t>(3141592653, -9, + 3.141592653); + verify_integer_multiplication_by_power_of_10<int64_t>( + 3141592653589793238, -18, 3.141592653589793238); + verify_integer_multiplication_by_power_of_10<int64_t>( + -3141592653589793238, -18, -3.141592653589793238); + verify_integer_multiplication_by_power_of_10<uint64_t>( + 3141592653589793238, -18, 3.141592653589793238); + verify_integer_multiplication_by_power_of_10<long long>( + -3141592653589793238, -18, -3.141592653589793238); + verify_integer_multiplication_by_power_of_10<unsigned long long>( + 3141592653589793238, -18, 3.141592653589793238); + + for (int mode : {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}) { + fesetround(mode); + INFO("fesetround(): " << std::string{round_name(mode)}); + + struct Guard { + ~Guard() { fesetround(FE_TONEAREST); } + } guard; + + verify_integer_multiplication_by_power_of_10(0, 0); + verify_integer_multiplication_by_power_of_10(1, 0); + verify_integer_multiplication_by_power_of_10(0, 1); + verify_integer_multiplication_by_power_of_10(1, 1); + verify_integer_multiplication_by_power_of_10(-1, 0); + verify_integer_multiplication_by_power_of_10(0, -1); + verify_integer_multiplication_by_power_of_10(-1, -1); + verify_integer_multiplication_by_power_of_10(-1, 1); + verify_integer_multiplication_by_power_of_10(1, -1); + + verify_integer_multiplication_by_power_of_10( + 49406564584124654, -340, std::numeric_limits<double>::denorm_min()); + verify_integer_multiplication_by_power_of_10( + 22250738585072014, -324, std::numeric_limits<double>::min()); + verify_integer_multiplication_by_power_of_10( + 17976931348623158, 292, std::numeric_limits<double>::max()); + + // DBL_TRUE_MIN / 2 underflows to 0 + verify_integer_multiplication_by_power_of_10(49406564584124654 / 2, -340, + 0.); + + // DBL_TRUE_MIN / 2 + 0.0000000000000001e-324 rounds to DBL_TRUE_MIN + verify_integer_multiplication_by_power_of_10( + 49406564584124654 / 2 + 1, -340, + std::numeric_limits<double>::denorm_min()); + + // DBL_MAX + 0.0000000000000001e308 overflows to infinity + verify_integer_multiplication_by_power_of_10( + 17976931348623158 + 1, 292, std::numeric_limits<double>::infinity()); + // DBL_MAX + 0.00000000000000001e308 overflows to infinity + verify_integer_multiplication_by_power_of_10( + 179769313486231580 + 1, 291, std::numeric_limits<double>::infinity()); + + // loosely verifying correct rounding of 1 to 64 bits + // worth of significant digits + verify_integer_multiplication_by_power_of_10(1, 42); + verify_integer_multiplication_by_power_of_10(1, -42); + verify_integer_multiplication_by_power_of_10(12, 42); + verify_integer_multiplication_by_power_of_10(12, -42); + verify_integer_multiplication_by_power_of_10(123, 42); + verify_integer_multiplication_by_power_of_10(123, -42); + verify_integer_multiplication_by_power_of_10(1234, 42); + verify_integer_multiplication_by_power_of_10(1234, -42); + verify_integer_multiplication_by_power_of_10(12345, 42); + verify_integer_multiplication_by_power_of_10(12345, -42); + verify_integer_multiplication_by_power_of_10(123456, 42); + verify_integer_multiplication_by_power_of_10(123456, -42); + verify_integer_multiplication_by_power_of_10(1234567, 42); + verify_integer_multiplication_by_power_of_10(1234567, -42); + verify_integer_multiplication_by_power_of_10(12345678, 42); + verify_integer_multiplication_by_power_of_10(12345678, -42); + verify_integer_multiplication_by_power_of_10(123456789, 42); + verify_integer_multiplication_by_power_of_10(1234567890, 42); + verify_integer_multiplication_by_power_of_10(1234567890, -42); + verify_integer_multiplication_by_power_of_10(12345678901, 42); + verify_integer_multiplication_by_power_of_10(12345678901, -42); + verify_integer_multiplication_by_power_of_10(123456789012, 42); + verify_integer_multiplication_by_power_of_10(123456789012, -42); + verify_integer_multiplication_by_power_of_10(1234567890123, 42); + verify_integer_multiplication_by_power_of_10(1234567890123, -42); + verify_integer_multiplication_by_power_of_10(12345678901234, 42); + verify_integer_multiplication_by_power_of_10(12345678901234, -42); + verify_integer_multiplication_by_power_of_10(123456789012345, 42); + verify_integer_multiplication_by_power_of_10(123456789012345, -42); + verify_integer_multiplication_by_power_of_10(1234567890123456, 42); + verify_integer_multiplication_by_power_of_10(1234567890123456, -42); + verify_integer_multiplication_by_power_of_10(12345678901234567, 42); + verify_integer_multiplication_by_power_of_10(12345678901234567, -42); + verify_integer_multiplication_by_power_of_10(123456789012345678, 42); + verify_integer_multiplication_by_power_of_10(123456789012345678, -42); + verify_integer_multiplication_by_power_of_10(1234567890123456789, 42); + verify_integer_multiplication_by_power_of_10(1234567890123456789, -42); + verify_integer_multiplication_by_power_of_10(12345678901234567890ull, 42); + verify_integer_multiplication_by_power_of_10(12345678901234567890ull, -42); + verify_integer_multiplication_by_power_of_10( + std::numeric_limits<int64_t>::max(), 42); + verify_integer_multiplication_by_power_of_10( + std::numeric_limits<int64_t>::max(), -42); + verify_integer_multiplication_by_power_of_10( + std::numeric_limits<uint64_t>::max(), 42); + verify_integer_multiplication_by_power_of_10( + std::numeric_limits<uint64_t>::max(), -42); + } +} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/tests/example_integer_times_pow10.cpp new/fast_float-8.1.0/tests/example_integer_times_pow10.cpp --- old/fast_float-8.0.2/tests/example_integer_times_pow10.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/tests/example_integer_times_pow10.cpp 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,12 @@ +#include "fast_float/fast_float.h" + +#include <iostream> + +int main() { + const uint64_t W = 12345678901234567; + const int Q = 23; + const double result = fast_float::integer_times_pow10(W, Q); + std::cout.precision(17); + std::cout << W << " * 10^" << Q << " = " << result << " (" + << (result == 12345678901234567e23 ? "==" : "!=") << "expected)\n"; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/tests/fast_int.cpp new/fast_float-8.1.0/tests/fast_int.cpp --- old/fast_float-8.0.2/tests/fast_int.cpp 2025-03-11 14:51:53.000000000 +0100 +++ new/fast_float-8.1.0/tests/fast_int.cpp 2025-09-18 17:38:45.000000000 +0200 @@ -831,6 +831,275 @@ return EXIT_FAILURE; } } + // dont parse UTF-16 code units of emojis as int if low byte is ascii digit + { + const std::u16string emojis[] = { + u"ℹ", u"ℹ️", u"☸", u"☸️", u"☹", u"☹️", u"✳", u"✳️", + u"✴", u"✴️", u"⤴", u"⤴️", u"⤵", u"⤵️", u"〰", u"〰️", + }; + bool failed = false; + auto array_size = sizeof(emojis) / sizeof(emojis[0]); + for (size_t i = 0; i < array_size; i++) { + auto e = emojis[i]; + int foo; + auto answer = fast_float::from_chars(e.data(), e.data() + e.size(), foo); + if (answer.ec == std::errc()) { + failed = true; + std::cerr << "Incorrectly parsed emoji #" << i << " as integer " << foo + << "." << std::endl; + } + } + + if (failed) { + return EXIT_FAILURE; + } + } + // dont parse UTF-32 code points of emojis as int if low byte is ascii digit + { + const std::u32string emojis[] = { + U"ℹ", + U"ℹ️", + U"☸", + U"☸️", + U"☹", + U"☹️", + U"✳", + U"✳️", + U"✴", + U"✴️", + U"⤴", + U"⤴️", + U"⤵", + U"⤵️", + U"〰", + U"〰️", + U"🈲", + U"🈳", + U"🈴", + U"🈵", + U"🈶", + U"🈷", + U"🈷️", + U"🈸", + U"🈹", + U"🌰", + U"🌱", + U"🌲", + U"🌳", + U"🌴", + U"🌵", + U"🌶", + U"🌶️", + U"🌷", + U"🌸", + U"🌹", + U"🐰", + U"🐱", + U"🐲", + U"🐳", + U"🐴", + U"🐵", + U"🐶", + U"🐷", + U"🐸", + U"🐹", + U"🔰", + U"🔱", + U"🔲", + U"🔳", + U"🔴", + U"🔵", + U"🔶", + U"🔷", + U"🔸", + U"🔹", + U"😰", + U"😱", + U"😲", + U"😳", + U"😴", + U"😵", + U"😵💫", + U"😶", + U"😶🌫", + U"😶🌫️", + U"😷", + U"😸", + U"😹", + U"🤰", + U"🤰🏻", + U"🤰🏼", + U"🤰🏽", + U"🤰🏾", + U"🤰🏿", + U"🤱", + U"🤱🏻", + U"🤱🏼", + U"🤱🏽", + U"🤱🏾", + U"🤱🏿", + U"🤲", + U"🤲🏻", + U"🤲🏼", + U"🤲🏽", + U"🤲🏾", + U"🤲🏿", + U"🤳", + U"🤳🏻", + U"🤳🏼", + U"🤳🏽", + U"🤳🏾", + U"🤳🏿", + U"🤴", + U"🤴🏻", + U"🤴🏼", + U"🤴🏽", + U"🤴🏾", + U"🤴🏿", + U"🤵", + U"🤵♀", + U"🤵♀️", + U"🤵♂", + U"🤵♂️", + U"🤵🏻", + U"🤵🏻♀", + U"🤵🏻♀️", + U"🤵🏻♂", + U"🤵🏻♂️", + U"🤵🏼", + U"🤵🏼♀", + U"🤵🏼♀️", + U"🤵🏼♂", + U"🤵🏼♂️", + U"🤵🏽", + U"🤵🏽♀", + U"🤵🏽♀️", + U"🤵🏽♂", + U"🤵🏽♂️", + U"🤵🏾", + U"🤵🏾♀", + U"🤵🏾♀️", + U"🤵🏾♂", + U"🤵🏾♂️", + U"🤵🏿", + U"🤵🏿♀", + U"🤵🏿♀️", + U"🤵🏿♂", + U"🤵🏿♂️", + U"🤶", + U"🤶🏻", + U"🤶🏼", + U"🤶🏽", + U"🤶🏾", + U"🤶🏿", + U"🤷", + U"🤷♀", + U"🤷♀️", + U"🤷♂", + U"🤷♂️", + U"🤷🏻", + U"🤷🏻♀", + U"🤷🏻♀️", + U"🤷🏻♂", + U"🤷🏻♂️", + U"🤷🏼", + U"🤷🏼♀", + U"🤷🏼♀️", + U"🤷🏼♂", + U"🤷🏼♂️", + U"🤷🏽", + U"🤷🏽♀", + U"🤷🏽♀️", + U"🤷🏽♂", + U"🤷🏽♂️", + U"🤷🏾", + U"🤷🏾♀", + U"🤷🏾♀️", + U"🤷🏾♂", + U"🤷🏾♂️", + U"🤷🏿", + U"🤷🏿♀", + U"🤷🏿♀️", + U"🤷🏿♂", + U"🤷🏿♂️", + U"🤸", + U"🤸♀", + U"🤸♀️", + U"🤸♂", + U"🤸♂️", + U"🤸🏻", + U"🤸🏻♀", + U"🤸🏻♀️", + U"🤸🏻♂", + U"🤸🏻♂️", + U"🤸🏼", + U"🤸🏼♀", + U"🤸🏼♀️", + U"🤸🏼♂", + U"🤸🏼♂️", + U"🤸🏽", + U"🤸🏽♀", + U"🤸🏽♀️", + U"🤸🏽♂", + U"🤸🏽♂️", + U"🤸🏾", + U"🤸🏾♀", + U"🤸🏾♀️", + U"🤸🏾♂", + U"🤸🏾♂️", + U"🤸🏿", + U"🤸🏿♀", + U"🤸🏿♀️", + U"🤸🏿♂", + U"🤸🏿♂️", + U"🤹", + U"🤹♀", + U"🤹♀️", + U"🤹♂", + U"🤹♂️", + U"🤹🏻", + U"🤹🏻♀", + U"🤹🏻♀️", + U"🤹🏻♂", + U"🤹🏻♂️", + U"🤹🏼", + U"🤹🏼♀", + U"🤹🏼♀️", + U"🤹🏼♂", + U"🤹🏼♂️", + U"🤹🏽", + U"🤹🏽♀", + U"🤹🏽♀️", + U"🤹🏽♂", + U"🤹🏽♂️", + U"🤹🏾", + U"🤹🏾♀", + U"🤹🏾♀️", + U"🤹🏾♂", + U"🤹🏾♂️", + U"🤹🏿", + U"🤹🏿♀", + U"🤹🏿♀️", + U"🤹🏿♂", + U"🤹🏿♂️", + }; + bool failed = false; + auto array_size = sizeof(emojis) / sizeof(emojis[0]); + for (size_t i = 0; i < array_size; i++) { + auto e = emojis[i]; + int foo; + auto answer = fast_float::from_chars(e.data(), e.data() + e.size(), foo); + if (answer.ec == std::errc()) { + failed = true; + std::cerr << "Incorrectly parsed emoji #" << i << " as integer " << foo + << "." << std::endl; + } + } + + if (failed) { + return EXIT_FAILURE; + } + } return EXIT_SUCCESS; } @@ -842,4 +1111,4 @@ std::cerr << "The test requires C++17." << std::endl; return EXIT_SUCCESS; } -#endif \ No newline at end of file +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.0.2/tests/p2497.cpp new/fast_float-8.1.0/tests/p2497.cpp --- old/fast_float-8.0.2/tests/p2497.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.1.0/tests/p2497.cpp 2025-09-18 17:38:45.000000000 +0200 @@ -0,0 +1,16 @@ +#include "fast_float/fast_float.h" + +#include <iostream> +#include <string> + +int main() { + std::string input = "3.1416 xyz "; + double result; + if (auto answer = fast_float::from_chars( + input.data(), input.data() + input.size(), result)) { + std::cout << "parsed the number " << result << std::endl; + return EXIT_SUCCESS; + } + std::cerr << "failed to parse " << result << std::endl; + return EXIT_FAILURE; +} \ No newline at end of file
