Microsoft's floating-point to_chars powered by Ryu and Ryu Printf
authorMark de Wever <koraq@xs4all.nl>
Tue, 9 Feb 2021 16:52:41 +0000 (17:52 +0100)
committerMark de Wever <koraq@xs4all.nl>
Sun, 12 Dec 2021 15:34:50 +0000 (16:34 +0100)
commitabb5dd6e99df623effc935b84e86f2e886580ad7
treeea9cfab852d182b0368fe2f05059f7e8a9a3f771
parentfc02ceb12aedeb43a993eac8226700810638e455
Microsoft's floating-point to_chars powered by Ryu and Ryu Printf

Microsoft would like to contribute its implementation of floating-point to_chars to libc++. This uses the impossibly fast Ryu and Ryu Printf algorithms invented by Ulf Adams at Google. Upstream repos: https://github.com/microsoft/STL and https://github.com/ulfjack/ryu .

Licensing notes: MSVC's STL is available under the Apache License v2.0 with LLVM Exception, intentionally chosen to match libc++. We've used Ryu under the Boost Software License.

This patch contains minor changes from Jorg Brown at Google, to adapt the code to libc++. He verified that it works in Google's Linux-based environment, but then I applied more changes on top of his, so any compiler errors are my fault. (I haven't tried to build and test libc++ yet.) Please tell me if we need to do anything else in order to follow https://llvm.org/docs/DeveloperPolicy.html#attribution-of-changes .

Notes:

* libc++'s integer charconv is unchanged (except for a small refactoring). MSVC's integer charconv hasn't been tuned for performance yet, so you're not missing anything.
* Floating-point from_chars isn't part of this patch because Jorg found that MSVC's implementation (derived from our CRT's strtod) was slower than Abseil's. If you're unable to use Abseil or another implementation due to licensing or technical considerations, Microsoft would be delighted if you used MSVC's from_chars (and you can just take it, or ask us to provide a patch like this). Ulf is also working on a novel algorithm for from_chars.
* This assumes that float is IEEE 32-bit, double is IEEE 64-bit, and long double is also IEEE 64-bit.
* I have added MSVC's charconv tests (the whole thing: integer/floating from_chars/to_chars), but haven't adapted them to libcxx's harness at all. (These tests will be available in the microsoft/STL repo soon.)
* Jorg added int128 codepaths. These were originally present in upstream Ryu, and I removed them from microsoft/STL purely for performance reasons (MSVC doesn't support int128; Clang on Windows does, but I found that x64 intrinsics were slightly faster).
* The implementation is split into 3 headers. In MSVC's STL, charconv contains only Microsoft-written code. xcharconv_ryu.h contains code derived from Ryu (with significant modifications and additions). xcharconv_ryu_tables.h contains Ryu's large lookup tables (they were sufficiently large to make editing inconvenient, hence the separate file). The xmeow.h convention is MSVC's for internal headers; you may wish to rename them.
* You should consider separately compiling the lookup tables (see https://github.com/microsoft/STL/issues/172 ) for compiler throughput and reduced object file size.
* See https://github.com/StephanTLavavej/llvm-project/commits/charconv for fine-grained history. (If necessary, I can perform some rebase surgery to show you what Jorg changed relative to the microsoft/STL repo; currently that's all fused into the first commit.)

Differential Revision: https://reviews.llvm.org/D70631
48 files changed:
libcxx/CREDITS.TXT
libcxx/docs/ReleaseNotes.rst
libcxx/docs/Status/Cxx17.rst
libcxx/docs/Status/Cxx17Papers.csv
libcxx/include/__availability
libcxx/include/charconv
libcxx/lib/abi/CHANGELOG.TXT
libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist
libcxx/src/CMakeLists.txt
libcxx/src/charconv.cpp
libcxx/src/include/ryu/common.h [new file with mode: 0644]
libcxx/src/include/ryu/d2fixed.h [new file with mode: 0644]
libcxx/src/include/ryu/d2fixed_full_table.h [new file with mode: 0644]
libcxx/src/include/ryu/d2s.h [new file with mode: 0644]
libcxx/src/include/ryu/d2s_full_table.h [new file with mode: 0644]
libcxx/src/include/ryu/d2s_intrinsics.h [new file with mode: 0644]
libcxx/src/include/ryu/digit_table.h [new file with mode: 0644]
libcxx/src/include/ryu/f2s.h [new file with mode: 0644]
libcxx/src/include/ryu/ryu.h [new file with mode: 0644]
libcxx/src/include/to_chars_floating_point.h [new file with mode: 0644]
libcxx/src/ryu/README.txt [new file with mode: 0644]
libcxx/src/ryu/d2fixed.cpp [new file with mode: 0644]
libcxx/src/ryu/d2s.cpp [new file with mode: 0644]
libcxx/src/ryu/f2s.cpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_fixed_precision_to_chars_test_cases_1.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_fixed_precision_to_chars_test_cases_2.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_fixed_precision_to_chars_test_cases_3.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_fixed_precision_to_chars_test_cases_4.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_from_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_general_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_hex_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_scientific_precision_to_chars_test_cases_1.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_scientific_precision_to_chars_test_cases_2.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_scientific_precision_to_chars_test_cases_3.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_scientific_precision_to_chars_test_cases_4.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/double_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_fixed_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_from_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_general_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_hex_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_scientific_precision_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/float_to_chars_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/floating_point_test_cases.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/test.hpp [new file with mode: 0644]
libcxx/test/std/utilities/charconv/charconv.msvc/test.pass.cpp [new file with mode: 0644]