Bug 1716518 - Upgrade ryu to v1.0.5.

Differential Revision: https://phabricator.services.mozilla.com/D117849

Depends on D117848
This commit is contained in:
Mike Hommey 2021-06-15 09:24:52 +00:00
parent 8774126633
commit 4a0ad733c3
30 changed files with 1858 additions and 1123 deletions

4
Cargo.lock generated
View File

@ -4412,9 +4412,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.2"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "safemem"

View File

@ -1 +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"}
{"files":{"Cargo.lock":"f7ef07c660c06ba004ca31a14cec7f907335c850bf6337e5010a3c3c1a2c4b09","Cargo.toml":"5c7e08556c74f5c3ef67f90e8e8c3f3fc4abe26eeeb62dc8b52888db46c82d03","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"f9662a7ce18253aad23f0153632fdd20e195c11e6fbd29fed4fbb5989ca4343b","benches/bench.rs":"ea6f919ff44d86ee26c69bf0b77d8a1502e687b26a68db8613f88d063470dd27","build.rs":"4d0cad8c0501f5b4d81eb91f693f8186db6edcc603c8906ae0305cfccd847df8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"ff9ad624b652c2b1aba7f44de06ae17b17ffca5efb0b05215385875c145d5ff8","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"630cea1a958a468f0f07f3748e3f52540a9e85fc667af5fef0e542b3c9b93394","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"56a1a53f0c418b82ca8c0d2523da70aa786c001250cdfca7847077d5d91e3b02","src/d2s_small_table.rs":"d4fdf0c0f6cfc35a2f5f89f6c1298ed2e1d7924e49d4a1bee8c640658606867d","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"55320c2301680d8be3a908620cccd9d103b0cd3ad7a7d3378589e274ffc2587b","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"1185a3ca950cf01909488c273e6390bacd9194d51beb842fbc60490771f6a5ec","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"1d097db65f63f495fcc67acca8c586ac37a0de9f62041712b5d555addd13b585","src/pretty/mantissa.rs":"765e0c1e7077e8ceeb3b66e5829263b53cf19ae110b078aa5f5866370c8add3c","src/pretty/mod.rs":"56de1d71eb4b16851fcdf2678bf579237d06fab887be1b5b7fa80cff43d64f62","src/s2d.rs":"e2b5a4e4826cfdb88c8aa00060a07596f0944b8f5e31031f764553032c57615a","src/s2f.rs":"c2ece3b397449b1c4dcedee03b702b323e7c4c41222ec64874f9fc1ba39e97f8","tests/common_test.rs":"12d1e069b3cd51299bd376100cff6823ac3540295d547d352eb67302a2a6544c","tests/d2s_table_test.rs":"9a6a0efb3e692dfaf048155e6f96799ea538721243bda899b4f05495379a42f3","tests/d2s_test.rs":"fe9d78d835039f905bc78e7cbf045c70898459e9f23b859b8491c5c3a658db35","tests/exhaustive.rs":"5ae5a567f11cc1d4b980655f1ec6e4784715d77ac49e39394f76763dc227f653","tests/f2s_test.rs":"f1345918e50f60ac7ca55f4b6e83fb3ea5ea5b3344994be2ce00bac6dd5a1e0d","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"f28f5d756e3d21b47b154862f420d19e3203bef3e4cf55327209fe19ebd8623d","tests/s2f_test.rs":"44ad9a2407c8b2d22479b320a204221ba03d43e6ab06000440308926c5b5585b"},"package":"71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"}

149
third_party/rust/ryu/Cargo.lock generated vendored
View File

@ -1,49 +1,60 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "bitflags"
version = "1.2.0"
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
name = "getrandom"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
name = "hermit-abi"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.62"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "no-panic"
version = "0.1.11"
version = "0.1.13"
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)",
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.10.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ppv-lite86"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.5"
version = "1.0.17"
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)",
@ -51,53 +62,74 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.2"
version = "1.0.6"
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)",
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.5.6"
version = "0.7.3"
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)",
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
version = "0.5.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)",
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.4.2"
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "1.0.2"
version = "1.0.5"
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)",
"no-panic 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.5"
version = "1.0.29"
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)",
"proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -107,38 +139,25 @@ 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"
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
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 cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
"checksum hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
"checksum no-panic 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b4da21758193a9f8a8f1dc698f121e70e8df07c71e4968e49762a5604bbdf72b"
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
"checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
"checksum syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0"
"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"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

View File

@ -11,15 +11,17 @@
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "ryu"
version = "1.0.2"
version = "1.0.5"
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"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies.no-panic]
version = "0.1"
optional = true
@ -27,9 +29,10 @@ optional = true
version = "1.8"
[dev-dependencies.rand]
version = "0.5"
version = "0.7"
[dev-dependencies.rand_xorshift]
version = "0.2"
[features]
small = []
[badges.travis-ci]
repository = "dtolnay/ryu"

View File

