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 2026-03-22 14:11:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fast_float (Old) and /work/SRC/openSUSE:Factory/.fast_float.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fast_float" Sun Mar 22 14:11:30 2026 rev:6 rq:1341528 version:8.2.4 Changes: -------- --- /work/SRC/openSUSE:Factory/fast_float/fast_float.changes 2026-02-06 19:07:00.371664551 +0100 +++ /work/SRC/openSUSE:Factory/.fast_float.new.8177/fast_float.changes 2026-03-22 14:11:48.992481148 +0100 @@ -1,0 +2,8 @@ +Fri Mar 20 09:02:30 UTC 2026 - Jan Engelhardt <[email protected]> + +- Update to release 8.2.4 + * Optimized uint16_t parsing with a similar approach to the one + used for uint8_t + * Optimized fastfloat_strncasecmp + +------------------------------------------------------------------- Old: ---- fast_float-8.2.2.tar.gz New: ---- fast_float-8.2.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fast_float.spec ++++++ --- /var/tmp/diff_new_pack.78O9Jq/_old 2026-03-22 14:11:49.516502696 +0100 +++ /var/tmp/diff_new_pack.78O9Jq/_new 2026-03-22 14:11:49.516502696 +0100 @@ -17,7 +17,7 @@ Name: fast_float -Version: 8.2.2 +Version: 8.2.4 Release: 0 Summary: Re-implementation of std::from_chars for parsing strings into numbers License: Apache-2.0 OR BSL-1.0 OR MIT ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.78O9Jq/_old 2026-03-22 14:11:49.552504176 +0100 +++ /var/tmp/diff_new_pack.78O9Jq/_new 2026-03-22 14:11:49.556504340 +0100 @@ -1,5 +1,5 @@ -mtime: 1770130772 -commit: b3e9000c8eda3c50a68a74c5ef090d467e08f8cb022d831216debd26ff244e13 +mtime: 1773997698 +commit: 7b5d61b840a2dc73555e382f6401426a7154255245620670d35b209af8f5b85f url: https://src.opensuse.org/jengelh/fast_float revision: master ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-03-20 10:08:28.000000000 +0100 @@ -0,0 +1 @@ +.osc ++++++ fast_float-8.2.2.tar.gz -> fast_float-8.2.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/ISSUE_TEMPLATE/bug_report.md new/fast_float-8.2.4/.github/ISSUE_TEMPLATE/bug_report.md --- old/fast_float-8.2.2/.github/ISSUE_TEMPLATE/bug_report.md 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.2.4/.github/ISSUE_TEMPLATE/bug_report.md 2026-03-10 17:10:12.000000000 +0100 @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Ideally, you should provide a reproducible test case. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. + +**Note:** Bug reports should come with a test case or, at least, an analysis. + +**Automated tool policy**: If you use an automated tool (e.g., static analysis, +LLM, etc.), you need to demonstrate an understanding of the issue you are raising. Usually, a bug is demonstrated by a test case. Do not copy-paste what a tool is telling you. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/alpine.yml new/fast_float-8.2.4/.github/workflows/alpine.yml --- old/fast_float-8.2.2/.github/workflows/alpine.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/alpine.yml 2026-03-10 17:10:12.000000000 +0100 @@ -18,7 +18,7 @@ - riscv64 steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/[email protected] - 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.2.2/.github/workflows/amalgamate-ubuntu24.yml new/fast_float-8.2.4/.github/workflows/amalgamate-ubuntu24.yml --- old/fast_float-8.2.2/.github/workflows/amalgamate-ubuntu24.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/amalgamate-ubuntu24.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Compile with amalgamation run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/cifuzz.yml new/fast_float-8.2.4/.github/workflows/cifuzz.yml --- old/fast_float-8.2.2/.github/workflows/cifuzz.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/cifuzz.yml 2026-03-10 17:10:12.000000000 +0100 @@ -20,7 +20,7 @@ fuzz-seconds: 300 output-sarif: true - name: Upload Crash - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/emscripten.yml new/fast_float-8.2.4/.github/workflows/emscripten.yml --- old/fast_float-8.2.2/.github/workflows/emscripten.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/emscripten.yml 2026-03-10 17:10:12.000000000 +0100 @@ -4,13 +4,13 @@ build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2 - - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.2.2 + - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 - uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 - name: Verify run: emcc -v - name: Checkout - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v3.6.0 + uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v3.6.0 - name: Configure run: emcmake cmake -B build - name: Build # We build but do not test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/lint_and_format_check.yml new/fast_float-8.2.4/.github/workflows/lint_and_format_check.yml --- old/fast_float-8.2.2/.github/workflows/lint_and_format_check.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/lint_and_format_check.yml 2026-03-10 17:10:12.000000000 +0100 @@ -24,10 +24,10 @@ lint-and-format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.7 + - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.1.7 - name: Run clang-format - uses: jidicula/clang-format-action@4726374d1aa3c6aecf132e5197e498979588ebc8 # v4.15.0 + uses: jidicula/clang-format-action@6cd220de46c89139a0365edae93eee8eb30ca8fe # v4.16.0 with: clang-format-version: '17' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/msys2-clang.yml new/fast_float-8.2.4/.github/workflows/msys2-clang.yml --- old/fast_float-8.2.2/.github/workflows/msys2-clang.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/msys2-clang.yml 2026-03-10 17:10:12.000000000 +0100 @@ -23,7 +23,7 @@ CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - uses: msys2/setup-msys2@v2 with: update: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/msys2.yml new/fast_float-8.2.4/.github/workflows/msys2.yml --- old/fast_float-8.2.2/.github/workflows/msys2.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/msys2.yml 2026-03-10 17:10:12.000000000 +0100 @@ -29,7 +29,7 @@ CMAKE_GENERATOR: Ninja steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - uses: msys2/setup-msys2@v2 with: update: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/on-release.yml new/fast_float-8.2.4/.github/workflows/on-release.yml --- old/fast_float-8.2.2/.github/workflows/on-release.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/on-release.yml 2026-03-10 17:10:12.000000000 +0100 @@ -16,7 +16,7 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Amalgamate fast_float.h run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/risc.yml new/fast_float-8.2.4/.github/workflows/risc.yml --- old/fast_float-8.2.2/.github/workflows/risc.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/risc.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Install packages run: | sudo apt-get update -q -y diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/s390x.yml new/fast_float-8.2.4/.github/workflows/s390x.yml --- old/fast_float-8.2.2/.github/workflows/s390x.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/s390x.yml 2026-03-10 17:10:12.000000000 +0100 @@ -12,7 +12,7 @@ build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - uses: uraimo/run-on-arch-action@v3 name: Test id: runcmd @@ -22,9 +22,9 @@ distro: ubuntu_latest install: | apt-get update -q -y - apt-get install -y cmake make g++ + apt-get install -y cmake make g++ git run: | - cmake -DCMAKE_BUILD_TYPE=Release -B build + cmake -DCMAKE_BUILD_TYPE=Release -B build -DFASTFLOAT_TEST=ON cmake --build build -j=2 ctest --output-on-failure --test-dir build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/ubuntu22-clang.yml new/fast_float-8.2.4/.github/workflows/ubuntu22-clang.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu22-clang.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu22-clang.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - 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.2.2/.github/workflows/ubuntu22-gcc12.yml new/fast_float-8.2.4/.github/workflows/ubuntu22-gcc12.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu22-gcc12.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu22-gcc12.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/ubuntu22-sanitize.yml new/fast_float-8.2.4/.github/workflows/ubuntu22-sanitize.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu22-sanitize.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu22-sanitize.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/ubuntu22.yml new/fast_float-8.2.4/.github/workflows/ubuntu22.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu22.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu22.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/ubuntu24-cxx20.yml new/fast_float-8.2.4/.github/workflows/ubuntu24-cxx20.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu24-cxx20.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu24-cxx20.yml 2026-03-10 17:10:12.000000000 +0100 @@ -8,7 +8,7 @@ strategy: fail-fast: false steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Use cmake run: | mkdir build && diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/ubuntu24.yml new/fast_float-8.2.4/.github/workflows/ubuntu24.yml --- old/fast_float-8.2.2/.github/workflows/ubuntu24.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/ubuntu24.yml 2026-03-10 17:10:12.000000000 +0100 @@ -6,7 +6,7 @@ ubuntu-build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v5 + - uses: actions/[email protected] - name: Use cmake run: | set -xe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/.github/workflows/vs17-arm-ci.yml new/fast_float-8.2.4/.github/workflows/vs17-arm-ci.yml --- old/fast_float-8.2.2/.github/workflows/vs17-arm-ci.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/vs17-arm-ci.yml 2026-03-10 17:10:12.000000000 +0100 @@ -14,7 +14,7 @@ - {gen: Visual Studio 17 2022, arch: ARM64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/[email protected] - 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.2.2/.github/workflows/vs17-ci.yml new/fast_float-8.2.4/.github/workflows/vs17-ci.yml --- old/fast_float-8.2.2/.github/workflows/vs17-ci.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/vs17-ci.yml 2026-03-10 17:10:12.000000000 +0100 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/[email protected] - 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.2.2/.github/workflows/vs17-clang-ci.yml new/fast_float-8.2.4/.github/workflows/vs17-clang-ci.yml --- old/fast_float-8.2.2/.github/workflows/vs17-clang-ci.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/vs17-clang-ci.yml 2026-03-10 17:10:12.000000000 +0100 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/[email protected] - 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.2.2/.github/workflows/vs17-cxx20.yml new/fast_float-8.2.4/.github/workflows/vs17-cxx20.yml --- old/fast_float-8.2.2/.github/workflows/vs17-cxx20.yml 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/.github/workflows/vs17-cxx20.yml 2026-03-10 17:10:12.000000000 +0100 @@ -16,7 +16,7 @@ - {gen: Visual Studio 17 2022, arch: x64, cfg: Debug} steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/[email protected] - 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.2.2/CMakeLists.txt new/fast_float-8.2.4/CMakeLists.txt --- old/fast_float-8.2.2/CMakeLists.txt 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/CMakeLists.txt 2026-03-10 17:10:12.000000000 +0100 @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.2.2 LANGUAGES CXX) +project(fast_float VERSION 8.2.4 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) @@ -57,13 +57,7 @@ endif() endif() -include(CheckCXXCompilerFlag) -unset(FASTFLOAT_COMPILER_SUPPORTS_PERMISSIVE) -CHECK_CXX_COMPILER_FLAG(/permissive- FASTFLOAT_COMPILER_SUPPORTS_PERMISSIVE) - -if(FASTFLOAT_COMPILER_SUPPORTS_PERMISSIVE) - target_compile_options(fast_float INTERFACE /permissive-) -endif() +target_compile_options(fast_float INTERFACE $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,19.10>>:/permissive->) if(FASTFLOAT_INSTALL) include(CMakePackageConfigHelpers) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/README.md new/fast_float-8.2.4/README.md --- old/fast_float-8.2.2/README.md 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/README.md 2026-03-10 17:10:12.000000000 +0100 @@ -3,6 +3,9 @@ [](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml) +*Note: This library is for C++ users. C programmers should consider [ffc.h](https://github.com/kolemannix/ffc.h). It is a high-performance port of fast_float to C.* + + The fast_float library provides fast header-only implementations for the C++ from_chars functions for `float` and `double` types as well as integer types. These functions convert ASCII strings representing decimal values (e.g., @@ -10,6 +13,7 @@ even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries. + Specifically, `fast_float` provides the following two functions to parse floating-point numbers with a C++17-like syntax (the library itself only requires C++11): @@ -69,7 +73,7 @@ } ``` -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: +Prior to C++26, checking for a successful `std::from_chars` conversion requires comparing the `from_chars_result::ec` member to `std::errc()`. As an extension `fast_float::from_chars` supports the improved C++26 API that allows checking the result by converting it to `bool`, like so: ```cpp #include "fast_float/fast_float.h" @@ -83,7 +87,7 @@ std::cout << "parsed the number " << result << std::endl; return EXIT_SUCCESS; } - std::cerr << "failed to parse " << result << std::endl; + std::cerr << "failed to parse " << input << std::endl; return EXIT_FAILURE; } ``` @@ -141,9 +145,12 @@ fixed-width floating-point types such as `std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`. * We only support the decimal format: we do not support hexadecimal strings. -* For values that are either very large or very small (e.g., `1e9999`), we - represent it using the infinity or negative infinity value and the returned +* For values that are very large positives or negatives (e.g., `1e9999`), we + represent them using a positive or negative infinity and the returned `ec` is set to `std::errc::result_out_of_range`. +* For values that are very close to zero (e.g., `1e-9999`), we represent them + using a positive or negative zero and the returned `ec` is set to + `std::errc::result_out_of_range`. We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems. @@ -485,6 +492,7 @@ [Jackson](https://github.com/FasterXML/jackson-core). * [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`. +* [There is a plain C port of the fast_float library](https://github.com/kolemannix/ffc.h) called ffc.h ## How fast is it? @@ -533,7 +541,7 @@ FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.2.2 + GIT_TAG tags/v8.2.4 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -549,7 +557,7 @@ CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.2.2) + GIT_TAG v8.2.4) ``` ## Using as single header @@ -561,7 +569,7 @@ You may directly download automatically generated single-header files: -<https://github.com/fastfloat/fast_float/releases/download/v8.2.2/fast_float.h> +<https://github.com/fastfloat/fast_float/releases/download/v8.2.4/fast_float.h> ## Benchmarking diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/benchmarks/CMakeLists.txt new/fast_float-8.2.4/benchmarks/CMakeLists.txt --- old/fast_float-8.2.2/benchmarks/CMakeLists.txt 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/benchmarks/CMakeLists.txt 2026-03-10 17:10:12.000000000 +0100 @@ -11,7 +11,9 @@ add_executable(realbenchmark benchmark.cpp) target_link_libraries(realbenchmark PRIVATE counters::counters) add_executable(bench_ip bench_ip.cpp) +add_executable(bench_uint16 bench_uint16.cpp) target_link_libraries(bench_ip PRIVATE counters::counters) +target_link_libraries(bench_uint16 PRIVATE counters::counters) set_property( TARGET realbenchmark @@ -19,8 +21,12 @@ set_property( TARGET bench_ip PROPERTY CXX_STANDARD 17) +set_property( + TARGET bench_uint16 + PROPERTY CXX_STANDARD 17) target_link_libraries(realbenchmark PUBLIC fast_float) target_link_libraries(bench_ip PUBLIC fast_float) +target_link_libraries(bench_uint16 PUBLIC fast_float) include(ExternalProject) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/benchmarks/bench_uint16.cpp new/fast_float-8.2.4/benchmarks/bench_uint16.cpp --- old/fast_float-8.2.2/benchmarks/bench_uint16.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/fast_float-8.2.4/benchmarks/bench_uint16.cpp 2026-03-10 17:10:12.000000000 +0100 @@ -0,0 +1,139 @@ +#include "counters/bench.h" +#include "fast_float/fast_float.h" +#include <charconv> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <random> +#include <atomic> +#include <string> +#include <vector> + +void pretty_print(size_t volume, size_t bytes, std::string name, + counters::event_aggregate agg) { + if (agg.inner_count > 1) { + printf("# (inner count: %d)\n", agg.inner_count); + } + printf("%-40s : ", name.c_str()); + printf(" %5.2f GB/s ", bytes / agg.fastest_elapsed_ns()); + printf(" %5.1f Mip/s ", volume * 1000.0 / agg.fastest_elapsed_ns()); + printf(" %5.2f ns/ip ", agg.fastest_elapsed_ns() / volume); + if (counters::event_collector().has_events()) { + printf(" %5.2f GHz ", agg.fastest_cycles() / agg.fastest_elapsed_ns()); + printf(" %5.2f c/ip ", agg.fastest_cycles() / volume); + printf(" %5.2f i/ip ", agg.fastest_instructions() / volume); + printf(" %5.2f c/b ", agg.fastest_cycles() / bytes); + printf(" %5.2f i/b ", agg.fastest_instructions() / bytes); + printf(" %5.2f i/c ", agg.fastest_instructions() / agg.fastest_cycles()); + } + printf("\n"); +} + +enum class parse_method { standard, fast_float }; + +void validate(const std::string &buffer, const std::vector<uint16_t> &expected, + char delimiter) { + const char *p = buffer.data(); + const char *pend = p + buffer.size(); + + for (size_t i = 0; i < expected.size(); i++) { + uint16_t val; + auto r = fast_float::from_chars(p, pend, val); + if (r.ec != std::errc() || val != expected[i]) { + printf("Validation failed at index %zu: expected %u, got %u\n", i, + expected[i], val); + std::abort(); + } + p = r.ptr; + if (i + 1 < expected.size()) { + if (p >= pend || *p != delimiter) { + printf("Validation failed at index %zu: delimiter mismatch\n", i); + std::abort(); + } + ++p; + } + } + + if (p != pend) { + printf("Validation failed: trailing bytes remain\n"); + std::abort(); + } + printf("Validation passed!\n"); +} + +int main() { + constexpr size_t N = 500000; + constexpr char delimiter = ','; + std::mt19937 rng(1234); + std::uniform_int_distribution<int> dist(0, 65535); + + std::vector<uint16_t> expected; + expected.reserve(N); + + std::string buffer; + buffer.reserve(N * 6); // up to 5 digits + delimiter + + for (size_t i = 0; i < N; ++i) { + uint16_t val = (uint16_t)dist(rng); + expected.push_back(val); + std::string s = std::to_string(val); + buffer.append(s); + if (i + 1 < N) { + buffer.push_back(delimiter); + } + } + + size_t total_bytes = buffer.size(); + + validate(buffer, expected, delimiter); + + volatile uint64_t sink = 0; + + pretty_print(N, total_bytes, "parse_uint16_std_fromchars", + counters::bench([&]() { + uint64_t sum = 0; + const char *p = buffer.data(); + const char *pend = p + buffer.size(); + for (size_t i = 0; i < N; ++i) { + uint16_t value = 0; + auto r = std::from_chars(p, pend, value); + if (r.ec != std::errc()) + std::abort(); + sum += value; + p = r.ptr; + if (i + 1 < N) { + if (p >= pend || *p != delimiter) + std::abort(); + ++p; + } + } + if (p != pend) + std::abort(); + sink += sum; + })); + + pretty_print(N, total_bytes, "parse_uint16_fastfloat", counters::bench([&]() { + uint64_t sum = 0; + const char *p = buffer.data(); + const char *pend = p + buffer.size(); + for (size_t i = 0; i < N; ++i) { + uint16_t value = 0; + auto r = fast_float::from_chars(p, pend, value); + if (r.ec != std::errc()) + std::abort(); + sum += value; + p = r.ptr; + if (i + 1 < N) { + if (p >= pend || *p != delimiter) + std::abort(); + ++p; + } + } + if (p != pend) + std::abort(); + sink += sum; + })); + + return EXIT_SUCCESS; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/include/fast_float/ascii_number.h new/fast_float-8.2.4/include/fast_float/ascii_number.h --- old/fast_float-8.2.2/include/fast_float/ascii_number.h 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/include/fast_float/ascii_number.h 2026-03-10 17:10:12.000000000 +0100 @@ -32,7 +32,7 @@ // able to optimize it well. template <typename UC> fastfloat_really_inline constexpr bool is_integer(UC c) noexcept { - return !(c > UC('9') || c < UC('0')); + return (unsigned)(c - UC('0')) <= 9u; } fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { @@ -68,6 +68,25 @@ return val; } +// Read 4 UC into a u32. Truncates UC if not char. +template <typename UC> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t +read4_to_u32(UC const *chars) { + if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) { + uint32_t val = 0; + for (int i = 0; i < 4; ++i) { + val |= uint32_t(uint8_t(*chars)) << (i * 8); + ++chars; + } + return val; + } + uint32_t val; + ::memcpy(&val, chars, sizeof(uint32_t)); +#if FASTFLOAT_IS_BIG_ENDIAN == 1 + val = byteswap_32(val); +#endif + return val; +} #ifdef FASTFLOAT_SSE2 fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) { @@ -149,6 +168,18 @@ 0x8080808080808080)); } +fastfloat_really_inline constexpr bool +is_made_of_four_digits_fast(uint32_t val) noexcept { + return !((((val + 0x46464646) | (val - 0x30303030)) & 0x80808080)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t +parse_four_digits_unrolled(uint32_t val) noexcept { + val -= 0x30303030; + val = (val * 10) + (val >> 8); + return (((val & 0x00FF00FF) * 0x00640001) >> 16) & 0xFFFF; +} + #ifdef FASTFLOAT_HAS_SIMD // Call this if chars might not be 8 digits. @@ -515,93 +546,145 @@ UC const *const start_digits = p; FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) { - const size_t len = (size_t)(pend - p); - if (len == 0) { - if (has_leading_zeros) { - value = 0; - answer.ec = std::errc(); - answer.ptr = p; - } else { - answer.ec = std::errc::invalid_argument; - answer.ptr = first; + if (base == 10) { + const size_t len = (size_t)(pend - p); + if (len == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; } - return answer; - } - uint32_t digits; + uint32_t digits; #if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST - if (std::is_constant_evaluated()) { - uint8_t str[4]{}; - for (size_t j = 0; j < 4 && j < len; ++j) { - str[j] = static_cast<uint8_t>(p[j]); - } - digits = std::bit_cast<uint32_t>(str); + if (std::is_constant_evaluated()) { + uint8_t str[4]{}; + for (size_t j = 0; j < 4 && j < len; ++j) { + str[j] = static_cast<uint8_t>(p[j]); + } + digits = std::bit_cast<uint32_t>(str); #if FASTFLOAT_IS_BIG_ENDIAN - digits = byteswap_32(digits); + digits = byteswap_32(digits); #endif - } + } #else - if (false) { - } + if (false) { + } #endif - else if (len >= 4) { - ::memcpy(&digits, p, 4); + else if (len >= 4) { + ::memcpy(&digits, p, 4); #if FASTFLOAT_IS_BIG_ENDIAN - digits = byteswap_32(digits); + digits = byteswap_32(digits); #endif - } else { - uint32_t b0 = static_cast<uint8_t>(p[0]); - uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu; - uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu; - uint32_t b3 = 0xFFu; - digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); - } - - uint32_t magic = - ((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u; - uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32 - uint32_t nd = (tz == 32) ? 4 : (tz >> 3); - nd = (uint32_t)std::min((size_t)nd, len); - if (nd == 0) { - if (has_leading_zeros) { - value = 0; - answer.ec = std::errc(); - answer.ptr = p; + } else { + uint32_t b0 = static_cast<uint8_t>(p[0]); + uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu; + uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu; + uint32_t b3 = 0xFFu; + digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); + } + + uint32_t magic = + ((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u; + uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32 + uint32_t nd = (tz == 32) ? 4 : (tz >> 3); + nd = (uint32_t)std::min((size_t)nd, len); + if (nd == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + return answer; + } + answer.ec = std::errc::invalid_argument; + answer.ptr = first; return answer; } - answer.ec = std::errc::invalid_argument; - answer.ptr = first; - return answer; - } - if (nd > 3) { - const UC *q = p + nd; - size_t rem = len - nd; - while (rem) { - if (*q < UC('0') || *q > UC('9')) - break; - ++q; - --rem; + if (nd > 3) { + const UC *q = p + nd; + size_t rem = len - nd; + while (rem) { + if (*q < UC('0') || *q > UC('9')) + break; + ++q; + --rem; + } + answer.ec = std::errc::result_out_of_range; + answer.ptr = q; + return answer; } - answer.ec = std::errc::result_out_of_range; - answer.ptr = q; - return answer; - } - digits ^= 0x30303030u; - digits <<= ((4 - nd) * 8); + digits ^= 0x30303030u; + digits <<= ((4 - nd) * 8); - uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) | - ((digits << 8) & 0xff0000); - if (check > 0x00020505) { - answer.ec = std::errc::result_out_of_range; + uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) | + ((digits << 8) & 0xff0000); + if (check > 0x00020505) { + answer.ec = std::errc::result_out_of_range; + answer.ptr = p + nd; + return answer; + } + value = (uint8_t)((0x640a01 * digits) >> 24); + answer.ec = std::errc(); answer.ptr = p + nd; return answer; } - value = (uint8_t)((0x640a01 * digits) >> 24); - answer.ec = std::errc(); - answer.ptr = p + nd; - return answer; + } + + FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint16_t>::value)) { + if (base == 10) { + const size_t len = size_t(pend - p); + if (len == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + if (len >= 4) { + uint32_t digits = read4_to_u32(p); + if (is_made_of_four_digits_fast(digits)) { + uint32_t v = parse_four_digits_unrolled(digits); + if (len >= 5 && is_integer(p[4])) { + v = v * 10 + uint32_t(p[4] - '0'); + if (len >= 6 && is_integer(p[5])) { + answer.ec = std::errc::result_out_of_range; + const UC *q = p + 5; + while (q != pend && is_integer(*q)) { + q++; + } + answer.ptr = q; + return answer; + } + if (v > 65535) { + answer.ec = std::errc::result_out_of_range; + answer.ptr = p + 5; + return answer; + } + value = uint16_t(v); + answer.ec = std::errc(); + answer.ptr = p + 5; + return answer; + } + // 4 digits + value = uint16_t(v); + answer.ec = std::errc(); + answer.ptr = p + 4; + return answer; + } + } + } } uint64_t i = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/include/fast_float/float_common.h new/fast_float-8.2.4/include/fast_float/float_common.h --- old/fast_float-8.2.2/include/fast_float/float_common.h 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/include/fast_float/float_common.h 2026-03-10 17:10:12.000000000 +0100 @@ -2,6 +2,7 @@ #define FASTFLOAT_FLOAT_COMMON_H #include <cfloat> +#include <cstddef> #include <cstdint> #include <cassert> #include <cstring> @@ -17,7 +18,7 @@ #define FASTFLOAT_VERSION_MAJOR 8 #define FASTFLOAT_VERSION_MINOR 2 -#define FASTFLOAT_VERSION_PATCH 2 +#define FASTFLOAT_VERSION_PATCH 4 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) @@ -267,18 +268,147 @@ > { }; +template <typename UC> +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp3(UC const *actual_mixedcase, + UC const *expected_lowercase) { + uint64_t mask{0}; + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + } + else { + return false; + } + + uint64_t val1{0}, val2{0}; + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < 3; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1 || sizeof(UC) == 2) { + ::memcpy(&val1, actual_mixedcase, 3 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 3 * sizeof(UC)); + val1 |= mask; + val2 |= mask; + return val1 == val2; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[2] | 32) == (expected_lowercase[2]); + } + else { + return false; + } + } +} + +template <typename UC> +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp5(UC const *actual_mixedcase, + UC const *expected_lowercase) { + uint64_t mask{0}; + uint64_t val1{0}, val2{0}; + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < 5; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { + mask = 0x2020202020202020; + ::memcpy(&val1, actual_mixedcase, 5 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 5 * sizeof(UC)); + val1 |= mask; + val2 |= mask; + return val1 == val2; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + ::memcpy(&val1, actual_mixedcase, 4 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 4 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + ::memcpy(&val1, actual_mixedcase + 2, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase + 2, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); + } + else { + return false; + } + } +} + // Compares two ASCII strings in a case insensitive manner. template <typename UC> inline FASTFLOAT_CONSTEXPR14 bool fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, size_t length) { - for (size_t i = 0; i < length; ++i) { - UC const actual = actual_mixedcase[i]; - if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) { - return false; + uint64_t mask{0}; + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + } + else { + return false; + } + + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < length; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + uint64_t val1{0}, val2{0}; + size_t sz{8 / (sizeof(UC))}; + for (size_t i = 0; i < length; i += sz) { + val1 = val2 = 0; + sz = std::min(sz, length - i); + ::memcpy(&val1, actual_mixedcase + i, sz * sizeof(UC)); + ::memcpy(&val2, expected_lowercase + i, sz * sizeof(UC)); + val1 |= mask; + val2 |= mask; + if (val1 != val2) { + return false; + } } + return true; } - return true; } #ifndef FLT_EVAL_METHOD diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/include/fast_float/parse_number.h new/fast_float-8.2.4/include/fast_float/parse_number.h --- old/fast_float-8.2.2/include/fast_float/parse_number.h 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/include/fast_float/parse_number.h 2026-03-10 17:10:12.000000000 +0100 @@ -35,7 +35,7 @@ ++first; } if (last - first >= 3) { - if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) { + if (fastfloat_strncasecmp3(first, str_const_nan<UC>())) { answer.ptr = (first += 3); value = minusSign ? -std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN(); @@ -54,9 +54,9 @@ } return answer; } - if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) { + if (fastfloat_strncasecmp3(first, str_const_inf<UC>())) { if ((last - first >= 8) && - fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) { + fastfloat_strncasecmp5(first + 3, str_const_inf<UC>() + 3)) { answer.ptr = first + 8; } else { answer.ptr = first + 3; @@ -251,7 +251,7 @@ * parsing options or other parsing custom function implemented by user. */ template <typename T, typename UC> -FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> +fastfloat_really_inline 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"); @@ -290,7 +290,7 @@ } template <typename T, typename UC> -FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_float_advanced(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { @@ -456,6 +456,7 @@ template <> struct from_chars_advanced_caller<1> { template <typename T, typename UC> + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> call(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { @@ -465,7 +466,7 @@ template <> struct from_chars_advanced_caller<2> { template <typename T, typename UC> - FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC> call(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { return from_chars_int_advanced(first, last, value, options); @@ -473,7 +474,7 @@ }; template <typename T, typename UC> -FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_advanced(UC const *first, UC const *last, T &value, parse_options_t<UC> options) noexcept { return from_chars_advanced_caller< diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/tests/basictest.cpp new/fast_float-8.2.4/tests/basictest.cpp --- old/fast_float-8.2.2/tests/basictest.cpp 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/tests/basictest.cpp 2026-03-10 17:10:12.000000000 +0100 @@ -1167,6 +1167,9 @@ // DBL_TRUE_MIN / 2 + 0.0000000000000001e-324 verify("2.4703282292062328e-324", 0x0.0000000000001p-1022); + verify("0.2470328229206232720e-323", 0.0, std::errc::result_out_of_range); + verify("0.2470328229206232721e-323", 0x0.0000000000001p-1022); + verify("-2.2222222222223e-322", -0x1.68p-1069); verify("9007199254740993.0", 0x1p+53); verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328); @@ -1262,8 +1265,13 @@ verify("4.9406564584124654e-324", 0x0.0000000000001p-1022); verify("2.2250738585072009e-308", 0x0.fffffffffffffp-1022); verify("2.2250738585072014e-308", 0x1p-1022); + verify("0.2225073858507201136e-307", 0x0.fffffffffffffp-1022); + verify("0.2225073858507201137e-307", 0x1p-1022); verify("1.7976931348623157e308", 0x1.fffffffffffffp+1023); verify("1.7976931348623158e308", 0x1.fffffffffffffp+1023); + verify("1.7976931348623158079e308", std::numeric_limits<double>::max()); + verify("1.7976931348623158080e308", std::numeric_limits<double>::infinity(), + std::errc::result_out_of_range); verify("4503599627370496.5", 4503599627370496.5); verify("4503599627475352.5", 4503599627475352.5); verify("4503599627475353.5", 4503599627475353.5); @@ -1543,6 +1551,8 @@ verify("0.7006492e-45", 0.f, std::errc::result_out_of_range); // FLT_TRUE_MIN / 2 + 0.0000001e-45 verify("0.7006493e-45", 0x1p-149f); + verify("0.7006492321624085354e-45", 0.f, std::errc::result_out_of_range); + verify("0.7006492321624085355e-45", 0x1p-149f); // max verify("340282346638528859811704183484516925440", 0x1.fffffep+127f); @@ -1553,6 +1563,9 @@ // that rounds to FLT_MAX verify("340282356779733661637539395458142568447", std::numeric_limits<float>::max()); + verify("0.3402823567797336616e39", std::numeric_limits<float>::max()); + verify("0.3402823567797336617e39", std::numeric_limits<float>::infinity(), + std::errc::result_out_of_range); verify("-1e-999", -0.0f, std::errc::result_out_of_range); verify("1." @@ -1563,6 +1576,8 @@ "175494140627517859246175898662808184331245864732796240031385942718174" "6759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f); + verify("1.1754942807573642917e-38", 0x1.fffffcp-127f); + verify("1.1754942807573642918e-38", std::numeric_limits<float>::min()); verify_runtime( append_zeros("1." "17549414062751785924617589866280818433124586473279624003138" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/tests/long_test.cpp new/fast_float-8.2.4/tests/long_test.cpp --- old/fast_float-8.2.2/tests/long_test.cpp 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/tests/long_test.cpp 2026-03-10 17:10:12.000000000 +0100 @@ -22,7 +22,7 @@ char const *begin = input.data(); char const *end = input.data() + input.size(); for (size_t i = 0; i < answers.size(); i++) { - T result_value; + T result_value = 0; while ((begin < end) && (std::isspace(*begin))) { begin++; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.2/tests/string_test.cpp new/fast_float-8.2.4/tests/string_test.cpp --- old/fast_float-8.2.2/tests/string_test.cpp 2025-12-31 19:12:46.000000000 +0100 +++ new/fast_float-8.2.4/tests/string_test.cpp 2026-03-10 17:10:12.000000000 +0100 @@ -98,7 +98,7 @@ char const *begin = input.data(); char const *end = input.data() + input.size(); for (size_t i = 0; i < answers.size(); i++) { - T result_value; + T result_value = 0; while ((begin < end) && (std::isspace(*begin))) { begin++; }
