summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ryu
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/ryu
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/ryu')
-rw-r--r--third_party/rust/ryu/.cargo-checksum.json1
-rw-r--r--third_party/rust/ryu/Cargo.lock144
-rw-r--r--third_party/rust/ryu/Cargo.toml35
-rw-r--r--third_party/rust/ryu/LICENSE-APACHE201
-rw-r--r--third_party/rust/ryu/LICENSE-BOOST23
-rw-r--r--third_party/rust/ryu/README.md114
-rw-r--r--third_party/rust/ryu/benches/bench.rs58
-rw-r--r--third_party/rust/ryu/build.rs66
-rw-r--r--third_party/rust/ryu/examples/upstream_benchmark.rs88
-rw-r--r--third_party/rust/ryu/src/buffer/mod.rs199
-rw-r--r--third_party/rust/ryu/src/common.rs75
-rw-r--r--third_party/rust/ryu/src/d2s.rs412
-rw-r--r--third_party/rust/ryu/src/d2s_full_table.rs643
-rw-r--r--third_party/rust/ryu/src/d2s_intrinsics.rs105
-rw-r--r--third_party/rust/ryu/src/d2s_small_table.rs206
-rw-r--r--third_party/rust/ryu/src/digit_table.rs28
-rw-r--r--third_party/rust/ryu/src/f2s.rs323
-rw-r--r--third_party/rust/ryu/src/lib.rs111
-rw-r--r--third_party/rust/ryu/src/pretty/exponent.rs49
-rw-r--r--third_party/rust/ryu/src/pretty/mantissa.rs51
-rw-r--r--third_party/rust/ryu/src/pretty/mod.rs228
-rw-r--r--third_party/rust/ryu/tests/d2s_table_test.rs52
-rw-r--r--third_party/rust/ryu/tests/d2s_test.rs321
-rw-r--r--third_party/rust/ryu/tests/exhaustive.rs55
-rw-r--r--third_party/rust/ryu/tests/f2s_test.rs173
-rw-r--r--third_party/rust/ryu/tests/macros/mod.rs8
26 files changed, 3769 insertions, 0 deletions
diff --git a/third_party/rust/ryu/.cargo-checksum.json b/third_party/rust/ryu/.cargo-checksum.json
new file mode 100644
index 0000000000..6f6f63322c
--- /dev/null
+++ b/third_party/rust/ryu/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"b5f6a8d622e52ec6b8818eba97aaaf94bcb60a9d79aaffb3542acada6474e587","Cargo.toml":"ae5e72bf5e666e219d92d8dfff0e13499e74001f1f25080b5933943fc578baae","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"66e8c5353ae528e44f178e783586720b152d023b632b0d9f1fed6d7d1453bad8","benches/bench.rs":"dabe26b848af09fbc2df83dce367edcc9f78dd77a130d588db6cba6622f02ee8","build.rs":"cc3565b28217b481459cf47b6191fb0cbddbbf510a72260be75ff54d7f050d3d","examples/upstream_benchmark.rs":"19db581f4653e1c8e23a933e845a24b1ded192a9850126cfa9c82a81cd6b3349","src/buffer/mod.rs":"aeef965f409fd659e94e8611fc3fa4cf9ebfd404090f91f7da881e4bb5053d29","src/common.rs":"860895e4b787c722467bf6f118669e346399051de4df4a40f8ecf2c5a49c16ce","src/d2s.rs":"69d7318592b5bb0ca923332ee54e1acc64e5c0bcd6f8ca6b22b0f4b08c653b11","src/d2s_full_table.rs":"7f7e475c54ae69d834574603bde9dcbe9f0d7cb09cfc3cda025319c903996bf8","src/d2s_intrinsics.rs":"3c5e1323e85500b628aaa74d3e9699d772c88348b14f4591dde32711c73c3714","src/d2s_small_table.rs":"3c035701e940cf7d03b1e22a0bf353ed87b68c7afd35ca15721c453cdb5fa0a1","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"5d04c8c8268049d401536495e9abcd0ea7101a23d93e4d67da6ccb4efc62e65c","src/lib.rs":"bdbe4f17e20550fc896850378fb0c2bf0a485dd32aec72ba5d0716a004a35f9b","src/pretty/exponent.rs":"15fd163fdb81573d331f24fda37f5403931512ffb08715a2695f0a0256b69b84","src/pretty/mantissa.rs":"7b0ea97069ee597f3bc0c8f2f3354c75be93d01c6a8135104ae82cd83df318e0","src/pretty/mod.rs":"005f381ab27392fe7273da551da38aacfce6998fd4fc101ae283ea88c3f4d9b8","tests/d2s_table_test.rs":"7012a7a47327fe1d9b46364d6e444a0ab863fd8c2e345ca48b98ca4a46372a40","tests/d2s_test.rs":"04e62fc5b0c723b5deddc8cf082d735427e1c74792493d04549affca67a5edfc","tests/exhaustive.rs":"8f265d8e3d7ff9cbaf1b433eb0040136eec829b87a03dae8dfc67d062b755b4b","tests/f2s_test.rs":"4b4ba8dad4ff85c643deaf99f05914094bf89e7abf55672b1583a52ae1aae53f","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c"},"package":"bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"} \ No newline at end of file
diff --git a/third_party/rust/ryu/Cargo.lock b/third_party/rust/ryu/Cargo.lock
new file mode 100644
index 0000000000..5615dada19
--- /dev/null
+++ b/third_party/rust/ryu/Cargo.lock
@@ -0,0 +1,144 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "bitflags"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cloudabi"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-cprng"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "no-panic"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ryu"
+version = "1.0.2"
+dependencies = [
+ "no-panic 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
+"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
+"checksum no-panic 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "98df96f963035dd2f8184e531675e9e3f84675144dca726882eed105f8317964"
+"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
+"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/third_party/rust/ryu/Cargo.toml b/third_party/rust/ryu/Cargo.toml
new file mode 100644
index 0000000000..08e16d5701
--- /dev/null
+++ b/third_party/rust/ryu/Cargo.toml
@@ -0,0 +1,35 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "ryu"
+version = "1.0.2"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+build = "build.rs"
+description = "Fast floating point to string conversion"
+documentation = "https://docs.rs/ryu"
+readme = "README.md"
+license = "Apache-2.0 OR BSL-1.0"
+repository = "https://github.com/dtolnay/ryu"
+[dependencies.no-panic]
+version = "0.1"
+optional = true
+[dev-dependencies.num_cpus]
+version = "1.8"
+
+[dev-dependencies.rand]
+version = "0.5"
+
+[features]
+small = []
+[badges.travis-ci]
+repository = "dtolnay/ryu"
diff --git a/third_party/rust/ryu/LICENSE-APACHE b/third_party/rust/ryu/LICENSE-APACHE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/third_party/rust/ryu/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/third_party/rust/ryu/LICENSE-BOOST b/third_party/rust/ryu/LICENSE-BOOST
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/third_party/rust/ryu/LICENSE-BOOST
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/ryu/README.md b/third_party/rust/ryu/README.md
new file mode 100644
index 0000000000..cc34dc2383
--- /dev/null
+++ b/third_party/rust/ryu/README.md
@@ -0,0 +1,114 @@
+# Ryū
+
+[![Build Status](https://api.travis-ci.org/dtolnay/ryu.svg?branch=master)](https://travis-ci.org/dtolnay/ryu)
+[![Latest Version](https://img.shields.io/crates/v/ryu.svg)](https://crates.io/crates/ryu)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/ryu)
+[![Rustc Version 1.15+](https://img.shields.io/badge/rustc-1.15+-lightgray.svg)](https://blog.rust-lang.org/2017/02/02/Rust-1.15.html)
+
+Pure Rust implementation of Ryū, an algorithm to quickly convert floating point
+numbers to decimal strings.
+
+The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf Adams
+includes a complete correctness proof of the algorithm. The paper is available
+under the creative commons CC-BY-SA license.
+
+This Rust implementation is a line-by-line port of Ulf Adams' implementation in
+C, [https://github.com/ulfjack/ryu][upstream].
+
+*Requirements: this crate supports any compiler version back to rustc 1.15; it
+uses nothing from the Rust standard library so is usable from no_std crates.*
+
+[paper]: https://dl.acm.org/citation.cfm?id=3192369
+[upstream]: https://github.com/ulfjack/ryu/tree/688f43b62276b400728baad54afc32c3ab9c1a95
+
+```toml
+[dependencies]
+ryu = "1.0"
+```
+
+## Example
+
+```rust
+fn main() {
+ let mut buffer = ryu::Buffer::new();
+ let printed = buffer.format(1.234);
+ assert_eq!(printed, "1.234");
+}
+```
+
+## Performance
+
+You can run upstream's benchmarks with:
+
+```console
+$ git clone https://github.com/ulfjack/ryu c-ryu
+$ cd c-ryu
+$ bazel run -c opt //ryu/benchmark
+```
+
+And the same benchmark against our implementation with:
+
+```console
+$ git clone https://github.com/dtolnay/ryu rust-ryu
+$ cd rust-ryu
+$ cargo run --example upstream_benchmark --release
+```
+
+These benchmarks measure the average time to print a 32-bit float and average
+time to print a 64-bit float, where the inputs are distributed as uniform random
+bit patterns 32 and 64 bits wide.
+
+The upstream C code, the unsafe direct Rust port, and the safe pretty Rust API
+all perform the same, taking around 21 nanoseconds to format a 32-bit float and
+31 nanoseconds to format a 64-bit float.
+
+There is also a Rust-specific benchmark comparing this implementation to the
+standard library which you can run with:
+
+```console
+$ cargo bench
+```
+
+The benchmark shows Ryu approximately 4-10x faster than the standard library
+across a range of f32 and f64 inputs. Measurements are in nanoseconds per
+iteration; smaller is better.
+
+| type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
+|:--------:|:----:|:------:|:-----------------:|:--------:|
+| RYU | 3ns | 28ns | 23ns | 22ns |
+| STD | 40ns | 106ns | 128ns | 110ns |
+
+| type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
+|:--------:|:----:|:------:|:-----------------:|:--------:|
+| RYU | 3ns | 50ns | 35ns | 32ns |
+| STD | 39ns | 105ns | 128ns | 202ns |
+
+## Formatting
+
+This library tends to produce more human-readable output than the standard
+library's to\_string, which never uses scientific notation. Here are two
+examples:
+
+- *ryu:* 1.23e40, *std:* 12300000000000000000000000000000000000000
+- *ryu:* 1.23e-40, *std:* 0.000000000000000000000000000000000000000123
+
+Both libraries print short decimals such as 0.0000123 without scientific
+notation.
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-BOOST">Boost Software License 1.0</a> at your
+option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/third_party/rust/ryu/benches/bench.rs b/third_party/rust/ryu/benches/bench.rs
new file mode 100644
index 0000000000..04d9bee818
--- /dev/null
+++ b/third_party/rust/ryu/benches/bench.rs
@@ -0,0 +1,58 @@
+// cargo bench
+
+#![feature(test)]
+
+extern crate ryu;
+extern crate test;
+
+macro_rules! benches {
+ ($($name:ident($value:expr),)*) => {
+ mod bench_ryu {
+ use test::{Bencher, black_box};
+ $(
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ use ryu;
+
+ let mut buf = ryu::Buffer::new();
+
+ b.iter(move || {
+ let value = black_box($value);
+ let formatted = buf.format_finite(value);
+ black_box(formatted);
+ });
+ }
+ )*
+ }
+
+ mod bench_std_fmt {
+ use test::{Bencher, black_box};
+ $(
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ use std::io::Write;
+
+ let mut buf = Vec::with_capacity(20);
+
+ b.iter(|| {
+ buf.clear();
+ let value = black_box($value);
+ write!(&mut buf, "{}", value).unwrap();
+ black_box(buf.as_slice());
+ });
+ }
+ )*
+ }
+ }
+}
+
+benches!(
+ bench_0_f64(0f64),
+ bench_short_f64(0.1234f64),
+ bench_e_f64(2.718281828459045f64),
+ bench_max_f64(::std::f64::MAX),
+ bench_0_f32(0f32),
+ bench_short_f32(0.1234f32),
+ bench_e_f32(2.718281828459045f32),
+ bench_max_f32(::std::f32::MAX),
+);
diff --git a/third_party/rust/ryu/build.rs b/third_party/rust/ryu/build.rs
new file mode 100644
index 0000000000..7b639e72f5
--- /dev/null
+++ b/third_party/rust/ryu/build.rs
@@ -0,0 +1,66 @@
+use std::env;
+use std::process::Command;
+use std::str::{self, FromStr};
+
+// The rustc-cfg strings below are *not* public API. Please let us know by
+// opening a GitHub issue if your build environment requires some way to enable
+// these cfgs other than by executing our build script.
+fn main() {
+ let minor = match rustc_minor_version() {
+ Some(minor) => minor,
+ None => return,
+ };
+
+ let target = env::var("TARGET").unwrap();
+ let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
+
+ // 128-bit integers stabilized in Rust 1.26:
+ // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
+ //
+ // Disabled on Emscripten targets as Emscripten doesn't
+ // currently support integers larger than 64 bits.
+ if minor >= 26 && !emscripten {
+ println!("cargo:rustc-cfg=integer128");
+ }
+
+ // #[must_use] on functions stabilized in Rust 1.27:
+ // https://blog.rust-lang.org/2018/06/21/Rust-1.27.html
+ if minor >= 27 {
+ println!("cargo:rustc-cfg=must_use_return");
+ }
+
+ // MaybeUninit<T> stabilized in Rust 1.36:
+ // https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html
+ if minor >= 36 {
+ println!("cargo:rustc-cfg=maybe_uninit");
+ }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+ let rustc = match env::var_os("RUSTC") {
+ Some(rustc) => rustc,
+ None => return None,
+ };
+
+ let output = match Command::new(rustc).arg("--version").output() {
+ Ok(output) => output,
+ Err(_) => return None,
+ };
+
+ let version = match str::from_utf8(&output.stdout) {
+ Ok(version) => version,
+ Err(_) => return None,
+ };
+
+ let mut pieces = version.split('.');
+ if pieces.next() != Some("rustc 1") {
+ return None;
+ }
+
+ let next = match pieces.next() {
+ Some(next) => next,
+ None => return None,
+ };
+
+ u32::from_str(next).ok()
+}
diff --git a/third_party/rust/ryu/examples/upstream_benchmark.rs b/third_party/rust/ryu/examples/upstream_benchmark.rs
new file mode 100644
index 0000000000..c9ef3aea8d
--- /dev/null
+++ b/third_party/rust/ryu/examples/upstream_benchmark.rs
@@ -0,0 +1,88 @@
+// cargo run --example upstream_benchmark --release
+
+extern crate rand;
+extern crate ryu;
+
+use rand::{Rng, SeedableRng};
+
+const SAMPLES: usize = 10000;
+const ITERATIONS: usize = 1000;
+
+struct MeanAndVariance {
+ n: i64,
+ mean: f64,
+ m2: f64,
+}
+
+impl MeanAndVariance {
+ fn new() -> Self {
+ MeanAndVariance {
+ n: 0,
+ mean: 0.0,
+ m2: 0.0,
+ }
+ }
+
+ fn update(&mut self, x: f64) {
+ self.n += 1;
+ let d = x - self.mean;
+ self.mean += d / self.n as f64;
+ let d2 = x - self.mean;
+ self.m2 += d * d2;
+ }
+
+ fn variance(&self) -> f64 {
+ self.m2 / (self.n - 1) as f64
+ }
+
+ fn stddev(&self) -> f64 {
+ self.variance().sqrt()
+ }
+}
+
+macro_rules! benchmark {
+ ($name:ident, $ty:ident) => {
+ fn $name() -> usize {
+ let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
+ let mut mv = MeanAndVariance::new();
+ let mut throwaway = 0;
+ for _ in 0..SAMPLES {
+ let f = loop {
+ let f = $ty::from_bits(rng.gen());
+ if f.is_finite() {
+ break f;
+ }
+ };
+
+ let t1 = std::time::SystemTime::now();
+ for _ in 0..ITERATIONS {
+ throwaway += ryu::Buffer::new().format_finite(f).len();
+ }
+ let duration = t1.elapsed().unwrap();
+ let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
+ mv.update(nanos as f64 / ITERATIONS as f64);
+ }
+ println!(
+ "{:12} {:8.3} {:8.3}",
+ concat!(stringify!($name), ":"),
+ mv.mean,
+ mv.stddev(),
+ );
+ throwaway
+ }
+ };
+}
+
+benchmark!(pretty32, f32);
+benchmark!(pretty64, f64);
+
+fn main() {
+ println!("{:>20}{:>9}", "Average", "Stddev");
+ let mut throwaway = 0;
+ throwaway += pretty32();
+ throwaway += pretty64();
+ if std::env::var_os("ryu-benchmark").is_some() {
+ // Prevent the compiler from optimizing the code away.
+ println!("{}", throwaway);
+ }
+}
diff --git a/third_party/rust/ryu/src/buffer/mod.rs b/third_party/rust/ryu/src/buffer/mod.rs
new file mode 100644
index 0000000000..881858ce71
--- /dev/null
+++ b/third_party/rust/ryu/src/buffer/mod.rs
@@ -0,0 +1,199 @@
+use core::{mem, slice, str};
+
+#[cfg(maybe_uninit)]
+use core::mem::MaybeUninit;
+
+use raw;
+
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
+
+const NAN: &'static str = "NaN";
+const INFINITY: &'static str = "inf";
+const NEG_INFINITY: &'static str = "-inf";
+
+/// Safe API for formatting floating point numbers to text.
+///
+/// ## Example
+///
+/// ```edition2018
+/// let mut buffer = ryu::Buffer::new();
+/// let printed = buffer.format_finite(1.234);
+/// assert_eq!(printed, "1.234");
+/// ```
+#[derive(Copy, Clone)]
+pub struct Buffer {
+ #[cfg(maybe_uninit)]
+ bytes: [MaybeUninit<u8>; 24],
+ #[cfg(not(maybe_uninit))]
+ bytes: [u8; 24],
+}
+
+impl Buffer {
+ /// This is a cheap operation; you don't need to worry about reusing buffers
+ /// for efficiency.
+ #[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ pub fn new() -> Self {
+ // assume_init is safe here, since this is an array of MaybeUninit, which does not need
+ // to be initialized.
+ #[cfg(maybe_uninit)]
+ let bytes = unsafe { MaybeUninit::uninit().assume_init() };
+ #[cfg(not(maybe_uninit))]
+ let bytes = unsafe { mem::uninitialized() };
+
+ Buffer { bytes: bytes }
+ }
+
+ /// Print a floating point number into this buffer and return a reference to
+ /// its string representation within the buffer.
+ ///
+ /// # Special cases
+ ///
+ /// This function formats NaN as the string "NaN", positive infinity as
+ /// "inf", and negative infinity as "-inf" to match std::fmt.
+ ///
+ /// If your input is known to be finite, you may get better performance by
+ /// calling the `format_finite` method instead of `format` to avoid the
+ /// checks for special cases.
+ #[cfg_attr(feature = "no-panic", inline)]
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ pub fn format<F: Float>(&mut self, f: F) -> &str {
+ if f.is_nonfinite() {
+ f.format_nonfinite()
+ } else {
+ self.format_finite(f)
+ }
+ }
+
+ /// Print a floating point number into this buffer and return a reference to
+ /// its string representation within the buffer.
+ ///
+ /// # Special cases
+ ///
+ /// This function **does not** check for NaN or infinity. If the input
+ /// number is not a finite float, the printed representation will be some
+ /// correctly formatted but unspecified numerical value.
+ ///
+ /// Please check [`is_finite`] yourself before calling this function, or
+ /// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
+ ///
+ /// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite
+ /// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan
+ /// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
+ #[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ pub fn format_finite<F: Float>(&mut self, f: F) -> &str {
+ unsafe {
+ let n = f.write_to_ryu_buffer(self.first_byte_pointer_mut());
+ debug_assert!(n <= self.bytes.len());
+ let slice = slice::from_raw_parts(self.first_byte_pointer(), n);
+ str::from_utf8_unchecked(slice)
+ }
+ }
+
+ #[inline]
+ #[cfg(maybe_uninit)]
+ fn first_byte_pointer(&self) -> *const u8 {
+ self.bytes[0].as_ptr()
+ }
+
+ #[inline]
+ #[cfg(not(maybe_uninit))]
+ fn first_byte_pointer(&self) -> *const u8 {
+ &self.bytes[0] as *const u8
+ }
+
+ #[inline]
+ #[cfg(maybe_uninit)]
+ fn first_byte_pointer_mut(&mut self) -> *mut u8 {
+ self.bytes[0].as_mut_ptr()
+ }
+
+ #[inline]
+ #[cfg(not(maybe_uninit))]
+ fn first_byte_pointer_mut(&mut self) -> *mut u8 {
+ &mut self.bytes[0] as *mut u8
+ }
+}
+
+impl Default for Buffer {
+ #[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ fn default() -> Self {
+ Buffer::new()
+ }
+}
+
+/// A floating point number, f32 or f64, that can be written into a
+/// [`ryu::Buffer`][Buffer].
+///
+/// This trait is sealed and cannot be implemented for types outside of the
+/// `ryu` crate.
+pub trait Float: Sealed {}
+impl Float for f32 {}
+impl Float for f64 {}
+
+pub trait Sealed: Copy {
+ fn is_nonfinite(self) -> bool;
+ fn format_nonfinite(self) -> &'static str;
+ unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
+}
+
+impl Sealed for f32 {
+ #[inline]
+ fn is_nonfinite(self) -> bool {
+ const EXP_MASK: u32 = 0x7f800000;
+ let bits = unsafe { mem::transmute::<f32, u32>(self) };
+ bits & EXP_MASK == EXP_MASK
+ }
+
+ #[cold]
+ #[cfg_attr(feature = "no-panic", inline)]
+ fn format_nonfinite(self) -> &'static str {
+ const MANTISSA_MASK: u32 = 0x007fffff;
+ const SIGN_MASK: u32 = 0x80000000;
+ let bits = unsafe { mem::transmute::<f32, u32>(self) };
+ if bits & MANTISSA_MASK != 0 {
+ NAN
+ } else if bits & SIGN_MASK != 0 {
+ NEG_INFINITY
+ } else {
+ INFINITY
+ }
+ }
+
+ #[inline]
+ unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
+ raw::format32(self, result)
+ }
+}
+
+impl Sealed for f64 {
+ #[inline]
+ fn is_nonfinite(self) -> bool {
+ const EXP_MASK: u64 = 0x7ff0000000000000;
+ let bits = unsafe { mem::transmute::<f64, u64>(self) };
+ bits & EXP_MASK == EXP_MASK
+ }
+
+ #[cold]
+ #[cfg_attr(feature = "no-panic", inline)]
+ fn format_nonfinite(self) -> &'static str {
+ const MANTISSA_MASK: u64 = 0x000fffffffffffff;
+ const SIGN_MASK: u64 = 0x8000000000000000;
+ let bits = unsafe { mem::transmute::<f64, u64>(self) };
+ if bits & MANTISSA_MASK != 0 {
+ NAN
+ } else if bits & SIGN_MASK != 0 {
+ NEG_INFINITY
+ } else {
+ INFINITY
+ }
+ }
+
+ #[inline]
+ unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
+ raw::format64(self, result)
+ }
+}
diff --git a/third_party/rust/ryu/src/common.rs b/third_party/rust/ryu/src/common.rs
new file mode 100644
index 0000000000..29e5cc591b
--- /dev/null
+++ b/third_party/rust/ryu/src/common.rs
@@ -0,0 +1,75 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn decimal_length9(v: u32) -> u32 {
+ // Function precondition: v is not a 10-digit number.
+ // (f2s: 9 digits are sufficient for round-tripping.)
+ debug_assert!(v < 1000000000);
+
+ if v >= 100000000 {
+ 9
+ } else if v >= 10000000 {
+ 8
+ } else if v >= 1000000 {
+ 7
+ } else if v >= 100000 {
+ 6
+ } else if v >= 10000 {
+ 5
+ } else if v >= 1000 {
+ 4
+ } else if v >= 100 {
+ 3
+ } else if v >= 10 {
+ 2
+ } else {
+ 1
+ }
+}
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)).
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn pow5bits(e: i32) -> i32 {
+ // This approximation works up to the point that the multiplication overflows at e = 3529.
+ // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
+ // than 2^9297.
+ debug_assert!(e >= 0);
+ debug_assert!(e <= 3528);
+ (((e as u32 * 1217359) >> 19) + 1) as i32
+}
+
+// Returns floor(log_10(2^e)).
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn log10_pow2(e: i32) -> u32 {
+ // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
+ debug_assert!(e >= 0);
+ debug_assert!(e <= 1650);
+ (e as u32 * 78913) >> 18
+}
+
+// Returns floor(log_10(5^e)).
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn log10_pow5(e: i32) -> u32 {
+ // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
+ debug_assert!(e >= 0);
+ debug_assert!(e <= 2620);
+ (e as u32 * 732923) >> 20
+}
diff --git a/third_party/rust/ryu/src/d2s.rs b/third_party/rust/ryu/src/d2s.rs
new file mode 100644
index 0000000000..cebef968e6
--- /dev/null
+++ b/third_party/rust/ryu/src/d2s.rs
@@ -0,0 +1,412 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+use core::ptr;
+
+#[cfg(maybe_uninit)]
+use core::mem::MaybeUninit;
+
+#[cfg(not(maybe_uninit))]
+use core::mem;
+
+use common::*;
+#[cfg(not(feature = "small"))]
+use d2s_full_table::*;
+use d2s_intrinsics::*;
+#[cfg(feature = "small")]
+use d2s_small_table::*;
+
+pub const DOUBLE_MANTISSA_BITS: u32 = 52;
+pub const DOUBLE_EXPONENT_BITS: u32 = 11;
+
+const DOUBLE_BIAS: i32 = 1023;
+const DOUBLE_POW5_INV_BITCOUNT: i32 = 122;
+const DOUBLE_POW5_BITCOUNT: i32 = 121;
+
+#[cfg(integer128)]
+#[cfg_attr(feature = "no-panic", inline)]
+fn mul_shift(m: u64, mul: &(u64, u64), j: u32) -> u64 {
+ let b0 = m as u128 * mul.0 as u128;
+ let b2 = m as u128 * mul.1 as u128;
+ (((b0 >> 64) + b2) >> (j - 64)) as u64
+}
+
+#[cfg(integer128)]
+#[cfg_attr(feature = "no-panic", inline)]
+unsafe fn mul_shift_all(
+ m: u64,
+ mul: &(u64, u64),
+ j: u32,
+ vp: *mut u64,
+ vm: *mut u64,
+ mm_shift: u32,
+) -> u64 {
+ ptr::write(vp, mul_shift(4 * m + 2, mul, j));
+ ptr::write(vm, mul_shift(4 * m - 1 - mm_shift as u64, mul, j));
+ mul_shift(4 * m, mul, j)
+}
+
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+unsafe fn mul_shift_all(
+ mut m: u64,
+ mul: &(u64, u64),
+ j: u32,
+ vp: *mut u64,
+ vm: *mut u64,
+ mm_shift: u32,
+) -> u64 {
+ m <<= 1;
+ // m is maximum 55 bits
+ let (lo, tmp) = umul128(m, mul.0);
+ let (mut mid, mut hi) = umul128(m, mul.1);
+ mid = mid.wrapping_add(tmp);
+ hi = hi.wrapping_add((mid < tmp) as u64); // overflow into hi
+
+ let lo2 = lo.wrapping_add(mul.0);
+ let mid2 = mid.wrapping_add(mul.1).wrapping_add((lo2 < lo) as u64);
+ let hi2 = hi.wrapping_add((mid2 < mid) as u64);
+ ptr::write(vp, shiftright128(mid2, hi2, j - 64 - 1));
+
+ if mm_shift == 1 {
+ let lo3 = lo.wrapping_sub(mul.0);
+ let mid3 = mid.wrapping_sub(mul.1).wrapping_sub((lo3 > lo) as u64);
+ let hi3 = hi.wrapping_sub((mid3 > mid) as u64);
+ ptr::write(vm, shiftright128(mid3, hi3, j - 64 - 1));
+ } else {
+ let lo3 = lo + lo;
+ let mid3 = mid.wrapping_add(mid).wrapping_add((lo3 < lo) as u64);
+ let hi3 = hi.wrapping_add(hi).wrapping_add((mid3 < mid) as u64);
+ let lo4 = lo3.wrapping_sub(mul.0);
+ let mid4 = mid3.wrapping_sub(mul.1).wrapping_sub((lo4 > lo3) as u64);
+ let hi4 = hi3.wrapping_sub((mid4 > mid3) as u64);
+ ptr::write(vm, shiftright128(mid4, hi4, j - 64));
+ }
+
+ shiftright128(mid, hi, j - 64 - 1)
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn decimal_length17(v: u64) -> u32 {
+ // This is slightly faster than a loop.
+ // The average output length is 16.38 digits, so we check high-to-low.
+ // Function precondition: v is not an 18, 19, or 20-digit number.
+ // (17 digits are sufficient for round-tripping.)
+ debug_assert!(v < 100000000000000000);
+
+ if v >= 10000000000000000 {
+ 17
+ } else if v >= 1000000000000000 {
+ 16
+ } else if v >= 100000000000000 {
+ 15
+ } else if v >= 10000000000000 {
+ 14
+ } else if v >= 1000000000000 {
+ 13
+ } else if v >= 100000000000 {
+ 12
+ } else if v >= 10000000000 {
+ 11
+ } else if v >= 1000000000 {
+ 10
+ } else if v >= 100000000 {
+ 9
+ } else if v >= 10000000 {
+ 8
+ } else if v >= 1000000 {
+ 7
+ } else if v >= 100000 {
+ 6
+ } else if v >= 10000 {
+ 5
+ } else if v >= 1000 {
+ 4
+ } else if v >= 100 {
+ 3
+ } else if v >= 10 {
+ 2
+ } else {
+ 1
+ }
+}
+
+// A floating decimal representing m * 10^e.
+pub struct FloatingDecimal64 {
+ pub mantissa: u64,
+ // Decimal exponent's range is -324 to 308
+ // inclusive, and can fit in i16 if needed.
+ pub exponent: i32,
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
+ let (e2, m2) = if ieee_exponent == 0 {
+ (
+ // We subtract 2 so that the bounds computation has 2 additional bits.
+ 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS as i32 - 2,
+ ieee_mantissa,
+ )
+ } else {
+ (
+ ieee_exponent as i32 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS as i32 - 2,
+ (1u64 << DOUBLE_MANTISSA_BITS) | ieee_mantissa,
+ )
+ };
+ let even = (m2 & 1) == 0;
+ let accept_bounds = even;
+
+ // Step 2: Determine the interval of valid decimal representations.
+ let mv = 4 * m2;
+ // Implicit bool -> int conversion. True is 1, false is 0.
+ let mm_shift = (ieee_mantissa != 0 || ieee_exponent <= 1) as u32;
+ // We would compute mp and mm like this:
+ // uint64_t mp = 4 * m2 + 2;
+ // uint64_t mm = mv - 1 - mm_shift;
+
+ // Step 3: Convert to a decimal power base using 128-bit arithmetic.
+ let mut vr: u64;
+ let mut vp: u64;
+ let mut vm: u64;
+ #[cfg(not(maybe_uninit))]
+ {
+ vp = unsafe { mem::uninitialized() };
+ vm = unsafe { mem::uninitialized() };
+ }
+ #[cfg(maybe_uninit)]
+ let mut vp_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
+ #[cfg(maybe_uninit)]
+ let mut vm_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
+ let e10: i32;
+ let mut vm_is_trailing_zeros = false;
+ let mut vr_is_trailing_zeros = false;
+ if e2 >= 0 {
+ // I tried special-casing q == 0, but there was no effect on performance.
+ // This expression is slightly faster than max(0, log10_pow2(e2) - 1).
+ let q = log10_pow2(e2) - (e2 > 3) as u32;
+ e10 = q as i32;
+ let k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q as i32) - 1;
+ let i = -e2 + q as i32 + k;
+ vr = unsafe {
+ mul_shift_all(
+ m2,
+ #[cfg(feature = "small")]
+ &compute_inv_pow5(q),
+ #[cfg(not(feature = "small"))]
+ {
+ debug_assert!(q < DOUBLE_POW5_INV_SPLIT.len() as u32);
+ DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
+ },
+ i as u32,
+ #[cfg(maybe_uninit)]
+ {
+ vp_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vp
+ },
+ #[cfg(maybe_uninit)]
+ {
+ vm_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vm
+ },
+ mm_shift,
+ )
+ };
+ #[cfg(maybe_uninit)]
+ {
+ vp = unsafe { vp_uninit.assume_init() };
+ vm = unsafe { vm_uninit.assume_init() };
+ }
+ if q <= 21 {
+ // This should use q <= 22, but I think 21 is also safe. Smaller values
+ // may still be safe, but it's more difficult to reason about them.
+ // Only one of mp, mv, and mm can be a multiple of 5, if any.
+ let mv_mod5 = (mv as u32).wrapping_sub(5u32.wrapping_mul(div5(mv) as u32));
+ if mv_mod5 == 0 {
+ vr_is_trailing_zeros = multiple_of_power_of_5(mv, q);
+ } else if accept_bounds {
+ // Same as min(e2 + (~mm & 1), pow5_factor(mm)) >= q
+ // <=> e2 + (~mm & 1) >= q && pow5_factor(mm) >= q
+ // <=> true && pow5_factor(mm) >= q, since e2 >= q.
+ vm_is_trailing_zeros = multiple_of_power_of_5(mv - 1 - mm_shift as u64, q);
+ } else {
+ // Same as min(e2 + 1, pow5_factor(mp)) >= q.
+ vp -= multiple_of_power_of_5(mv + 2, q) as u64;
+ }
+ }
+ } else {
+ // This expression is slightly faster than max(0, log10_pow5(-e2) - 1).
+ let q = log10_pow5(-e2) - (-e2 > 1) as u32;
+ e10 = q as i32 + e2;
+ let i = -e2 - q as i32;
+ let k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
+ let j = q as i32 - k;
+ vr = unsafe {
+ mul_shift_all(
+ m2,
+ #[cfg(feature = "small")]
+ &compute_pow5(i as u32),
+ #[cfg(not(feature = "small"))]
+ {
+ debug_assert!(i < DOUBLE_POW5_SPLIT.len() as i32);
+ DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
+ },
+ j as u32,
+ #[cfg(maybe_uninit)]
+ {
+ vp_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vp
+ },
+ #[cfg(maybe_uninit)]
+ {
+ vm_uninit.as_mut_ptr()
+ },
+ #[cfg(not(maybe_uninit))]
+ {
+ &mut vm
+ },
+ mm_shift,
+ )
+ };
+ #[cfg(maybe_uninit)]
+ {
+ vp = unsafe { vp_uninit.assume_init() };
+ vm = unsafe { vm_uninit.assume_init() };
+ }
+ if q <= 1 {
+ // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
+ // mv = 4 * m2, so it always has at least two trailing 0 bits.
+ vr_is_trailing_zeros = true;
+ if accept_bounds {
+ // mm = mv - 1 - mm_shift, so it has 1 trailing 0 bit iff mm_shift == 1.
+ vm_is_trailing_zeros = mm_shift == 1;
+ } else {
+ // mp = mv + 2, so it always has at least one trailing 0 bit.
+ vp -= 1;
+ }
+ } else if q < 63 {
+ // TODO(ulfjack): Use a tighter bound here.
+ // We want to know if the full product has at least q trailing zeros.
+ // We need to compute min(p2(mv), p5(mv) - e2) >= q
+ // <=> p2(mv) >= q && p5(mv) - e2 >= q
+ // <=> p2(mv) >= q (because -e2 >= q)
+ vr_is_trailing_zeros = multiple_of_power_of_2(mv, q);
+ }
+ }
+
+ // Step 4: Find the shortest decimal representation in the interval of valid representations.
+ let mut removed = 0i32;
+ let mut last_removed_digit = 0u8;
+ // On average, we remove ~2 digits.
+ let output = if vm_is_trailing_zeros || vr_is_trailing_zeros {
+ // General case, which happens rarely (~0.7%).
+ loop {
+ let vp_div10 = div10(vp);
+ let vm_div10 = div10(vm);
+ if vp_div10 <= vm_div10 {
+ break;
+ }
+ let vm_mod10 = (vm as u32).wrapping_sub(10u32.wrapping_mul(vm_div10 as u32));
+ let vr_div10 = div10(vr);
+ let vr_mod10 = (vr as u32).wrapping_sub(10u32.wrapping_mul(vr_div10 as u32));
+ vm_is_trailing_zeros &= vm_mod10 == 0;
+ vr_is_trailing_zeros &= last_removed_digit == 0;
+ last_removed_digit = vr_mod10 as u8;
+ vr = vr_div10;
+ vp = vp_div10;
+ vm = vm_div10;
+ removed += 1;
+ }
+ if vm_is_trailing_zeros {
+ loop {
+ let vm_div10 = div10(vm);
+ let vm_mod10 = (vm as u32).wrapping_sub(10u32.wrapping_mul(vm_div10 as u32));
+ if vm_mod10 != 0 {
+ break;
+ }
+ let vp_div10 = div10(vp);
+ let vr_div10 = div10(vr);
+ let vr_mod10 = (vr as u32).wrapping_sub(10u32.wrapping_mul(vr_div10 as u32));
+ vr_is_trailing_zeros &= last_removed_digit == 0;
+ last_removed_digit = vr_mod10 as u8;
+ vr = vr_div10;
+ vp = vp_div10;
+ vm = vm_div10;
+ removed += 1;
+ }
+ }
+ if vr_is_trailing_zeros && last_removed_digit == 5 && vr % 2 == 0 {
+ // Round even if the exact number is .....50..0.
+ last_removed_digit = 4;
+ }
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ vr + ((vr == vm && (!accept_bounds || !vm_is_trailing_zeros)) || last_removed_digit >= 5)
+ as u64
+ } else {
+ // Specialized for the common case (~99.3%). Percentages below are relative to this.
+ let mut round_up = false;
+ let vp_div100 = div100(vp);
+ let vm_div100 = div100(vm);
+ // Optimization: remove two digits at a time (~86.2%).
+ if vp_div100 > vm_div100 {
+ let vr_div100 = div100(vr);
+ let vr_mod100 = (vr as u32).wrapping_sub(100u32.wrapping_mul(vr_div100 as u32));
+ round_up = vr_mod100 >= 50;
+ vr = vr_div100;
+ vp = vp_div100;
+ vm = vm_div100;
+ removed += 2;
+ }
+ // Loop iterations below (approximately), without optimization above:
+ // 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
+ // Loop iterations below (approximately), with optimization above:
+ // 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
+ loop {
+ let vp_div10 = div10(vp);
+ let vm_div10 = div10(vm);
+ if vp_div10 <= vm_div10 {
+ break;
+ }
+ let vr_div10 = div10(vr);
+ let vr_mod10 = (vr as u32).wrapping_sub(10u32.wrapping_mul(vr_div10 as u32));
+ round_up = vr_mod10 >= 5;
+ vr = vr_div10;
+ vp = vp_div10;
+ vm = vm_div10;
+ removed += 1;
+ }
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ vr + (vr == vm || round_up) as u64
+ };
+ let exp = e10 + removed;
+
+ FloatingDecimal64 {
+ exponent: exp,
+ mantissa: output,
+ }
+}
diff --git a/third_party/rust/ryu/src/d2s_full_table.rs b/third_party/rust/ryu/src/d2s_full_table.rs
new file mode 100644
index 0000000000..eac50dcfc8
--- /dev/null
+++ b/third_party/rust/ryu/src/d2s_full_table.rs
@@ -0,0 +1,643 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+pub static DOUBLE_POW5_INV_SPLIT: [(u64, u64); 292] = [
+ (1, 288230376151711744),
+ (3689348814741910324, 230584300921369395),
+ (2951479051793528259, 184467440737095516),
+ (17118578500402463900, 147573952589676412),
+ (12632330341676300947, 236118324143482260),
+ (10105864273341040758, 188894659314785808),
+ (15463389048156653253, 151115727451828646),
+ (17362724847566824558, 241785163922925834),
+ (17579528692795369969, 193428131138340667),
+ (6684925324752475329, 154742504910672534),
+ (18074578149087781173, 247588007857076054),
+ (18149011334012135262, 198070406285660843),
+ (3451162622983977240, 158456325028528675),
+ (5521860196774363583, 253530120045645880),
+ (4417488157419490867, 202824096036516704),
+ (7223339340677503017, 162259276829213363),
+ (7867994130342094503, 259614842926741381),
+ (2605046489531765280, 207691874341393105),
+ (2084037191625412224, 166153499473114484),
+ (10713157136084480204, 265845599156983174),
+ (12259874523609494487, 212676479325586539),
+ (13497248433629505913, 170141183460469231),
+ (14216899864323388813, 272225893536750770),
+ (11373519891458711051, 217780714829400616),
+ (5409467098425058518, 174224571863520493),
+ (4965798542738183305, 278759314981632789),
+ (7661987648932456967, 223007451985306231),
+ (2440241304404055250, 178405961588244985),
+ (3904386087046488400, 285449538541191976),
+ (17880904128604832013, 228359630832953580),
+ (14304723302883865611, 182687704666362864),
+ (15133127457049002812, 146150163733090291),
+ (16834306301794583852, 233840261972944466),
+ (9778096226693756759, 187072209578355573),
+ (15201174610838826053, 149657767662684458),
+ (2185786488890659746, 239452428260295134),
+ (5437978005854438120, 191561942608236107),
+ (15418428848909281466, 153249554086588885),
+ (6222742084545298729, 245199286538542217),
+ (16046240111861969953, 196159429230833773),
+ (1768945645263844993, 156927543384667019),
+ (10209010661905972635, 251084069415467230),
+ (8167208529524778108, 200867255532373784),
+ (10223115638361732810, 160693804425899027),
+ (1599589762411131202, 257110087081438444),
+ (4969020624670815285, 205688069665150755),
+ (3975216499736652228, 164550455732120604),
+ (13739044029062464211, 263280729171392966),
+ (7301886408508061046, 210624583337114373),
+ (13220206756290269483, 168499666669691498),
+ (17462981995322520850, 269599466671506397),
+ (6591687966774196033, 215679573337205118),
+ (12652048002903177473, 172543658669764094),
+ (9175230360419352987, 276069853871622551),
+ (3650835473593572067, 220855883097298041),
+ (17678063637842498946, 176684706477838432),
+ (13527506561580357021, 282695530364541492),
+ (3443307619780464970, 226156424291633194),
+ (6443994910566282300, 180925139433306555),
+ (5155195928453025840, 144740111546645244),
+ (15627011115008661990, 231584178474632390),
+ (12501608892006929592, 185267342779705912),
+ (2622589484121723027, 148213874223764730),
+ (4196143174594756843, 237142198758023568),
+ (10735612169159626121, 189713759006418854),
+ (12277838550069611220, 151771007205135083),
+ (15955192865369467629, 242833611528216133),
+ (1696107848069843133, 194266889222572907),
+ (12424932722681605476, 155413511378058325),
+ (1433148282581017146, 248661618204893321),
+ (15903913885032455010, 198929294563914656),
+ (9033782293284053685, 159143435651131725),
+ (14454051669254485895, 254629497041810760),
+ (11563241335403588716, 203703597633448608),
+ (16629290697806691620, 162962878106758886),
+ (781423413297334329, 260740604970814219),
+ (4314487545379777786, 208592483976651375),
+ (3451590036303822229, 166873987181321100),
+ (5522544058086115566, 266998379490113760),
+ (4418035246468892453, 213598703592091008),
+ (10913125826658934609, 170878962873672806),
+ (10082303693170474728, 273406340597876490),
+ (8065842954536379782, 218725072478301192),
+ (17520720807854834795, 174980057982640953),
+ (5897060404116273733, 279968092772225526),
+ (1028299508551108663, 223974474217780421),
+ (15580034865808528224, 179179579374224336),
+ (17549358155809824511, 286687326998758938),
+ (2971440080422128639, 229349861599007151),
+ (17134547323305344204, 183479889279205720),
+ (13707637858644275364, 146783911423364576),
+ (14553522944347019935, 234854258277383322),
+ (4264120725993795302, 187883406621906658),
+ (10789994210278856888, 150306725297525326),
+ (9885293106962350374, 240490760476040522),
+ (529536856086059653, 192392608380832418),
+ (7802327114352668369, 153914086704665934),
+ (1415676938738538420, 246262538727465495),
+ (1132541550990830736, 197010030981972396),
+ (15663428499760305882, 157608024785577916),
+ (17682787970132668764, 252172839656924666),
+ (10456881561364224688, 201738271725539733),
+ (15744202878575200397, 161390617380431786),
+ (17812026976236499989, 258224987808690858),
+ (3181575136763469022, 206579990246952687),
+ (13613306553636506187, 165263992197562149),
+ (10713244041592678929, 264422387516099439),
+ (12259944048016053467, 211537910012879551),
+ (6118606423670932450, 169230328010303641),
+ (2411072648389671274, 270768524816485826),
+ (16686253377679378312, 216614819853188660),
+ (13349002702143502650, 173291855882550928),
+ (17669055508687693916, 277266969412081485),
+ (14135244406950155133, 221813575529665188),
+ (240149081334393137, 177450860423732151),
+ (11452284974360759988, 283921376677971441),
+ (5472479164746697667, 227137101342377153),
+ (11756680961281178780, 181709681073901722),
+ (2026647139541122378, 145367744859121378),
+ (18000030682233437097, 232588391774594204),
+ (18089373360528660001, 186070713419675363),
+ (3403452244197197031, 148856570735740291),
+ (16513570034941246220, 238170513177184465),
+ (13210856027952996976, 190536410541747572),
+ (3189987192878576934, 152429128433398058),
+ (1414630693863812771, 243886605493436893),
+ (8510402184574870864, 195109284394749514),
+ (10497670562401807014, 156087427515799611),
+ (9417575270359070576, 249739884025279378),
+ (14912757845771077107, 199791907220223502),
+ (4551508647133041040, 159833525776178802),
+ (10971762650154775986, 255733641241886083),
+ (16156107749607641435, 204586912993508866),
+ (9235537384944202825, 163669530394807093),
+ (11087511001168814197, 261871248631691349),
+ (12559357615676961681, 209496998905353079),
+ (13736834907283479668, 167597599124282463),
+ (18289587036911657145, 268156158598851941),
+ (10942320814787415393, 214524926879081553),
+ (16132554281313752961, 171619941503265242),
+ (11054691591134363444, 274591906405224388),
+ (16222450902391311402, 219673525124179510),
+ (12977960721913049122, 175738820099343608),
+ (17075388340318968271, 281182112158949773),
+ (2592264228029443648, 224945689727159819),
+ (5763160197165465241, 179956551781727855),
+ (9221056315464744386, 287930482850764568),
+ (14755542681855616155, 230344386280611654),
+ (15493782960226403247, 184275509024489323),
+ (1326979923955391628, 147420407219591459),
+ (9501865507812447252, 235872651551346334),
+ (11290841220991868125, 188698121241077067),
+ (1653975347309673853, 150958496992861654),
+ (10025058185179298811, 241533595188578646),
+ (4330697733401528726, 193226876150862917),
+ (14532604630946953951, 154581500920690333),
+ (1116074521063664381, 247330401473104534),
+ (4582208431592841828, 197864321178483627),
+ (14733813189500004432, 158291456942786901),
+ (16195403473716186445, 253266331108459042),
+ (5577625149489128510, 202613064886767234),
+ (8151448934333213131, 162090451909413787),
+ (16731667109675051333, 259344723055062059),
+ (17074682502481951390, 207475778444049647),
+ (6281048372501740465, 165980622755239718),
+ (6360328581260874421, 265568996408383549),
+ (8777611679750609860, 212455197126706839),
+ (10711438158542398211, 169964157701365471),
+ (9759603424184016492, 271942652322184754),
+ (11497031554089123517, 217554121857747803),
+ (16576322872755119460, 174043297486198242),
+ (11764721337440549842, 278469275977917188),
+ (16790474699436260520, 222775420782333750),
+ (13432379759549008416, 178220336625867000),
+ (3045063541568861850, 285152538601387201),
+ (17193446092222730773, 228122030881109760),
+ (13754756873778184618, 182497624704887808),
+ (18382503128506368341, 145998099763910246),
+ (3586563302416817083, 233596959622256395),
+ (2869250641933453667, 186877567697805116),
+ (17052795772514404226, 149502054158244092),
+ (12527077977055405469, 239203286653190548),
+ (17400360011128145022, 191362629322552438),
+ (2852241564676785048, 153090103458041951),
+ (15631632947708587046, 244944165532867121),
+ (8815957543424959314, 195955332426293697),
+ (18120812478965698421, 156764265941034957),
+ (14235904707377476180, 250822825505655932),
+ (4010026136418160298, 200658260404524746),
+ (17965416168102169531, 160526608323619796),
+ (2919224165770098987, 256842573317791675),
+ (2335379332616079190, 205474058654233340),
+ (1868303466092863352, 164379246923386672),
+ (6678634360490491686, 263006795077418675),
+ (5342907488392393349, 210405436061934940),
+ (4274325990713914679, 168324348849547952),
+ (10528270399884173809, 269318958159276723),
+ (15801313949391159694, 215455166527421378),
+ (1573004715287196786, 172364133221937103),
+ (17274202803427156150, 275782613155099364),
+ (17508711057483635243, 220626090524079491),
+ (10317620031244997871, 176500872419263593),
+ (12818843235250086271, 282401395870821749),
+ (13944423402941979340, 225921116696657399),
+ (14844887537095493795, 180736893357325919),
+ (15565258844418305359, 144589514685860735),
+ (6457670077359736959, 231343223497377177),
+ (16234182506113520537, 185074578797901741),
+ (9297997190148906106, 148059663038321393),
+ (11187446689496339446, 236895460861314229),
+ (12639306166338981880, 189516368689051383),
+ (17490142562555006151, 151613094951241106),
+ (2158786396894637579, 242580951921985771),
+ (16484424376483351356, 194064761537588616),
+ (9498190686444770762, 155251809230070893),
+ (11507756283569722895, 248402894768113429),
+ (12895553841597688639, 198722315814490743),
+ (17695140702761971558, 158977852651592594),
+ (17244178680193423523, 254364564242548151),
+ (10105994129412828495, 203491651394038521),
+ (4395446488788352473, 162793321115230817),
+ (10722063196803274280, 260469313784369307),
+ (1198952927958798777, 208375451027495446),
+ (15716557601334680315, 166700360821996356),
+ (17767794532651667857, 266720577315194170),
+ (14214235626121334286, 213376461852155336),
+ (7682039686155157106, 170701169481724269),
+ (1223217053622520399, 273121871170758831),
+ (15735968901865657612, 218497496936607064),
+ (16278123936234436413, 174797997549285651),
+ (219556594781725998, 279676796078857043),
+ (7554342905309201445, 223741436863085634),
+ (9732823138989271479, 178993149490468507),
+ (815121763415193074, 286389039184749612),
+ (11720143854957885429, 229111231347799689),
+ (13065463898708218666, 183288985078239751),
+ (6763022304224664610, 146631188062591801),
+ (3442138057275642729, 234609900900146882),
+ (13821756890046245153, 187687920720117505),
+ (11057405512036996122, 150150336576094004),
+ (6623802375033462826, 240240538521750407),
+ (16367088344252501231, 192192430817400325),
+ (13093670675402000985, 153753944653920260),
+ (2503129006933649959, 246006311446272417),
+ (13070549649772650937, 196805049157017933),
+ (17835137349301941396, 157444039325614346),
+ (2710778055689733971, 251910462920982955),
+ (2168622444551787177, 201528370336786364),
+ (5424246770383340065, 161222696269429091),
+ (1300097203129523457, 257956314031086546),
+ (15797473021471260058, 206365051224869236),
+ (8948629602435097724, 165092040979895389),
+ (3249760919670425388, 264147265567832623),
+ (9978506365220160957, 211317812454266098),
+ (15361502721659949412, 169054249963412878),
+ (2442311466204457120, 270486799941460606),
+ (16711244431931206989, 216389439953168484),
+ (17058344360286875914, 173111551962534787),
+ (12535955717491360170, 276978483140055660),
+ (10028764573993088136, 221582786512044528),
+ (15401709288678291155, 177266229209635622),
+ (9885339602917624555, 283625966735416996),
+ (4218922867592189321, 226900773388333597),
+ (14443184738299482427, 181520618710666877),
+ (4175850161155765295, 145216494968533502),
+ (10370709072591134795, 232346391949653603),
+ (15675264887556728482, 185877113559722882),
+ (5161514280561562140, 148701690847778306),
+ (879725219414678777, 237922705356445290),
+ (703780175531743021, 190338164285156232),
+ (11631070584651125387, 152270531428124985),
+ (162968861732249003, 243632850284999977),
+ (11198421533611530172, 194906280227999981),
+ (5269388412147313814, 155925024182399985),
+ (8431021459435702103, 249480038691839976),
+ (3055468352806651359, 199584030953471981),
+ (17201769941212962380, 159667224762777584),
+ (16454785461715008838, 255467559620444135),
+ (13163828369372007071, 204374047696355308),
+ (17909760324981426303, 163499238157084246),
+ (2830174816776909822, 261598781051334795),
+ (2264139853421527858, 209279024841067836),
+ (16568707141704863579, 167423219872854268),
+ (4373838538276319787, 267877151796566830),
+ (3499070830621055830, 214301721437253464),
+ (6488605479238754987, 171441377149802771),
+ (3003071137298187333, 274306203439684434),
+ (6091805724580460189, 219444962751747547),
+ (15941491023890099121, 175555970201398037),
+ (10748990379256517301, 280889552322236860),
+ (8599192303405213841, 224711641857789488),
+ (14258051472207991719, 179769313486231590),
+];
+
+pub static DOUBLE_POW5_SPLIT: [(u64, u64); 326] = [
+ (0, 72057594037927936),
+ (0, 90071992547409920),
+ (0, 112589990684262400),
+ (0, 140737488355328000),
+ (0, 87960930222080000),
+ (0, 109951162777600000),
+ (0, 137438953472000000),
+ (0, 85899345920000000),
+ (0, 107374182400000000),
+ (0, 134217728000000000),
+ (0, 83886080000000000),
+ (0, 104857600000000000),
+ (0, 131072000000000000),
+ (0, 81920000000000000),
+ (0, 102400000000000000),
+ (0, 128000000000000000),
+ (0, 80000000000000000),
+ (0, 100000000000000000),
+ (0, 125000000000000000),
+ (0, 78125000000000000),
+ (0, 97656250000000000),
+ (0, 122070312500000000),
+ (0, 76293945312500000),
+ (0, 95367431640625000),
+ (0, 119209289550781250),
+ (4611686018427387904, 74505805969238281),
+ (10376293541461622784, 93132257461547851),
+ (8358680908399640576, 116415321826934814),
+ (612489549322387456, 72759576141834259),
+ (14600669991935148032, 90949470177292823),
+ (13639151471491547136, 113686837721616029),
+ (3213881284082270208, 142108547152020037),
+ (4314518811765112832, 88817841970012523),
+ (781462496279003136, 111022302462515654),
+ (10200200157203529728, 138777878078144567),
+ (13292654125893287936, 86736173798840354),
+ (7392445620511834112, 108420217248550443),
+ (4628871007212404736, 135525271560688054),
+ (16728102434789916672, 84703294725430033),
+ (7075069988205232128, 105879118406787542),
+ (18067209522111315968, 132348898008484427),
+ (8986162942105878528, 82718061255302767),
+ (6621017659204960256, 103397576569128459),
+ (3664586055578812416, 129246970711410574),
+ (16125424340018921472, 80779356694631608),
+ (1710036351314100224, 100974195868289511),
+ (15972603494424788992, 126217744835361888),
+ (9982877184015493120, 78886090522101180),
+ (12478596480019366400, 98607613152626475),
+ (10986559581596820096, 123259516440783094),
+ (2254913720070624656, 77037197775489434),
+ (12042014186943056628, 96296497219361792),
+ (15052517733678820785, 120370621524202240),
+ (9407823583549262990, 75231638452626400),
+ (11759779479436578738, 94039548065783000),
+ (14699724349295723422, 117549435082228750),
+ (4575641699882439235, 73468396926392969),
+ (10331238143280436948, 91835496157991211),
+ (8302361660673158281, 114794370197489014),
+ (1154580038986672043, 143492962746861268),
+ (9944984561221445835, 89683101716788292),
+ (12431230701526807293, 112103877145985365),
+ (1703980321626345405, 140129846432481707),
+ (17205888765512323542, 87581154020301066),
+ (12283988920035628619, 109476442525376333),
+ (1519928094762372062, 136845553156720417),
+ (12479170105294952299, 85528470722950260),
+ (15598962631618690374, 106910588403687825),
+ (5663645234241199255, 133638235504609782),
+ (17374836326682913246, 83523897190381113),
+ (7883487353071477846, 104404871487976392),
+ (9854359191339347308, 130506089359970490),
+ (10770660513014479971, 81566305849981556),
+ (13463325641268099964, 101957882312476945),
+ (2994098996302961243, 127447352890596182),
+ (15706369927971514489, 79654595556622613),
+ (5797904354682229399, 99568244445778267),
+ (2635694424925398845, 124460305557222834),
+ (6258995034005762182, 77787690973264271),
+ (3212057774079814824, 97234613716580339),
+ (17850130272881932242, 121543267145725423),
+ (18073860448192289507, 75964541966078389),
+ (8757267504958198172, 94955677457597987),
+ (6334898362770359811, 118694596821997484),
+ (13182683513586250689, 74184123013748427),
+ (11866668373555425458, 92730153767185534),
+ (5609963430089506015, 115912692208981918),
+ (17341285199088104971, 72445432630613698),
+ (12453234462005355406, 90556790788267123),
+ (10954857059079306353, 113195988485333904),
+ (13693571323849132942, 141494985606667380),
+ (17781854114260483896, 88434366004167112),
+ (3780573569116053255, 110542957505208891),
+ (114030942967678664, 138178696881511114),
+ (4682955357782187069, 86361685550944446),
+ (15077066234082509644, 107952106938680557),
+ (5011274737320973344, 134940133673350697),
+ (14661261756894078100, 84337583545844185),
+ (4491519140835433913, 105421979432305232),
+ (5614398926044292391, 131777474290381540),
+ (12732371365632458552, 82360921431488462),
+ (6692092170185797382, 102951151789360578),
+ (17588487249587022536, 128688939736700722),
+ (15604490549419276989, 80430587335437951),
+ (14893927168346708332, 100538234169297439),
+ (14005722942005997511, 125672792711621799),
+ (15671105866394830300, 78545495444763624),
+ (1142138259283986260, 98181869305954531),
+ (15262730879387146537, 122727336632443163),
+ (7233363790403272633, 76704585395276977),
+ (13653390756431478696, 95880731744096221),
+ (3231680390257184658, 119850914680120277),
+ (4325643253124434363, 74906821675075173),
+ (10018740084832930858, 93633527093843966),
+ (3300053069186387764, 117041908867304958),
+ (15897591223523656064, 73151193042065598),
+ (10648616992549794273, 91438991302581998),
+ (4087399203832467033, 114298739128227498),
+ (14332621041645359599, 142873423910284372),
+ (18181260187883125557, 89295889943927732),
+ (4279831161144355331, 111619862429909666),
+ (14573160988285219972, 139524828037387082),
+ (13719911636105650386, 87203017523366926),
+ (7926517508277287175, 109003771904208658),
+ (684774848491833161, 136254714880260823),
+ (7345513307948477581, 85159196800163014),
+ (18405263671790372785, 106448996000203767),
+ (18394893571310578077, 133061245000254709),
+ (13802651491282805250, 83163278125159193),
+ (3418256308821342851, 103954097656448992),
+ (4272820386026678563, 129942622070561240),
+ (2670512741266674102, 81214138794100775),
+ (17173198981865506339, 101517673492625968),
+ (3019754653622331308, 126897091865782461),
+ (4193189667727651020, 79310682416114038),
+ (14464859121514339583, 99138353020142547),
+ (13469387883465536574, 123922941275178184),
+ (8418367427165960359, 77451838296986365),
+ (15134645302384838353, 96814797871232956),
+ (471562554271496325, 121018497339041196),
+ (9518098633274461011, 75636560836900747),
+ (7285937273165688360, 94545701046125934),
+ (18330793628311886258, 118182126307657417),
+ (4539216990053847055, 73863828942285886),
+ (14897393274422084627, 92329786177857357),
+ (4786683537745442072, 115412232722321697),
+ (14520892257159371055, 72132645451451060),
+ (18151115321449213818, 90165806814313825),
+ (8853836096529353561, 112707258517892282),
+ (1843923083806916143, 140884073147365353),
+ (12681666973447792349, 88052545717103345),
+ (2017025661527576725, 110065682146379182),
+ (11744654113764246714, 137582102682973977),
+ (422879793461572340, 85988814176858736),
+ (528599741826965425, 107486017721073420),
+ (660749677283706782, 134357522151341775),
+ (7330497575943398595, 83973451344588609),
+ (13774807988356636147, 104966814180735761),
+ (3383451930163631472, 131208517725919702),
+ (15949715511634433382, 82005323578699813),
+ (6102086334260878016, 102506654473374767),
+ (3015921899398709616, 128133318091718459),
+ (18025852251620051174, 80083323807324036),
+ (4085571240815512351, 100104154759155046),
+ (14330336087874166247, 125130193448943807),
+ (15873989082562435760, 78206370905589879),
+ (15230800334775656796, 97757963631987349),
+ (5203442363187407284, 122197454539984187),
+ (946308467778435600, 76373409087490117),
+ (5794571603150432404, 95466761359362646),
+ (16466586540792816313, 119333451699203307),
+ (7985773578781816244, 74583407312002067),
+ (5370530955049882401, 93229259140002584),
+ (6713163693812353001, 116536573925003230),
+ (18030785363914884337, 72835358703127018),
+ (13315109668038829614, 91044198378908773),
+ (2808829029766373305, 113805247973635967),
+ (17346094342490130344, 142256559967044958),
+ (6229622945628943561, 88910349979403099),
+ (3175342663608791547, 111137937474253874),
+ (13192550366365765242, 138922421842817342),
+ (3633657960551215372, 86826513651760839),
+ (18377130505971182927, 108533142064701048),
+ (4524669058754427043, 135666427580876311),
+ (9745447189362598758, 84791517238047694),
+ (2958436949848472639, 105989396547559618),
+ (12921418224165366607, 132486745684449522),
+ (12687572408530742033, 82804216052780951),
+ (11247779492236039638, 103505270065976189),
+ (224666310012885835, 129381587582470237),
+ (2446259452971747599, 80863492239043898),
+ (12281196353069460307, 101079365298804872),
+ (15351495441336825384, 126349206623506090),
+ (14206370669262903769, 78968254139691306),
+ (8534591299723853903, 98710317674614133),
+ (15279925143082205283, 123387897093267666),
+ (14161639232853766206, 77117435683292291),
+ (13090363022639819853, 96396794604115364),
+ (16362953778299774816, 120495993255144205),
+ (12532689120651053212, 75309995784465128),
+ (15665861400813816515, 94137494730581410),
+ (10358954714162494836, 117671868413226763),
+ (4168503687137865320, 73544917758266727),
+ (598943590494943747, 91931147197833409),
+ (5360365506546067587, 114913933997291761),
+ (11312142901609972388, 143642417496614701),
+ (9375932322719926695, 89776510935384188),
+ (11719915403399908368, 112220638669230235),
+ (10038208235822497557, 140275798336537794),
+ (10885566165816448877, 87672373960336121),
+ (18218643725697949000, 109590467450420151),
+ (18161618638695048346, 136988084313025189),
+ (13656854658398099168, 85617552695640743),
+ (12459382304570236056, 107021940869550929),
+ (1739169825430631358, 133777426086938662),
+ (14922039196176308311, 83610891304336663),
+ (14040862976792997485, 104513614130420829),
+ (3716020665709083144, 130642017663026037),
+ (4628355925281870917, 81651261039391273),
+ (10397130925029726550, 102064076299239091),
+ (8384727637859770284, 127580095374048864),
+ (5240454773662356427, 79737559608780540),
+ (6550568467077945534, 99671949510975675),
+ (3576524565420044014, 124589936888719594),
+ (6847013871814915412, 77868710555449746),
+ (17782139376623420074, 97335888194312182),
+ (13004302183924499284, 121669860242890228),
+ (17351060901807587860, 76043662651806392),
+ (3242082053549933210, 95054578314757991),
+ (17887660622219580224, 118818222893447488),
+ (11179787888887237640, 74261389308404680),
+ (13974734861109047050, 92826736635505850),
+ (8245046539531533005, 116033420794382313),
+ (16682369133275677888, 72520887996488945),
+ (7017903361312433648, 90651109995611182),
+ (17995751238495317868, 113313887494513977),
+ (8659630992836983623, 141642359368142472),
+ (5412269370523114764, 88526474605089045),
+ (11377022731581281359, 110658093256361306),
+ (4997906377621825891, 138322616570451633),
+ (14652906532082110942, 86451635356532270),
+ (9092761128247862869, 108064544195665338),
+ (2142579373455052779, 135080680244581673),
+ (12868327154477877747, 84425425152863545),
+ (2250350887815183471, 105531781441079432),
+ (2812938609768979339, 131914726801349290),
+ (6369772649532999991, 82446704250843306),
+ (17185587848771025797, 103058380313554132),
+ (3035240737254230630, 128822975391942666),
+ (6508711479211282048, 80514359619964166),
+ (17359261385868878368, 100642949524955207),
+ (17087390713908710056, 125803686906194009),
+ (3762090168551861929, 78627304316371256),
+ (4702612710689827411, 98284130395464070),
+ (15101637925217060072, 122855162994330087),
+ (16356052730901744401, 76784476871456304),
+ (1998321839917628885, 95980596089320381),
+ (7109588318324424010, 119975745111650476),
+ (13666864735807540814, 74984840694781547),
+ (12471894901332038114, 93731050868476934),
+ (6366496589810271835, 117163813585596168),
+ (3979060368631419896, 73227383490997605),
+ (9585511479216662775, 91534229363747006),
+ (2758517312166052660, 114417786704683758),
+ (12671518677062341634, 143022233380854697),
+ (1002170145522881665, 89388895863034186),
+ (10476084718758377889, 111736119828792732),
+ (13095105898447972362, 139670149785990915),
+ (5878598177316288774, 87293843616244322),
+ (16571619758500136775, 109117304520305402),
+ (11491152661270395161, 136396630650381753),
+ (264441385652915120, 85247894156488596),
+ (330551732066143900, 106559867695610745),
+ (5024875683510067779, 133199834619513431),
+ (10058076329834874218, 83249896637195894),
+ (3349223375438816964, 104062370796494868),
+ (4186529219298521205, 130077963495618585),
+ (14145795808130045513, 81298727184761615),
+ (13070558741735168987, 101623408980952019),
+ (11726512408741573330, 127029261226190024),
+ (7329070255463483331, 79393288266368765),
+ (13773023837756742068, 99241610332960956),
+ (17216279797195927585, 124052012916201195),
+ (8454331864033760789, 77532508072625747),
+ (5956228811614813082, 96915635090782184),
+ (7445286014518516353, 121144543863477730),
+ (9264989777501460624, 75715339914673581),
+ (16192923240304213684, 94644174893341976),
+ (1794409976670715490, 118305218616677471),
+ (8039035263060279037, 73940761635423419),
+ (5437108060397960892, 92425952044279274),
+ (16019757112352226923, 115532440055349092),
+ (788976158365366019, 72207775034593183),
+ (14821278253238871236, 90259718793241478),
+ (9303225779693813237, 112824648491551848),
+ (11629032224617266546, 141030810614439810),
+ (11879831158813179495, 88144256634024881),
+ (1014730893234310657, 110180320792531102),
+ (10491785653397664129, 137725400990663877),
+ (8863209042587234033, 86078375619164923),
+ (6467325284806654637, 107597969523956154),
+ (17307528642863094104, 134497461904945192),
+ (10817205401789433815, 84060913690590745),
+ (18133192770664180173, 105076142113238431),
+ (18054804944902837312, 131345177641548039),
+ (18201782118205355176, 82090736025967524),
+ (4305483574047142354, 102613420032459406),
+ (14605226504413703751, 128266775040574257),
+ (2210737537617482988, 80166734400358911),
+ (16598479977304017447, 100208418000448638),
+ (11524727934775246001, 125260522500560798),
+ (2591268940807140847, 78287826562850499),
+ (17074144231291089770, 97859783203563123),
+ (16730994270686474309, 122324729004453904),
+ (10456871419179046443, 76452955627783690),
+ (3847717237119032246, 95566194534729613),
+ (9421332564826178211, 119457743168412016),
+ (5888332853016361382, 74661089480257510),
+ (16583788103125227536, 93326361850321887),
+ (16118049110479146516, 116657952312902359),
+ (16991309721690548428, 72911220195563974),
+ (12015765115258409727, 91139025244454968),
+ (15019706394073012159, 113923781555568710),
+ (9551260955736489391, 142404726944460888),
+ (5969538097335305869, 89002954340288055),
+ (2850236603241744433, 111253692925360069),
+];
diff --git a/third_party/rust/ryu/src/d2s_intrinsics.rs b/third_party/rust/ryu/src/d2s_intrinsics.rs
new file mode 100644
index 0000000000..ca95aa4345
--- /dev/null
+++ b/third_party/rust/ryu/src/d2s_intrinsics.rs
@@ -0,0 +1,105 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+// Returns (lo, hi).
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn umul128(a: u64, b: u64) -> (u64, u64) {
+ let a_lo = a as u32;
+ let a_hi = (a >> 32) as u32;
+ let b_lo = b as u32;
+ let b_hi = (b >> 32) as u32;
+
+ let b00 = a_lo as u64 * b_lo as u64;
+ let b01 = a_lo as u64 * b_hi as u64;
+ let b10 = a_hi as u64 * b_lo as u64;
+ let b11 = a_hi as u64 * b_hi as u64;
+
+ let b00_lo = b00 as u32;
+ let b00_hi = (b00 >> 32) as u32;
+
+ let mid1 = b10 + b00_hi as u64;
+ let mid1_lo = mid1 as u32;
+ let mid1_hi = (mid1 >> 32) as u32;
+
+ let mid2 = b01 + mid1_lo as u64;
+ let mid2_lo = mid2 as u32;
+ let mid2_hi = (mid2 >> 32) as u32;
+
+ let p_hi = b11 + mid1_hi as u64 + mid2_hi as u64;
+ let p_lo = ((mid2_lo as u64) << 32) | b00_lo as u64;
+
+ (p_lo, p_hi)
+}
+
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn shiftright128(lo: u64, hi: u64, dist: u32) -> u64 {
+ // We don't need to handle the case dist >= 64 here (see above).
+ debug_assert!(dist > 0);
+ debug_assert!(dist < 64);
+ (hi << (64 - dist)) | (lo >> dist)
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn div5(x: u64) -> u64 {
+ x / 5
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn div10(x: u64) -> u64 {
+ x / 10
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn div100(x: u64) -> u64 {
+ x / 100
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+fn pow5_factor(mut value: u64) -> u32 {
+ let mut count = 0u32;
+ loop {
+ debug_assert!(value != 0);
+ let q = div5(value);
+ let r = (value as u32).wrapping_sub(5u32.wrapping_mul(q as u32));
+ if r != 0 {
+ break;
+ }
+ value = q;
+ count += 1;
+ }
+ count
+}
+
+// Returns true if value is divisible by 5^p.
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
+ // I tried a case distinction on p, but there was no performance difference.
+ pow5_factor(value) >= p
+}
+
+// Returns true if value is divisible by 2^p.
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
+ debug_assert!(value != 0);
+ // return __builtin_ctzll(value) >= p;
+ (value & ((1u64 << p) - 1)) == 0
+}
diff --git a/third_party/rust/ryu/src/d2s_small_table.rs b/third_party/rust/ryu/src/d2s_small_table.rs
new file mode 100644
index 0000000000..fc4a1a2a3b
--- /dev/null
+++ b/third_party/rust/ryu/src/d2s_small_table.rs
@@ -0,0 +1,206 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+use common::*;
+#[cfg(not(integer128))]
+use d2s_intrinsics::*;
+
+pub static DOUBLE_POW5_TABLE: [u64; 26] = [
+ 1,
+ 5,
+ 25,
+ 125,
+ 625,
+ 3125,
+ 15625,
+ 78125,
+ 390625,
+ 1953125,
+ 9765625,
+ 48828125,
+ 244140625,
+ 1220703125,
+ 6103515625,
+ 30517578125,
+ 152587890625,
+ 762939453125,
+ 3814697265625,
+ 19073486328125,
+ 95367431640625,
+ 476837158203125,
+ 2384185791015625,
+ 11920928955078125,
+ 59604644775390625,
+ 298023223876953125,
+];
+
+pub static DOUBLE_POW5_SPLIT2: [(u64, u64); 13] = [
+ (0, 72057594037927936),
+ (10376293541461622784, 93132257461547851),
+ (15052517733678820785, 120370621524202240),
+ (6258995034005762182, 77787690973264271),
+ (14893927168346708332, 100538234169297439),
+ (4272820386026678563, 129942622070561240),
+ (7330497575943398595, 83973451344588609),
+ (18377130505971182927, 108533142064701048),
+ (10038208235822497557, 140275798336537794),
+ (7017903361312433648, 90651109995611182),
+ (6366496589810271835, 117163813585596168),
+ (9264989777501460624, 75715339914673581),
+ (17074144231291089770, 97859783203563123),
+];
+
+// Unfortunately, the results are sometimes off by one. We use an additional
+// lookup table to store those cases and adjust the result.
+pub static POW5_OFFSETS: [u32; 13] = [
+ 0x00000000, 0x00000000, 0x00000000, 0x033c55be, 0x03db77d8, 0x0265ffb2, 0x00000800, 0x01a8ff56,
+ 0x00000000, 0x0037a200, 0x00004000, 0x03fffffc, 0x00003ffe,
+];
+
+pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 13] = [
+ (1, 288230376151711744),
+ (7661987648932456967, 223007451985306231),
+ (12652048002903177473, 172543658669764094),
+ (5522544058086115566, 266998379490113760),
+ (3181575136763469022, 206579990246952687),
+ (4551508647133041040, 159833525776178802),
+ (1116074521063664381, 247330401473104534),
+ (17400360011128145022, 191362629322552438),
+ (9297997190148906106, 148059663038321393),
+ (11720143854957885429, 229111231347799689),
+ (15401709288678291155, 177266229209635622),
+ (3003071137298187333, 274306203439684434),
+ (17516772882021341108, 212234145163966538),
+];
+
+pub static POW5_INV_OFFSETS: [u32; 20] = [
+ 0x51505404, 0x55054514, 0x45555545, 0x05511411, 0x00505010, 0x00000004, 0x00000000, 0x00000000,
+ 0x55555040, 0x00505051, 0x00050040, 0x55554000, 0x51659559, 0x00001000, 0x15000010, 0x55455555,
+ 0x41404051, 0x00001010, 0x00000014, 0x00000000,
+];
+
+// Computes 5^i in the form required by Ryu.
+#[cfg(integer128)]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
+ let base = i / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = i - base2;
+ debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
+ let b0 = m as u128 * mul.0 as u128;
+ let b2 = m as u128 * mul.1 as u128;
+ let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
+ debug_assert!(base < POW5_OFFSETS.len() as u32);
+ let shifted_sum = (b0 >> delta)
+ + (b2 << (64 - delta))
+ + ((*POW5_OFFSETS.get_unchecked(base as usize) >> offset) & 1) as u128;
+ (shifted_sum as u64, (shifted_sum >> 64) as u64)
+}
+
+// Computes 5^-i in the form required by Ryu.
+#[cfg(integer128)]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
+ let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = base2 - i;
+ debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize); // 5^offset
+ let b0 = m as u128 * (mul.0 - 1) as u128;
+ let b2 = m as u128 * mul.1 as u128; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
+ let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
+ debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
+ let shifted_sum = ((b0 >> delta) + (b2 << (64 - delta)))
+ + 1
+ + ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u128;
+ (shifted_sum as u64, (shifted_sum >> 64) as u64)
+}
+
+// Computes 5^i in the form required by Ryu, and stores it in the given pointer.
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
+ let base = i / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = i - base2;
+ debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
+ let (low1, mut high1) = umul128(m, mul.1);
+ let (low0, high0) = umul128(m, mul.0);
+ let sum = high0 + low1;
+ if sum < high0 {
+ high1 += 1; // overflow into high1
+ }
+ // high1 | sum | low0
+ let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
+ debug_assert!(base < POW5_OFFSETS.len() as u32);
+ (
+ shiftright128(low0, sum, delta as u32)
+ + ((*POW5_OFFSETS.get_unchecked(base as usize) >> offset) & 1) as u64,
+ shiftright128(sum, high1, delta as u32),
+ )
+}
+
+// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
+#[cfg(not(integer128))]
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
+ let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
+ let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
+ let offset = base2 - i;
+ debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
+ let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
+ if offset == 0 {
+ return mul;
+ }
+ debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
+ let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
+ let (low1, mut high1) = umul128(m, mul.1);
+ let (low0, high0) = umul128(m, mul.0 - 1);
+ let sum = high0 + low1;
+ if sum < high0 {
+ high1 += 1; // overflow into high1
+ }
+ // high1 | sum | low0
+ let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
+ debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
+ (
+ shiftright128(low0, sum, delta as u32)
+ + 1
+ + ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
+ shiftright128(sum, high1, delta as u32),
+ )
+}
diff --git a/third_party/rust/ryu/src/digit_table.rs b/third_party/rust/ryu/src/digit_table.rs
new file mode 100644
index 0000000000..d871f03f77
--- /dev/null
+++ b/third_party/rust/ryu/src/digit_table.rs
@@ -0,0 +1,28 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+// A table of all two-digit numbers. This is used to speed up decimal digit
+// generation by copying pairs of digits into the final output.
+pub static DIGIT_TABLE: [u8; 200] = *b"\
+ 0001020304050607080910111213141516171819\
+ 2021222324252627282930313233343536373839\
+ 4041424344454647484950515253545556575859\
+ 6061626364656667686970717273747576777879\
+ 8081828384858687888990919293949596979899";
diff --git a/third_party/rust/ryu/src/f2s.rs b/third_party/rust/ryu/src/f2s.rs
new file mode 100644
index 0000000000..4ad50a1bce
--- /dev/null
+++ b/third_party/rust/ryu/src/f2s.rs
@@ -0,0 +1,323 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+use common::*;
+
+pub const FLOAT_MANTISSA_BITS: u32 = 23;
+pub const FLOAT_EXPONENT_BITS: u32 = 8;
+
+const FLOAT_BIAS: i32 = 127;
+const FLOAT_POW5_INV_BITCOUNT: i32 = 59;
+const FLOAT_POW5_BITCOUNT: i32 = 61;
+
+// This table is generated by PrintFloatLookupTable.
+static FLOAT_POW5_INV_SPLIT: [u64; 32] = [
+ 576460752303423489,
+ 461168601842738791,
+ 368934881474191033,
+ 295147905179352826,
+ 472236648286964522,
+ 377789318629571618,
+ 302231454903657294,
+ 483570327845851670,
+ 386856262276681336,
+ 309485009821345069,
+ 495176015714152110,
+ 396140812571321688,
+ 316912650057057351,
+ 507060240091291761,
+ 405648192073033409,
+ 324518553658426727,
+ 519229685853482763,
+ 415383748682786211,
+ 332306998946228969,
+ 531691198313966350,
+ 425352958651173080,
+ 340282366920938464,
+ 544451787073501542,
+ 435561429658801234,
+ 348449143727040987,
+ 557518629963265579,
+ 446014903970612463,
+ 356811923176489971,
+ 570899077082383953,
+ 456719261665907162,
+ 365375409332725730,
+ 1 << 63,
+];
+
+static FLOAT_POW5_SPLIT: [u64; 47] = [
+ 1152921504606846976,
+ 1441151880758558720,
+ 1801439850948198400,
+ 2251799813685248000,
+ 1407374883553280000,
+ 1759218604441600000,
+ 2199023255552000000,
+ 1374389534720000000,
+ 1717986918400000000,
+ 2147483648000000000,
+ 1342177280000000000,
+ 1677721600000000000,
+ 2097152000000000000,
+ 1310720000000000000,
+ 1638400000000000000,
+ 2048000000000000000,
+ 1280000000000000000,
+ 1600000000000000000,
+ 2000000000000000000,
+ 1250000000000000000,
+ 1562500000000000000,
+ 1953125000000000000,
+ 1220703125000000000,
+ 1525878906250000000,
+ 1907348632812500000,
+ 1192092895507812500,
+ 1490116119384765625,
+ 1862645149230957031,
+ 1164153218269348144,
+ 1455191522836685180,
+ 1818989403545856475,
+ 2273736754432320594,
+ 1421085471520200371,
+ 1776356839400250464,
+ 2220446049250313080,
+ 1387778780781445675,
+ 1734723475976807094,
+ 2168404344971008868,
+ 1355252715606880542,
+ 1694065894508600678,
+ 2117582368135750847,
+ 1323488980084844279,
+ 1654361225106055349,
+ 2067951531382569187,
+ 1292469707114105741,
+ 1615587133892632177,
+ 2019483917365790221,
+];
+
+#[cfg_attr(feature = "no-panic", inline)]
+fn pow5_factor(mut value: u32) -> u32 {
+ let mut count = 0u32;
+ loop {
+ debug_assert!(value != 0);
+ let q = value / 5;
+ let r = value % 5;
+ if r != 0 {
+ break;
+ }
+ value = q;
+ count += 1;
+ }
+ count
+}
+
+// Returns true if value is divisible by 5^p.
+#[cfg_attr(feature = "no-panic", inline)]
+fn multiple_of_power_of_5(value: u32, p: u32) -> bool {
+ pow5_factor(value) >= p
+}
+
+// Returns true if value is divisible by 2^p.
+#[cfg_attr(feature = "no-panic", inline)]
+fn multiple_of_power_of_2(value: u32, p: u32) -> bool {
+ // return __builtin_ctz(value) >= p;
+ (value & ((1u32 << p) - 1)) == 0
+}
+
+// It seems to be slightly faster to avoid uint128_t here, although the
+// generated code for uint128_t looks slightly nicer.
+#[cfg_attr(feature = "no-panic", inline)]
+fn mul_shift(m: u32, factor: u64, shift: i32) -> u32 {
+ debug_assert!(shift > 32);
+
+ // The casts here help MSVC to avoid calls to the __allmul library
+ // function.
+ let factor_lo = factor as u32;
+ let factor_hi = (factor >> 32) as u32;
+ let bits0 = m as u64 * factor_lo as u64;
+ let bits1 = m as u64 * factor_hi as u64;
+
+ let sum = (bits0 >> 32) + bits1;
+ let shifted_sum = sum >> (shift - 32);
+ debug_assert!(shifted_sum <= u32::max_value() as u64);
+ shifted_sum as u32
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+fn mul_pow5_inv_div_pow2(m: u32, q: u32, j: i32) -> u32 {
+ debug_assert!(q < FLOAT_POW5_INV_SPLIT.len() as u32);
+ unsafe { mul_shift(m, *FLOAT_POW5_INV_SPLIT.get_unchecked(q as usize), j) }
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+fn mul_pow5_div_pow2(m: u32, i: u32, j: i32) -> u32 {
+ debug_assert!(i < FLOAT_POW5_SPLIT.len() as u32);
+ unsafe { mul_shift(m, *FLOAT_POW5_SPLIT.get_unchecked(i as usize), j) }
+}
+
+// A floating decimal representing m * 10^e.
+pub struct FloatingDecimal32 {
+ pub mantissa: u32,
+ // Decimal exponent's range is -45 to 38
+ // inclusive, and can fit in i16 if needed.
+ pub exponent: i32,
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
+ let (e2, m2) = if ieee_exponent == 0 {
+ (
+ // We subtract 2 so that the bounds computation has 2 additional bits.
+ 1 - FLOAT_BIAS - FLOAT_MANTISSA_BITS as i32 - 2,
+ ieee_mantissa,
+ )
+ } else {
+ (
+ ieee_exponent as i32 - FLOAT_BIAS - FLOAT_MANTISSA_BITS as i32 - 2,
+ (1u32 << FLOAT_MANTISSA_BITS) | ieee_mantissa,
+ )
+ };
+ let even = (m2 & 1) == 0;
+ let accept_bounds = even;
+
+ // Step 2: Determine the interval of valid decimal representations.
+ let mv = 4 * m2;
+ let mp = 4 * m2 + 2;
+ // Implicit bool -> int conversion. True is 1, false is 0.
+ let mm_shift = (ieee_mantissa != 0 || ieee_exponent <= 1) as u32;
+ let mm = 4 * m2 - 1 - mm_shift;
+
+ // Step 3: Convert to a decimal power base using 64-bit arithmetic.
+ let mut vr: u32;
+ let mut vp: u32;
+ let mut vm: u32;
+ let e10: i32;
+ let mut vm_is_trailing_zeros = false;
+ let mut vr_is_trailing_zeros = false;
+ let mut last_removed_digit = 0u8;
+ if e2 >= 0 {
+ let q = log10_pow2(e2);
+ e10 = q as i32;
+ let k = FLOAT_POW5_INV_BITCOUNT + pow5bits(q as i32) - 1;
+ let i = -e2 + q as i32 + k;
+ vr = mul_pow5_inv_div_pow2(mv, q, i);
+ vp = mul_pow5_inv_div_pow2(mp, q, i);
+ vm = mul_pow5_inv_div_pow2(mm, q, i);
+ if q != 0 && (vp - 1) / 10 <= vm / 10 {
+ // We need to know one removed digit even if we are not going to loop below. We could use
+ // q = X - 1 above, except that would require 33 bits for the result, and we've found that
+ // 32-bit arithmetic is faster even on 64-bit machines.
+ let l = FLOAT_POW5_INV_BITCOUNT + pow5bits(q as i32 - 1) - 1;
+ last_removed_digit =
+ (mul_pow5_inv_div_pow2(mv, q - 1, -e2 + q as i32 - 1 + l) % 10) as u8;
+ }
+ if q <= 9 {
+ // The largest power of 5 that fits in 24 bits is 5^10, but q <= 9 seems to be safe as well.
+ // Only one of mp, mv, and mm can be a multiple of 5, if any.
+ if mv % 5 == 0 {
+ vr_is_trailing_zeros = multiple_of_power_of_5(mv, q);
+ } else if accept_bounds {
+ vm_is_trailing_zeros = multiple_of_power_of_5(mm, q);
+ } else {
+ vp -= multiple_of_power_of_5(mp, q) as u32;
+ }
+ }
+ } else {
+ let q = log10_pow5(-e2);
+ e10 = q as i32 + e2;
+ let i = -e2 - q as i32;
+ let k = pow5bits(i) - FLOAT_POW5_BITCOUNT;
+ let mut j = q as i32 - k;
+ vr = mul_pow5_div_pow2(mv, i as u32, j);
+ vp = mul_pow5_div_pow2(mp, i as u32, j);
+ vm = mul_pow5_div_pow2(mm, i as u32, j);
+ if q != 0 && (vp - 1) / 10 <= vm / 10 {
+ j = q as i32 - 1 - (pow5bits(i + 1) - FLOAT_POW5_BITCOUNT);
+ last_removed_digit = (mul_pow5_div_pow2(mv, (i + 1) as u32, j) % 10) as u8;
+ }
+ if q <= 1 {
+ // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
+ // mv = 4 * m2, so it always has at least two trailing 0 bits.
+ vr_is_trailing_zeros = true;
+ if accept_bounds {
+ // mm = mv - 1 - mm_shift, so it has 1 trailing 0 bit iff mm_shift == 1.
+ vm_is_trailing_zeros = mm_shift == 1;
+ } else {
+ // mp = mv + 2, so it always has at least one trailing 0 bit.
+ vp -= 1;
+ }
+ } else if q < 31 {
+ // TODO(ulfjack): Use a tighter bound here.
+ vr_is_trailing_zeros = multiple_of_power_of_2(mv, q - 1);
+ }
+ }
+
+ // Step 4: Find the shortest decimal representation in the interval of valid representations.
+ let mut removed = 0i32;
+ let output = if vm_is_trailing_zeros || vr_is_trailing_zeros {
+ // General case, which happens rarely (~4.0%).
+ while vp / 10 > vm / 10 {
+ vm_is_trailing_zeros &= vm - (vm / 10) * 10 == 0;
+ vr_is_trailing_zeros &= last_removed_digit == 0;
+ last_removed_digit = (vr % 10) as u8;
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ removed += 1;
+ }
+ if vm_is_trailing_zeros {
+ while vm % 10 == 0 {
+ vr_is_trailing_zeros &= last_removed_digit == 0;
+ last_removed_digit = (vr % 10) as u8;
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ removed += 1;
+ }
+ }
+ if vr_is_trailing_zeros && last_removed_digit == 5 && vr % 2 == 0 {
+ // Round even if the exact number is .....50..0.
+ last_removed_digit = 4;
+ }
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ vr + ((vr == vm && (!accept_bounds || !vm_is_trailing_zeros)) || last_removed_digit >= 5)
+ as u32
+ } else {
+ // Specialized for the common case (~96.0%). Percentages below are relative to this.
+ // Loop iterations below (approximately):
+ // 0: 13.6%, 1: 70.7%, 2: 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
+ while vp / 10 > vm / 10 {
+ last_removed_digit = (vr % 10) as u8;
+ vr /= 10;
+ vp /= 10;
+ vm /= 10;
+ removed += 1;
+ }
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ vr + (vr == vm || last_removed_digit >= 5) as u32
+ };
+ let exp = e10 + removed;
+
+ FloatingDecimal32 {
+ exponent: exp,
+ mantissa: output,
+ }
+}
diff --git a/third_party/rust/ryu/src/lib.rs b/third_party/rust/ryu/src/lib.rs
new file mode 100644
index 0000000000..8aecb51e5b
--- /dev/null
+++ b/third_party/rust/ryu/src/lib.rs
@@ -0,0 +1,111 @@
+//! Pure Rust implementation of Ryū, an algorithm to quickly convert floating
+//! point numbers to decimal strings.
+//!
+//! The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf
+//! Adams includes a complete correctness proof of the algorithm. The paper is
+//! available under the creative commons CC-BY-SA license.
+//!
+//! This Rust implementation is a line-by-line port of Ulf Adams' implementation
+//! in C, [https://github.com/ulfjack/ryu][upstream].
+//!
+//! [paper]: https://dl.acm.org/citation.cfm?id=3192369
+//! [upstream]: https://github.com/ulfjack/ryu
+//!
+//! # Example
+//!
+//! ```edition2018
+//! fn main() {
+//! let mut buffer = ryu::Buffer::new();
+//! let printed = buffer.format(1.234);
+//! assert_eq!(printed, "1.234");
+//! }
+//! ```
+//!
+//! ## Performance
+//!
+//! You can run upstream's benchmarks with:
+//!
+//! ```console
+//! $ git clone https://github.com/ulfjack/ryu c-ryu
+//! $ cd c-ryu
+//! $ bazel run -c opt //ryu/benchmark
+//! ```
+//!
+//! And the same benchmark against our implementation with:
+//!
+//! ```console
+//! $ git clone https://github.com/dtolnay/ryu rust-ryu
+//! $ cd rust-ryu
+//! $ cargo run --example upstream_benchmark --release
+//! ```
+//!
+//! These benchmarks measure the average time to print a 32-bit float and average
+//! time to print a 64-bit float, where the inputs are distributed as uniform random
+//! bit patterns 32 and 64 bits wide.
+//!
+//! The upstream C code, the unsafe direct Rust port, and the safe pretty Rust API
+//! all perform the same, taking around 21 nanoseconds to format a 32-bit float and
+//! 31 nanoseconds to format a 64-bit float.
+//!
+//! There is also a Rust-specific benchmark comparing this implementation to the
+//! standard library which you can run with:
+//!
+//! ```console
+//! $ cargo bench
+//! ```
+//!
+//! The benchmark shows Ryu approximately 4-10x faster than the standard library
+//! across a range of f32 and f64 inputs. Measurements are in nanoseconds per
+//! iteration; smaller is better.
+//!
+//! | type=f32 | 0.0 | 0.1234 | 2.718281828459045 | f32::MAX |
+//! |:--------:|:----:|:------:|:-----------------:|:--------:|
+//! | RYU | 3ns | 28ns | 23ns | 22ns |
+//! | STD | 40ns | 106ns | 128ns | 110ns |
+//!
+//! | type=f64 | 0.0 | 0.1234 | 2.718281828459045 | f64::MAX |
+//! |:--------:|:----:|:------:|:-----------------:|:--------:|
+//! | RYU | 3ns | 50ns | 35ns | 32ns |
+//! | STD | 39ns | 105ns | 128ns | 202ns |
+//!
+//! ## Formatting
+//!
+//! This library tends to produce more human-readable output than the standard
+//! library's to\_string, which never uses scientific notation. Here are two
+//! examples:
+//!
+//! - *ryu:* 1.23e40, *std:* 12300000000000000000000000000000000000000
+//! - *ryu:* 1.23e-40, *std:* 0.000000000000000000000000000000000000000123
+//!
+//! Both libraries print short decimals such as 0.0000123 without scientific
+//! notation.
+
+#![no_std]
+#![doc(html_root_url = "https://docs.rs/ryu/1.0.2")]
+#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
+#![cfg_attr(
+ feature = "cargo-clippy",
+ allow(cast_lossless, many_single_char_names, unreadable_literal,)
+)]
+
+#[cfg(feature = "no-panic")]
+extern crate no_panic;
+
+mod buffer;
+mod common;
+mod d2s;
+#[cfg(not(feature = "small"))]
+mod d2s_full_table;
+mod d2s_intrinsics;
+#[cfg(feature = "small")]
+mod d2s_small_table;
+mod digit_table;
+mod f2s;
+mod pretty;
+
+pub use buffer::{Buffer, Float};
+
+/// Unsafe functions that mirror the API of the C implementation of Ryū.
+pub mod raw {
+ pub use pretty::{format32, format64};
+}
diff --git a/third_party/rust/ryu/src/pretty/exponent.rs b/third_party/rust/ryu/src/pretty/exponent.rs
new file mode 100644
index 0000000000..f10643f22d
--- /dev/null
+++ b/third_party/rust/ryu/src/pretty/exponent.rs
@@ -0,0 +1,49 @@
+use core::ptr;
+
+use digit_table::*;
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn write_exponent3(mut k: isize, mut result: *mut u8) -> usize {
+ let sign = k < 0;
+ if sign {
+ *result = b'-';
+ result = result.offset(1);
+ k = -k;
+ }
+
+ debug_assert!(k < 1000);
+ if k >= 100 {
+ *result = b'0' + (k / 100) as u8;
+ k %= 100;
+ let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
+ ptr::copy_nonoverlapping(d, result.offset(1), 2);
+ sign as usize + 3
+ } else if k >= 10 {
+ let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
+ ptr::copy_nonoverlapping(d, result, 2);
+ sign as usize + 2
+ } else {
+ *result = b'0' + k as u8;
+ sign as usize + 1
+ }
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn write_exponent2(mut k: isize, mut result: *mut u8) -> usize {
+ let sign = k < 0;
+ if sign {
+ *result = b'-';
+ result = result.offset(1);
+ k = -k;
+ }
+
+ debug_assert!(k < 100);
+ if k >= 10 {
+ let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
+ ptr::copy_nonoverlapping(d, result, 2);
+ sign as usize + 2
+ } else {
+ *result = b'0' + k as u8;
+ sign as usize + 1
+ }
+}
diff --git a/third_party/rust/ryu/src/pretty/mantissa.rs b/third_party/rust/ryu/src/pretty/mantissa.rs
new file mode 100644
index 0000000000..428023233d
--- /dev/null
+++ b/third_party/rust/ryu/src/pretty/mantissa.rs
@@ -0,0 +1,51 @@
+use core::ptr;
+
+use digit_table::*;
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
+ if (output >> 32) != 0 {
+ // One expensive 64-bit division.
+ let mut output2 = (output - 100_000_000 * (output / 100_000_000)) as u32;
+ output /= 100_000_000;
+
+ let c = output2 % 10_000;
+ output2 /= 10_000;
+ let d = output2 % 10_000;
+ let c0 = (c % 100) << 1;
+ let c1 = (c / 100) << 1;
+ let d0 = (d % 100) << 1;
+ let d1 = (d / 100) << 1;
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2);
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2);
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d0 as usize), result.offset(-6), 2);
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d1 as usize), result.offset(-8), 2);
+ result = result.offset(-8);
+ }
+ write_mantissa(output as u32, result);
+}
+
+#[cfg_attr(feature = "no-panic", inline)]
+pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
+ while output >= 10_000 {
+ let c = (output - 10_000 * (output / 10_000)) as u32;
+ output /= 10_000;
+ let c0 = (c % 100) << 1;
+ let c1 = (c / 100) << 1;
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2);
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2);
+ result = result.offset(-4);
+ }
+ if output >= 100 {
+ let c = ((output % 100) << 1) as u32;
+ output /= 100;
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2);
+ result = result.offset(-2);
+ }
+ if output >= 10 {
+ let c = (output << 1) as u32;
+ ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2);
+ } else {
+ *result.offset(-1) = b'0' + output as u8;
+ }
+}
diff --git a/third_party/rust/ryu/src/pretty/mod.rs b/third_party/rust/ryu/src/pretty/mod.rs
new file mode 100644
index 0000000000..3dead1bf36
--- /dev/null
+++ b/third_party/rust/ryu/src/pretty/mod.rs
@@ -0,0 +1,228 @@
+mod exponent;
+mod mantissa;
+
+use core::{mem, ptr};
+
+use self::exponent::*;
+use self::mantissa::*;
+use common;
+use d2s;
+use d2s::*;
+use f2s::*;
+
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
+
+/// Print f64 to the given buffer and return number of bytes written.
+///
+/// At most 24 bytes will be written.
+///
+/// ## Special cases
+///
+/// This function **does not** check for NaN or infinity. If the input
+/// number is not a finite float, the printed representation will be some
+/// correctly formatted but unspecified numerical value.
+///
+/// Please check [`is_finite`] yourself before calling this function, or
+/// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
+///
+/// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite
+/// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan
+/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
+///
+/// ## Safety
+///
+/// The `result` pointer argument must point to sufficiently many writable bytes
+/// to hold Ryū's representation of `f`.
+///
+/// ## Example
+///
+/// ```edition2018
+/// use std::mem::MaybeUninit;
+///
+/// let f = 1.234f64;
+///
+/// unsafe {
+/// let mut buffer: [MaybeUninit<u8>; 24] = MaybeUninit::uninit().assume_init();
+/// let len = ryu::raw::format64(f, buffer.as_mut_ptr() as *mut u8);
+/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
+/// let print = std::str::from_utf8_unchecked(slice);
+/// assert_eq!(print, "1.234");
+/// }
+/// ```
+#[cfg_attr(must_use_return, must_use)]
+#[cfg_attr(feature = "no-panic", no_panic)]
+pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
+ let bits = mem::transmute::<f64, u64>(f);
+ let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
+ let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
+ let ieee_exponent =
+ (bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1);
+
+ let mut index = 0isize;
+ if sign {
+ *result = b'-';
+ index += 1;
+ }
+
+ if ieee_exponent == 0 && ieee_mantissa == 0 {
+ ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
+ return sign as usize + 3;
+ }
+
+ let v = d2d(ieee_mantissa, ieee_exponent);
+
+ let length = d2s::decimal_length17(v.mantissa) as isize;
+ let k = v.exponent as isize;
+ let kk = length + k; // 10^(kk-1) <= v < 10^kk
+ debug_assert!(k >= -324);
+
+ if 0 <= k && kk <= 16 {
+ // 1234e7 -> 12340000000.0
+ write_mantissa_long(v.mantissa, result.offset(index + length));
+ for i in length..kk {
+ *result.offset(index + i) = b'0';
+ }
+ *result.offset(index + kk) = b'.';
+ *result.offset(index + kk + 1) = b'0';
+ index as usize + kk as usize + 2
+ } else if 0 < kk && kk <= 16 {
+ // 1234e-2 -> 12.34
+ write_mantissa_long(v.mantissa, result.offset(index + length + 1));
+ ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
+ *result.offset(index + kk) = b'.';
+ index as usize + length as usize + 1
+ } else if -5 < kk && kk <= 0 {
+ // 1234e-6 -> 0.001234
+ *result.offset(index) = b'0';
+ *result.offset(index + 1) = b'.';
+ let offset = 2 - kk;
+ for i in 2..offset {
+ *result.offset(index + i) = b'0';
+ }
+ write_mantissa_long(v.mantissa, result.offset(index + length + offset));
+ index as usize + length as usize + offset as usize
+ } else if length == 1 {
+ // 1e30
+ *result.offset(index) = b'0' + v.mantissa as u8;
+ *result.offset(index + 1) = b'e';
+ index as usize + 2 + write_exponent3(kk - 1, result.offset(index + 2))
+ } else {
+ // 1234e30 -> 1.234e33
+ write_mantissa_long(v.mantissa, result.offset(index + length + 1));
+ *result.offset(index) = *result.offset(index + 1);
+ *result.offset(index + 1) = b'.';
+ *result.offset(index + length + 1) = b'e';
+ index as usize
+ + length as usize
+ + 2
+ + write_exponent3(kk - 1, result.offset(index + length + 2))
+ }
+}
+
+/// Print f32 to the given buffer and return number of bytes written.
+///
+/// At most 16 bytes will be written.
+///
+/// ## Special cases
+///
+/// This function **does not** check for NaN or infinity. If the input
+/// number is not a finite float, the printed representation will be some
+/// correctly formatted but unspecified numerical value.
+///
+/// Please check [`is_finite`] yourself before calling this function, or
+/// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
+///
+/// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_finite
+/// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_nan
+/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f32.html#method.is_infinite
+///
+/// ## Safety
+///
+/// The `result` pointer argument must point to sufficiently many writable bytes
+/// to hold Ryū's representation of `f`.
+///
+/// ## Example
+///
+/// ```edition2018
+/// use std::mem::MaybeUninit;
+///
+/// let f = 1.234f32;
+///
+/// unsafe {
+/// let mut buffer: [MaybeUninit<u8>; 16] = MaybeUninit::uninit().assume_init();
+/// let len = ryu::raw::format32(f, buffer.as_mut_ptr() as *mut u8);
+/// let slice = std::slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
+/// let print = std::str::from_utf8_unchecked(slice);
+/// assert_eq!(print, "1.234");
+/// }
+/// ```
+#[cfg_attr(must_use_return, must_use)]
+#[cfg_attr(feature = "no-panic", no_panic)]
+pub unsafe fn format32(f: f32, result: *mut u8) -> usize {
+ let bits = mem::transmute::<f32, u32>(f);
+ let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
+ let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
+ let ieee_exponent =
+ ((bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1)) as u32;
+
+ let mut index = 0isize;
+ if sign {
+ *result = b'-';
+ index += 1;
+ }
+
+ if ieee_exponent == 0 && ieee_mantissa == 0 {
+ ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
+ return sign as usize + 3;
+ }
+
+ let v = f2d(ieee_mantissa, ieee_exponent);
+
+ let length = common::decimal_length9(v.mantissa) as isize;
+ let k = v.exponent as isize;
+ let kk = length + k; // 10^(kk-1) <= v < 10^kk
+ debug_assert!(k >= -45);
+
+ if 0 <= k && kk <= 13 {
+ // 1234e7 -> 12340000000.0
+ write_mantissa(v.mantissa, result.offset(index + length));
+ for i in length..kk {
+ *result.offset(index + i) = b'0';
+ }
+ *result.offset(index + kk) = b'.';
+ *result.offset(index + kk + 1) = b'0';
+ index as usize + kk as usize + 2
+ } else if 0 < kk && kk <= 13 {
+ // 1234e-2 -> 12.34
+ write_mantissa(v.mantissa, result.offset(index + length + 1));
+ ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
+ *result.offset(index + kk) = b'.';
+ index as usize + length as usize + 1
+ } else if -6 < kk && kk <= 0 {
+ // 1234e-6 -> 0.001234
+ *result.offset(index) = b'0';
+ *result.offset(index + 1) = b'.';
+ let offset = 2 - kk;
+ for i in 2..offset {
+ *result.offset(index + i) = b'0';
+ }
+ write_mantissa(v.mantissa, result.offset(index + length + offset));
+ index as usize + length as usize + offset as usize
+ } else if length == 1 {
+ // 1e30
+ *result.offset(index) = b'0' + v.mantissa as u8;
+ *result.offset(index + 1) = b'e';
+ index as usize + 2 + write_exponent2(kk - 1, result.offset(index + 2))
+ } else {
+ // 1234e30 -> 1.234e33
+ write_mantissa(v.mantissa, result.offset(index + length + 1));
+ *result.offset(index) = *result.offset(index + 1);
+ *result.offset(index + 1) = b'.';
+ *result.offset(index + length + 1) = b'e';
+ index as usize
+ + length as usize
+ + 2
+ + write_exponent2(kk - 1, result.offset(index + length + 2))
+ }
+}
diff --git a/third_party/rust/ryu/tests/d2s_table_test.rs b/third_party/rust/ryu/tests/d2s_table_test.rs
new file mode 100644
index 0000000000..8f27726db4
--- /dev/null
+++ b/third_party/rust/ryu/tests/d2s_table_test.rs
@@ -0,0 +1,52 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+#![allow(dead_code)]
+
+extern crate core;
+
+#[path = "../src/common.rs"]
+mod common;
+
+#[path = "../src/d2s_full_table.rs"]
+mod d2s_full_table;
+
+#[path = "../src/d2s_intrinsics.rs"]
+mod d2s_intrinsics;
+
+#[path = "../src/d2s_small_table.rs"]
+mod d2s_small_table;
+
+use d2s_full_table::*;
+use d2s_small_table::*;
+
+#[test]
+fn test_compute_pow5() {
+ for (i, entry) in DOUBLE_POW5_SPLIT.iter().enumerate() {
+ assert_eq!(*entry, unsafe { compute_pow5(i as u32) }, "entry {}", i);
+ }
+}
+
+#[test]
+fn test_compute_inv_pow5() {
+ for (i, entry) in DOUBLE_POW5_INV_SPLIT.iter().enumerate() {
+ assert_eq!(*entry, unsafe { compute_inv_pow5(i as u32) }, "entry {}", i);
+ }
+}
diff --git a/third_party/rust/ryu/tests/d2s_test.rs b/third_party/rust/ryu/tests/d2s_test.rs
new file mode 100644
index 0000000000..c30a305212
--- /dev/null
+++ b/third_party/rust/ryu/tests/d2s_test.rs
@@ -0,0 +1,321 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+extern crate rand;
+extern crate ryu;
+
+#[macro_use]
+mod macros;
+
+use std::f64;
+
+fn pretty(f: f64) -> String {
+ ryu::Buffer::new().format(f).to_owned()
+}
+
+fn ieee_parts_to_double(sign: bool, ieee_exponent: u32, ieee_mantissa: u64) -> f64 {
+ assert!(ieee_exponent <= 2047);
+ assert!(ieee_mantissa <= (1u64 << 53) - 1);
+ f64::from_bits(((sign as u64) << 63) | ((ieee_exponent as u64) << 52) | ieee_mantissa)
+}
+
+#[test]
+fn test_ryu() {
+ check!(0.3);
+ check!(1234000000000000.0);
+ check!(1.234e16);
+ check!(2.71828);
+ check!(1.1e128);
+ check!(1.1e-64);
+ check!(2.718281828459045);
+ check!(5e-324);
+ check!(1.7976931348623157e308);
+}
+
+#[test]
+fn test_random() {
+ let mut buffer = ryu::Buffer::new();
+ for _ in 0..1000000 {
+ let f: f64 = rand::random();
+ assert_eq!(f, buffer.format_finite(f).parse().unwrap());
+ }
+}
+
+#[test]
+fn test_non_finite() {
+ for i in 0u64..1 << 23 {
+ let f = f64::from_bits((((1 << 11) - 1) << 52) + (i << 29));
+ assert!(!f.is_finite(), "f={}", f);
+ ryu::Buffer::new().format_finite(f);
+ }
+}
+
+#[test]
+fn test_basic() {
+ check!(0.0);
+ check!(-0.0);
+ check!(1.0);
+ check!(-1.0);
+ assert_eq!(pretty(f64::NAN), "NaN");
+ assert_eq!(pretty(f64::INFINITY), "inf");
+ assert_eq!(pretty(f64::NEG_INFINITY), "-inf");
+}
+
+#[test]
+fn test_switch_to_subnormal() {
+ check!(2.2250738585072014e-308);
+}
+
+#[test]
+fn test_min_and_max() {
+ assert_eq!(f64::from_bits(0x7fefffffffffffff), 1.7976931348623157e308);
+ check!(1.7976931348623157e308);
+ assert_eq!(f64::from_bits(1), 5e-324);
+ check!(5e-324);
+}
+
+#[test]
+fn test_lots_of_trailing_zeros() {
+ check!(2.9802322387695312e-8);
+}
+
+#[test]
+fn test_regression() {
+ check!(-2.109808898695963e16);
+ check!(4.940656e-318);
+ check!(1.18575755e-316);
+ check!(2.989102097996e-312);
+ check!(9060801153433600.0);
+ check!(4.708356024711512e18);
+ check!(9.409340012568248e18);
+ check!(1.2345678);
+}
+
+#[test]
+fn test_looks_like_pow5() {
+ // These numbers have a mantissa that is a multiple of the largest power of
+ // 5 that fits, and an exponent that causes the computation for q to result
+ // in 22, which is a corner case for Ryu.
+ assert_eq!(f64::from_bits(0x4830F0CF064DD592), 5.764607523034235e39);
+ check!(5.764607523034235e39);
+ assert_eq!(f64::from_bits(0x4840F0CF064DD592), 1.152921504606847e40);
+ check!(1.152921504606847e40);
+ assert_eq!(f64::from_bits(0x4850F0CF064DD592), 2.305843009213694e40);
+ check!(2.305843009213694e40);
+}
+
+#[test]
+fn test_output_length() {
+ check!(1.0); // already tested in Basic
+ check!(1.2);
+ check!(1.23);
+ check!(1.234);
+ check!(1.2345);
+ check!(1.23456);
+ check!(1.234567);
+ check!(1.2345678); // already tested in Regression
+ check!(1.23456789);
+ check!(1.234567895); // 1.234567890 would be trimmed
+ check!(1.2345678901);
+ check!(1.23456789012);
+ check!(1.234567890123);
+ check!(1.2345678901234);
+ check!(1.23456789012345);
+ check!(1.234567890123456);
+ check!(1.2345678901234567);
+
+ // Test 32-bit chunking
+ check!(4.294967294); // 2^32 - 2
+ check!(4.294967295); // 2^32 - 1
+ check!(4.294967296); // 2^32
+ check!(4.294967297); // 2^32 + 1
+ check!(4.294967298); // 2^32 + 2
+}
+
+// Test min, max shift values in shiftright128
+#[test]
+fn test_min_max_shift() {
+ let max_mantissa = (1u64 << 53) - 1;
+
+ // 32-bit opt-size=0: 49 <= dist <= 50
+ // 32-bit opt-size=1: 30 <= dist <= 50
+ // 64-bit opt-size=0: 50 <= dist <= 50
+ // 64-bit opt-size=1: 30 <= dist <= 50
+ assert_eq!(1.7800590868057611E-307, ieee_parts_to_double(false, 4, 0));
+ check!(1.7800590868057611e-307);
+ // 32-bit opt-size=0: 49 <= dist <= 49
+ // 32-bit opt-size=1: 28 <= dist <= 49
+ // 64-bit opt-size=0: 50 <= dist <= 50
+ // 64-bit opt-size=1: 28 <= dist <= 50
+ assert_eq!(
+ 2.8480945388892175E-306,
+ ieee_parts_to_double(false, 6, max_mantissa)
+ );
+ check!(2.8480945388892175e-306);
+ // 32-bit opt-size=0: 52 <= dist <= 53
+ // 32-bit opt-size=1: 2 <= dist <= 53
+ // 64-bit opt-size=0: 53 <= dist <= 53
+ // 64-bit opt-size=1: 2 <= dist <= 53
+ assert_eq!(2.446494580089078E-296, ieee_parts_to_double(false, 41, 0));
+ check!(2.446494580089078e-296);
+ // 32-bit opt-size=0: 52 <= dist <= 52
+ // 32-bit opt-size=1: 2 <= dist <= 52
+ // 64-bit opt-size=0: 53 <= dist <= 53
+ // 64-bit opt-size=1: 2 <= dist <= 53
+ assert_eq!(
+ 4.8929891601781557E-296,
+ ieee_parts_to_double(false, 40, max_mantissa)
+ );
+ check!(4.8929891601781557e-296);
+
+ // 32-bit opt-size=0: 57 <= dist <= 58
+ // 32-bit opt-size=1: 57 <= dist <= 58
+ // 64-bit opt-size=0: 58 <= dist <= 58
+ // 64-bit opt-size=1: 58 <= dist <= 58
+ assert_eq!(1.8014398509481984E16, ieee_parts_to_double(false, 1077, 0));
+ check!(1.8014398509481984e16);
+ // 32-bit opt-size=0: 57 <= dist <= 57
+ // 32-bit opt-size=1: 57 <= dist <= 57
+ // 64-bit opt-size=0: 58 <= dist <= 58
+ // 64-bit opt-size=1: 58 <= dist <= 58
+ assert_eq!(
+ 3.6028797018963964E16,
+ ieee_parts_to_double(false, 1076, max_mantissa)
+ );
+ check!(3.6028797018963964e16);
+ // 32-bit opt-size=0: 51 <= dist <= 52
+ // 32-bit opt-size=1: 51 <= dist <= 59
+ // 64-bit opt-size=0: 52 <= dist <= 52
+ // 64-bit opt-size=1: 52 <= dist <= 59
+ assert_eq!(2.900835519859558E-216, ieee_parts_to_double(false, 307, 0));
+ check!(2.900835519859558e-216);
+ // 32-bit opt-size=0: 51 <= dist <= 51
+ // 32-bit opt-size=1: 51 <= dist <= 59
+ // 64-bit opt-size=0: 52 <= dist <= 52
+ // 64-bit opt-size=1: 52 <= dist <= 59
+ assert_eq!(
+ 5.801671039719115E-216,
+ ieee_parts_to_double(false, 306, max_mantissa)
+ );
+ check!(5.801671039719115e-216);
+
+ // https://github.com/ulfjack/ryu/commit/19e44d16d80236f5de25800f56d82606d1be00b9#commitcomment-30146483
+ // 32-bit opt-size=0: 49 <= dist <= 49
+ // 32-bit opt-size=1: 44 <= dist <= 49
+ // 64-bit opt-size=0: 50 <= dist <= 50
+ // 64-bit opt-size=1: 44 <= dist <= 50
+ assert_eq!(
+ 3.196104012172126E-27,
+ ieee_parts_to_double(false, 934, 0x000FA7161A4D6E0C)
+ );
+ check!(3.196104012172126e-27);
+}
+
+#[test]
+fn test_small_integers() {
+ check!(9007199254740991.0); // 2^53-1
+ check!(9007199254740992.0); // 2^53
+
+ check!(1.0);
+ check!(12.0);
+ check!(123.0);
+ check!(1234.0);
+ check!(12345.0);
+ check!(123456.0);
+ check!(1234567.0);
+ check!(12345678.0);
+ check!(123456789.0);
+ check!(1234567890.0);
+ check!(1234567895.0);
+ check!(12345678901.0);
+ check!(123456789012.0);
+ check!(1234567890123.0);
+ check!(12345678901234.0);
+ check!(123456789012345.0);
+ check!(1234567890123456.0);
+
+ // 10^i
+ check!(1.0);
+ check!(10.0);
+ check!(100.0);
+ check!(1000.0);
+ check!(10000.0);
+ check!(100000.0);
+ check!(1000000.0);
+ check!(10000000.0);
+ check!(100000000.0);
+ check!(1000000000.0);
+ check!(10000000000.0);
+ check!(100000000000.0);
+ check!(1000000000000.0);
+ check!(10000000000000.0);
+ check!(100000000000000.0);
+ check!(1000000000000000.0);
+
+ // 10^15 + 10^i
+ check!(1000000000000001.0);
+ check!(1000000000000010.0);
+ check!(1000000000000100.0);
+ check!(1000000000001000.0);
+ check!(1000000000010000.0);
+ check!(1000000000100000.0);
+ check!(1000000001000000.0);
+ check!(1000000010000000.0);
+ check!(1000000100000000.0);
+ check!(1000001000000000.0);
+ check!(1000010000000000.0);
+ check!(1000100000000000.0);
+ check!(1001000000000000.0);
+ check!(1010000000000000.0);
+ check!(1100000000000000.0);
+
+ // Largest power of 2 <= 10^(i+1)
+ check!(8.0);
+ check!(64.0);
+ check!(512.0);
+ check!(8192.0);
+ check!(65536.0);
+ check!(524288.0);
+ check!(8388608.0);
+ check!(67108864.0);
+ check!(536870912.0);
+ check!(8589934592.0);
+ check!(68719476736.0);
+ check!(549755813888.0);
+ check!(8796093022208.0);
+ check!(70368744177664.0);
+ check!(562949953421312.0);
+ check!(9007199254740992.0);
+
+ // 1000 * (Largest power of 2 <= 10^(i+1))
+ check!(8000.0);
+ check!(64000.0);
+ check!(512000.0);
+ check!(8192000.0);
+ check!(65536000.0);
+ check!(524288000.0);
+ check!(8388608000.0);
+ check!(67108864000.0);
+ check!(536870912000.0);
+ check!(8589934592000.0);
+ check!(68719476736000.0);
+ check!(549755813888000.0);
+ check!(8796093022208000.0);
+}
diff --git a/third_party/rust/ryu/tests/exhaustive.rs b/third_party/rust/ryu/tests/exhaustive.rs
new file mode 100644
index 0000000000..5c36969ffc
--- /dev/null
+++ b/third_party/rust/ryu/tests/exhaustive.rs
@@ -0,0 +1,55 @@
+#![cfg(exhaustive)]
+
+extern crate num_cpus;
+extern crate ryu;
+
+use std::str;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::Arc;
+use std::thread;
+
+#[test]
+fn test_exhaustive() {
+ const BATCH_SIZE: u32 = 1_000_000;
+ let counter = Arc::new(AtomicUsize::new(0));
+ let finished = Arc::new(AtomicUsize::new(0));
+
+ let mut workers = Vec::new();
+ for _ in 0..num_cpus::get() {
+ let counter = counter.clone();
+ let finished = finished.clone();
+ workers.push(thread::spawn(move || loop {
+ let batch = counter.fetch_add(1, Ordering::SeqCst) as u32;
+ if batch > u32::max_value() / BATCH_SIZE {
+ return;
+ }
+
+ let min = batch * BATCH_SIZE;
+ let max = if batch == u32::max_value() / BATCH_SIZE {
+ u32::max_value()
+ } else {
+ min + BATCH_SIZE - 1
+ };
+
+ let mut bytes = [0u8; 24];
+ let mut buffer = ryu::Buffer::new();
+ for u in min..=max {
+ let f = f32::from_bits(u);
+ if !f.is_finite() {
+ continue;
+ }
+ let n = unsafe { ryu::raw::format32(f, &mut bytes[0]) };
+ assert_eq!(Ok(Ok(f)), str::from_utf8(&bytes[..n]).map(str::parse));
+ assert_eq!(Ok(f), buffer.format_finite(f).parse());
+ }
+
+ let increment = (max - min + 1) as usize;
+ let update = finished.fetch_add(increment, Ordering::SeqCst);
+ println!("{}", update + increment);
+ }));
+ }
+
+ for w in workers {
+ w.join().unwrap();
+ }
+}
diff --git a/third_party/rust/ryu/tests/f2s_test.rs b/third_party/rust/ryu/tests/f2s_test.rs
new file mode 100644
index 0000000000..82968b4a86
--- /dev/null
+++ b/third_party/rust/ryu/tests/f2s_test.rs
@@ -0,0 +1,173 @@
+// Translated from C to Rust. The original C code can be found at
+// https://github.com/ulfjack/ryu and carries the following license:
+//
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+extern crate rand;
+extern crate ryu;
+
+#[macro_use]
+mod macros;
+
+use std::f32;
+
+fn pretty(f: f32) -> String {
+ ryu::Buffer::new().format(f).to_owned()
+}
+
+#[test]
+fn test_ryu() {
+ check!(0.3);
+ check!(1234000000000.0);
+ check!(1.234e13);
+ check!(2.71828);
+ check!(1.1e32);
+ check!(1.1e-32);
+ check!(2.7182817);
+ check!(1e-45);
+ check!(3.4028235e38);
+ check!(-0.001234);
+}
+
+#[test]
+fn test_random() {
+ let mut buffer = ryu::Buffer::new();
+ for _ in 0..1000000 {
+ let f: f32 = rand::random();
+ assert_eq!(f, buffer.format_finite(f).parse().unwrap());
+ }
+}
+
+#[test]
+fn test_non_finite() {
+ for i in 0u32..1 << 23 {
+ let f = f32::from_bits((((1 << 8) - 1) << 23) + i);
+ assert!(!f.is_finite(), "f={}", f);
+ ryu::Buffer::new().format_finite(f);
+ }
+}
+
+#[test]
+fn test_basic() {
+ check!(0.0);
+ check!(-0.0);
+ check!(1.0);
+ check!(-1.0);
+ assert_eq!(pretty(f32::NAN), "NaN");
+ assert_eq!(pretty(f32::INFINITY), "inf");
+ assert_eq!(pretty(f32::NEG_INFINITY), "-inf");
+}
+
+#[test]
+fn test_switch_to_subnormal() {
+ check!(1.1754944e-38);
+}
+
+#[test]
+fn test_min_and_max() {
+ assert_eq!(f32::from_bits(0x7f7fffff), 3.4028235e38);
+ check!(3.4028235e38);
+ assert_eq!(f32::from_bits(1), 1e-45);
+ check!(1e-45);
+}
+
+// Check that we return the exact boundary if it is the shortest
+// representation, but only if the original floating point number is even.
+#[test]
+fn test_boundary_round_even() {
+ check!(33554450.0);
+ check!(9000000000.0);
+ check!(34366720000.0);
+}
+
+// If the exact value is exactly halfway between two shortest representations,
+// then we round to even. It seems like this only makes a difference if the
+// last two digits are ...2|5 or ...7|5, and we cut off the 5.
+#[test]
+fn test_exact_value_round_even() {
+ check!(305404.12);
+ check!(8099.0312);
+}
+
+#[test]
+fn test_lots_of_trailing_zeros() {
+ // Pattern for the first test: 00111001100000000000000000000000
+ check!(0.00024414062);
+ check!(0.0024414062);
+ check!(0.0043945312);
+ check!(0.0063476562);
+}
+
+#[test]
+fn test_regression() {
+ check!(4.7223665e21);
+ check!(8388608.0);
+ check!(16777216.0);
+ check!(33554436.0);
+ check!(67131496.0);
+ check!(1.9310392e-38);
+ check!(-2.47e-43);
+ check!(1.993244e-38);
+ check!(4103.9004);
+ check!(5339999700.0);
+ check!(6.0898e-39);
+ check!(0.0010310042);
+ check!(2.882326e17);
+ check!(7.038531e-26);
+ check!(9.223404e17);
+ check!(67108870.0);
+ check!(1e-44);
+ check!(2.816025e14);
+ check!(9.223372e18);
+ check!(1.5846086e29);
+ check!(1.1811161e19);
+ check!(5.368709e18);
+ check!(4.6143166e18);
+ check!(0.007812537);
+ check!(1e-45);
+ check!(1.18697725e20);
+ check!(1.00014165e-36);
+ check!(200.0);
+ check!(33554432.0);
+}
+
+#[test]
+fn test_looks_like_pow5() {
+ // These numbers have a mantissa that is the largest power of 5 that fits,
+ // and an exponent that causes the computation for q to result in 10, which
+ // is a corner case for Ryu.
+ assert_eq!(f32::from_bits(0x5D1502F9), 6.7108864e17);
+ check!(6.7108864e17);
+ assert_eq!(f32::from_bits(0x5D9502F9), 1.3421773e18);
+ check!(1.3421773e18);
+ assert_eq!(f32::from_bits(0x5E1502F9), 2.6843546e18);
+ check!(2.6843546e18);
+}
+
+#[test]
+fn test_output_length() {
+ check!(1.0); // already tested in Basic
+ check!(1.2);
+ check!(1.23);
+ check!(1.234);
+ check!(1.2345);
+ check!(1.23456);
+ check!(1.234567);
+ check!(1.2345678);
+ check!(1.23456735e-36);
+}
diff --git a/third_party/rust/ryu/tests/macros/mod.rs b/third_party/rust/ryu/tests/macros/mod.rs
new file mode 100644
index 0000000000..de6fb465e8
--- /dev/null
+++ b/third_party/rust/ryu/tests/macros/mod.rs
@@ -0,0 +1,8 @@
+macro_rules! check {
+ ($f:tt) => {
+ assert_eq!(pretty($f), stringify!($f));
+ };
+ (-$f:tt) => {
+ assert_eq!(pretty(-$f), concat!("-", stringify!($f)));
+ };
+}