casaroli opened a new pull request, #21507:
URL: https://github.com/apache/nuttx/pull/21507

   depends-on: apache/nuttx/pull/21506
   
   This branch holds the commits of #21474, #21493, #21505 and #21506, and 5 
commits of its own, because these commits change the same code. **Review only 
the last 5 commits.** It stays a draft until #21506 merges. Part of #21467, 
step 4.
   
   ## Summary
   
   The engine of `%e`, `%f` and `%g` scaled the value with `double` operations. 
It had 15 significant digits, it did not round `%.0f`, and the last digits 
could be wrong. On a CPU with no FPU it pulled in the soft-float code of libgcc.
   
   - **A new engine on the bits**, in all builds with floating point. It uses 
integers only: no floating point operation. Up to 17 significant digits, `%.0f` 
rounds, and ties are correct where the value is exact in 64 bits. It handles 
binary64 and binary32, in both byte orders.
   - **`LIBC_PRINTF_EXACT`**, off in Minimal and Default, on in Full. All 
digits of a `double` are correctly rounded, at any precision. The fast path 
proves its digits with an error bound. Only other values take 
`vsprintf_float_big()`, a function of its own.
   - **`LIBC_PRINTF_EXACT_LDOUBLE`**, off in Minimal and Default, on in Full. 
The same for `long double`, in `vsprintf_ldouble()`, a function that only `%L` 
calls.
   - The first commit only moves code, with no output change. The last commit 
updates the documentation page.
   
   `lib_dtoa_engine.c` and `lib_dtoa_data.c` go away. The new files are under 
Apache-2.0.
   
   ## Impact
   
   **The digits of `%e`, `%f` and `%g` change in Default.** They are nearer to 
the correct result at each precision. For example `%.1f` of 2.25 was `2.3` and 
is now `2.2`. A program or test that compares an exact string can see a change. 
`%g` now uses the precision of the format to select its form. No ABI change. No 
architecture code. Flat, protected and kernel builds.
   
   Image text, with floating point on in both builds. Boards: 
`nucleo-f072rb:nsh`, `nucleo-f103rb:nsh`, `rv-virt:nsh`, `qemu-armv8a:nsh`:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | Output PR | 56,856 | 38,604 | 230,462 | 328,268 |
   | This PR | 54,424 | 36,684 | 231,272 | 329,284 |
   | Delta | -2,432 | -1,920 | +810 | +1,016 |
   | `LIBC_PRINTF_EXACT` adds | +1,528 | +1,360 | +1,624 | +1,912 |
   | `LIBC_PRINTF_EXACT_LDOUBLE` adds | +0 | +0 | +162 | +324 |
   
   With floating point off, the image text is the same as #21505 on Cortex-M0 
and Cortex-M3. The engine is larger than the old table code on CPUs with an FPU 
or with the soft-float code linked anyway. libgcc in the image, floating point 
on, Cortex-M0: 10,432 before, 7,376 now. Most of the rest comes from 
`/proc/uptime`: 2,028 with the integer path in the uptime PR.
   
   Stack frames, in bytes, with both options on:
   
   | | Cortex-M0 | Cortex-M3 | rv32 | arm64 |
   |---|---:|---:|---:|---:|
   | `vsprintf_float()` | 88 | 96 | 96 | 112 |
   | `__dtoa_engine()` | 104 | 88 | 112 | 64 |
   | `vsprintf_putfloat()` | 72 | 80 | 96 | 128 |
   | `vsprintf_float_big()` | 256 | 256 | 256 | 288 |
   | `vsprintf_ldouble()` | - | - | 2,624 | 2,624 |
   
   ## Testing
   
   Accuracy, against the printf of the host (Apple libc), under ASan and UBSan, 
in `%e` and `%f` at each precision over random bits, decimals, integers, powers 
of ten and ties:
   
   - `LIBC_PRINTF_EXACT`: 9,109,842 conversions of `double`, 0 differences; 
9,388,638 in the binary32 path, 0 differences.
   - Default: 100% of ties, and 99.6% or more at each precision up to 17 digits 
in `%e`. `%f` of large values stops at 17 digits.
   - `LIBC_PRINTF_EXACT_LDOUBLE`, against glibc: binary128 on arm64 (15,624 
runs) and s390x (7,074), and x87 on x86_64 (10,296): 0 differences.
   
   The same vectors give the same hash on arm64, s390x (big endian), x86_64 and 
AVR with a 64-bit `double`, and on arm64 and AVR with a 32-bit `double`, with 
and without the option. z80 with sdcc: compile only.
   
   printf-report suite, C99 and correctly rounded:
   
   | | Output PR | This PR |
   |---|---:|---:|
   | Default | 73.84 / 69.14 | 75.73 / 72.73 |
   | `%a` and C23 on | 94.85 / 90.08 | 96.74 / 93.74 |
   | `%a`, C23 and exact on | | 97.39 / 97.38 |
   
   0 tests go from pass to fail, and 0 crashes. The rest is mainly `%#g`, which 
has its own PR.
   
   - Host harness: 58 builds with clang and 59 with gcc, under ASan and UBSan, 
all profiles and options: 0 reports. The correct-usage cases that differ are 
only in builds with an option off.
   - Runtime: ostest and the printf test on rv32 flat and on arm64 kernel, in 
Default, Full, Default + exact, Default + both options and Minimal + float: all 
pass, 0 failures. Cortex-M0 under Renode: the printf test and a test of the 
digits, with the option on and off: all pass.
   - Builds with `-Wno-cpp -Werror`: `nucleo-f072rb:nsh`, `nucleo-f103rb:nsh`, 
`rv-virt:nsh`, `qemu-armv8a:nsh`, `mps2-an500:knsh`, `qemu-armv8a:knsh`, 
`rv-virt:knsh`, 48 builds in all with the profiles and options: all pass.
   - `tools/checkpatch.sh`: pass. Documentation: Sphinx gives no warning from 
this page.
   
   Not run: hardware, a CMake build, a protected build at run time.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to