@ -1,9 +1,9 @@
# 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)
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/ryu-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/ryu)
[<img alt="crates.io" src="https://img.shields.io/crates/v/ryu.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/ryu)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-ryu-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/ryu)
[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/ryu/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/ryu/actions?query=branch%3Amaster)
Pure Rust implementation of Ryū, an algorithm to quickly convert floating point
numbers to decimal strings.
@ -15,11 +15,11 @@ 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
*Requirements: this crate supports any compiler version back to rustc 1.31; 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
[upstream]: https://github.com/ulfjack/ryu/tree/1c413e127f8d02afd12eb6259bc80163722f1385
```toml
[dependencies]
@ -69,7 +69,7 @@ standard library which you can run with:
$ cargo bench
```
The benchmark shows Ryu approximately 4-10x faster than the standard library
The benchmark shows Ryū 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.

View File

@ -2,18 +2,19 @@
#![feature(test)]
extern crate ryu;
extern crate test;
use std::io::Write;
use std::{f32, f64};
use test::{black_box, Bencher};
macro_rules! benches {
($($name:ident($value:expr),)*) => {
mod bench_ryu {
use test::{Bencher, black_box};
use super::*;
$(
#[bench]
fn $name(b: &mut Bencher) {
use ryu;
let mut buf = ryu::Buffer::new();
b.iter(move || {
@ -26,12 +27,10 @@ macro_rules! benches {
}
mod bench_std_fmt {
use test::{Bencher, black_box};
use super::*;
$(
#[bench]
fn $name(b: &mut Bencher) {
use std::io::Write;
let mut buf = Vec::with_capacity(20);
b.iter(|| {
@ -43,16 +42,16 @@ macro_rules! benches {
}
)*
}
}
};
}
benches!(
benches! {
bench_0_f64(0f64),
bench_short_f64(0.1234f64),
bench_e_f64(2.718281828459045f64),
bench_max_f64(::std::f64::MAX),
bench_max_f64(f64::MAX),
bench_0_f32(0f32),
bench_short_f32(0.1234f32),
bench_e_f32(2.718281828459045f32),
bench_max_f32(::std::f32::MAX),
);
bench_max_f32(f32::MAX),
}

View File

@ -14,21 +14,12 @@ fn main() {
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
// 128-bit integers disabled on Emscripten targets as Emscripten doesn't
// currently support integers larger than 64 bits.
if minor >= 26 && !emscripten {
if !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 {
@ -37,30 +28,13 @@ fn main() {
}
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 rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
let next = pieces.next()?;
u32::from_str(next).ok()
}

View File

@ -1,8 +1,5 @@
// cargo run --example upstream_benchmark --release
extern crate rand;
extern crate ryu;
use rand::{Rng, SeedableRng};
const SAMPLES: usize = 10000;
@ -43,7 +40,7 @@ impl MeanAndVariance {
macro_rules! benchmark {
($name:ident, $ty:ident) => {
fn $name() -> usize {
let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
let mut rng = rand_xorshift::XorShiftRng::from_seed([123u8; 16]);
let mut mv = MeanAndVariance::new();
let mut throwaway = 0;
for _ in 0..SAMPLES {

View File

@ -1,10 +1,7 @@
use core::{mem, slice, str};
use crate::raw;
#[cfg(maybe_uninit)]
use core::mem::MaybeUninit;
use raw;
use core::{mem, slice, str};
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
@ -16,12 +13,11 @@ const NEG_INFINITY: &'static str = "-inf";
///
/// ## 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],
@ -38,7 +34,7 @@ impl Buffer {
// 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() };
let bytes = [MaybeUninit::<u8>::uninit(); 24];
#[cfg(not(maybe_uninit))]
let bytes = unsafe { mem::uninitialized() };
@ -85,35 +81,20 @@ impl Buffer {
#[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());
let n = f.write_to_ryu_buffer(self.bytes.as_mut_ptr() as *mut u8);
debug_assert!(n <= self.bytes.len());
let slice = slice::from_raw_parts(self.first_byte_pointer(), n);
let slice = slice::from_raw_parts(self.bytes.as_ptr() as *const u8, n);
str::from_utf8_unchecked(slice)
}
}
}
#[inline]
#[cfg(maybe_uninit)]
fn first_byte_pointer(&self) -> *const u8 {
self.bytes[0].as_ptr()
}
impl Copy for Buffer {}
impl Clone for Buffer {
#[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
fn clone(&self) -> Self {
Buffer::new()
}
}

View File

@ -18,6 +18,8 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
// Returns the number of decimal digits in v, which must not contain more than 9
// digits.
#[cfg_attr(feature = "no-panic", inline)]
pub fn decimal_length9(v: u32) -> u32 {
// Function precondition: v is not a 10-digit number.
@ -45,29 +47,47 @@ pub fn decimal_length9(v: u32) -> u32 {
}
}
// Returns e == 0 ? 1 : ceil(log_2(5^e)).
// Returns e == 0 ? 1 : [log_2(5^e)]; requires 0 <= e <= 3528.
#[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.
#[allow(dead_code)]
pub fn log2_pow5(e: i32) -> i32 /* or u32 -> u32 */ {
// 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) as i32
}
// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528.
#[cfg_attr(feature = "no-panic", inline)]
pub fn pow5bits(e: i32) -> i32 /* or u32 -> u32 */ {
// 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 {
#[allow(dead_code)]
pub fn ceil_log2_pow5(e: i32) -> i32 /* or u32 -> u32 */ {
log2_pow5(e) + 1
}
// Returns floor(log_10(2^e)); requires 0 <= e <= 1650.
#[cfg_attr(feature = "no-panic", inline)]
pub fn log10_pow2(e: i32) -> u32 /* or u32 -> 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)).
// Returns floor(log_10(5^e)); requires 0 <= e <= 2620.
#[cfg_attr(feature = "no-panic", inline)]
pub fn log10_pow5(e: i32) -> u32 {
pub fn log10_pow5(e: i32) -> u32 /* or u32 -> 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);

View File

@ -18,90 +18,22 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use core::ptr;
use crate::common::*;
#[cfg(not(feature = "small"))]
pub use crate::d2s_full_table::*;
use crate::d2s_intrinsics::*;
#[cfg(feature = "small")]
pub use crate::d2s_small_table::*;
#[cfg(not(maybe_uninit))]
use core::mem;
#[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)
}
pub const DOUBLE_BIAS: i32 = 1023;
pub const DOUBLE_POW5_INV_BITCOUNT: i32 = 125;
pub const DOUBLE_POW5_BITCOUNT: i32 = 125;
#[cfg_attr(feature = "no-panic", inline)]
pub fn decimal_length17(v: u64) -> u32 {
@ -205,7 +137,7 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
let k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q as i32) - 1;
let i = -e2 + q as i32 + k;
vr = unsafe {
mul_shift_all(
mul_shift_all_64(
m2,
#[cfg(feature = "small")]
&compute_inv_pow5(q),
@ -264,7 +196,7 @@ pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
let k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
let j = q as i32 - k;
vr = unsafe {
mul_shift_all(
mul_shift_all_64(
m2,
#[cfg(feature = "small")]
&compute_pow5(i as u32),

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,8 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use core::ptr;
// Returns (lo, hi).
#[cfg(not(integer128))]
#[cfg_attr(feature = "no-panic", inline)]
@ -100,6 +102,70 @@ pub fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
#[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;
debug_assert!(p < 64);
// __builtin_ctzll doesn't appear to be faster here.
(value & ((1u64 << p) - 1)) == 0
}
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub fn mul_shift_64(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)]
pub unsafe fn mul_shift_all_64(
m: u64,
mul: &(u64, u64),
j: u32,
vp: *mut u64,
vm: *mut u64,
mm_shift: u32,
) -> u64 {
ptr::write(vp, mul_shift_64(4 * m + 2, mul, j));
ptr::write(vm, mul_shift_64(4 * m - 1 - mm_shift as u64, mul, j));
mul_shift_64(4 * m, mul, j)
}
#[cfg(not(integer128))]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn mul_shift_all_64(
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)
}

View File

@ -18,9 +18,53 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use common::*;
use crate::common::*;
#[cfg(not(integer128))]
use d2s_intrinsics::*;
use crate::d2s_intrinsics::*;
pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 13] = [
(1, 2305843009213693952),
(5955668970331000884, 1784059615882449851),
(8982663654677661702, 1380349269358112757),
(7286864317269821294, 2135987035920910082),
(7005857020398200553, 1652639921975621497),
(17965325103354776697, 1278668206209430417),
(8928596168509315048, 1978643211784836272),
(10075671573058298858, 1530901034580419511),
(597001226353042382, 1184477304306571148),
(1527430471115325346, 1832889850782397517),
(12533209867169019542, 1418129833677084982),
(5577825024675947042, 2194449627517475473),
(11006974540203867551, 1697873161311732311),
];
pub static POW5_INV_OFFSETS: [u32; 19] = [
0x54544554, 0x04055545, 0x10041000, 0x00400414, 0x40010000, 0x41155555, 0x00000454, 0x00010044,
0x40000000, 0x44000041, 0x50454450, 0x55550054, 0x51655554, 0x40004000, 0x01000001, 0x00010500,
0x51515411, 0x05555554, 0x00000000,
];
pub static DOUBLE_POW5_SPLIT2: [(u64, u64); 13] = [
(0, 1152921504606846976),
(0, 1490116119384765625),
(1032610780636961552, 1925929944387235853),
(7910200175544436838, 1244603055572228341),
(16941905809032713930, 1608611746708759036),
(13024893955298202172, 2079081953128979843),
(6607496772837067824, 1343575221513417750),
(17332926989895652603, 1736530273035216783),
(13037379183483547984, 2244412773384604712),
(1605989338741628675, 1450417759929778918),
(9630225068416591280, 1874621017369538693),
(665883850346957067, 1211445438634777304),
(14931890668723713708, 1565756531257009982),
];
pub static POW5_OFFSETS: [u32; 21] = [
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40000000, 0x59695995, 0x55545555, 0x56555515,
0x41150504, 0x40555410, 0x44555145, 0x44504540, 0x45555550, 0x40004000, 0x96440440, 0x55565565,
0x54454045, 0x40154151, 0x55559155, 0x51405555, 0x00000105,
];
pub static DOUBLE_POW5_TABLE: [u64; 26] = [
1,
@ -51,52 +95,7 @@ pub static DOUBLE_POW5_TABLE: [u64; 26] = [
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.
// Computes 5^i in the form required by Ryū.
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
@ -116,11 +115,11 @@ pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
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;
+ ((*POW5_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.
// Computes 5^-i in the form required by Ryū.
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
@ -144,7 +143,7 @@ pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
(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.
// Computes 5^i in the form required by Ryū, 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) {
@ -169,12 +168,12 @@ pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
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,
+ ((*POW5_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
shiftright128(sum, high1, delta as u32),
)
}
// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
// Computes 5^-i in the form required by Ryū, 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) {

View File

@ -18,160 +18,13 @@
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use common::*;
use crate::common::*;
use crate::f2s_intrinsics::*;
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) }
}
pub use crate::f2s_intrinsics::{FLOAT_POW5_BITCOUNT, FLOAT_POW5_INV_BITCOUNT};
// A floating decimal representing m * 10^e.
pub struct FloatingDecimal32 {
@ -233,11 +86,11 @@ pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
// 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);
vr_is_trailing_zeros = multiple_of_power_of_5_32(mv, q);
} else if accept_bounds {
vm_is_trailing_zeros = multiple_of_power_of_5(mm, q);
vm_is_trailing_zeros = multiple_of_power_of_5_32(mm, q);
} else {
vp -= multiple_of_power_of_5(mp, q) as u32;
vp -= multiple_of_power_of_5_32(mp, q) as u32;
}
}
} else {
@ -266,7 +119,7 @@ pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
}
} else if q < 31 {
// TODO(ulfjack): Use a tighter bound here.
vr_is_trailing_zeros = multiple_of_power_of_2(mv, q - 1);
vr_is_trailing_zeros = multiple_of_power_of_2_32(mv, q - 1);
}
}

View File

@ -0,0 +1,113 @@
// 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 crate::d2s;
pub const FLOAT_POW5_INV_BITCOUNT: i32 = d2s::DOUBLE_POW5_INV_BITCOUNT - 64;
pub const FLOAT_POW5_BITCOUNT: i32 = d2s::DOUBLE_POW5_BITCOUNT - 64;
#[cfg_attr(feature = "no-panic", inline)]
fn pow5factor_32(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)]
pub fn multiple_of_power_of_5_32(value: u32, p: u32) -> bool {
pow5factor_32(value) >= p
}
// Returns true if value is divisible by 2^p.
#[cfg_attr(feature = "no-panic", inline)]
pub fn multiple_of_power_of_2_32(value: u32, p: u32) -> bool {
// __builtin_ctz doesn't appear to be faster here.
(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_32(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)]
pub fn mul_pow5_inv_div_pow2(m: u32, q: u32, j: i32) -> u32 {
#[cfg(feature = "small")]
{
// The inverse multipliers are defined as [2^x / 5^y] + 1; the upper 64
// bits from the double lookup table are the correct bits for [2^x /
// 5^y], so we have to add 1 here. Note that we rely on the fact that
// the added 1 that's already stored in the table never overflows into
// the upper 64 bits.
let pow5 = unsafe { d2s::compute_inv_pow5(q) };
mul_shift_32(m, pow5.1 + 1, j)
}
#[cfg(not(feature = "small"))]
{
debug_assert!(q < d2s::DOUBLE_POW5_INV_SPLIT.len() as u32);
unsafe {
mul_shift_32(
m,
d2s::DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize).1 + 1,
j,
)
}
}
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn mul_pow5_div_pow2(m: u32, i: u32, j: i32) -> u32 {
#[cfg(feature = "small")]
{
let pow5 = unsafe { d2s::compute_pow5(i) };
mul_shift_32(m, pow5.1, j)
}
#[cfg(not(feature = "small"))]
{
debug_assert!(i < d2s::DOUBLE_POW5_SPLIT.len() as u32);
unsafe { mul_shift_32(m, d2s::DOUBLE_POW5_SPLIT.get_unchecked(i as usize).1, j) }
}
}

View File

@ -1,3 +1,11 @@
//! [![github]](https://github.com/dtolnay/ryu)&ensp;[![crates-io]](https://crates.io/crates/ryu)&ensp;[![docs-rs]](https://docs.rs/ryu)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
//! <br>
//!
//! Pure Rust implementation of Ryū, an algorithm to quickly convert floating
//! point numbers to decimal strings.
//!
@ -13,7 +21,7 @@
//!
//! # Example
//!
//! ```edition2018
//! ```
//! fn main() {
//! let mut buffer = ryu::Buffer::new();
//! let printed = buffer.format(1.234);
@ -54,7 +62,7 @@
//! $ cargo bench
//! ```
//!
//! The benchmark shows Ryu approximately 4-10x faster than the standard library
//! The benchmark shows Ryū 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.
//!
@ -81,16 +89,13 @@
//! notation.
#![no_std]
#![doc(html_root_url = "https://docs.rs/ryu/1.0.2")]
#![doc(html_root_url = "https://docs.rs/ryu/1.0.5")]
#![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;
@ -101,11 +106,12 @@ mod d2s_intrinsics;
mod d2s_small_table;
mod digit_table;
mod f2s;
mod f2s_intrinsics;
mod pretty;
pub use buffer::{Buffer, Float};
pub use crate::buffer::{Buffer, Float};
/// Unsafe functions that mirror the API of the C implementation of Ryū.
pub mod raw {
pub use pretty::{format32, format64};
pub use crate::pretty::{format32, format64};
}

19
third_party/rust/ryu/src/parse.rs vendored Normal file
View File

@ -0,0 +1,19 @@
use core::fmt::{self, Display};
#[derive(Copy, Clone, Debug)]
pub enum Error {
InputTooShort,
InputTooLong,
MalformedInput,
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let msg = match self {
Error::InputTooShort => "input too short",
Error::InputTooLong => "input too long",
Error::MalformedInput => "malformed input",
};
formatter.write_str(msg)
}
}

View File

@ -1,7 +1,6 @@
use crate::digit_table::*;
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;

View File

@ -1,7 +1,6 @@
use crate::digit_table::*;
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 {

View File

@ -1,15 +1,12 @@
mod exponent;
mod mantissa;
use core::{mem, ptr};
use self::exponent::*;
use self::mantissa::*;
use common;
use d2s;
use d2s::*;
use f2s::*;
use crate::common;
use crate::d2s::{self, *};
use crate::f2s::*;
use core::{mem, ptr};
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
@ -37,20 +34,20 @@ use no_panic::no_panic;
///
/// ## Example
///
/// ```edition2018
/// use std::mem::MaybeUninit;
/// ```
/// use std::{mem::MaybeUninit, slice, str};
///
/// let f = 1.234f64;
///
/// unsafe {
/// let mut buffer: [MaybeUninit<u8>; 24] = MaybeUninit::uninit().assume_init();
/// let mut buffer = [MaybeUninit::<u8>::uninit(); 24];
/// 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);
/// let slice = slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
/// let print = str::from_utf8_unchecked(slice);
/// assert_eq!(print, "1.234");
/// }
/// ```
#[cfg_attr(must_use_return, must_use)]
#[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);
@ -144,20 +141,20 @@ pub unsafe fn format64(f: f64, result: *mut u8) -> usize {
///
/// ## Example
///
/// ```edition2018
/// use std::mem::MaybeUninit;
/// ```
/// use std::{mem::MaybeUninit, slice, str};
///
/// let f = 1.234f32;
///
/// unsafe {
/// let mut buffer: [MaybeUninit<u8>; 16] = MaybeUninit::uninit().assume_init();
/// let mut buffer = [MaybeUninit::<u8>::uninit(); 16];
/// 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);
/// let slice = slice::from_raw_parts(buffer.as_ptr() as *const u8, len);
/// let print = str::from_utf8_unchecked(slice);
/// assert_eq!(print, "1.234");
/// }
/// ```
#[cfg_attr(must_use_return, must_use)]
#[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);

216
third_party/rust/ryu/src/s2d.rs vendored Normal file
View File

@ -0,0 +1,216 @@
use crate::common::*;
use crate::d2s;
use crate::d2s_intrinsics::*;
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
const DOUBLE_EXPONENT_BIAS: usize = 1023;
fn floor_log2(value: u64) -> u32 {
63_u32.wrapping_sub(value.leading_zeros())
}
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn s2d(buffer: &[u8]) -> Result<f64, Error> {
let len = buffer.len();
if len == 0 {
return Err(Error::InputTooShort);
}
let mut m10digits = 0;
let mut e10digits = 0;
let mut dot_index = len;
let mut e_index = len;
let mut m10 = 0u64;
let mut e10 = 0i32;
let mut signed_m = false;
let mut signed_e = false;
let mut i = 0;
if unsafe { *buffer.get_unchecked(0) } == b'-' {
signed_m = true;
i += 1;
}
while let Some(c) = buffer.get(i).copied() {
if c == b'.' {
if dot_index != len {
return Err(Error::MalformedInput);
}
dot_index = i;
i += 1;
continue;
}
if c < b'0' || c > b'9' {
break;
}
if m10digits >= 17 {
return Err(Error::InputTooLong);
}
m10 = 10 * m10 + (c - b'0') as u64;
if m10 != 0 {
m10digits += 1;
}
i += 1;
}
if let Some(b'e') | Some(b'E') = buffer.get(i) {
e_index = i;
i += 1;
match buffer.get(i) {
Some(b'-') => {
signed_e = true;
i += 1;
}
Some(b'+') => i += 1,
_ => {}
}
while let Some(c) = buffer.get(i).copied() {
if c < b'0' || c > b'9' {
return Err(Error::MalformedInput);
}
if e10digits > 3 {
// TODO: Be more lenient. Return +/-Infinity or +/-0 instead.
return Err(Error::InputTooLong);
}
e10 = 10 * e10 + (c - b'0') as i32;
if e10 != 0 {
e10digits += 1;
}
i += 1;
}
}
if i < len {
return Err(Error::MalformedInput);
}
if signed_e {
e10 = -e10;
}
e10 -= if dot_index < e_index {
(e_index - dot_index - 1) as i32
} else {
0
};
if m10 == 0 {
return Ok(if signed_m { -0.0 } else { 0.0 });
}
if m10digits + e10 <= -324 || m10 == 0 {
// Number is less than 1e-324, which should be rounded down to 0; return
// +/-0.0.
let ieee = (signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS);
return Ok(f64::from_bits(ieee));
}
if m10digits + e10 >= 310 {
// Number is larger than 1e+309, which should be rounded to +/-Infinity.
let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
| (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
return Ok(f64::from_bits(ieee));
}
// Convert to binary float m2 * 2^e2, while retaining information about
// whether the conversion was exact (trailing_zeros).
let e2: i32;
let m2: u64;
let mut trailing_zeros: bool;
if e10 >= 0 {
// The length of m * 10^e in bits is:
// log2(m10 * 10^e10) = log2(m10) + e10 log2(10) = log2(m10) + e10 + e10 * log2(5)
//
// We want to compute the DOUBLE_MANTISSA_BITS + 1 top-most bits (+1 for
// the implicit leading one in IEEE format). We therefore choose a
// binary output exponent of
// log2(m10 * 10^e10) - (DOUBLE_MANTISSA_BITS + 1).
//
// We use floor(log2(5^e10)) so that we get at least this many bits;
// better to have an additional bit than to not have enough bits.
e2 = floor_log2(m10)
.wrapping_add(e10 as u32)
.wrapping_add(log2_pow5(e10) as u32)
.wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;
// We now compute [m10 * 10^e10 / 2^e2] = [m10 * 5^e10 / 2^(e2-e10)].
// To that end, we use the DOUBLE_POW5_SPLIT table.
let j = e2
.wrapping_sub(e10)
.wrapping_sub(ceil_log2_pow5(e10))
.wrapping_add(d2s::DOUBLE_POW5_BITCOUNT);
debug_assert!(j >= 0);
debug_assert!(e10 < d2s::DOUBLE_POW5_SPLIT.len() as i32);
m2 = mul_shift_64(
m10,
unsafe { d2s::DOUBLE_POW5_SPLIT.get_unchecked(e10 as usize) },
j as u32,
);
// We also compute if the result is exact, i.e.,
// [m10 * 10^e10 / 2^e2] == m10 * 10^e10 / 2^e2.
// This can only be the case if 2^e2 divides m10 * 10^e10, which in turn
// requires that the largest power of 2 that divides m10 + e10 is
// greater than e2. If e2 is less than e10, then the result must be
// exact. Otherwise we use the existing multiple_of_power_of_2 function.
trailing_zeros =
e2 < e10 || e2 - e10 < 64 && multiple_of_power_of_2(m10, (e2 - e10) as u32);
} else {
e2 = floor_log2(m10)
.wrapping_add(e10 as u32)
.wrapping_sub(ceil_log2_pow5(-e10) as u32)
.wrapping_sub(d2s::DOUBLE_MANTISSA_BITS + 1) as i32;
let j = e2
.wrapping_sub(e10)
.wrapping_add(ceil_log2_pow5(-e10))
.wrapping_sub(1)
.wrapping_add(d2s::DOUBLE_POW5_INV_BITCOUNT);
debug_assert!(-e10 < d2s::DOUBLE_POW5_INV_SPLIT.len() as i32);
m2 = mul_shift_64(
m10,
unsafe { d2s::DOUBLE_POW5_INV_SPLIT.get_unchecked(-e10 as usize) },
j as u32,
);
trailing_zeros = multiple_of_power_of_5(m10, -e10 as u32);
}
// Compute the final IEEE exponent.
let mut ieee_e2 = i32::max(0, e2 + DOUBLE_EXPONENT_BIAS as i32 + floor_log2(m2) as i32) as u32;
if ieee_e2 > 0x7fe {
// Final IEEE exponent is larger than the maximum representable; return +/-Infinity.
let ieee = ((signed_m as u64) << (d2s::DOUBLE_EXPONENT_BITS + d2s::DOUBLE_MANTISSA_BITS))
| (0x7ff_u64 << d2s::DOUBLE_MANTISSA_BITS);
return Ok(f64::from_bits(ieee));
}
// We need to figure out how much we need to shift m2. The tricky part is
// that we need to take the final IEEE exponent into account, so we need to
// reverse the bias and also special-case the value 0.
let shift = if ieee_e2 == 0 { 1 } else { ieee_e2 as i32 }
.wrapping_sub(e2)
.wrapping_sub(DOUBLE_EXPONENT_BIAS as i32)
.wrapping_sub(d2s::DOUBLE_MANTISSA_BITS as i32);
debug_assert!(shift >= 0);
// We need to round up if the exact value is more than 0.5 above the value
// we computed. That's equivalent to checking if the last removed bit was 1
// and either the value was not just trailing zeros or the result would
// otherwise be odd.
//
// We need to update trailing_zeros given that we have the exact output
// exponent ieee_e2 now.
trailing_zeros &= (m2 & ((1_u64 << (shift - 1)) - 1)) == 0;
let last_removed_bit = (m2 >> (shift - 1)) & 1;
let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);
let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u64);
if ieee_m2 == (1_u64 << (d2s::DOUBLE_MANTISSA_BITS + 1)) {
// Due to how the IEEE represents +/-Infinity, we don't need to check
// for overflow here.
ieee_e2 += 1;
}
ieee_m2 &= (1_u64 << d2s::DOUBLE_MANTISSA_BITS) - 1;
let ieee = ((((signed_m as u64) << d2s::DOUBLE_EXPONENT_BITS) | ieee_e2 as u64)
<< d2s::DOUBLE_MANTISSA_BITS)
| ieee_m2;
Ok(f64::from_bits(ieee))
}

207
third_party/rust/ryu/src/s2f.rs vendored Normal file
View File

@ -0,0 +1,207 @@
use crate::common::*;
use crate::f2s;
use crate::f2s_intrinsics::*;
use crate::parse::Error;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
const FLOAT_EXPONENT_BIAS: usize = 127;
fn floor_log2(value: u32) -> u32 {
31_u32.wrapping_sub(value.leading_zeros())
}
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn s2f(buffer: &[u8]) -> Result<f32, Error> {
let len = buffer.len();
if len == 0 {
return Err(Error::InputTooShort);
}
let mut m10digits = 0;
let mut e10digits = 0;
let mut dot_index = len;
let mut e_index = len;
let mut m10 = 0u32;
let mut e10 = 0i32;
let mut signed_m = false;
let mut signed_e = false;
let mut i = 0;
if unsafe { *buffer.get_unchecked(0) } == b'-' {
signed_m = true;
i += 1;
}
while let Some(c) = buffer.get(i).copied() {
if c == b'.' {
if dot_index != len {
return Err(Error::MalformedInput);
}
dot_index = i;
i += 1;
continue;
}
if c < b'0' || c > b'9' {
break;
}
if m10digits >= 9 {
return Err(Error::InputTooLong);
}
m10 = 10 * m10 + (c - b'0') as u32;
if m10 != 0 {
m10digits += 1;
}
i += 1;
}
if let Some(b'e') | Some(b'E') = buffer.get(i) {
e_index = i;
i += 1;
match buffer.get(i) {
Some(b'-') => {
signed_e = true;
i += 1;
}
Some(b'+') => i += 1,
_ => {}
}
while let Some(c) = buffer.get(i).copied() {
if c < b'0' || c > b'9' {
return Err(Error::MalformedInput);
}
if e10digits > 3 {
// TODO: Be more lenient. Return +/-Infinity or +/-0 instead.
return Err(Error::InputTooLong);
}
e10 = 10 * e10 + (c - b'0') as i32;
if e10 != 0 {
e10digits += 1;
}
i += 1;
}
}
if i < len {
return Err(Error::MalformedInput);
}
if signed_e {
e10 = -e10;
}
e10 -= if dot_index < e_index {
(e_index - dot_index - 1) as i32
} else {
0
};
if m10 == 0 {
return Ok(if signed_m { -0.0 } else { 0.0 });
}
if m10digits + e10 <= -46 || m10 == 0 {
// Number is less than 1e-46, which should be rounded down to 0; return
// +/-0.0.
let ieee = (signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS);
return Ok(f32::from_bits(ieee));
}
if m10digits + e10 >= 40 {
// Number is larger than 1e+39, which should be rounded to +/-Infinity.
let ieee = ((signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS))
| (0xff_u32 << f2s::FLOAT_MANTISSA_BITS);
return Ok(f32::from_bits(ieee));
}
// Convert to binary float m2 * 2^e2, while retaining information about
// whether the conversion was exact (trailing_zeros).
let e2: i32;
let m2: u32;
let mut trailing_zeros: bool;
if e10 >= 0 {
// The length of m * 10^e in bits is:
// log2(m10 * 10^e10) = log2(m10) + e10 log2(10) = log2(m10) + e10 + e10 * log2(5)
//
// We want to compute the FLOAT_MANTISSA_BITS + 1 top-most bits (+1 for
// the implicit leading one in IEEE format). We therefore choose a
// binary output exponent of
// log2(m10 * 10^e10) - (FLOAT_MANTISSA_BITS + 1).
//
// We use floor(log2(5^e10)) so that we get at least this many bits; better to
// have an additional bit than to not have enough bits.
e2 = floor_log2(m10)
.wrapping_add(e10 as u32)
.wrapping_add(log2_pow5(e10) as u32)
.wrapping_sub(f2s::FLOAT_MANTISSA_BITS + 1) as i32;
// We now compute [m10 * 10^e10 / 2^e2] = [m10 * 5^e10 / 2^(e2-e10)].
// To that end, we use the FLOAT_POW5_SPLIT table.
let j = e2
.wrapping_sub(e10)
.wrapping_sub(ceil_log2_pow5(e10))
.wrapping_add(f2s::FLOAT_POW5_BITCOUNT);
debug_assert!(j >= 0);
m2 = mul_pow5_div_pow2(m10, e10 as u32, j);
// We also compute if the result is exact, i.e.,
// [m10 * 10^e10 / 2^e2] == m10 * 10^e10 / 2^e2.
// This can only be the case if 2^e2 divides m10 * 10^e10, which in turn
// requires that the largest power of 2 that divides m10 + e10 is
// greater than e2. If e2 is less than e10, then the result must be
// exact. Otherwise we use the existing multiple_of_power_of_2 function.
trailing_zeros =
e2 < e10 || e2 - e10 < 32 && multiple_of_power_of_2_32(m10, (e2 - e10) as u32);
} else {
e2 = floor_log2(m10)
.wrapping_add(e10 as u32)
.wrapping_sub(ceil_log2_pow5(-e10) as u32)
.wrapping_sub(f2s::FLOAT_MANTISSA_BITS + 1) as i32;
let j = e2
.wrapping_sub(e10)
.wrapping_add(ceil_log2_pow5(-e10))
.wrapping_sub(1)
.wrapping_add(f2s::FLOAT_POW5_INV_BITCOUNT);
m2 = mul_pow5_inv_div_pow2(m10, -e10 as u32, j);
trailing_zeros = multiple_of_power_of_5_32(m10, -e10 as u32);
}
// Compute the final IEEE exponent.
let mut ieee_e2 = i32::max(0, e2 + FLOAT_EXPONENT_BIAS as i32 + floor_log2(m2) as i32) as u32;
if ieee_e2 > 0xfe {
// Final IEEE exponent is larger than the maximum representable; return
// +/-Infinity.
let ieee = ((signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS))
| (0xff_u32 << f2s::FLOAT_MANTISSA_BITS);
return Ok(f32::from_bits(ieee));
}
// We need to figure out how much we need to shift m2. The tricky part is
// that we need to take the final IEEE exponent into account, so we need to
// reverse the bias and also special-case the value 0.
let shift = if ieee_e2 == 0 { 1 } else { ieee_e2 as i32 }
.wrapping_sub(e2)
.wrapping_sub(FLOAT_EXPONENT_BIAS as i32)
.wrapping_sub(f2s::FLOAT_MANTISSA_BITS as i32);
debug_assert!(shift >= 0);
// We need to round up if the exact value is more than 0.5 above the value
// we computed. That's equivalent to checking if the last removed bit was 1
// and either the value was not just trailing zeros or the result would
// otherwise be odd.
//
// We need to update trailing_zeros given that we have the exact output
// exponent ieee_e2 now.
trailing_zeros &= (m2 & ((1_u32 << (shift - 1)) - 1)) == 0;
let last_removed_bit = (m2 >> (shift - 1)) & 1;
let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);
let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u32);
if ieee_m2 == (1_u32 << (f2s::FLOAT_MANTISSA_BITS + 1)) {
// Due to how the IEEE represents +/-Infinity, we don't need to check
// for overflow here.
ieee_e2 += 1;
}
ieee_m2 &= (1_u32 << f2s::FLOAT_MANTISSA_BITS) - 1;
let ieee = ((((signed_m as u32) << f2s::FLOAT_EXPONENT_BITS) | ieee_e2 as u32)
<< f2s::FLOAT_MANTISSA_BITS)
| ieee_m2;
Ok(f32::from_bits(ieee))
}

View File

@ -0,0 +1,83 @@
// 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)]
#[path = "../src/common.rs"]
mod common;
use common::*;
#[test]
fn test_decimal_length9() {
assert_eq!(1, decimal_length9(0));
assert_eq!(1, decimal_length9(1));
assert_eq!(1, decimal_length9(9));
assert_eq!(2, decimal_length9(10));
assert_eq!(2, decimal_length9(99));
assert_eq!(3, decimal_length9(100));
assert_eq!(3, decimal_length9(999));
assert_eq!(9, decimal_length9(999999999));
}
#[test]
fn test_ceil_log2_pow5() {
assert_eq!(1, ceil_log2_pow5(0));
assert_eq!(3, ceil_log2_pow5(1));
assert_eq!(5, ceil_log2_pow5(2));
assert_eq!(7, ceil_log2_pow5(3));
assert_eq!(10, ceil_log2_pow5(4));
assert_eq!(8192, ceil_log2_pow5(3528));
}
#[test]
fn test_log10_pow2() {
assert_eq!(0, log10_pow2(0));
assert_eq!(0, log10_pow2(1));
assert_eq!(0, log10_pow2(2));
assert_eq!(0, log10_pow2(3));
assert_eq!(1, log10_pow2(4));
assert_eq!(496, log10_pow2(1650));
}
#[test]
fn test_log10_pow5() {
assert_eq!(0, log10_pow5(0));
assert_eq!(0, log10_pow5(1));
assert_eq!(1, log10_pow5(2));
assert_eq!(2, log10_pow5(3));
assert_eq!(2, log10_pow5(4));
assert_eq!(1831, log10_pow5(2620));
}
#[test]
fn test_float_to_bits() {
assert_eq!(0, 0.0_f32.to_bits());
assert_eq!(0x40490fda, 3.1415926_f32.to_bits());
}
#[test]
fn test_double_to_bits() {
assert_eq!(0, 0.0_f64.to_bits());
assert_eq!(
0x400921FB54442D18,
3.1415926535897932384626433_f64.to_bits(),
);
}

View File

@ -20,8 +20,6 @@
#![allow(dead_code)]
extern crate core;
#[path = "../src/common.rs"]
mod common;
@ -46,7 +44,7 @@ fn test_compute_pow5() {
#[test]
fn test_compute_inv_pow5() {
for (i, entry) in DOUBLE_POW5_INV_SPLIT.iter().enumerate() {
for (i, entry) in DOUBLE_POW5_INV_SPLIT[..292].iter().enumerate() {
assert_eq!(*entry, unsafe { compute_inv_pow5(i as u32) }, "entry {}", i);
}
}

View File

@ -18,9 +18,6 @@
// 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;
@ -51,14 +48,16 @@ fn test_ryu() {
#[test]
fn test_random() {
let n = if cfg!(miri) { 100 } else { 1000000 };
let mut buffer = ryu::Buffer::new();
for _ in 0..1000000 {
for _ in 0..n {
let f: f64 = rand::random();
assert_eq!(f, buffer.format_finite(f).parse().unwrap());
}
}
#[test]
#[cfg_attr(miri, ignore)]
fn test_non_finite() {
for i in 0u64..1 << 23 {
let f = f64::from_bits((((1 << 11) - 1) << 52) + (i << 29));
@ -112,7 +111,7 @@ fn test_regression() {
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.
// in 22, which is a corner case for Ryū.
assert_eq!(f64::from_bits(0x4830F0CF064DD592), 5.764607523034235e39);
check!(5.764607523034235e39);
assert_eq!(f64::from_bits(0x4840F0CF064DD592), 1.152921504606847e40);

View File

@ -1,8 +1,5 @@
#![cfg(exhaustive)]
extern crate num_cpus;
extern crate ryu;
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

View File

@ -18,9 +18,6 @@
// 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;
@ -46,14 +43,16 @@ fn test_ryu() {
#[test]
fn test_random() {
let n = if cfg!(miri) { 100 } else { 1000000 };
let mut buffer = ryu::Buffer::new();
for _ in 0..1000000 {
for _ in 0..n {
let f: f32 = rand::random();
assert_eq!(f, buffer.format_finite(f).parse().unwrap());
}
}
#[test]
#[cfg_attr(miri, ignore)]
fn test_non_finite() {
for i in 0u32..1 << 23 {
let f = f32::from_bits((((1 << 8) - 1) << 23) + i);
@ -150,7 +149,7 @@ fn test_regression() {
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.
// is a corner case for Ryū.
assert_eq!(f32::from_bits(0x5D1502F9), 6.7108864e17);
check!(6.7108864e17);
assert_eq!(f32::from_bits(0x5D9502F9), 1.3421773e18);

130
third_party/rust/ryu/tests/s2d_test.rs vendored Normal file
View File

@ -0,0 +1,130 @@
// 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(not(feature = "small"))]
#![allow(dead_code)]
#[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.rs"]
mod d2s;
#[path = "../src/s2d.rs"]
mod s2d;
#[path = "../src/parse.rs"]
mod parse;
use crate::parse::Error;
use crate::s2d::s2d;
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
*self as u8 == *other as u8
}
}
#[test]
fn test_bad_input() {
assert_eq!(Error::MalformedInput, s2d(b"x").unwrap_err());
assert_eq!(Error::MalformedInput, s2d(b"1..1").unwrap_err());
assert_eq!(Error::MalformedInput, s2d(b"..").unwrap_err());
assert_eq!(Error::MalformedInput, s2d(b"1..1").unwrap_err());
assert_eq!(Error::MalformedInput, s2d(b"1ee1").unwrap_err());
assert_eq!(Error::MalformedInput, s2d(b"1e.1").unwrap_err());
assert_eq!(Error::InputTooShort, s2d(b"").unwrap_err());
assert_eq!(Error::InputTooLong, s2d(b"123456789012345678").unwrap_err());
assert_eq!(Error::InputTooLong, s2d(b"1e12345").unwrap_err());
}
#[test]
fn test_basic() {
assert_eq!(0.0, s2d(b"0").unwrap());
assert_eq!(-0.0, s2d(b"-0").unwrap());
assert_eq!(1.0, s2d(b"1").unwrap());
assert_eq!(2.0, s2d(b"2").unwrap());
assert_eq!(123456789.0, s2d(b"123456789").unwrap());
assert_eq!(123.456, s2d(b"123.456").unwrap());
assert_eq!(123.456, s2d(b"123456e-3").unwrap());
assert_eq!(123.456, s2d(b"1234.56e-1").unwrap());
assert_eq!(1.453, s2d(b"1.453").unwrap());
assert_eq!(1453.0, s2d(b"1.453e+3").unwrap());
assert_eq!(0.0, s2d(b".0").unwrap());
assert_eq!(1.0, s2d(b"1e0").unwrap());
assert_eq!(1.0, s2d(b"1E0").unwrap());
assert_eq!(1.0, s2d(b"000001.000000").unwrap());
}
#[test]
fn test_min_max() {
assert_eq!(
1.7976931348623157e308,
s2d(b"1.7976931348623157e308").unwrap(),
);
assert_eq!(5E-324, s2d(b"5E-324").unwrap());
}
#[test]
fn test_mantissa_rounding_overflow() {
// This results in binary mantissa that is all ones and requires rounding up
// because it is closer to 1 than to the next smaller float. This is a
// regression test that the mantissa overflow is handled correctly by
// increasing the exponent.
assert_eq!(1.0, s2d(b"0.99999999999999999").unwrap());
// This number overflows the mantissa *and* the IEEE exponent.
assert_eq!(f64::INFINITY, s2d(b"1.7976931348623159e308").unwrap());
}
#[test]
fn test_underflow() {
assert_eq!(0.0, s2d(b"2.4e-324").unwrap());
assert_eq!(0.0, s2d(b"1e-324").unwrap());
assert_eq!(0.0, s2d(b"9.99999e-325").unwrap());
// These are just about halfway between 0 and the smallest float.
// The first is just below the halfway point, the second just above.
assert_eq!(0.0, s2d(b"2.4703282292062327e-324").unwrap());
assert_eq!(5e-324, s2d(b"2.4703282292062328e-324").unwrap());
}
#[test]
fn test_overflow() {
assert_eq!(f64::INFINITY, s2d(b"2e308").unwrap());
assert_eq!(f64::INFINITY, s2d(b"1e309").unwrap());
}
#[test]
fn test_table_size_denormal() {
assert_eq!(5e-324, s2d(b"4.9406564584124654e-324").unwrap());
}
#[test]
fn test_issue157() {
assert_eq!(
1.2999999999999999E+154,
s2d(b"1.2999999999999999E+154").unwrap(),
);
}

77
third_party/rust/ryu/tests/s2f_test.rs vendored Normal file
View File

@ -0,0 +1,77 @@
// 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)]
#[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.rs"]
mod d2s;
#[path = "../src/f2s_intrinsics.rs"]
mod f2s_intrinsics;
#[path = "../src/f2s.rs"]
mod f2s;
#[path = "../src/s2f.rs"]
mod s2f;
#[path = "../src/parse.rs"]
mod parse;
use crate::parse::Error;
use crate::s2f::s2f;
impl PartialEq for Error {
fn eq(&self, other: &Self) -> bool {
*self as u8 == *other as u8
}
}
#[test]
fn test_basic() {
assert_eq!(0.0, s2f(b"0").unwrap());
assert_eq!(-0.0, s2f(b"-0").unwrap());
assert_eq!(1.0, s2f(b"1").unwrap());
assert_eq!(-1.0, s2f(b"-1").unwrap());
assert_eq!(123456792.0, s2f(b"123456789").unwrap());
assert_eq!(299792448.0, s2f(b"299792458").unwrap());
}
#[test]
fn test_min_max() {
assert_eq!(1e-45, s2f(b"1e-45").unwrap());
assert_eq!(f32::MIN_POSITIVE, s2f(b"1.1754944e-38").unwrap());
assert_eq!(f32::MAX, s2f(b"3.4028235e+38").unwrap());
}
#[test]
fn test_mantissa_rounding_overflow() {
assert_eq!(1.0, s2f(b"0.999999999").unwrap());
assert_eq!(f32::INFINITY, s2f(b"3.4028236e+38").unwrap());
}