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-06-09 14:21:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fast_float (Old) and /work/SRC/openSUSE:Factory/.fast_float.new.2375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fast_float" Tue Jun 9 14:21:06 2026 rev:9 rq:1358090 version:8.2.8 Changes: -------- --- /work/SRC/openSUSE:Factory/fast_float/fast_float.changes 2026-06-02 19:47:13.284886581 +0200 +++ /work/SRC/openSUSE:Factory/.fast_float.new.2375/fast_float.changes 2026-06-09 14:22:50.638886570 +0200 @@ -1,0 +2,13 @@ +Tue Jun 9 01:50:15 UTC 2026 - Jan Engelhardt <[email protected]> + +- Update to release 8.2.8 + * Fix some compile errors when used with clang + +------------------------------------------------------------------- +Mon Jun 8 10:03:59 UTC 2026 - Jan Engelhardt <[email protected]> + +- Update to release 8.2.7 + * Skip materializing `parsed_number_string_t` spans + on the hot path. + +------------------------------------------------------------------- Old: ---- fast_float-8.2.6.tar.gz New: ---- fast_float-8.2.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fast_float.spec ++++++ --- /var/tmp/diff_new_pack.WuiXZC/_old 2026-06-09 14:22:52.986983805 +0200 +++ /var/tmp/diff_new_pack.WuiXZC/_new 2026-06-09 14:22:53.002984467 +0200 @@ -17,7 +17,7 @@ Name: fast_float -Version: 8.2.6 +Version: 8.2.8 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.WuiXZC/_old 2026-06-09 14:22:53.162991094 +0200 +++ /var/tmp/diff_new_pack.WuiXZC/_new 2026-06-09 14:22:53.210993082 +0200 @@ -1,5 +1,5 @@ -mtime: 1780373873 -commit: e339164932ee4eedc02db4a90ed76a617baf4e844b3025f7a06ad5431876cbd4 +mtime: 1780969843 +commit: ff5212b5693b154ad7890f0d001476d22b6f6b7e33c12ad2c1df8d6247a98a8e 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-06-09 03:50:43.000000000 +0200 @@ -0,0 +1 @@ +.osc ++++++ fast_float-8.2.6.tar.gz -> fast_float-8.2.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/.github/workflows/emscripten.yml new/fast_float-8.2.8/.github/workflows/emscripten.yml --- old/fast_float-8.2.6/.github/workflows/emscripten.yml 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/.github/workflows/emscripten.yml 2026-06-08 21:29:36.000000000 +0200 @@ -5,8 +5,8 @@ runs-on: ubuntu-latest steps: - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.2.2 - - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - - uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + - uses: mymindstorm/setup-emsdk@4528d102f7230f0e7b276855c01ea1159be0e984 # v16 - name: Verify run: emcc -v - name: Checkout diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/.github/workflows/lint_and_format_check.yml new/fast_float-8.2.8/.github/workflows/lint_and_format_check.yml --- old/fast_float-8.2.6/.github/workflows/lint_and_format_check.yml 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/.github/workflows/lint_and_format_check.yml 2026-06-08 21:29:36.000000000 +0200 @@ -27,7 +27,7 @@ - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v4.1.7 - name: Run clang-format - uses: jidicula/clang-format-action@3a18028048f01a66653b4e3bf8d968d2e7e2cb8b # v4.17.0 + uses: jidicula/clang-format-action@654a770daa28443dd111d133e4083e21c1075674 # v4.18.0 with: clang-format-version: '17' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/CMakeLists.txt new/fast_float-8.2.8/CMakeLists.txt --- old/fast_float-8.2.6/CMakeLists.txt 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/CMakeLists.txt 2026-06-08 21:29:36.000000000 +0200 @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.2.6 LANGUAGES CXX) +project(fast_float VERSION 8.2.8 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.2.6/README.md new/fast_float-8.2.8/README.md --- old/fast_float-8.2.6/README.md 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/README.md 2026-06-08 21:29:36.000000000 +0200 @@ -531,7 +531,7 @@ FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.2.6 + GIT_TAG tags/v8.2.8 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -547,7 +547,7 @@ CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.2.6) + GIT_TAG v8.2.8) ``` ## Using as single header @@ -559,7 +559,7 @@ You may directly download automatically generated single-header files: -<https://github.com/fastfloat/fast_float/releases/download/v8.2.6/fast_float.h> +<https://github.com/fastfloat/fast_float/releases/download/v8.2.8/fast_float.h> ## Benchmarking diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/docs/index.html new/fast_float-8.2.8/docs/index.html --- old/fast_float-8.2.6/docs/index.html 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/docs/index.html 2026-06-08 21:29:36.000000000 +0200 @@ -221,7 +221,7 @@ <pre data-lang="cmake"><code>FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v{{VERSION}} + GIT_TAG tags/<span data-version>v{{VERSION}}</span> GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) target_link_libraries(myprogram PUBLIC fast_float)</code></pre> @@ -232,13 +232,13 @@ <pre data-lang="cmake"><code>CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v{{VERSION}})</code></pre> + GIT_TAG <span data-version>v{{VERSION}}</span>)</code></pre> </article> <article class="card"> <h3>Single header</h3> <p>Download a pre-amalgamated header — no build system required.</p> -<pre data-lang="bash"><code>curl -LO https://github.com/fastfloat/fast_float/releases/download/v{{VERSION}}/fast_float.h</code></pre> +<pre data-lang="bash"><code>curl -LO https://github.com/fastfloat/fast_float/releases/download/<span data-version>v{{VERSION}}</span>/fast_float.h</code></pre> </article> <article class="card"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/include/fast_float/ascii_number.h new/fast_float-8.2.8/include/fast_float/ascii_number.h --- old/fast_float-8.2.6/include/fast_float/ascii_number.h 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/include/fast_float/ascii_number.h 2026-06-08 21:29:36.000000000 +0200 @@ -330,10 +330,17 @@ // Assuming that you use no more than 19 digits, this will // parse an ASCII string. +// +// store_spans is a *runtime* flag (not a template parameter, deliberately: a +// template would create a second instantiation of this whole function and the +// extra icache pressure wipes out the gain). When false, the integer/fraction +// spans (read only by the rare digit_comp slow path) are not materialized, +// which keeps the fat parsed_number_string_t off the hot path. The caller +// re-parses with store_spans=true if the slow path is actually reached. template <bool basic_json_fmt, typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t<UC> -parse_number_string(UC const *p, UC const *pend, - parse_options_t<UC> options) noexcept { +parse_number_string(UC const *p, UC const *pend, parse_options_t<UC> options, + bool store_spans = true) noexcept { chars_format const fmt = detail::adjust_for_feature_macros(options.format); UC const decimal_point = options.decimal_point; @@ -402,7 +409,9 @@ } UC const *const end_of_integer_part = p; int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = span<UC const>(start_digits, size_t(digit_count)); + if (store_spans) { + answer.integer = span<UC const>(start_digits, size_t(digit_count)); + } FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { // at least 1 digit in integer part, without leading zeros if (digit_count == 0) { @@ -429,7 +438,9 @@ i = i * 10 + digit; // in rare cases, this will overflow, but that's ok } exponent = before - p; - answer.fraction = span<UC const>(before, size_t(p - before)); + if (store_spans) { + answer.fraction = span<UC const>(before, size_t(p - before)); + } digit_count -= exponent; } FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { @@ -514,29 +525,35 @@ if (digit_count > 19) { answer.too_many_digits = true; - // Let us start again, this time, avoiding overflows. - // We don't need to call if is_integer, since we use the - // pre-tokenized spans from above. - i = 0; - p = answer.integer.ptr; - UC const *int_end = p + answer.integer.len(); - uint64_t const minimal_nineteen_digit_integer{1000000000000000000}; - while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { - i = i * 10 + uint64_t(*p - UC('0')); - ++p; - } - 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; - UC const *frac_end = p + answer.fraction.len(); - while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) { + // The truncation recompute below reads the integer/fraction spans. When + // store_spans is false we didn't materialize them, so just flag + // too_many_digits; the caller re-parses with store_spans=true to obtain + // the corrected mantissa/exponent before taking the slow path. + if (store_spans) { + // Let us start again, this time, avoiding overflows. + // We don't need to call if is_integer, since we use the + // pre-tokenized spans from above. + i = 0; + p = answer.integer.ptr; + UC const *int_end = p + answer.integer.len(); + uint64_t const minimal_nineteen_digit_integer{1000000000000000000}; + while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { i = i * 10 + uint64_t(*p - UC('0')); ++p; } - exponent = answer.fraction.ptr - p + exp_number; + 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; + UC const *frac_end = p + answer.fraction.len(); + while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + exponent = answer.fraction.ptr - p + exp_number; + } + // We have now corrected both exponent and i, to a truncated value } - // We have now corrected both exponent and i, to a truncated value } } answer.exponent = exponent; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/include/fast_float/fast_float.h new/fast_float-8.2.8/include/fast_float/fast_float.h --- old/fast_float-8.2.6/include/fast_float/fast_float.h 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/include/fast_float/fast_float.h 2026-06-08 21:29:36.000000000 +0200 @@ -7,12 +7,12 @@ namespace fast_float { /** * This function parses the character sequence [first,last) for a number. It - * parses floating-point numbers expecting a locale-indepent format equivalent - * to what is used by std::strtod in the default ("C") locale. The resulting - * floating-point value is the closest floating-point values (using either float - * or double), using the "round to even" convention for values that would - * otherwise fall right in-between two values. That is, we provide exact parsing - * according to the IEEE standard. + * parses floating-point numbers expecting a locale-independent format + * equivalent to what is used by std::strtod in the default ("C") locale. The + * resulting floating-point value is the closest floating-point values (using + * either float or double), using the "round to even" convention for values that + * would otherwise fall right in-between two values. That is, we provide exact + * parsing according to the IEEE standard. * * Given a successful parse, the pointer (`ptr`) in the returned value is set to * point right after the parsed number, and the `value` referenced is set to the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/include/fast_float/float_common.h new/fast_float-8.2.8/include/fast_float/float_common.h --- old/fast_float-8.2.6/include/fast_float/float_common.h 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/include/fast_float/float_common.h 2026-06-08 21:29:36.000000000 +0200 @@ -18,7 +18,7 @@ #define FASTFLOAT_VERSION_MAJOR 8 #define FASTFLOAT_VERSION_MINOR 2 -#define FASTFLOAT_VERSION_PATCH 6 +#define FASTFLOAT_VERSION_PATCH 8 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) @@ -197,6 +197,28 @@ #define fastfloat_really_inline inline __attribute__((always_inline)) #endif +// Branch-probability hint marking the rare slow-path branches as cold, so the +// optimizer keeps the out-of-line slow-path re-parse off the hot path (and does +// not duplicate the force-inlined hot scanner into the caller, which bloated +// the hot frame and hurt ILP on some targets). Used at the call site as +// if fastfloat_unlikely(cond) { ... } +// (the macro supplies the parentheses). It expands to the standard [[unlikely]] +// attribute when supported, otherwise to __builtin_expect on GCC/Clang, or +// to a no-op elsewhere (e.g. pre-C++20 MSVC, which has no equivalent hint). +#ifdef __has_cpp_attribute +#if __has_cpp_attribute(unlikely) >= 201803L +#define FASTFLOAT_USE_UNLIKELY_ATTR 1 +#endif +#endif + +#ifdef FASTFLOAT_USE_UNLIKELY_ATTR +#define fastfloat_unlikely(x) (x) [[unlikely]] +#elif defined(__GNUC__) || defined(__clang__) +#define fastfloat_unlikely(x) (__builtin_expect(!!(x), 0)) +#else +#define fastfloat_unlikely(x) (x) +#endif + #ifndef FASTFLOAT_ASSERT #define FASTFLOAT_ASSERT(x) \ { ((void)(x)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fast_float-8.2.6/include/fast_float/parse_number.h new/fast_float-8.2.8/include/fast_float/parse_number.h --- old/fast_float-8.2.6/include/fast_float/parse_number.h 2026-06-02 00:07:41.000000000 +0200 +++ new/fast_float-8.2.8/include/fast_float/parse_number.h 2026-06-08 21:29:36.000000000 +0200 @@ -289,6 +289,23 @@ return answer; } +// Slow path: re-parse materializing the integer/fraction spans the hot no-span +// parse skipped, then run the full algorithm. The two callers reach it only +// through a fastfloat_unlikely branch, so the optimizer keeps this re-parse off +// the hot path on its own (no function-level noinline needed). +// from_chars_advanced already handles both the too_many_digits disambiguation +// and the am.power2<0 digit_comp recompute, so both slow branches collapse to +// one helper call. +template <typename T, typename UC> +FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> +parse_number_slow_path(UC const *first, UC const *last, T &value, + parse_options_t<UC> options, bool bjf) noexcept { + parsed_number_string_t<UC> pns = + bjf ? parse_number_string<true, UC>(first, last, options, true) + : parse_number_string<false, UC>(first, last, options, true); + return from_chars_advanced(pns, value); +} + template <typename T, typename UC> fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC> from_chars_float_advanced(UC const *first, UC const *last, T &value, @@ -312,10 +329,15 @@ answer.ptr = first; return answer; } + bool const bjf = uint64_t(fmt & detail::basic_json_fmt) != 0; + + // Fast path: parse WITHOUT materializing the integer/fraction spans (read + // only by the rare slow paths). Skipping their stores keeps the fat + // parsed_number_string_t off the hot path. store_spans is a runtime argument, + // so this reuses the single parse_number_string instantiation. parsed_number_string_t<UC> pns = - uint64_t(fmt & detail::basic_json_fmt) - ? parse_number_string<true, UC>(first, last, options) - : parse_number_string<false, UC>(first, last, options); + bjf ? parse_number_string<true, UC>(first, last, options, false) + : parse_number_string<false, UC>(first, last, options, false); if (!pns.valid) { if (uint64_t(fmt & chars_format::no_infnan)) { answer.ec = std::errc::invalid_argument; @@ -326,8 +348,49 @@ } } - // call overload that takes parsed_number_string_t directly. - return from_chars_advanced(pns, value); + // Slow path A (rare): > 19 significant digits. The no-span parse left the + // mantissa un-truncated and skipped the span-based recompute; the cold helper + // re-parses with spans and runs the full algorithm. + // +// We have to disable -Wc++20-extensions for the [[unlikely]] attribute +// See comment for @jwakely at +// https://github.com/fastfloat/fast_float/pull/387#discussion_r3366943539 +// This is unfortunate. +#ifdef __clang__ +#pragma clang diagnostic push +#if (!defined(__APPLE_CC__) && __clang_major__ >= 10) || (__clang_major__ >= 13) +#pragma clang diagnostic ignored "-Wc++20-extensions" +#endif +#endif + if fastfloat_unlikely (pns.too_many_digits) { + return parse_number_slow_path<T, UC>(first, last, value, options, bjf); + } + answer.ec = std::errc(); // be optimistic + answer.ptr = pns.lastmatch; + + if (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); + // Slow path B (rare): Eisel-Lemire could not resolve; digit_comp needs the + // integer/fraction spans. Route to the cold helper (clinger there is a + // dead-effect since it already failed here; the cold re-parse + digit_comp + // via from_chars_advanced reproduces this branch). + if fastfloat_unlikely (am.power2 < 0) { + return parse_number_slow_path<T, UC>(first, last, value, options, bjf); + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + to_float(pns.negative, am, value); + // Test for over/underflow. + if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || + am.power2 == binary_format<T>::infinite_power()) { + answer.ec = std::errc::result_out_of_range; + } + return answer; } template <typename T, typename UC, typename>
