373 Commits

Author SHA1 Message Date
github-actions[bot]
6480055523 Version 8.3.3 2026-10-11 21:03:03 +00:00
HedgehogInTheCPP
ad630d9c2e Merge branch 'main' of https://github.com/fastfloat/fast_float 2026-10-10 01:54:56 +03:00
github-actions[bot]
42f254836e Version 8.3.2 2026-10-09 19:56:38 +00:00
github-actions[bot]
f3f02c8ad0 Version 8.3.1 2026-10-04 16:26:53 +00:00
HedgehogInTheCPP
f89bb255b6 lint unfck. 2026-09-23 02:53:12 +03:00
HedgehogInTheCPP
ac96536399 Cleanup for code related with merge and add some documentation.
Merge branch 'main' of https://github.com/fastfloat/fast_float
2026-09-23 02:51:34 +03:00
Daniel Lemire
cdc385d058
Merge pull request #408 from jadidbourbaki/float16-exactness
Fix std::float16_t rounding of subnormal ties and fast-path overflow
2026-09-22 14:11:44 -04:00
Daniel Lemire
82623d83c5 Avoid right-shifting a negative value in subnormal_ties_possible() 2026-09-22 13:57:31 -04:00
Daniel Lemire
b57a12270e Fold the format at compile time under clang, mark cold checks unlikely
Clang generated ~35% more instructions per float than GCC on identical
code (canada.txt, 64-bit: 276 vs 200 i/f on a Xeon Gold 6548N). Two
causes, confirmed with exact instruction traces:

1. Clang declines to inline the parser (from_chars_caller<T>::call) into
   its callers, so parse_options stays a runtime value and every format
   flag is re-tested on every conversion: javascript, skip_white_space,
   allow_leading_plus, fixed/scientific, the decimal point, the JSON
   dispatch. GCC inlines the whole parser into each call site, where
   chars_format::general is a constant, and all of it folds away.

   Fix: from_chars dispatches chars_format::general to a
   from_chars_fixed_format<T, UC, Fmt> instantiation, so the format is a
   compile-time constant inside the parser body whether or not the user's
   call is inlined. The call forwarder gets fastfloat_clang_really_inline
   so that it folds into that instantiation.

2. Clang if-converts the rare over/underflow fix-ups at the end of
   compute_float and the result_out_of_range test into cmov chains that
   every conversion executes. Marking them fastfloat_clang_unlikely keeps
   them as never-taken branches.

Both are applied under clang only, and GCC's generated code is identical
to before (verified on the object code). That is on purpose: forcing
always_inline on from_chars, or even on the trivial call forwarder,
regressed GCC by up to 14% on mesh.txt by changing its inlining order;
dispatching to the fixed-format instantiation made it stop inlining into
the loop; and the unlikely hints alone cost it 2-6% on mesh.txt by
reordering blocks (GCC already emits branches there).

realbenchmark, cycles per float, 5 interleaved rounds, medians:

clang 21, Xeon Gold 6548N        before   after
  canada.txt ASCII  (64)          49.7    44.6   -10%
  canada.txt UTF-16 (64)          57.4    52.0    -9%
  mesh.txt   ASCII  (64)          26.5    22.4   -16%
  mesh.txt   UTF-16 (64)          28.1    24.0   -15%
  (32-bit: -8% to -14%)
gcc 14, same machine: generated code unchanged.
Apple clang 17, arm64: +3% to +18% Mfloat/s.
2026-09-21 22:30:43 -04:00
Daniel Lemire
7e45de0c3b Restore the simple loop in fastfloat_strncasecmp
PR #356 replaced the 3/5-character case-insensitive compare used by
parse_infnan with SWAR helpers (fastfloat_strncasecmp3/5 plus a generic
memcpy-based fastfloat_strncasecmp). That code only runs for "nan",
"inf" and "infinity" inputs, so it cannot help ordinary parsing, but it
grew the inlined inf/nan tail of the parser: on x86-64 (GCC 14 and
clang 21) the per-commit benchmarks dropped by 1.5-2.5% because the
extra dead code changed inlining decisions and register allocation on
the hot path (+7 instructions/float on canada.txt).

Go back to the plain loop, which the compiler unrolls for the constant
lengths 3 and 5, and drop the now-unused generic SWAR function. The
`actual < 256` guard of the original is unnecessary: OR-ing 0x20 into
a value can only equal an ASCII lowercase letter when the value is that
letter or its uppercase form, so the plain OR is exact for every
character type.
2026-09-21 22:05:34 -04:00
Raúl Marín
b2e41e8b88 Keep chars_format::javascript out of the common hot path
8.3.0 added the ECMAScript leading-zero rule as a runtime test on fmt inside
parse_number_string, so unlike basic_json_fmt its error returns and Annex B
octal scan land in the parser body that every from_chars instantiation
force-inlines. from_chars_caller<double>::call grew from 935 to 1031
instructions and other formats lost about 3% on short inputs.

Make the rule a compile-time parameter of the parser body, selected once at the
entry point, and take chars_format::javascript out to a cold conversion before
anything else is live so the branch is a tail call. parse_number_string keeps
its signature and behaviour.

benchmarks/benchmark.cpp, Intel Xeon 6975P-C, clang 22.1.8, cycles per float,
best of 7:

              canada.txt    mesh.txt
  8.2.10         47.03        24.78
  8.3.0          47.34        26.08
  this           46.28        24.86
2026-09-21 19:47:21 +00:00
HedgehogInTheCPP
d577161969 additional cleanup, more unlikely and likely. Fix JSON related errors. Speedup JSON parsing if errors. 2026-09-19 23:01:11 +03:00
HedgehogInTheCPP
5f6c3c8df9 More optimized code especially if FASTFLOAT_ISNOT_CHECKED_BOUNDS or FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN defined.
Cleanup in many parsing parts.
Fix an error in JSON parsing.
2026-09-19 20:29:11 +03:00
HedgehogInTheCPP
c8894d3722 Cleanup for code near merged code: compiler generate much better code in any mode without manual unroling because it's less branching and also it's allow more inlining which is better.
Merge branch 'main' of https://github.com/fastfloat/fast_float
2026-09-18 22:08:56 +03:00
Daniel Lemire
b0ab987b3d Version 8.3.0 2026-09-15 11:03:18 -04:00
Daniel Lemire
3254622f74 Add chars_format::javascript_sloppy (Annex B NonOctalDecimalIntegerLiteral)
chars_format::javascript follows the strict-mode grammar, which rejects
any leading zero. In sloppy mode, JavaScript also accepts a leading zero
when one of the digits is 8 or 9 ("08.5" is 8.5, Annex B's
NonOctalDecimalIntegerLiteral). A leading zero followed only by octal
digits is a LegacyOctalIntegerLiteral ("0775"), which is not a decimal
number: it is rejected with the new parse_error::legacy_octal_integer_part
so the caller can parse it in base 8.

javascript_sloppy sets one extra bit on top of javascript, and the check
lives inside the existing runtime JavaScript branch of
parse_number_string<false>, so the general path is unchanged. An
interleaved A/B with realbenchmark on canada.txt and mesh.txt (ASCII and
UTF-16, 32/64-bit) shows identical instructions per float and cycles
within noise.

Document both formats in the README.
2026-09-15 10:52:49 -04:00
jadidbourbaki
20a9b35333 Gate the subnormal tie test on a compile-time predicate 2026-09-15 09:11:27 -04:00
jadidbourbaki
abb4c8659a Fix std::float16_t rounding of subnormal ties and fast-path overflow 2026-09-14 22:15:45 -04:00
Daniel Lemire
4fcb7e3249 Fix clang-format 17 on FASTFLOAT_ASSERT macros 2026-09-14 20:46:52 -04:00
Daniel Lemire
f837a78057 Add chars_format::javascript (ECMAScript DecimalLiteral)
The JSON format rejects leading zeros, which JavaScript also rejects,
but it further requires digits on both sides of the decimal point,
which JavaScript does not: ".5", "5." and "5.e3" are all valid
DecimalLiteral productions. Users lexing JavaScript therefore could not
use chars_format::json and had to re-check the integer span themselves
after a general-mode parse.

chars_format::javascript is general mode plus the leading-zero rule
(reported as leading_zeros_in_integer_part), with no_infnan. It is a
runtime check on the format, like fortran, so it reuses the existing
parse_number_string<false> instantiation. A leading minus sign is
accepted, and a leading plus sign with allow_leading_plus.

Claude-Session: https://claude.ai/code/session_01KbAWRBpE3MPy5cXECc5vWZ
2026-09-14 19:36:49 -04:00
HedgehogInTheCPP
15ab8caa1f reduce data cache pressure. 2026-09-04 03:08:31 +03:00
HedgehogInTheCPP
42abbcbb34 lint unfck. 2026-08-29 17:52:00 +03:00
HedgehogInTheCPP
9b3d9f7b1a add fastfloat_noinline from https://github.com/fastfloat/fast_float/pull/403 my fork don't need any additional from this PR because it's already simd optimized more strictly. 2026-08-29 17:33:00 +03:00
HedgehogInTheCPP
870fc1a720 Improvements detection of features, part 15, added FASTFLOAT_NO_UNIQUE_ADDRESS and improves more. 2026-08-25 22:54:57 +03:00
HedgehogInTheCPP
73f4d844a8 typo fixed. 2026-08-22 23:10:03 +03:00
HedgehogInTheCPP
207069edcd FASTFLOAT_ASSUME and Clang related crutches cleanup. 2026-08-22 22:14:00 +03:00
HedgehogInTheCPP
bc1316970c More cleanup by FASTFLOAT_ONLY_ROUNDS_TO_NEAREST_SUPPORTED. 2026-08-22 21:46:25 +03:00
HedgehogInTheCPP
677cfe8425 Improvements detection of features, part 12. 2026-08-21 23:10:50 +03:00
HedgehogInTheCPP
57cb772715 final cleanup for full / 128 bit multiplication: constexpr fix, нахуй старые говны мамонтов. 2026-08-21 22:33:56 +03:00
HedgehogInTheCPP
25e448109d constexpr fix for ancient standard. 2026-08-21 17:59:34 +03:00
HedgehogInTheCPP
7c82411fd6 constexpr fix 2026-08-21 17:51:24 +03:00
HedgehogInTheCPP
a4d25ebe28 final cleanup for full / 128 bit multiplication 2026-08-21 17:42:04 +03:00
HedgehogInTheCPP
cbdea5e381 fix constexpr for umul128. 2026-08-21 17:11:02 +03:00
HedgehogInTheCPP
8b851d996d additional cleanup for full_multiplication. 2026-08-21 16:30:10 +03:00
HedgehogInTheCPP
9e5fc2693c big cleanup of 128bit multiplication. 2026-08-21 15:54:32 +03:00
Daniel Lemire
12e310aa8f Avoid old-style casts
Replace C-style casts with static_cast/const_cast so -Wold-style-cast
is clean, and enable that warning in the Unix test builds and the
amalgamated-header CI job.
2026-08-20 13:30:32 -04:00
HedgehogInTheCPP
e7a29e0915 Documentation updated and hardware level detection cleanup. 2026-08-20 18:45:31 +03:00
HedgehogInTheCPP
4a71c111f2 improve error messages when type is unsupported.
cleanup of functions naming.
logical improvements of the FASTFLOAT_ISNOT_CHECKED_BOUNDS when FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN isn't enabled.
2026-08-19 17:00:32 +03:00
HedgehogInTheCPP
bfbe4c4869 FASTFLOAT_HAS_SIMD -> FASTFLOAT_USE_SIMD 2026-08-18 23:43:56 +03:00
HedgehogInTheCPP
262ed0c0fe lint unfck 2026-08-18 23:36:24 +03:00
HedgehogInTheCPP
006cb32e16 cleanup more + reimplement cross compiler support and add more fastfloat_unlikely 2026-08-18 23:31:26 +03:00
HedgehogInTheCPP
2aa1746bb9 try to apply std everywhere is possible. 2026-08-18 18:35:13 +03:00
HedgehogInTheCPP
5e7936a02a cleanup 2026-08-18 00:06:53 +03:00
HedgehogInTheCPP
371a224039 fix 2026-08-17 23:29:36 +03:00
HedgehogInTheCPP
055f966c76 lint unfck 2026-08-17 22:13:35 +03:00
HedgehogInTheCPP
8e954fada3 fix 2026-08-17 22:06:46 +03:00
HedgehogInTheCPP
da875ff9cf fixes for old standards. 2026-08-17 21:54:19 +03:00
HedgehogInTheCPP
5d65edb6cd added cross platform and cross compiler parse_digits_until_19 and cleanup related code. 2026-08-17 21:36:11 +03:00
HedgehogInTheCPP
deada1436d cleanup 2026-08-17 20:02:12 +03:00
HedgehogInTheCPP
37d25dd546 Continue rework of the FASTFLOAT_X86_SIMD realization: cleanup and improvements.
Improvements in the FASTFLOAT_ISNOT_CHECKED_BOUNDS switch: cleanup more.
cleanup if constexpr usage.
2026-08-17 19:46:05 +03:00