seamonkey/TOP-NOBUG-revendor-253172.patch

9388 lines
348 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HG changeset patch
# User Frank-Rainer Grahl <frgrahl@gmx.net>
# Date 1694901743 -7200
# Parent b5cbf8136d77cde697224f8bfecac2e03f751f1a
No Bug - Revendor rust dependencies. r=me a=me
diff --git a/Cargo.lock b/Cargo.lock
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -102,16 +102,22 @@ dependencies = [
"libc",
"log 0.3.9",
"slab",
"tokio-core",
"tokio-uds",
]
[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
name = "base64"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "979d348dc50dfcd050a87df408ec61f01a0a27ee9b4ebdc6085baba8275b2c7f"
dependencies = [
"byteorder",
]
@@ -1033,31 +1039,31 @@ dependencies = [
[[package]]
name = "mp4parse"
version = "0.10.1"
dependencies = [
"bitreader",
"byteorder",
"log 0.4.1",
"mp4parse_fallible",
- "num-traits 0.2.0",
+ "num-traits 0.2.15",
]
[[package]]
name = "mp4parse-gtest"
version = "0.1.0"
[[package]]
name = "mp4parse_capi"
version = "0.10.1"
dependencies = [
"byteorder",
"log 0.4.1",
"mp4parse",
- "num-traits 0.2.0",
+ "num-traits 0.2.15",
]
[[package]]
name = "mp4parse_fallible"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
@@ -1125,24 +1131,27 @@ dependencies = [
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
- "num-traits 0.2.0",
+ "num-traits 0.2.15",
]
[[package]]
name = "num-traits"
-version = "0.2.0"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
[[package]]
name = "num_cpus"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
dependencies = [
"libc",
@@ -1168,17 +1177,17 @@ dependencies = [
]
[[package]]
name = "packed_simd"
version = "0.3.9"
source = "git+https://github.com/hsivonen/packed_simd?rev=e588ceb568878e1a3156ea9ce551d5b63ef0cdc4#e588ceb568878e1a3156ea9ce551d5b63ef0cdc4"
dependencies = [
"cfg-if 1.0.0",
- "num-traits",
+ "num-traits 0.2.15",
]
[[package]]
name = "parking_lot"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37f364e2ce5efa24c7d0b6646d5bb61145551a0112f107ffd7499f1a3e322fbd"
dependencies = [
diff --git a/third_party/rust/autocfg/.cargo-checksum.json b/third_party/rust/autocfg/.cargo-checksum.json
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.lock":"3d91565ed13de572a9ebde408a0c98e33f931d6ab52f212b0830a60b4ab26b77","Cargo.toml":"39f627122dceaad42146634719fde802fca3baa1b3908753af723074ae2a6d69","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"4c8f9b5016f2a0c3dbeca5bc41241f57db5568f803e58c1fa480ae2b3638d0a9","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"6fa01458e8f9258d84f83ead24fdb0cdf9aec10838b0262f1dfbdf79c530c537","src/tests.rs":"f0e6dc1ad9223c0336c02e215ea3940acb2af6c3bc8fd791e16cd4e786e6a608","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f"},"package":"d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"}
\ No newline at end of file
diff --git a/third_party/rust/autocfg/Cargo.lock b/third_party/rust/autocfg/Cargo.lock
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
diff --git a/third_party/rust/autocfg/Cargo.toml b/third_party/rust/autocfg/Cargo.toml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/Cargo.toml
@@ -0,0 +1,24 @@
+# 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 are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+name = "autocfg"
+version = "1.1.0"
+authors = ["Josh Stone <cuviper@gmail.com>"]
+exclude = ["/.github/**", "/bors.toml"]
+description = "Automatic cfg for Rust compiler features"
+readme = "README.md"
+keywords = ["rustc", "build", "autoconf"]
+categories = ["development-tools::build-utils"]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/cuviper/autocfg"
+
+[dependencies]
diff --git a/third_party/rust/autocfg/LICENSE-APACHE b/third_party/rust/autocfg/LICENSE-APACHE
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/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/autocfg/LICENSE-MIT b/third_party/rust/autocfg/LICENSE-MIT
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 Josh Stone
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+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 AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF 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/autocfg/README.md b/third_party/rust/autocfg/README.md
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/README.md
@@ -0,0 +1,95 @@
+autocfg
+=======
+
+[![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg)
+[![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg)
+![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg)
+![build status](https://github.com/cuviper/autocfg/workflows/master/badge.svg)
+
+A Rust library for build scripts to automatically configure code based on
+compiler support. Code snippets are dynamically tested to see if the `rustc`
+will accept them, rather than hard-coding specific version support.
+
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[build-dependencies]
+autocfg = "1"
+```
+
+Then use it in your `build.rs` script to detect compiler features. For
+example, to test for 128-bit integer support, it might look like:
+
+```rust
+extern crate autocfg;
+
+fn main() {
+ let ac = autocfg::new();
+ ac.emit_has_type("i128");
+
+ // (optional) We don't need to rerun for anything external.
+ autocfg::rerun_path("build.rs");
+}
+```
+
+If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
+for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
+rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
+should only be used when the compiler supports it.
+
+
+## Release Notes
+
+- 1.1.0 (2022-02-07)
+ - Use `CARGO_ENCODED_RUSTFLAGS` when it is set.
+
+- 1.0.1 (2020-08-20)
+ - Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold.
+
+- 1.0.0 (2020-01-08)
+ - 🎉 Release 1.0! 🎉 (no breaking changes)
+ - Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions.
+ - Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions.
+
+- 0.1.7 (2019-10-20)
+ - Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla.
+
+- 0.1.6 (2019-08-19)
+ - Add `probe`/`emit_sysroot_crate`, by @leo60228.
+
+- 0.1.5 (2019-07-16)
+ - Mask some warnings from newer rustc.
+
+- 0.1.4 (2019-05-22)
+ - Relax `std`/`no_std` probing to a warning instead of an error.
+ - Improve `rustc` bootstrap compatibility.
+
+- 0.1.3 (2019-05-21)
+ - Auto-detects if `#![no_std]` is needed for the `$TARGET`.
+
+- 0.1.2 (2019-01-16)
+ - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`.
+ - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`.
+
+
+## Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is
+its entire reason for existence, so this crate will be extremely conservative
+about raising this requirement. If this is ever deemed necessary, it will be
+treated as a major breaking change for semver purposes.
+
+
+## License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+ http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+ http://opensource.org/licenses/MIT)
+
+at your option.
diff --git a/third_party/rust/autocfg/examples/integers.rs b/third_party/rust/autocfg/examples/integers.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/examples/integers.rs
@@ -0,0 +1,9 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+ for i in 3..8 {
+ ac.emit_has_type(&format!("i{}", 1 << i));
+ }
+}
diff --git a/third_party/rust/autocfg/examples/paths.rs b/third_party/rust/autocfg/examples/paths.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/examples/paths.rs
@@ -0,0 +1,22 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+
+ // since ancient times...
+ ac.emit_has_path("std::vec::Vec");
+ ac.emit_path_cfg("std::vec::Vec", "has_vec");
+
+ // rustc 1.10.0
+ ac.emit_has_path("std::panic::PanicInfo");
+ ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");
+
+ // rustc 1.20.0
+ ac.emit_has_path("std::mem::ManuallyDrop");
+ ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");
+
+ // rustc 1.25.0
+ ac.emit_has_path("std::ptr::NonNull");
+ ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
+}
diff --git a/third_party/rust/autocfg/examples/traits.rs b/third_party/rust/autocfg/examples/traits.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/examples/traits.rs
@@ -0,0 +1,26 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+
+ // since ancient times...
+ ac.emit_has_trait("std::ops::Add");
+ ac.emit_trait_cfg("std::ops::Add", "has_ops");
+
+ // trait parameters have to be provided
+ ac.emit_has_trait("std::borrow::Borrow<str>");
+ ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");
+
+ // rustc 1.8.0
+ ac.emit_has_trait("std::ops::AddAssign");
+ ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");
+
+ // rustc 1.12.0
+ ac.emit_has_trait("std::iter::Sum");
+ ac.emit_trait_cfg("std::iter::Sum", "has_sum");
+
+ // rustc 1.28.0
+ ac.emit_has_trait("std::alloc::GlobalAlloc");
+ ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
+}
diff --git a/third_party/rust/autocfg/examples/versions.rs b/third_party/rust/autocfg/examples/versions.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/examples/versions.rs
@@ -0,0 +1,9 @@
+extern crate autocfg;
+
+fn main() {
+ // Normally, cargo will set `OUT_DIR` for build scripts.
+ let ac = autocfg::AutoCfg::with_dir("target").unwrap();
+ for i in 0..100 {
+ ac.emit_rustc_version(1, i);
+ }
+}
diff --git a/third_party/rust/autocfg/src/error.rs b/third_party/rust/autocfg/src/error.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/src/error.rs
@@ -0,0 +1,69 @@
+use std::error;
+use std::fmt;
+use std::io;
+use std::num;
+use std::str;
+
+/// A common error type for the `autocfg` crate.
+#[derive(Debug)]
+pub struct Error {
+ kind: ErrorKind,
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ "AutoCfg error"
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ match self.kind {
+ ErrorKind::Io(ref e) => Some(e),
+ ErrorKind::Num(ref e) => Some(e),
+ ErrorKind::Utf8(ref e) => Some(e),
+ ErrorKind::Other(_) => None,
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ match self.kind {
+ ErrorKind::Io(ref e) => e.fmt(f),
+ ErrorKind::Num(ref e) => e.fmt(f),
+ ErrorKind::Utf8(ref e) => e.fmt(f),
+ ErrorKind::Other(s) => s.fmt(f),
+ }
+ }
+}
+
+#[derive(Debug)]
+enum ErrorKind {
+ Io(io::Error),
+ Num(num::ParseIntError),
+ Utf8(str::Utf8Error),
+ Other(&'static str),
+}
+
+pub fn from_io(e: io::Error) -> Error {
+ Error {
+ kind: ErrorKind::Io(e),
+ }
+}
+
+pub fn from_num(e: num::ParseIntError) -> Error {
+ Error {
+ kind: ErrorKind::Num(e),
+ }
+}
+
+pub fn from_utf8(e: str::Utf8Error) -> Error {
+ Error {
+ kind: ErrorKind::Utf8(e),
+ }
+}
+
+pub fn from_str(s: &'static str) -> Error {
+ Error {
+ kind: ErrorKind::Other(s),
+ }
+}
diff --git a/third_party/rust/autocfg/src/lib.rs b/third_party/rust/autocfg/src/lib.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/src/lib.rs
@@ -0,0 +1,453 @@
+//! A Rust library for build scripts to automatically configure code based on
+//! compiler support. Code snippets are dynamically tested to see if the `rustc`
+//! will accept them, rather than hard-coding specific version support.
+//!
+//!
+//! ## Usage
+//!
+//! Add this to your `Cargo.toml`:
+//!
+//! ```toml
+//! [build-dependencies]
+//! autocfg = "1"
+//! ```
+//!
+//! Then use it in your `build.rs` script to detect compiler features. For
+//! example, to test for 128-bit integer support, it might look like:
+//!
+//! ```rust
+//! extern crate autocfg;
+//!
+//! fn main() {
+//! # // Normally, cargo will set `OUT_DIR` for build scripts.
+//! # std::env::set_var("OUT_DIR", "target");
+//! let ac = autocfg::new();
+//! ac.emit_has_type("i128");
+//!
+//! // (optional) We don't need to rerun for anything external.
+//! autocfg::rerun_path("build.rs");
+//! }
+//! ```
+//!
+//! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
+//! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the
+//! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
+//! should only be used when the compiler supports it.
+//!
+//! ## Caution
+//!
+//! Many of the probing methods of `AutoCfg` document the particular template they
+//! use, **subject to change**. The inputs are not validated to make sure they are
+//! semantically correct for their expected use, so it's _possible_ to escape and
+//! inject something unintended. However, such abuse is unsupported and will not
+//! be considered when making changes to the templates.
+
+#![deny(missing_debug_implementations)]
+#![deny(missing_docs)]
+// allow future warnings that can't be fixed while keeping 1.0 compatibility
+#![allow(unknown_lints)]
+#![allow(bare_trait_objects)]
+#![allow(ellipsis_inclusive_range_patterns)]
+
+/// Local macro to avoid `std::try!`, deprecated in Rust 1.39.
+macro_rules! try {
+ ($result:expr) => {
+ match $result {
+ Ok(value) => value,
+ Err(error) => return Err(error),
+ }
+ };
+}
+
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{stderr, Write};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+#[allow(deprecated)]
+use std::sync::atomic::ATOMIC_USIZE_INIT;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+mod error;
+pub use error::Error;
+
+mod version;
+use version::Version;
+
+#[cfg(test)]
+mod tests;
+
+/// Helper to detect compiler features for `cfg` output in build scripts.
+#[derive(Clone, Debug)]
+pub struct AutoCfg {
+ out_dir: PathBuf,
+ rustc: PathBuf,
+ rustc_version: Version,
+ target: Option<OsString>,
+ no_std: bool,
+ rustflags: Vec<String>,
+}
+
+/// Writes a config flag for rustc on standard out.
+///
+/// This looks like: `cargo:rustc-cfg=CFG`
+///
+/// Cargo will use this in arguments to rustc, like `--cfg CFG`.
+pub fn emit(cfg: &str) {
+ println!("cargo:rustc-cfg={}", cfg);
+}
+
+/// Writes a line telling Cargo to rerun the build script if `path` changes.
+///
+/// This looks like: `cargo:rerun-if-changed=PATH`
+///
+/// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier
+/// versions of cargo will simply ignore the directive.
+pub fn rerun_path(path: &str) {
+ println!("cargo:rerun-if-changed={}", path);
+}
+
+/// Writes a line telling Cargo to rerun the build script if the environment
+/// variable `var` changes.
+///
+/// This looks like: `cargo:rerun-if-env-changed=VAR`
+///
+/// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier
+/// versions of cargo will simply ignore the directive.
+pub fn rerun_env(var: &str) {
+ println!("cargo:rerun-if-env-changed={}", var);
+}
+
+/// Create a new `AutoCfg` instance.
+///
+/// # Panics
+///
+/// Panics if `AutoCfg::new()` returns an error.
+pub fn new() -> AutoCfg {
+ AutoCfg::new().unwrap()
+}
+
+impl AutoCfg {
+ /// Create a new `AutoCfg` instance.
+ ///
+ /// # Common errors
+ ///
+ /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
+ /// - The version output from `rustc` can't be parsed.
+ /// - `OUT_DIR` is not set in the environment, or is not a writable directory.
+ ///
+ pub fn new() -> Result<Self, Error> {
+ match env::var_os("OUT_DIR") {
+ Some(d) => Self::with_dir(d),
+ None => Err(error::from_str("no OUT_DIR specified!")),
+ }
+ }
+
+ /// Create a new `AutoCfg` instance with the specified output directory.
+ ///
+ /// # Common errors
+ ///
+ /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
+ /// - The version output from `rustc` can't be parsed.
+ /// - `dir` is not a writable directory.
+ ///
+ pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error> {
+ let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
+ let rustc: PathBuf = rustc.into();
+ let rustc_version = try!(Version::from_rustc(&rustc));
+
+ let target = env::var_os("TARGET");
+
+ // Sanity check the output directory
+ let dir = dir.into();
+ let meta = try!(fs::metadata(&dir).map_err(error::from_io));
+ if !meta.is_dir() || meta.permissions().readonly() {
+ return Err(error::from_str("output path is not a writable directory"));
+ }
+
+ let mut ac = AutoCfg {
+ rustflags: rustflags(&target, &dir),
+ out_dir: dir,
+ rustc: rustc,
+ rustc_version: rustc_version,
+ target: target,
+ no_std: false,
+ };
+
+ // Sanity check with and without `std`.
+ if !ac.probe("").unwrap_or(false) {
+ ac.no_std = true;
+ if !ac.probe("").unwrap_or(false) {
+ // Neither worked, so assume nothing...
+ ac.no_std = false;
+ let warning = b"warning: autocfg could not probe for `std`\n";
+ stderr().write_all(warning).ok();
+ }
+ }
+ Ok(ac)
+ }
+
+ /// Test whether the current `rustc` reports a version greater than
+ /// or equal to "`major`.`minor`".
+ pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
+ self.rustc_version >= Version::new(major, minor, 0)
+ }
+
+ /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`,
+ /// if the current `rustc` is at least that version.
+ pub fn emit_rustc_version(&self, major: usize, minor: usize) {
+ if self.probe_rustc_version(major, minor) {
+ emit(&format!("rustc_{}_{}", major, minor));
+ }
+ }
+
+ fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
+ #[allow(deprecated)]
+ static ID: AtomicUsize = ATOMIC_USIZE_INIT;
+
+ let id = ID.fetch_add(1, Ordering::Relaxed);
+ let mut command = Command::new(&self.rustc);
+ command
+ .arg("--crate-name")
+ .arg(format!("probe{}", id))
+ .arg("--crate-type=lib")
+ .arg("--out-dir")
+ .arg(&self.out_dir)
+ .arg("--emit=llvm-ir");
+
+ if let Some(target) = self.target.as_ref() {
+ command.arg("--target").arg(target);
+ }
+
+ command.args(&self.rustflags);
+
+ command.arg("-").stdin(Stdio::piped());
+ let mut child = try!(command.spawn().map_err(error::from_io));
+ let mut stdin = child.stdin.take().expect("rustc stdin");
+
+ if self.no_std {
+ try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
+ }
+ try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
+ drop(stdin);
+
+ let status = try!(child.wait().map_err(error::from_io));
+ Ok(status.success())
+ }
+
+ /// Tests whether the given sysroot crate can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// extern crate CRATE as probe;
+ /// ```
+ pub fn probe_sysroot_crate(&self, name: &str) -> bool {
+ self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true.
+ pub fn emit_sysroot_crate(&self, name: &str) {
+ if self.probe_sysroot_crate(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Tests whether the given path can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub use PATH;
+ /// ```
+ pub fn probe_path(&self, path: &str) -> bool {
+ self.probe(format!("pub use {};", path)).unwrap_or(false)
+ }
+
+ /// Emits a config value `has_PATH` if `probe_path` returns true.
+ ///
+ /// Any non-identifier characters in the `path` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_path(&self, path: &str) {
+ if self.probe_path(path) {
+ emit(&format!("has_{}", mangle(path)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_path` returns true.
+ pub fn emit_path_cfg(&self, path: &str, cfg: &str) {
+ if self.probe_path(path) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given trait can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub trait Probe: TRAIT + Sized {}
+ /// ```
+ pub fn probe_trait(&self, name: &str) -> bool {
+ self.probe(format!("pub trait Probe: {} + Sized {{}}", name))
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_TRAIT` if `probe_trait` returns true.
+ ///
+ /// Any non-identifier characters in the trait `name` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_trait(&self, name: &str) {
+ if self.probe_trait(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_trait` returns true.
+ pub fn emit_trait_cfg(&self, name: &str, cfg: &str) {
+ if self.probe_trait(name) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given type can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub type Probe = TYPE;
+ /// ```
+ pub fn probe_type(&self, name: &str) -> bool {
+ self.probe(format!("pub type Probe = {};", name))
+ .unwrap_or(false)
+ }
+
+ /// Emits a config value `has_TYPE` if `probe_type` returns true.
+ ///
+ /// Any non-identifier characters in the type `name` will be replaced with
+ /// `_` in the generated config value.
+ pub fn emit_has_type(&self, name: &str) {
+ if self.probe_type(name) {
+ emit(&format!("has_{}", mangle(name)));
+ }
+ }
+
+ /// Emits the given `cfg` value if `probe_type` returns true.
+ pub fn emit_type_cfg(&self, name: &str, cfg: &str) {
+ if self.probe_type(name) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given expression can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub fn probe() { let _ = EXPR; }
+ /// ```
+ pub fn probe_expression(&self, expr: &str) -> bool {
+ self.probe(format!("pub fn probe() {{ let _ = {}; }}", expr))
+ .unwrap_or(false)
+ }
+
+ /// Emits the given `cfg` value if `probe_expression` returns true.
+ pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) {
+ if self.probe_expression(expr) {
+ emit(cfg);
+ }
+ }
+
+ /// Tests whether the given constant expression can be used.
+ ///
+ /// The test code is subject to change, but currently looks like:
+ ///
+ /// ```ignore
+ /// pub const PROBE: () = ((), EXPR).0;
+ /// ```
+ pub fn probe_constant(&self, expr: &str) -> bool {
+ self.probe(format!("pub const PROBE: () = ((), {}).0;", expr))
+ .unwrap_or(false)
+ }
+
+ /// Emits the given `cfg` value if `probe_constant` returns true.
+ pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) {
+ if self.probe_constant(expr) {
+ emit(cfg);
+ }
+ }
+}
+
+fn mangle(s: &str) -> String {
+ s.chars()
+ .map(|c| match c {
+ 'A'...'Z' | 'a'...'z' | '0'...'9' => c,
+ _ => '_',
+ })
+ .collect()
+}
+
+fn dir_contains_target(
+ target: &Option<OsString>,
+ dir: &Path,
+ cargo_target_dir: Option<OsString>,
+) -> bool {
+ target
+ .as_ref()
+ .and_then(|target| {
+ dir.to_str().and_then(|dir| {
+ let mut cargo_target_dir = cargo_target_dir
+ .map(PathBuf::from)
+ .unwrap_or_else(|| PathBuf::from("target"));
+ cargo_target_dir.push(target);
+
+ cargo_target_dir
+ .to_str()
+ .map(|cargo_target_dir| dir.contains(&cargo_target_dir))
+ })
+ })
+ .unwrap_or(false)
+}
+
+fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {
+ // Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets
+ // CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This
+ // includes any source of flags, whether from the environment, toml config, or
+ // whatever may come in the future. The value is either an empty string, or a
+ // list of arguments separated by the ASCII unit separator (US), 0x1f.
+ if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") {
+ return if a.is_empty() {
+ Vec::new()
+ } else {
+ a.split('\x1f').map(str::to_string).collect()
+ };
+ }
+
+ // Otherwise, we have to take a more heuristic approach, and we don't
+ // support values from toml config at all.
+ //
+ // Cargo only applies RUSTFLAGS for building TARGET artifact in
+ // cross-compilation environment. Sadly, we don't have a way to detect
+ // when we're building HOST artifact in a cross-compilation environment,
+ // so for now we only apply RUSTFLAGS when cross-compiling an artifact.
+ //
+ // See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030.
+ if *target != env::var_os("HOST")
+ || dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR"))
+ {
+ if let Ok(rustflags) = env::var("RUSTFLAGS") {
+ // This is meant to match how cargo handles the RUSTFLAGS environment variable.
+ // See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441
+ return rustflags
+ .split(' ')
+ .map(str::trim)
+ .filter(|s| !s.is_empty())
+ .map(str::to_string)
+ .collect();
+ }
+ }
+
+ Vec::new()
+}
diff --git a/third_party/rust/autocfg/src/tests.rs b/third_party/rust/autocfg/src/tests.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/src/tests.rs
@@ -0,0 +1,174 @@
+use super::AutoCfg;
+use std::env;
+use std::path::Path;
+
+impl AutoCfg {
+ fn core_std(&self, path: &str) -> String {
+ let krate = if self.no_std { "core" } else { "std" };
+ format!("{}::{}", krate, path)
+ }
+
+ fn assert_std(&self, probe_result: bool) {
+ assert_eq!(!self.no_std, probe_result);
+ }
+
+ fn assert_min(&self, major: usize, minor: usize, probe_result: bool) {
+ assert_eq!(self.probe_rustc_version(major, minor), probe_result);
+ }
+
+ fn for_test() -> Result<Self, super::error::Error> {
+ match env::var_os("TESTS_TARGET_DIR") {
+ Some(d) => Self::with_dir(d),
+ None => Self::with_dir("target"),
+ }
+ }
+}
+
+#[test]
+fn autocfg_version() {
+ let ac = AutoCfg::for_test().unwrap();
+ println!("version: {:?}", ac.rustc_version);
+ assert!(ac.probe_rustc_version(1, 0));
+}
+
+#[test]
+fn version_cmp() {
+ use super::version::Version;
+ let v123 = Version::new(1, 2, 3);
+
+ assert!(Version::new(1, 0, 0) < v123);
+ assert!(Version::new(1, 2, 2) < v123);
+ assert!(Version::new(1, 2, 3) == v123);
+ assert!(Version::new(1, 2, 4) > v123);
+ assert!(Version::new(1, 10, 0) > v123);
+ assert!(Version::new(2, 0, 0) > v123);
+}
+
+#[test]
+fn probe_add() {
+ let ac = AutoCfg::for_test().unwrap();
+ let add = ac.core_std("ops::Add");
+ let add_rhs = add.clone() + "<i32>";
+ let add_rhs_output = add.clone() + "<i32, Output = i32>";
+ let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output;
+ assert!(ac.probe_path(&add));
+ assert!(ac.probe_trait(&add));
+ assert!(ac.probe_trait(&add_rhs));
+ assert!(ac.probe_trait(&add_rhs_output));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_add_rhs_output));
+}
+
+#[test]
+fn probe_as_ref() {
+ let ac = AutoCfg::for_test().unwrap();
+ let as_ref = ac.core_std("convert::AsRef");
+ let as_ref_str = as_ref.clone() + "<str>";
+ let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str;
+ assert!(ac.probe_path(&as_ref));
+ assert!(ac.probe_trait(&as_ref_str));
+ assert!(ac.probe_type(&as_ref_str));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_as_ref_str));
+}
+
+#[test]
+fn probe_i128() {
+ let ac = AutoCfg::for_test().unwrap();
+ let i128_path = ac.core_std("i128");
+ ac.assert_min(1, 26, ac.probe_path(&i128_path));
+ ac.assert_min(1, 26, ac.probe_type("i128"));
+}
+
+#[test]
+fn probe_sum() {
+ let ac = AutoCfg::for_test().unwrap();
+ let sum = ac.core_std("iter::Sum");
+ let sum_i32 = sum.clone() + "<i32>";
+ let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32;
+ ac.assert_min(1, 12, ac.probe_path(&sum));
+ ac.assert_min(1, 12, ac.probe_trait(&sum));
+ ac.assert_min(1, 12, ac.probe_trait(&sum_i32));
+ ac.assert_min(1, 12, ac.probe_type(&sum_i32));
+ ac.assert_min(1, 27, ac.probe_type(&dyn_sum_i32));
+}
+
+#[test]
+fn probe_std() {
+ let ac = AutoCfg::for_test().unwrap();
+ ac.assert_std(ac.probe_sysroot_crate("std"));
+}
+
+#[test]
+fn probe_alloc() {
+ let ac = AutoCfg::for_test().unwrap();
+ ac.assert_min(1, 36, ac.probe_sysroot_crate("alloc"));
+}
+
+#[test]
+fn probe_bad_sysroot_crate() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(!ac.probe_sysroot_crate("doesnt_exist"));
+}
+
+#[test]
+fn probe_no_std() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_type("i32"));
+ assert!(ac.probe_type("[i32]"));
+ ac.assert_std(ac.probe_type("Vec<i32>"));
+}
+
+#[test]
+fn probe_expression() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_expression(r#""test".trim_left()"#));
+ ac.assert_min(1, 30, ac.probe_expression(r#""test".trim_start()"#));
+ ac.assert_std(ac.probe_expression("[1, 2, 3].to_vec()"));
+}
+
+#[test]
+fn probe_constant() {
+ let ac = AutoCfg::for_test().unwrap();
+ assert!(ac.probe_constant("1 + 2 + 3"));
+ ac.assert_min(1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"));
+ ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#));
+}
+
+#[test]
+fn dir_does_not_contain_target() {
+ assert!(!super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new("/project/target/debug/build/project-ea75983148559682/out"),
+ None,
+ ));
+}
+
+#[test]
+fn dir_does_contain_target() {
+ assert!(super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new(
+ "/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
+ ),
+ None,
+ ));
+}
+
+#[test]
+fn dir_does_not_contain_target_with_custom_target_dir() {
+ assert!(!super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new("/project/custom/debug/build/project-ea75983148559682/out"),
+ Some("custom".into()),
+ ));
+}
+
+#[test]
+fn dir_does_contain_target_with_custom_target_dir() {
+ assert!(super::dir_contains_target(
+ &Some("x86_64-unknown-linux-gnu".into()),
+ Path::new(
+ "/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
+ ),
+ Some("custom".into()),
+ ));
+}
diff --git a/third_party/rust/autocfg/src/version.rs b/third_party/rust/autocfg/src/version.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/src/version.rs
@@ -0,0 +1,60 @@
+use std::path::Path;
+use std::process::Command;
+use std::str;
+
+use super::{error, Error};
+
+/// A version structure for making relative comparisons.
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Version {
+ major: usize,
+ minor: usize,
+ patch: usize,
+}
+
+impl Version {
+ /// Creates a `Version` instance for a specific `major.minor.patch` version.
+ pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+ Version {
+ major: major,
+ minor: minor,
+ patch: patch,
+ }
+ }
+
+ pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
+ // Get rustc's verbose version
+ let output = try!(Command::new(rustc)
+ .args(&["--version", "--verbose"])
+ .output()
+ .map_err(error::from_io));
+ if !output.status.success() {
+ return Err(error::from_str("could not execute rustc"));
+ }
+ let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
+
+ // Find the release line in the verbose version output.
+ let release = match output.lines().find(|line| line.starts_with("release: ")) {
+ Some(line) => &line["release: ".len()..],
+ None => return Err(error::from_str("could not find rustc release")),
+ };
+
+ // Strip off any extra channel info, e.g. "-beta.N", "-nightly"
+ let version = match release.find('-') {
+ Some(i) => &release[..i],
+ None => release,
+ };
+
+ // Split the version into semver components.
+ let mut iter = version.splitn(3, '.');
+ let major = try!(iter.next().ok_or(error::from_str("missing major version")));
+ let minor = try!(iter.next().ok_or(error::from_str("missing minor version")));
+ let patch = try!(iter.next().ok_or(error::from_str("missing patch version")));
+
+ Ok(Version::new(
+ try!(major.parse().map_err(error::from_num)),
+ try!(minor.parse().map_err(error::from_num)),
+ try!(patch.parse().map_err(error::from_num)),
+ ))
+ }
+}
diff --git a/third_party/rust/autocfg/tests/rustflags.rs b/third_party/rust/autocfg/tests/rustflags.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/autocfg/tests/rustflags.rs
@@ -0,0 +1,33 @@
+extern crate autocfg;
+
+use std::env;
+
+/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS
+/// environment variables when running rustc.
+#[test]
+fn test_with_sysroot() {
+ // Use the same path as this test binary.
+ let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
+ env::set_var("OUT_DIR", &format!("{}", dir.display()));
+
+ // If we have encoded rustflags, they take precedence, even if empty.
+ env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
+ env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("std"));
+ assert!(!ac.probe_sysroot_crate("autocfg"));
+
+ // Now try again with useful encoded args.
+ env::set_var(
+ "CARGO_ENCODED_RUSTFLAGS",
+ &format!("-L\x1f{}", dir.display()),
+ );
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("autocfg"));
+
+ // Try the old-style RUSTFLAGS, ensuring HOST != TARGET.
+ env::remove_var("CARGO_ENCODED_RUSTFLAGS");
+ env::set_var("HOST", "lol");
+ let ac = autocfg::AutoCfg::new().unwrap();
+ assert!(ac.probe_sysroot_crate("autocfg"));
+}
diff --git a/third_party/rust/num-traits/.cargo-checksum.json b/third_party/rust/num-traits/.cargo-checksum.json
--- a/third_party/rust/num-traits/.cargo-checksum.json
+++ b/third_party/rust/num-traits/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"d6798dc92f8b83a8811446ae2e47c51564eb2b49162051b61a1eeec8bbed0da6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fc9a4b3719a828c9128e957ee7b9e2f795cc92a7cc50c1dda50e14126e0b4a77","RELEASES.md":"86c3e6703e6948bfc23c165a8b121930b8da4ffc7c38ab49d7a9e27b1655090e","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","ci/rustup.sh":"723d546a1ffefcdd5d4db9fb26dbf4128954e3991aff32932284cdc67fa5c85e","ci/test_full.sh":"c64b1d6f96baad0ea3bceb6842e7a706c4b414c99fddca55c2c30c81ae63d33a","src/bounds.rs":"d75e65f4f0e1337be06d2753ca06c23f099beb91d15215ac3230e9d441fcf4d0","src/cast.rs":"c06d1fd279b78386795384885a12742f9f31c95f364761acf0ed110184dc6bbc","src/float.rs":"841a2614519aac9f54b87e84a542df49346aa27254bd226b2dabe7966304fd0f","src/identities.rs":"f5389cf96b0d7ef55bd688961a58c4d7c0f3bd3bd48fe771948534e6bc05f29c","src/int.rs":"d6c51c943198a3aa071bfeb748101b2ce806fdef1ed6c26ef8f28f1e5a810f47","src/lib.rs":"29e4583f84b13ce2c0a6e5bbf4932183a19878e3cbab2387896b9e11c7729d5d","src/ops/checked.rs":"b2fc7ce21bca9c237f29149a553156a80d5ef94100c55128e05b946a575634c4","src/ops/mod.rs":"668ea4d117bc1fdf7eaf0fe16692fa40dfbdfcbc7a2010237fe395ce0086e02e","src/ops/saturating.rs":"46821d815c90c16b2f6bec0b94b4d7ebdbddf3ea42edc0467de738c56abf6436","src/ops/wrapping.rs":"5b274e7fc77d11ba37bb2fc98dabbbb8910f83b14d2505f775bd5a2e19445f6b","src/pow.rs":"4cedc57fc1446f436f729a68c1c4de797d316e4c1c341dead8f6ea0801c9f1ac","src/real.rs":"5e9436436593ed9c005078b9fe33477714490f959cae66ae2ae610da3eceb5f6","src/sign.rs":"f86aa7e9720698807455eabaf5f77b9fe68432fbb1a9291faf73b0c9f648d540"},"package":"e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"}
\ No newline at end of file
+{"files":{"Cargo.toml":"5b2749641deeabb2dfcc8e4d7e26ccfbc306800021e0d24e8367f313e57f9def","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"81e7df6fa6bea6f8c2809f9af68e3d32e7a4504b93394f775d37ed3d9f7f9166","RELEASES.md":"e1f774cba66e5e15e1086ab8afebece771140dd4168f59dca8dd4fd5e50b72dc","build.rs":"cf682b2322303196e241048cb56d873597b78a3b4e3f275f6f761dadb33a65f5","src/bounds.rs":"c90190de4dfba13c49119dbdf889726f8ece1cbd7dfd4bbfa364ea995f627e49","src/cast.rs":"8c8384dcdfaf926b9331399d528278fc73851f8b5e1105dee343f4f19557e932","src/float.rs":"6a84820f4828515639565848a63359b3e69329aa36b990178adbfc7d141ef0c5","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"bb4c0f4ce8d71e262bd9119ab820dd5a79e2bd476a8ad7e84b2167733b11d9d8","src/lib.rs":"cc0c8352b3f29a22b17f76e9cfe12acb279ec2aac5e22a9395569d58445c137c","src/macros.rs":"ee96613a2c73a3bef10ec7ae4d359dbf5f0b41f83e8a87c3d62ccc18dd27e498","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/euclid.rs":"71e0e181bd365c196a7dea980c2ec8bd47fd1d1d9b47bd3f401edcadb861eb0b","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"3bea8b98fa7537c0a5b4562d1b9d4d49481f1e2e88941cfd4cc8f0f3f0870fb3","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/overflowing.rs":"1b92882a5a738ea4cafdb0971101dc438be9043f540e1246f58f7c9ecf6348dc","src/ops/saturating.rs":"6fb4b2a2c78d9202152a84586d7b068444b78d3caed4b293980832672a234d4b","src/ops/wrapping.rs":"0acf88c0e5fc81a3c6790b31986ab9be5b16c720c9e27461fe5d69b710ffcaba","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"83562caa3501c6873558eb64c9e3bfe25b4b20d38562a7aa7cc9adafcb3ff037","tests/cast.rs":"0a41785611b3909ecb4a88d6d5264a85564f6de8fbfc761436d3c8baafc8e3d0"},"package":"578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"}
\ No newline at end of file
diff --git a/third_party/rust/num-traits/Cargo.toml b/third_party/rust/num-traits/Cargo.toml
--- a/third_party/rust/num-traits/Cargo.toml
+++ b/third_party/rust/num-traits/Cargo.toml
@@ -1,30 +1,51 @@
# 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
+# 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)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
name = "num-traits"
-version = "0.2.0"
+version = "0.2.15"
authors = ["The Rust Project Developers"]
+build = "build.rs"
+exclude = [
+ "/bors.toml",
+ "/ci/*",
+ "/.github/*",
+]
description = "Numeric traits for generic mathematics"
homepage = "https://github.com/rust-num/num-traits"
documentation = "https://docs.rs/num-traits"
readme = "README.md"
-keywords = ["mathematics", "numerics"]
-categories = ["algorithms", "science"]
-license = "MIT/Apache-2.0"
+keywords = [
+ "mathematics",
+ "numerics",
+]
+categories = [
+ "algorithms",
+ "science",
+ "no-std",
+]
+license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-num/num-traits"
-[dependencies]
+[package.metadata.docs.rs]
+features = ["std"]
+
+[dependencies.libm]
+version = "0.2.0"
+optional = true
+
+[build-dependencies.autocfg]
+version = "1"
[features]
default = ["std"]
+i128 = []
std = []
diff --git a/third_party/rust/num-traits/README.md b/third_party/rust/num-traits/README.md
--- a/third_party/rust/num-traits/README.md
+++ b/third_party/rust/num-traits/README.md
@@ -1,44 +1,63 @@
# num-traits
[![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits)
[![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits)
-![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)
-[![Travis status](https://travis-ci.org/rust-num/num-traits.svg?branch=master)](https://travis-ci.org/rust-num/num-traits)
+[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
+[![build status](https://github.com/rust-num/num-traits/workflows/master/badge.svg)](https://github.com/rust-num/num-traits/actions)
Numeric traits for generic mathematics in Rust.
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
num-traits = "0.2"
```
-and this to your crate root:
-
-```rust
-extern crate num_traits;
-```
-
## Features
This crate can be used without the standard library (`#![no_std]`) by disabling
-the default `std` feature. Use this in `Cargo.toml`:
+the default `std` feature. Use this in `Cargo.toml`:
```toml
[dependencies.num-traits]
version = "0.2"
default-features = false
+# features = ["libm"] # <--- Uncomment if you wish to use `Float` and `Real` without `std`
```
-The `Float` and `Real` traits are only available when `std` is enabled.
+The `Float` and `Real` traits are only available when either `std` or `libm` is enabled.
+The `libm` feature is only available with Rust 1.31 and later ([see PR #99](https://github.com/rust-num/num-traits/pull/99)).
+
+The `FloatCore` trait is always available. `MulAdd` and `MulAddAssign` for `f32`
+and `f64` also require `std` or `libm`, as do implementations of signed and floating-
+point exponents in `Pow`.
+
+Implementations for `i128` and `u128` are only available with Rust 1.26 and
+later. The build script automatically detects this, but you can make it
+mandatory by enabling the `i128` crate feature.
## Releases
Release notes are available in [RELEASES.md](RELEASES.md).
## Compatibility
The `num-traits` crate is tested for rustc 1.8 and greater.
+
+## License
+
+Licensed under either of
+
+ * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
+ * [MIT license](http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/third_party/rust/num-traits/RELEASES.md b/third_party/rust/num-traits/RELEASES.md
--- a/third_party/rust/num-traits/RELEASES.md
+++ b/third_party/rust/num-traits/RELEASES.md
@@ -1,26 +1,244 @@
-# Release 0.2.0
+# Release 0.2.15 (2022-05-02)
+
+- [The new `Euclid` trait calculates Euclidean division][195], where the
+ remainder is always positive or zero.
+- [The new `LowerBounded` and `UpperBounded` traits][210] separately describe
+ types with lower and upper bounds. These traits are automatically implemented
+ for all fully-`Bounded` types.
+- [The new `Float::copysign` method copies the sign of the argument][207] to
+ to the magnitude of `self`.
+- [The new `PrimInt::leading_ones` and `trailing_ones` methods][205] are the
+ complement of the existing methods that count zero bits.
+- [The new `PrimInt::reverse_bits` method reverses the order of all bits][202]
+ of a primitive integer.
+- [Improved `Num::from_str_radix` for floats][201], also [ignoring case][214].
+- [`Float` and `FloatCore` use more from `libm`][196] when that is enabled.
+
+**Contributors**: @alion02, @clarfonthey, @cuviper, @ElectronicRU,
+@ibraheemdev, @SparrowLii, @sshilovsky, @tspiteri, @XAMPPRocky, @Xiretza
+
+[195]: https://github.com/rust-num/num-traits/pull/195
+[196]: https://github.com/rust-num/num-traits/pull/196
+[201]: https://github.com/rust-num/num-traits/pull/201
+[202]: https://github.com/rust-num/num-traits/pull/202
+[205]: https://github.com/rust-num/num-traits/pull/205
+[207]: https://github.com/rust-num/num-traits/pull/207
+[210]: https://github.com/rust-num/num-traits/pull/210
+[214]: https://github.com/rust-num/num-traits/pull/214
+
+# Release 0.2.14 (2020-10-29)
+
+- Clarify the license specification as "MIT OR Apache-2.0".
+
+**Contributors**: @cuviper
+
+# Release 0.2.13 (2020-10-29)
+
+- [The new `OverflowingAdd`, `OverflowingSub`, and `OverflowingMul` traits][180]
+ return a tuple with the operation result and a `bool` indicating overflow.
+- [The "i128" feature now overrides compiler probes for that support][185].
+ This may fix scenarios where `autocfg` probing doesn't work properly.
+- [Casts from large `f64` values to `f32` now saturate to infinity][186]. They
+ previously returned `None` because that was once thought to be undefined
+ behavior, but [rust#15536] resolved that such casts are fine.
+- [`Num::from_str_radix` documents requirements for radix support][192], which
+ are now more relaxed than previously implied. It is suggested to accept at
+ least `2..=36` without panicking, but `Err` may be returned otherwise.
+
+**Contributors**: @cuviper, @Enet4, @KaczuH, @martin-t, @newpavlov
+
+[180]: https://github.com/rust-num/num-traits/pull/180
+[185]: https://github.com/rust-num/num-traits/pull/185
+[186]: https://github.com/rust-num/num-traits/pull/186
+[192]: https://github.com/rust-num/num-traits/issues/192
+[rust#15536]: https://github.com/rust-lang/rust/issues/15536
+
+# Release 0.2.12 (2020-06-11)
+
+- [The new `WrappingNeg` trait][153] will wrap the result if it exceeds the
+ boundary of the type, e.g. `i32::MIN.wrapping_neg() == i32::MIN`.
+- [The new `SaturatingAdd`, `SaturatingSub`, and `SaturatingMul` traits][165]
+ will saturate at the numeric bounds if the operation would overflow. These
+ soft-deprecate the existing `Saturating` trait that only has addition and
+ subtraction methods.
+- [Added new constants for logarithms, `FloatConst::{LOG10_2, LOG2_10}`][171].
+
+**Contributors**: @cuviper, @ocstl, @trepetti, @vallentin
+
+[153]: https://github.com/rust-num/num-traits/pull/153
+[165]: https://github.com/rust-num/num-traits/pull/165
+[171]: https://github.com/rust-num/num-traits/pull/171
+
+# Release 0.2.11 (2020-01-09)
+
+- [Added the full circle constant τ as `FloatConst::TAU`][145].
+- [Updated the `autocfg` build dependency to 1.0][148].
+
+**Contributors**: @cuviper, @m-ou-se
+
+[145]: https://github.com/rust-num/num-traits/pull/145
+[148]: https://github.com/rust-num/num-traits/pull/148
+
+# Release 0.2.10 (2019-11-22)
+
+- [Updated the `libm` dependency to 0.2][144].
+
+**Contributors**: @CryZe
+
+[144]: https://github.com/rust-num/num-traits/pull/144
+
+# Release 0.2.9 (2019-11-12)
+
+- [A new optional `libm` dependency][99] enables the `Float` and `Real` traits
+ in `no_std` builds.
+- [The new `clamp_min` and `clamp_max`][122] limit minimum and maximum values
+ while preserving input `NAN`s.
+- [Fixed a panic in floating point `from_str_radix` on invalid signs][126].
+- Miscellaneous documentation updates.
+
+**Contributors**: @cuviper, @dingelish, @HeroicKatora, @jturner314, @ocstl,
+@Shnatsel, @termoshtt, @waywardmonkeys, @yoanlcq
+
+[99]: https://github.com/rust-num/num-traits/pull/99
+[122]: https://github.com/rust-num/num-traits/pull/122
+[126]: https://github.com/rust-num/num-traits/pull/126
+
+# Release 0.2.8 (2019-05-21)
+
+- [Fixed feature detection on `no_std` targets][116].
-- **breaking change**: There is now a `std` feature, enabled by default, along
+**Contributors**: @cuviper
+
+[116]: https://github.com/rust-num/num-traits/pull/116
+
+# Release 0.2.7 (2019-05-20)
+
+- [Documented when `CheckedShl` and `CheckedShr` return `None`][90].
+- [The new `Zero::set_zero` and `One::set_one`][104] will set values to their
+ identities in place, possibly optimized better than direct assignment.
+- [Documented general features and intentions of `PrimInt`][108].
+
+**Contributors**: @cuviper, @dvdhrm, @ignatenkobrain, @lcnr, @samueltardieu
+
+[90]: https://github.com/rust-num/num-traits/pull/90
+[104]: https://github.com/rust-num/num-traits/pull/104
+[108]: https://github.com/rust-num/num-traits/pull/108
+
+# Release 0.2.6 (2018-09-13)
+
+- [Documented that `pow(0, 0)` returns `1`][79]. Mathematically, this is not
+ strictly defined, but the current behavior is a pragmatic choice that has
+ precedent in Rust `core` for the primitives and in many other languages.
+- [The new `WrappingShl` and `WrappingShr` traits][81] will wrap the shift count
+ if it exceeds the bit size of the type.
+
+**Contributors**: @cuviper, @edmccard, @meltinglava
+
+[79]: https://github.com/rust-num/num-traits/pull/79
+[81]: https://github.com/rust-num/num-traits/pull/81
+
+# Release 0.2.5 (2018-06-20)
+
+- [Documentation for `mul_add` now clarifies that it's not always faster.][70]
+- [The default methods in `FromPrimitive` and `ToPrimitive` are more robust.][73]
+
+**Contributors**: @cuviper, @frewsxcv
+
+[70]: https://github.com/rust-num/num-traits/pull/70
+[73]: https://github.com/rust-num/num-traits/pull/73
+
+# Release 0.2.4 (2018-05-11)
+
+- [Support for 128-bit integers is now automatically detected and enabled.][69]
+ Setting the `i128` crate feature now causes the build script to panic if such
+ support is not detected.
+
+**Contributors**: @cuviper
+
+[69]: https://github.com/rust-num/num-traits/pull/69
+
+# Release 0.2.3 (2018-05-10)
+
+- [The new `CheckedNeg` and `CheckedRem` traits][63] perform checked `Neg` and
+ `Rem`, returning `Some(output)` or `None` on overflow.
+- [The `no_std` implementation of `FloatCore::to_degrees` for `f32`][61] now
+ uses a constant for greater accuracy, mirroring [rust#47919]. (With `std` it
+ just calls the inherent `f32::to_degrees` in the standard library.)
+- [The new `MulAdd` and `MulAddAssign` traits][59] perform a fused multiply-
+ add. For integer types this is just a convenience, but for floating point
+ types this produces a more accurate result than the separate operations.
+- [All applicable traits are now implemented for 128-bit integers][60] starting
+ with Rust 1.26, enabled by the new `i128` crate feature. The `FromPrimitive`
+ and `ToPrimitive` traits now also have corresponding 128-bit methods, which
+ default to converting via 64-bit integers for compatibility.
+
+**Contributors**: @cuviper, @LEXUGE, @regexident, @vks
+
+[59]: https://github.com/rust-num/num-traits/pull/59
+[60]: https://github.com/rust-num/num-traits/pull/60
+[61]: https://github.com/rust-num/num-traits/pull/61
+[63]: https://github.com/rust-num/num-traits/pull/63
+[rust#47919]: https://github.com/rust-lang/rust/pull/47919
+
+# Release 0.2.2 (2018-03-18)
+
+- [Casting from floating point to integers now returns `None` on overflow][52],
+ avoiding [rustc's undefined behavior][rust-10184]. This applies to the `cast`
+ function and the traits `NumCast`, `FromPrimitive`, and `ToPrimitive`.
+
+**Contributors**: @apopiak, @cuviper, @dbarella
+
+[52]: https://github.com/rust-num/num-traits/pull/52
+[rust-10184]: https://github.com/rust-lang/rust/issues/10184
+
+
+# Release 0.2.1 (2018-03-01)
+
+- [The new `FloatCore` trait][32] offers a subset of `Float` for `#![no_std]` use.
+ [This includes everything][41] except the transcendental functions and FMA.
+- [The new `Inv` trait][37] returns the multiplicative inverse, or reciprocal.
+- [The new `Pow` trait][37] performs exponentiation, much like the existing `pow`
+ function, but with generic exponent types.
+- [The new `One::is_one` method][39] tests if a value equals 1. Implementers
+ should override this method if there's a more efficient way to check for 1,
+ rather than comparing with a temporary `one()`.
+
+**Contributors**: @clarcharr, @cuviper, @vks
+
+[32]: https://github.com/rust-num/num-traits/pull/32
+[37]: https://github.com/rust-num/num-traits/pull/37
+[39]: https://github.com/rust-num/num-traits/pull/39
+[41]: https://github.com/rust-num/num-traits/pull/41
+
+
+# Release 0.2.0 (2018-02-06)
+
+- **breaking change**: [There is now a `std` feature][30], enabled by default, along
with the implication that building *without* this feature makes this a
- `#[no_std]` crate.
+ `#![no_std]` crate.
- The `Float` and `Real` traits are only available when `std` is enabled.
- Otherwise, the API is unchanged, and num-traits 0.1.43 now re-exports its
items from num-traits 0.2 for compatibility (the [semver-trick]).
**Contributors**: @cuviper, @termoshtt, @vks
[semver-trick]: https://github.com/dtolnay/semver-trick
+[30]: https://github.com/rust-num/num-traits/pull/30
-# Release 0.1.43
+
+# Release 0.1.43 (2018-02-06)
-- All items are now re-exported from num-traits 0.2 for compatibility.
+- All items are now [re-exported from num-traits 0.2][31] for compatibility.
-# Release 0.1.42
+[31]: https://github.com/rust-num/num-traits/pull/31
+
+
+# Release 0.1.42 (2018-01-22)
- [num-traits now has its own source repository][num-356] at [rust-num/num-traits][home].
- [`ParseFloatError` now implements `Display`][22].
- [The new `AsPrimitive` trait][17] implements generic casting with the `as` operator.
- [The new `CheckedShl` and `CheckedShr` traits][21] implement generic
support for the `checked_shl` and `checked_shr` methods on primitive integers.
- [The new `Real` trait][23] offers a subset of `Float` functionality that may be applicable to more
types, with a blanket implementation for all existing `T: Float` types.
diff --git a/third_party/rust/num-traits/bors.toml b/third_party/rust/num-traits/bors.toml
deleted file mode 100644
--- a/third_party/rust/num-traits/bors.toml
+++ /dev/null
@@ -1,3 +0,0 @@
-status = [
- "continuous-integration/travis-ci/push",
-]
diff --git a/third_party/rust/num-traits/build.rs b/third_party/rust/num-traits/build.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/build.rs
@@ -0,0 +1,29 @@
+extern crate autocfg;
+
+use std::env;
+
+fn main() {
+ let ac = autocfg::new();
+
+ // If the "i128" feature is explicity requested, don't bother probing for it.
+ // It will still cause a build error if that was set improperly.
+ if env::var_os("CARGO_FEATURE_I128").is_some() || ac.probe_type("i128") {
+ autocfg::emit("has_i128");
+ }
+
+ ac.emit_expression_cfg(
+ "unsafe { 1f64.to_int_unchecked::<i32>() }",
+ "has_to_int_unchecked",
+ );
+
+ ac.emit_expression_cfg("1u32.reverse_bits()", "has_reverse_bits");
+ ac.emit_expression_cfg("1u32.trailing_ones()", "has_leading_trailing_ones");
+ ac.emit_expression_cfg("{ let mut x = 1; x += &2; }", "has_int_assignop_ref");
+ ac.emit_expression_cfg("1u32.div_euclid(1u32)", "has_div_euclid");
+
+ if env::var_os("CARGO_FEATURE_STD").is_some() {
+ ac.emit_expression_cfg("1f64.copysign(-1f64)", "has_copysign");
+ }
+
+ autocfg::rerun_path("build.rs");
+}
diff --git a/third_party/rust/num-traits/ci/rustup.sh b/third_party/rust/num-traits/ci/rustup.sh
deleted file mode 100644
--- a/third_party/rust/num-traits/ci/rustup.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-# Use rustup to locally run the same suite of tests as .travis.yml.
-# (You should first install/update 1.8.0, stable, beta, and nightly.)
-
-set -ex
-
-export TRAVIS_RUST_VERSION
-for TRAVIS_RUST_VERSION in 1.8.0 stable beta nightly; do
- run="rustup run $TRAVIS_RUST_VERSION"
- $run cargo build --verbose
- $run $PWD/ci/test_full.sh
-done
diff --git a/third_party/rust/num-traits/ci/test_full.sh b/third_party/rust/num-traits/ci/test_full.sh
deleted file mode 100644
--- a/third_party/rust/num-traits/ci/test_full.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-echo Testing num-traits on rustc ${TRAVIS_RUST_VERSION}
-
-# num-traits should build and test everywhere.
-cargo build --verbose
-cargo test --verbose
-
-# test `no_std`
-cargo build --verbose --no-default-features
-cargo test --verbose --no-default-features
diff --git a/third_party/rust/num-traits/src/bounds.rs b/third_party/rust/num-traits/src/bounds.rs
--- a/third_party/rust/num-traits/src/bounds.rs
+++ b/third_party/rust/num-traits/src/bounds.rs
@@ -1,66 +1,106 @@
-use core::{usize, u8, u16, u32, u64};
-use core::{isize, i8, i16, i32, i64};
+use core::num::Wrapping;
use core::{f32, f64};
-use core::num::Wrapping;
+#[cfg(has_i128)]
+use core::{i128, u128};
+use core::{i16, i32, i64, i8, isize};
+use core::{u16, u32, u64, u8, usize};
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
- /// returns the smallest finite number this type can represent
+ /// Returns the smallest finite number this type can represent
+ fn min_value() -> Self;
+ /// Returns the largest finite number this type can represent
+ fn max_value() -> Self;
+}
+
+/// Numbers which have lower bounds
+pub trait LowerBounded {
+ /// Returns the smallest finite number this type can represent
fn min_value() -> Self;
- /// returns the largest finite number this type can represent
+}
+
+// FIXME: With a major version bump, this should be a supertrait instead
+impl<T: Bounded> LowerBounded for T {
+ fn min_value() -> T {
+ Bounded::min_value()
+ }
+}
+
+/// Numbers which have upper bounds
+pub trait UpperBounded {
+ /// Returns the largest finite number this type can represent
fn max_value() -> Self;
}
+// FIXME: With a major version bump, this should be a supertrait instead
+impl<T: Bounded> UpperBounded for T {
+ fn max_value() -> T {
+ Bounded::max_value()
+ }
+}
+
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
#[inline]
- fn min_value() -> $t { $min }
+ fn min_value() -> $t {
+ $min
+ }
#[inline]
- fn max_value() -> $t { $max }
+ fn max_value() -> $t {
+ $max
+ }
}
- }
+ };
}
bounded_impl!(usize, usize::MIN, usize::MAX);
-bounded_impl!(u8, u8::MIN, u8::MAX);
-bounded_impl!(u16, u16::MIN, u16::MAX);
-bounded_impl!(u32, u32::MIN, u32::MAX);
-bounded_impl!(u64, u64::MIN, u64::MAX);
+bounded_impl!(u8, u8::MIN, u8::MAX);
+bounded_impl!(u16, u16::MIN, u16::MAX);
+bounded_impl!(u32, u32::MIN, u32::MAX);
+bounded_impl!(u64, u64::MIN, u64::MAX);
+#[cfg(has_i128)]
+bounded_impl!(u128, u128::MIN, u128::MAX);
bounded_impl!(isize, isize::MIN, isize::MAX);
-bounded_impl!(i8, i8::MIN, i8::MAX);
-bounded_impl!(i16, i16::MIN, i16::MAX);
-bounded_impl!(i32, i32::MIN, i32::MAX);
-bounded_impl!(i64, i64::MIN, i64::MAX);
+bounded_impl!(i8, i8::MIN, i8::MAX);
+bounded_impl!(i16, i16::MIN, i16::MAX);
+bounded_impl!(i32, i32::MIN, i32::MAX);
+bounded_impl!(i64, i64::MIN, i64::MAX);
+#[cfg(has_i128)]
+bounded_impl!(i128, i128::MIN, i128::MAX);
impl<T: Bounded> Bounded for Wrapping<T> {
- fn min_value() -> Self { Wrapping(T::min_value()) }
- fn max_value() -> Self { Wrapping(T::max_value()) }
+ fn min_value() -> Self {
+ Wrapping(T::min_value())
+ }
+ fn max_value() -> Self {
+ Wrapping(T::max_value())
+ }
}
bounded_impl!(f32, f32::MIN, f32::MAX);
macro_rules! for_each_tuple_ {
( $m:ident !! ) => (
$m! { }
);
( $m:ident !! $h:ident, $($t:ident,)* ) => (
$m! { $h $($t)* }
for_each_tuple_! { $m !! $($t,)* }
);
}
macro_rules! for_each_tuple {
- ( $m:ident ) => (
+ ($m:ident) => {
for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, }
- );
+ };
}
macro_rules! bounded_tuple {
( $($name:ident)* ) => (
impl<$($name: Bounded,)*> Bounded for ($($name,)*) {
#[inline]
fn min_value() -> Self {
($($name::min_value(),)*)
@@ -71,29 +111,43 @@ macro_rules! bounded_tuple {
}
}
);
}
for_each_tuple!(bounded_tuple);
bounded_impl!(f64, f64::MIN, f64::MAX);
-
#[test]
fn wrapping_bounded() {
macro_rules! test_wrapping_bounded {
($($t:ty)+) => {
$(
- assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value());
- assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value());
+ assert_eq!(<Wrapping<$t> as Bounded>::min_value().0, <$t>::min_value());
+ assert_eq!(<Wrapping<$t> as Bounded>::max_value().0, <$t>::max_value());
)+
};
}
test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
}
+#[cfg(has_i128)]
+#[test]
+fn wrapping_bounded_i128() {
+ macro_rules! test_wrapping_bounded {
+ ($($t:ty)+) => {
+ $(
+ assert_eq!(<Wrapping<$t> as Bounded>::min_value().0, <$t>::min_value());
+ assert_eq!(<Wrapping<$t> as Bounded>::max_value().0, <$t>::max_value());
+ )+
+ };
+ }
+
+ test_wrapping_bounded!(u128 i128);
+}
+
#[test]
fn wrapping_is_bounded() {
fn require_bounded<T: Bounded>(_: &T) {}
require_bounded(&Wrapping(42_u32));
require_bounded(&Wrapping(-42));
}
diff --git a/third_party/rust/num-traits/src/cast.rs b/third_party/rust/num-traits/src/cast.rs
--- a/third_party/rust/num-traits/src/cast.rs
+++ b/third_party/rust/num-traits/src/cast.rs
@@ -1,409 +1,681 @@
-use core::f64;
use core::mem::size_of;
use core::num::Wrapping;
-
-use identities::Zero;
-use bounds::Bounded;
+use core::{f32, f64};
+#[cfg(has_i128)]
+use core::{i128, u128};
+use core::{i16, i32, i64, i8, isize};
+use core::{u16, u32, u64, u8, usize};
/// A generic trait for converting a value to a number.
+///
+/// A value can be represented by the target type when it lies within
+/// the range of scalars supported by the target type.
+/// For example, a negative integer cannot be represented by an unsigned
+/// integer type, and an `i64` with a very high magnitude might not be
+/// convertible to an `i32`.
+/// On the other hand, conversions with possible precision loss or truncation
+/// are admitted, like an `f32` with a decimal part to an integer type, or
+/// even a large `f64` saturating to `f32` infinity.
pub trait ToPrimitive {
- /// Converts the value of `self` to an `isize`.
+ /// Converts the value of `self` to an `isize`. If the value cannot be
+ /// represented by an `isize`, then `None` is returned.
#[inline]
fn to_isize(&self) -> Option<isize> {
- self.to_i64().and_then(|x| x.to_isize())
+ self.to_i64().as_ref().and_then(ToPrimitive::to_isize)
}
- /// Converts the value of `self` to an `i8`.
+ /// Converts the value of `self` to an `i8`. If the value cannot be
+ /// represented by an `i8`, then `None` is returned.
#[inline]
fn to_i8(&self) -> Option<i8> {
- self.to_i64().and_then(|x| x.to_i8())
+ self.to_i64().as_ref().and_then(ToPrimitive::to_i8)
}
- /// Converts the value of `self` to an `i16`.
+ /// Converts the value of `self` to an `i16`. If the value cannot be
+ /// represented by an `i16`, then `None` is returned.
#[inline]
fn to_i16(&self) -> Option<i16> {
- self.to_i64().and_then(|x| x.to_i16())
+ self.to_i64().as_ref().and_then(ToPrimitive::to_i16)
}
- /// Converts the value of `self` to an `i32`.
+ /// Converts the value of `self` to an `i32`. If the value cannot be
+ /// represented by an `i32`, then `None` is returned.
#[inline]
fn to_i32(&self) -> Option<i32> {
- self.to_i64().and_then(|x| x.to_i32())
+ self.to_i64().as_ref().and_then(ToPrimitive::to_i32)
}
- /// Converts the value of `self` to an `i64`.
+ /// Converts the value of `self` to an `i64`. If the value cannot be
+ /// represented by an `i64`, then `None` is returned.
fn to_i64(&self) -> Option<i64>;
- /// Converts the value of `self` to a `usize`.
+ /// Converts the value of `self` to an `i128`. If the value cannot be
+ /// represented by an `i128` (`i64` under the default implementation), then
+ /// `None` is returned.
+ ///
+ /// This method is only available with feature `i128` enabled on Rust >= 1.26.
+ ///
+ /// The default implementation converts through `to_i64()`. Types implementing
+ /// this trait should override this method if they can represent a greater range.
#[inline]
- fn to_usize(&self) -> Option<usize> {
- self.to_u64().and_then(|x| x.to_usize())
+ #[cfg(has_i128)]
+ fn to_i128(&self) -> Option<i128> {
+ self.to_i64().map(From::from)
}
- /// Converts the value of `self` to an `u8`.
+ /// Converts the value of `self` to a `usize`. If the value cannot be
+ /// represented by a `usize`, then `None` is returned.
+ #[inline]
+ fn to_usize(&self) -> Option<usize> {
+ self.to_u64().as_ref().and_then(ToPrimitive::to_usize)
+ }
+
+ /// Converts the value of `self` to a `u8`. If the value cannot be
+ /// represented by a `u8`, then `None` is returned.
#[inline]
fn to_u8(&self) -> Option<u8> {
- self.to_u64().and_then(|x| x.to_u8())
+ self.to_u64().as_ref().and_then(ToPrimitive::to_u8)
}
- /// Converts the value of `self` to an `u16`.
+ /// Converts the value of `self` to a `u16`. If the value cannot be
+ /// represented by a `u16`, then `None` is returned.
#[inline]
fn to_u16(&self) -> Option<u16> {
- self.to_u64().and_then(|x| x.to_u16())
+ self.to_u64().as_ref().and_then(ToPrimitive::to_u16)
}
- /// Converts the value of `self` to an `u32`.
+ /// Converts the value of `self` to a `u32`. If the value cannot be
+ /// represented by a `u32`, then `None` is returned.
#[inline]
fn to_u32(&self) -> Option<u32> {
- self.to_u64().and_then(|x| x.to_u32())
+ self.to_u64().as_ref().and_then(ToPrimitive::to_u32)
}
- /// Converts the value of `self` to an `u64`.
- #[inline]
+ /// Converts the value of `self` to a `u64`. If the value cannot be
+ /// represented by a `u64`, then `None` is returned.
fn to_u64(&self) -> Option<u64>;
- /// Converts the value of `self` to an `f32`.
+ /// Converts the value of `self` to a `u128`. If the value cannot be
+ /// represented by a `u128` (`u64` under the default implementation), then
+ /// `None` is returned.
+ ///
+ /// This method is only available with feature `i128` enabled on Rust >= 1.26.
+ ///
+ /// The default implementation converts through `to_u64()`. Types implementing
+ /// this trait should override this method if they can represent a greater range.
+ #[inline]
+ #[cfg(has_i128)]
+ fn to_u128(&self) -> Option<u128> {
+ self.to_u64().map(From::from)
+ }
+
+ /// Converts the value of `self` to an `f32`. Overflows may map to positive
+ /// or negative inifinity, otherwise `None` is returned if the value cannot
+ /// be represented by an `f32`.
#[inline]
fn to_f32(&self) -> Option<f32> {
- self.to_f64().and_then(|x| x.to_f32())
+ self.to_f64().as_ref().and_then(ToPrimitive::to_f32)
}
- /// Converts the value of `self` to an `f64`.
+ /// Converts the value of `self` to an `f64`. Overflows may map to positive
+ /// or negative inifinity, otherwise `None` is returned if the value cannot
+ /// be represented by an `f64`.
+ ///
+ /// The default implementation tries to convert through `to_i64()`, and
+ /// failing that through `to_u64()`. Types implementing this trait should
+ /// override this method if they can represent a greater range.
#[inline]
fn to_f64(&self) -> Option<f64> {
- self.to_i64().and_then(|x| x.to_f64())
+ match self.to_i64() {
+ Some(i) => i.to_f64(),
+ None => self.to_u64().as_ref().and_then(ToPrimitive::to_f64),
+ }
}
}
macro_rules! impl_to_primitive_int_to_int {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
+ ($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$DstT> {
+ let min = $DstT::MIN as $SrcT;
+ let max = $DstT::MAX as $SrcT;
+ if size_of::<$SrcT>() <= size_of::<$DstT>() || (min <= *self && *self <= max) {
+ Some(*self as $DstT)
} else {
- let n = $slf as i64;
- let min_value: $DstT = Bounded::min_value();
- let max_value: $DstT = Bounded::max_value();
- if min_value as i64 <= n && n <= max_value as i64 {
- Some($slf as $DstT)
- } else {
- None
- }
+ None
}
}
- )
+ )*}
}
macro_rules! impl_to_primitive_int_to_uint {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- let zero: $SrcT = Zero::zero();
- let max_value: $DstT = Bounded::max_value();
- if zero <= $slf && $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
+ ($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$DstT> {
+ let max = $DstT::MAX as $SrcT;
+ if 0 <= *self && (size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max) {
+ Some(*self as $DstT)
} else {
None
}
}
- )
+ )*}
}
macro_rules! impl_to_primitive_int {
- ($T:ty) => (
+ ($T:ident) => {
impl ToPrimitive for $T {
- #[inline]
- fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
+ impl_to_primitive_int_to_int! { $T:
+ fn to_isize -> isize;
+ fn to_i8 -> i8;
+ fn to_i16 -> i16;
+ fn to_i32 -> i32;
+ fn to_i64 -> i64;
+ #[cfg(has_i128)]
+ fn to_i128 -> i128;
+ }
+
+ impl_to_primitive_int_to_uint! { $T:
+ fn to_usize -> usize;
+ fn to_u8 -> u8;
+ fn to_u16 -> u16;
+ fn to_u32 -> u32;
+ fn to_u64 -> u64;
+ #[cfg(has_i128)]
+ fn to_u128 -> u128;
+ }
#[inline]
- fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
- #[inline]
- fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
+ fn to_f32(&self) -> Option<f32> {
+ Some(*self as f32)
+ }
#[inline]
- fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
-
- #[inline]
- fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
+ fn to_f64(&self) -> Option<f64> {
+ Some(*self as f64)
+ }
}
- )
+ };
}
impl_to_primitive_int!(isize);
impl_to_primitive_int!(i8);
impl_to_primitive_int!(i16);
impl_to_primitive_int!(i32);
impl_to_primitive_int!(i64);
+#[cfg(has_i128)]
+impl_to_primitive_int!(i128);
macro_rules! impl_to_primitive_uint_to_int {
- ($DstT:ty, $slf:expr) => (
- {
- let max_value: $DstT = Bounded::max_value();
- if $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
+ ($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$DstT> {
+ let max = $DstT::MAX as $SrcT;
+ if size_of::<$SrcT>() < size_of::<$DstT>() || *self <= max {
+ Some(*self as $DstT)
+ } else {
+ None
+ }
+ }
+ )*}
+}
+
+macro_rules! impl_to_primitive_uint_to_uint {
+ ($SrcT:ident : $( $(#[$cfg:meta])* fn $method:ident -> $DstT:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$DstT> {
+ let max = $DstT::MAX as $SrcT;
+ if size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max {
+ Some(*self as $DstT)
} else {
None
}
}
- )
-}
-
-macro_rules! impl_to_primitive_uint_to_uint {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
- } else {
- let zero: $SrcT = Zero::zero();
- let max_value: $DstT = Bounded::max_value();
- if zero <= $slf && $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- }
- )
+ )*}
}
macro_rules! impl_to_primitive_uint {
- ($T:ty) => (
+ ($T:ident) => {
impl ToPrimitive for $T {
- #[inline]
- fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
+ impl_to_primitive_uint_to_int! { $T:
+ fn to_isize -> isize;
+ fn to_i8 -> i8;
+ fn to_i16 -> i16;
+ fn to_i32 -> i32;
+ fn to_i64 -> i64;
+ #[cfg(has_i128)]
+ fn to_i128 -> i128;
+ }
+
+ impl_to_primitive_uint_to_uint! { $T:
+ fn to_usize -> usize;
+ fn to_u8 -> u8;
+ fn to_u16 -> u16;
+ fn to_u32 -> u32;
+ fn to_u64 -> u64;
+ #[cfg(has_i128)]
+ fn to_u128 -> u128;
+ }
#[inline]
- fn to_usize(&self) -> Option<usize> {
- impl_to_primitive_uint_to_uint!($T, usize, *self)
+ fn to_f32(&self) -> Option<f32> {
+ Some(*self as f32)
}
#[inline]
- fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
- #[inline]
- fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
-
- #[inline]
- fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
+ fn to_f64(&self) -> Option<f64> {
+ Some(*self as f64)
+ }
}
- )
+ };
}
impl_to_primitive_uint!(usize);
impl_to_primitive_uint!(u8);
impl_to_primitive_uint!(u16);
impl_to_primitive_uint!(u32);
impl_to_primitive_uint!(u64);
+#[cfg(has_i128)]
+impl_to_primitive_uint!(u128);
macro_rules! impl_to_primitive_float_to_float {
- ($SrcT:ident, $DstT:ident, $slf:expr) => (
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
- } else {
- // Make sure the value is in range for the cast.
- // NaN and +-inf are cast as they are.
- let n = $slf as f64;
- let max_value: $DstT = ::core::$DstT::MAX;
- if n != n || n == f64::INFINITY || n == f64::NEG_INFINITY
- || (-max_value as f64 <= n && n <= max_value as f64)
- {
- Some($slf as $DstT)
+ ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
+ #[inline]
+ fn $method(&self) -> Option<$DstT> {
+ // We can safely cast all values, whether NaN, +-inf, or finite.
+ // Finite values that are reducing size may saturate to +-inf.
+ Some(*self as $DstT)
+ }
+ )*}
+}
+
+#[cfg(has_to_int_unchecked)]
+macro_rules! float_to_int_unchecked {
+ // SAFETY: Must not be NaN or infinite; must be representable as the integer after truncating.
+ // We already checked that the float is in the exclusive range `(MIN-1, MAX+1)`.
+ ($float:expr => $int:ty) => {
+ unsafe { $float.to_int_unchecked::<$int>() }
+ };
+}
+
+#[cfg(not(has_to_int_unchecked))]
+macro_rules! float_to_int_unchecked {
+ ($float:expr => $int:ty) => {
+ $float as $int
+ };
+}
+
+macro_rules! impl_to_primitive_float_to_signed_int {
+ ($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$i> {
+ // Float as int truncates toward zero, so we want to allow values
+ // in the exclusive range `(MIN-1, MAX+1)`.
+ if size_of::<$f>() > size_of::<$i>() {
+ // With a larger size, we can represent the range exactly.
+ const MIN_M1: $f = $i::MIN as $f - 1.0;
+ const MAX_P1: $f = $i::MAX as $f + 1.0;
+ if *self > MIN_M1 && *self < MAX_P1 {
+ return Some(float_to_int_unchecked!(*self => $i));
+ }
} else {
- None
+ // We can't represent `MIN-1` exactly, but there's no fractional part
+ // at this magnitude, so we can just use a `MIN` inclusive boundary.
+ const MIN: $f = $i::MIN as $f;
+ // We can't represent `MAX` exactly, but it will round up to exactly
+ // `MAX+1` (a power of two) when we cast it.
+ const MAX_P1: $f = $i::MAX as $f;
+ if *self >= MIN && *self < MAX_P1 {
+ return Some(float_to_int_unchecked!(*self => $i));
+ }
}
+ None
}
- )
+ )*}
+}
+
+macro_rules! impl_to_primitive_float_to_unsigned_int {
+ ($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $u:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$u> {
+ // Float as int truncates toward zero, so we want to allow values
+ // in the exclusive range `(-1, MAX+1)`.
+ if size_of::<$f>() > size_of::<$u>() {
+ // With a larger size, we can represent the range exactly.
+ const MAX_P1: $f = $u::MAX as $f + 1.0;
+ if *self > -1.0 && *self < MAX_P1 {
+ return Some(float_to_int_unchecked!(*self => $u));
+ }
+ } else {
+ // We can't represent `MAX` exactly, but it will round up to exactly
+ // `MAX+1` (a power of two) when we cast it.
+ // (`u128::MAX as f32` is infinity, but this is still ok.)
+ const MAX_P1: $f = $u::MAX as $f;
+ if *self > -1.0 && *self < MAX_P1 {
+ return Some(float_to_int_unchecked!(*self => $u));
+ }
+ }
+ None
+ }
+ )*}
}
macro_rules! impl_to_primitive_float {
- ($T:ident) => (
+ ($T:ident) => {
impl ToPrimitive for $T {
- #[inline]
- fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
+ impl_to_primitive_float_to_signed_int! { $T:
+ fn to_isize -> isize;
+ fn to_i8 -> i8;
+ fn to_i16 -> i16;
+ fn to_i32 -> i32;
+ fn to_i64 -> i64;
+ #[cfg(has_i128)]
+ fn to_i128 -> i128;
+ }
- #[inline]
- fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
- #[inline]
- fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
- #[inline]
- fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
+ impl_to_primitive_float_to_unsigned_int! { $T:
+ fn to_usize -> usize;
+ fn to_u8 -> u8;
+ fn to_u16 -> u16;
+ fn to_u32 -> u32;
+ fn to_u64 -> u64;
+ #[cfg(has_i128)]
+ fn to_u128 -> u128;
+ }
- #[inline]
- fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
+ impl_to_primitive_float_to_float! { $T:
+ fn to_f32 -> f32;
+ fn to_f64 -> f64;
+ }
}
- )
+ };
}
impl_to_primitive_float!(f32);
impl_to_primitive_float!(f64);
/// A generic trait for converting a number to a value.
+///
+/// A value can be represented by the target type when it lies within
+/// the range of scalars supported by the target type.
+/// For example, a negative integer cannot be represented by an unsigned
+/// integer type, and an `i64` with a very high magnitude might not be
+/// convertible to an `i32`.
+/// On the other hand, conversions with possible precision loss or truncation
+/// are admitted, like an `f32` with a decimal part to an integer type, or
+/// even a large `f64` saturating to `f32` infinity.
pub trait FromPrimitive: Sized {
- /// Convert an `isize` to return an optional value of this type. If the
- /// value cannot be represented by this value, the `None` is returned.
+ /// Converts an `isize` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_isize(n: isize) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
+ n.to_i64().and_then(FromPrimitive::from_i64)
}
- /// Convert an `i8` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `i8` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_i8(n: i8) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
+ FromPrimitive::from_i64(From::from(n))
}
- /// Convert an `i16` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `i16` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_i16(n: i16) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
+ FromPrimitive::from_i64(From::from(n))
+ }
+
+ /// Converts an `i32` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ #[inline]
+ fn from_i32(n: i32) -> Option<Self> {
+ FromPrimitive::from_i64(From::from(n))
}
- /// Convert an `i32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `i64` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ fn from_i64(n: i64) -> Option<Self>;
+
+ /// Converts an `i128` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ ///
+ /// This method is only available with feature `i128` enabled on Rust >= 1.26.
+ ///
+ /// The default implementation converts through `from_i64()`. Types implementing
+ /// this trait should override this method if they can represent a greater range.
#[inline]
- fn from_i32(n: i32) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
+ #[cfg(has_i128)]
+ fn from_i128(n: i128) -> Option<Self> {
+ n.to_i64().and_then(FromPrimitive::from_i64)
}
- /// Convert an `i64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- fn from_i64(n: i64) -> Option<Self>;
-
- /// Convert a `usize` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts a `usize` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_usize(n: usize) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
+ n.to_u64().and_then(FromPrimitive::from_u64)
}
- /// Convert an `u8` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `u8` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_u8(n: u8) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
+ FromPrimitive::from_u64(From::from(n))
}
- /// Convert an `u16` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `u16` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_u16(n: u16) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
+ FromPrimitive::from_u64(From::from(n))
+ }
+
+ /// Converts an `u32` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ #[inline]
+ fn from_u32(n: u32) -> Option<Self> {
+ FromPrimitive::from_u64(From::from(n))
}
- /// Convert an `u32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_u32(n: u32) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Convert an `u64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `u64` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
fn from_u64(n: u64) -> Option<Self>;
- /// Convert a `f32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts an `u128` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ ///
+ /// This method is only available with feature `i128` enabled on Rust >= 1.26.
+ ///
+ /// The default implementation converts through `from_u64()`. Types implementing
+ /// this trait should override this method if they can represent a greater range.
+ #[inline]
+ #[cfg(has_i128)]
+ fn from_u128(n: u128) -> Option<Self> {
+ n.to_u64().and_then(FromPrimitive::from_u64)
+ }
+
+ /// Converts a `f32` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
#[inline]
fn from_f32(n: f32) -> Option<Self> {
- FromPrimitive::from_f64(n as f64)
+ FromPrimitive::from_f64(From::from(n))
}
- /// Convert a `f64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
+ /// Converts a `f64` to return an optional value of this type. If the
+ /// value cannot be represented by this type, then `None` is returned.
+ ///
+ /// The default implementation tries to convert through `from_i64()`, and
+ /// failing that through `from_u64()`. Types implementing this trait should
+ /// override this method if they can represent a greater range.
#[inline]
fn from_f64(n: f64) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
+ match n.to_i64() {
+ Some(i) => FromPrimitive::from_i64(i),
+ None => n.to_u64().and_then(FromPrimitive::from_u64),
+ }
}
}
macro_rules! impl_from_primitive {
- ($T:ty, $to_ty:ident) => (
+ ($T:ty, $to_ty:ident) => {
#[allow(deprecated)]
impl FromPrimitive for $T {
- #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
+ #[inline]
+ fn from_isize(n: isize) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_i8(n: i8) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_i16(n: i16) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_i32(n: i32) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_i64(n: i64) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[cfg(has_i128)]
+ #[inline]
+ fn from_i128(n: i128) -> Option<$T> {
+ n.$to_ty()
+ }
- #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
+ #[inline]
+ fn from_usize(n: usize) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_u8(n: u8) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_u16(n: u16) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_u32(n: u32) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_u64(n: u64) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[cfg(has_i128)]
+ #[inline]
+ fn from_u128(n: u128) -> Option<$T> {
+ n.$to_ty()
+ }
- #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
+ #[inline]
+ fn from_f32(n: f32) -> Option<$T> {
+ n.$to_ty()
+ }
+ #[inline]
+ fn from_f64(n: f64) -> Option<$T> {
+ n.$to_ty()
+ }
}
- )
+ };
}
impl_from_primitive!(isize, to_isize);
-impl_from_primitive!(i8, to_i8);
-impl_from_primitive!(i16, to_i16);
-impl_from_primitive!(i32, to_i32);
-impl_from_primitive!(i64, to_i64);
+impl_from_primitive!(i8, to_i8);
+impl_from_primitive!(i16, to_i16);
+impl_from_primitive!(i32, to_i32);
+impl_from_primitive!(i64, to_i64);
+#[cfg(has_i128)]
+impl_from_primitive!(i128, to_i128);
impl_from_primitive!(usize, to_usize);
-impl_from_primitive!(u8, to_u8);
-impl_from_primitive!(u16, to_u16);
-impl_from_primitive!(u32, to_u32);
-impl_from_primitive!(u64, to_u64);
-impl_from_primitive!(f32, to_f32);
-impl_from_primitive!(f64, to_f64);
+impl_from_primitive!(u8, to_u8);
+impl_from_primitive!(u16, to_u16);
+impl_from_primitive!(u32, to_u32);
+impl_from_primitive!(u64, to_u64);
+#[cfg(has_i128)]
+impl_from_primitive!(u128, to_u128);
+impl_from_primitive!(f32, to_f32);
+impl_from_primitive!(f64, to_f64);
+macro_rules! impl_to_primitive_wrapping {
+ ($( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(&self) -> Option<$i> {
+ (self.0).$method()
+ }
+ )*}
+}
impl<T: ToPrimitive> ToPrimitive for Wrapping<T> {
- fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
- fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
-}
-impl<T: FromPrimitive> FromPrimitive for Wrapping<T> {
- fn from_u64(n: u64) -> Option<Self> { T::from_u64(n).map(Wrapping) }
- fn from_i64(n: i64) -> Option<Self> { T::from_i64(n).map(Wrapping) }
+ impl_to_primitive_wrapping! {
+ fn to_isize -> isize;
+ fn to_i8 -> i8;
+ fn to_i16 -> i16;
+ fn to_i32 -> i32;
+ fn to_i64 -> i64;
+ #[cfg(has_i128)]
+ fn to_i128 -> i128;
+
+ fn to_usize -> usize;
+ fn to_u8 -> u8;
+ fn to_u16 -> u16;
+ fn to_u32 -> u32;
+ fn to_u64 -> u64;
+ #[cfg(has_i128)]
+ fn to_u128 -> u128;
+
+ fn to_f32 -> f32;
+ fn to_f64 -> f64;
+ }
}
+macro_rules! impl_from_primitive_wrapping {
+ ($( $(#[$cfg:meta])* fn $method:ident ( $i:ident ); )*) => {$(
+ #[inline]
+ $(#[$cfg])*
+ fn $method(n: $i) -> Option<Self> {
+ T::$method(n).map(Wrapping)
+ }
+ )*}
+}
+
+impl<T: FromPrimitive> FromPrimitive for Wrapping<T> {
+ impl_from_primitive_wrapping! {
+ fn from_isize(isize);
+ fn from_i8(i8);
+ fn from_i16(i16);
+ fn from_i32(i32);
+ fn from_i64(i64);
+ #[cfg(has_i128)]
+ fn from_i128(i128);
+
+ fn from_usize(usize);
+ fn from_u8(u8);
+ fn from_u16(u16);
+ fn from_u32(u32);
+ fn from_u64(u64);
+ #[cfg(has_i128)]
+ fn from_u128(u128);
+
+ fn from_f32(f32);
+ fn from_f64(f64);
+ }
+}
/// Cast from one machine scalar to another.
///
/// # Examples
///
/// ```
/// # use num_traits as num;
/// let twenty: f32 = num::cast(0x14).unwrap();
@@ -413,182 +685,130 @@ impl<T: FromPrimitive> FromPrimitive for
#[inline]
pub fn cast<T: NumCast, U: NumCast>(n: T) -> Option<U> {
NumCast::from(n)
}
/// An interface for casting between machine scalars.
pub trait NumCast: Sized + ToPrimitive {
/// Creates a number from another value that can be converted into
- /// a primitive via the `ToPrimitive` trait.
+ /// a primitive via the `ToPrimitive` trait. If the source value cannot be
+ /// represented by the target type, then `None` is returned.
+ ///
+ /// A value can be represented by the target type when it lies within
+ /// the range of scalars supported by the target type.
+ /// For example, a negative integer cannot be represented by an unsigned
+ /// integer type, and an `i64` with a very high magnitude might not be
+ /// convertible to an `i32`.
+ /// On the other hand, conversions with possible precision loss or truncation
+ /// are admitted, like an `f32` with a decimal part to an integer type, or
+ /// even a large `f64` saturating to `f32` infinity.
fn from<T: ToPrimitive>(n: T) -> Option<Self>;
}
macro_rules! impl_num_cast {
- ($T:ty, $conv:ident) => (
+ ($T:ty, $conv:ident) => {
impl NumCast for $T {
#[inline]
#[allow(deprecated)]
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
// `$conv` could be generated using `concat_idents!`, but that
// macro seems to be broken at the moment
n.$conv()
}
}
- )
+ };
}
-impl_num_cast!(u8, to_u8);
-impl_num_cast!(u16, to_u16);
-impl_num_cast!(u32, to_u32);
-impl_num_cast!(u64, to_u64);
+impl_num_cast!(u8, to_u8);
+impl_num_cast!(u16, to_u16);
+impl_num_cast!(u32, to_u32);
+impl_num_cast!(u64, to_u64);
+#[cfg(has_i128)]
+impl_num_cast!(u128, to_u128);
impl_num_cast!(usize, to_usize);
-impl_num_cast!(i8, to_i8);
-impl_num_cast!(i16, to_i16);
-impl_num_cast!(i32, to_i32);
-impl_num_cast!(i64, to_i64);
+impl_num_cast!(i8, to_i8);
+impl_num_cast!(i16, to_i16);
+impl_num_cast!(i32, to_i32);
+impl_num_cast!(i64, to_i64);
+#[cfg(has_i128)]
+impl_num_cast!(i128, to_i128);
impl_num_cast!(isize, to_isize);
-impl_num_cast!(f32, to_f32);
-impl_num_cast!(f64, to_f64);
+impl_num_cast!(f32, to_f32);
+impl_num_cast!(f64, to_f64);
impl<T: NumCast> NumCast for Wrapping<T> {
fn from<U: ToPrimitive>(n: U) -> Option<Self> {
T::from(n).map(Wrapping)
}
}
/// A generic interface for casting between machine scalars with the
/// `as` operator, which admits narrowing and precision loss.
-/// Implementers of this trait AsPrimitive should behave like a primitive
+/// Implementers of this trait `AsPrimitive` should behave like a primitive
/// numeric type (e.g. a newtype around another primitive), and the
/// intended conversion must never fail.
///
/// # Examples
///
/// ```
/// # use num_traits::AsPrimitive;
/// let three: i32 = (3.14159265f32).as_();
/// assert_eq!(three, 3);
/// ```
-///
+///
/// # Safety
-///
-/// Currently, some uses of the `as` operator are not entirely safe.
-/// In particular, it is undefined behavior if:
-///
-/// - A truncated floating point value cannot fit in the target integer
-/// type ([#10184](https://github.com/rust-lang/rust/issues/10184));
-///
+///
+/// **In Rust versions before 1.45.0**, some uses of the `as` operator were not entirely safe.
+/// In particular, it was undefined behavior if
+/// a truncated floating point value could not fit in the target integer
+/// type ([#10184](https://github.com/rust-lang/rust/issues/10184)).
+///
/// ```ignore
/// # use num_traits::AsPrimitive;
/// let x: u8 = (1.04E+17).as_(); // UB
/// ```
-///
-/// - Or a floating point value does not fit in another floating
-/// point type ([#15536](https://github.com/rust-lang/rust/issues/15536)).
///
-/// ```ignore
-/// # use num_traits::AsPrimitive;
-/// let x: f32 = (1e300f64).as_(); // UB
-/// ```
-///
pub trait AsPrimitive<T>: 'static + Copy
where
- T: 'static + Copy
+ T: 'static + Copy,
{
/// Convert a value to another, using the `as` operator.
fn as_(self) -> T;
}
macro_rules! impl_as_primitive {
- ($T: ty => $( $U: ty ),* ) => {
- $(
+ (@ $T: ty => $(#[$cfg:meta])* impl $U: ty ) => {
+ $(#[$cfg])*
impl AsPrimitive<$U> for $T {
#[inline] fn as_(self) -> $U { self as $U }
}
- )*
+ };
+ (@ $T: ty => { $( $U: ty ),* } ) => {$(
+ impl_as_primitive!(@ $T => impl $U);
+ )*};
+ ($T: ty => { $( $U: ty ),* } ) => {
+ impl_as_primitive!(@ $T => { $( $U ),* });
+ impl_as_primitive!(@ $T => { u8, u16, u32, u64, usize });
+ impl_as_primitive!(@ $T => #[cfg(has_i128)] impl u128);
+ impl_as_primitive!(@ $T => { i8, i16, i32, i64, isize });
+ impl_as_primitive!(@ $T => #[cfg(has_i128)] impl i128);
};
}
-impl_as_primitive!(u8 => char, u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(i8 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(u16 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(i16 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(u32 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(i32 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(u64 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(i64 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(usize => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(isize => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(f32 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(f64 => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64, f32, f64);
-impl_as_primitive!(char => char, u8, i8, u16, i16, u32, i32, u64, isize, usize, i64);
-impl_as_primitive!(bool => u8, i8, u16, i16, u32, i32, u64, isize, usize, i64);
-
-#[test]
-fn to_primitive_float() {
- use core::f32;
- use core::f64;
-
- let f32_toolarge = 1e39f64;
- assert_eq!(f32_toolarge.to_f32(), None);
- assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX));
- assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX));
- assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY));
- assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY));
- assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan()));
-}
-
-#[test]
-fn wrapping_to_primitive() {
- macro_rules! test_wrapping_to_primitive {
- ($($t:ty)+) => {
- $({
- let i: $t = 0;
- let w = Wrapping(i);
- assert_eq!(i.to_u8(), w.to_u8());
- assert_eq!(i.to_u16(), w.to_u16());
- assert_eq!(i.to_u32(), w.to_u32());
- assert_eq!(i.to_u64(), w.to_u64());
- assert_eq!(i.to_usize(), w.to_usize());
- assert_eq!(i.to_i8(), w.to_i8());
- assert_eq!(i.to_i16(), w.to_i16());
- assert_eq!(i.to_i32(), w.to_i32());
- assert_eq!(i.to_i64(), w.to_i64());
- assert_eq!(i.to_isize(), w.to_isize());
- assert_eq!(i.to_f32(), w.to_f32());
- assert_eq!(i.to_f64(), w.to_f64());
- })+
- };
- }
-
- test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
-}
-
-#[test]
-fn wrapping_is_toprimitive() {
- fn require_toprimitive<T: ToPrimitive>(_: &T) {}
- require_toprimitive(&Wrapping(42));
-}
-
-#[test]
-fn wrapping_is_fromprimitive() {
- fn require_fromprimitive<T: FromPrimitive>(_: &T) {}
- require_fromprimitive(&Wrapping(42));
-}
-
-#[test]
-fn wrapping_is_numcast() {
- fn require_numcast<T: NumCast>(_: &T) {}
- require_numcast(&Wrapping(42));
-}
-
-#[test]
-fn as_primitive() {
- let x: f32 = (1.625f64).as_();
- assert_eq!(x, 1.625f32);
-
- let x: f32 = (3.14159265358979323846f64).as_();
- assert_eq!(x, 3.1415927f32);
-
- let x: u8 = (768i16).as_();
- assert_eq!(x, 0);
-}
+impl_as_primitive!(u8 => { char, f32, f64 });
+impl_as_primitive!(i8 => { f32, f64 });
+impl_as_primitive!(u16 => { f32, f64 });
+impl_as_primitive!(i16 => { f32, f64 });
+impl_as_primitive!(u32 => { f32, f64 });
+impl_as_primitive!(i32 => { f32, f64 });
+impl_as_primitive!(u64 => { f32, f64 });
+impl_as_primitive!(i64 => { f32, f64 });
+#[cfg(has_i128)]
+impl_as_primitive!(u128 => { f32, f64 });
+#[cfg(has_i128)]
+impl_as_primitive!(i128 => { f32, f64 });
+impl_as_primitive!(usize => { f32, f64 });
+impl_as_primitive!(isize => { f32, f64 });
+impl_as_primitive!(f32 => { f32, f64 });
+impl_as_primitive!(f64 => { f32, f64 });
+impl_as_primitive!(char => { char });
+impl_as_primitive!(bool => {});
diff --git a/third_party/rust/num-traits/src/float.rs b/third_party/rust/num-traits/src/float.rs
--- a/third_party/rust/num-traits/src/float.rs
+++ b/third_party/rust/num-traits/src/float.rs
@@ -1,36 +1,969 @@
-#[cfg(feature = "std")]
-use std::mem;
-#[cfg(feature = "std")]
-use std::ops::Neg;
-#[cfg(feature = "std")]
-use std::num::FpCategory;
+use core::mem;
+use core::num::FpCategory;
+use core::ops::{Add, Div, Neg};
+
+use core::f32;
+use core::f64;
+
+use {Num, NumCast, ToPrimitive};
+
+#[cfg(all(not(feature = "std"), feature = "libm"))]
+use libm;
+
+/// Generic trait for floating point numbers that works with `no_std`.
+///
+/// This trait implements a subset of the `Float` trait.
+pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
+ /// Returns positive infinity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::infinity() == x);
+ /// }
+ ///
+ /// check(f32::INFINITY);
+ /// check(f64::INFINITY);
+ /// ```
+ fn infinity() -> Self;
+
+ /// Returns negative infinity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::neg_infinity() == x);
+ /// }
+ ///
+ /// check(f32::NEG_INFINITY);
+ /// check(f64::NEG_INFINITY);
+ /// ```
+ fn neg_infinity() -> Self;
+
+ /// Returns NaN.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ ///
+ /// fn check<T: FloatCore>() {
+ /// let n = T::nan();
+ /// assert!(n != n);
+ /// }
+ ///
+ /// check::<f32>();
+ /// check::<f64>();
+ /// ```
+ fn nan() -> Self;
+
+ /// Returns `-0.0`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(n: T) {
+ /// let z = T::neg_zero();
+ /// assert!(z.is_zero());
+ /// assert!(T::one() / z == n);
+ /// }
+ ///
+ /// check(f32::NEG_INFINITY);
+ /// check(f64::NEG_INFINITY);
+ /// ```
+ fn neg_zero() -> Self;
+
+ /// Returns the smallest finite value that this type can represent.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::min_value() == x);
+ /// }
+ ///
+ /// check(f32::MIN);
+ /// check(f64::MIN);
+ /// ```
+ fn min_value() -> Self;
+
+ /// Returns the smallest positive, normalized value that this type can represent.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::min_positive_value() == x);
+ /// }
+ ///
+ /// check(f32::MIN_POSITIVE);
+ /// check(f64::MIN_POSITIVE);
+ /// ```
+ fn min_positive_value() -> Self;
+
+ /// Returns epsilon, a small positive value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::epsilon() == x);
+ /// }
+ ///
+ /// check(f32::EPSILON);
+ /// check(f64::EPSILON);
+ /// ```
+ fn epsilon() -> Self;
+
+ /// Returns the largest finite value that this type can represent.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T) {
+ /// assert!(T::max_value() == x);
+ /// }
+ ///
+ /// check(f32::MAX);
+ /// check(f64::MAX);
+ /// ```
+ fn max_value() -> Self;
+
+ /// Returns `true` if the number is NaN.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_nan() == p);
+ /// }
+ ///
+ /// check(f32::NAN, true);
+ /// check(f32::INFINITY, false);
+ /// check(f64::NAN, true);
+ /// check(0.0f64, false);
+ /// ```
+ #[inline]
+ fn is_nan(self) -> bool {
+ self != self
+ }
+
+ /// Returns `true` if the number is infinite.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_infinite() == p);
+ /// }
+ ///
+ /// check(f32::INFINITY, true);
+ /// check(f32::NEG_INFINITY, true);
+ /// check(f32::NAN, false);
+ /// check(f64::INFINITY, true);
+ /// check(f64::NEG_INFINITY, true);
+ /// check(0.0f64, false);
+ /// ```
+ #[inline]
+ fn is_infinite(self) -> bool {
+ self == Self::infinity() || self == Self::neg_infinity()
+ }
+
+ /// Returns `true` if the number is neither infinite or NaN.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_finite() == p);
+ /// }
+ ///
+ /// check(f32::INFINITY, false);
+ /// check(f32::MAX, true);
+ /// check(f64::NEG_INFINITY, false);
+ /// check(f64::MIN_POSITIVE, true);
+ /// check(f64::NAN, false);
+ /// ```
+ #[inline]
+ fn is_finite(self) -> bool {
+ !(self.is_nan() || self.is_infinite())
+ }
+
+ /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_normal() == p);
+ /// }
+ ///
+ /// check(f32::INFINITY, false);
+ /// check(f32::MAX, true);
+ /// check(f64::NEG_INFINITY, false);
+ /// check(f64::MIN_POSITIVE, true);
+ /// check(0.0f64, false);
+ /// ```
+ #[inline]
+ fn is_normal(self) -> bool {
+ self.classify() == FpCategory::Normal
+ }
+
+ /// Returns the floating point category of the number. If only one property
+ /// is going to be tested, it is generally faster to use the specific
+ /// predicate instead.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ /// use std::num::FpCategory;
+ ///
+ /// fn check<T: FloatCore>(x: T, c: FpCategory) {
+ /// assert!(x.classify() == c);
+ /// }
+ ///
+ /// check(f32::INFINITY, FpCategory::Infinite);
+ /// check(f32::MAX, FpCategory::Normal);
+ /// check(f64::NAN, FpCategory::Nan);
+ /// check(f64::MIN_POSITIVE, FpCategory::Normal);
+ /// check(f64::MIN_POSITIVE / 2.0, FpCategory::Subnormal);
+ /// check(0.0f64, FpCategory::Zero);
+ /// ```
+ fn classify(self) -> FpCategory;
+
+ /// Returns the largest integer less than or equal to a number.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.floor() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, f32::INFINITY);
+ /// check(0.9f32, 0.0);
+ /// check(1.0f32, 1.0);
+ /// check(1.1f32, 1.0);
+ /// check(-0.0f64, 0.0);
+ /// check(-0.9f64, -1.0);
+ /// check(-1.0f64, -1.0);
+ /// check(-1.1f64, -2.0);
+ /// check(f64::MIN, f64::MIN);
+ /// ```
+ #[inline]
+ fn floor(self) -> Self {
+ let f = self.fract();
+ if f.is_nan() || f.is_zero() {
+ self
+ } else if self < Self::zero() {
+ self - f - Self::one()
+ } else {
+ self - f
+ }
+ }
+
+ /// Returns the smallest integer greater than or equal to a number.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.ceil() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, f32::INFINITY);
+ /// check(0.9f32, 1.0);
+ /// check(1.0f32, 1.0);
+ /// check(1.1f32, 2.0);
+ /// check(-0.0f64, 0.0);
+ /// check(-0.9f64, -0.0);
+ /// check(-1.0f64, -1.0);
+ /// check(-1.1f64, -1.0);
+ /// check(f64::MIN, f64::MIN);
+ /// ```
+ #[inline]
+ fn ceil(self) -> Self {
+ let f = self.fract();
+ if f.is_nan() || f.is_zero() {
+ self
+ } else if self > Self::zero() {
+ self - f + Self::one()
+ } else {
+ self - f
+ }
+ }
+
+ /// Returns the nearest integer to a number. Round half-way cases away from `0.0`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.round() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, f32::INFINITY);
+ /// check(0.4f32, 0.0);
+ /// check(0.5f32, 1.0);
+ /// check(0.6f32, 1.0);
+ /// check(-0.4f64, 0.0);
+ /// check(-0.5f64, -1.0);
+ /// check(-0.6f64, -1.0);
+ /// check(f64::MIN, f64::MIN);
+ /// ```
+ #[inline]
+ fn round(self) -> Self {
+ let one = Self::one();
+ let h = Self::from(0.5).expect("Unable to cast from 0.5");
+ let f = self.fract();
+ if f.is_nan() || f.is_zero() {
+ self
+ } else if self > Self::zero() {
+ if f < h {
+ self - f
+ } else {
+ self - f + one
+ }
+ } else {
+ if -f < h {
+ self - f
+ } else {
+ self - f - one
+ }
+ }
+ }
+
+ /// Return the integer part of a number.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.trunc() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, f32::INFINITY);
+ /// check(0.9f32, 0.0);
+ /// check(1.0f32, 1.0);
+ /// check(1.1f32, 1.0);
+ /// check(-0.0f64, 0.0);
+ /// check(-0.9f64, -0.0);
+ /// check(-1.0f64, -1.0);
+ /// check(-1.1f64, -1.0);
+ /// check(f64::MIN, f64::MIN);
+ /// ```
+ #[inline]
+ fn trunc(self) -> Self {
+ let f = self.fract();
+ if f.is_nan() {
+ self
+ } else {
+ self - f
+ }
+ }
+
+ /// Returns the fractional part of a number.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.fract() == y);
+ /// }
+ ///
+ /// check(f32::MAX, 0.0);
+ /// check(0.75f32, 0.75);
+ /// check(1.0f32, 0.0);
+ /// check(1.25f32, 0.25);
+ /// check(-0.0f64, 0.0);
+ /// check(-0.75f64, -0.75);
+ /// check(-1.0f64, 0.0);
+ /// check(-1.25f64, -0.25);
+ /// check(f64::MIN, 0.0);
+ /// ```
+ #[inline]
+ fn fract(self) -> Self {
+ if self.is_zero() {
+ Self::zero()
+ } else {
+ self % Self::one()
+ }
+ }
+
+ /// Computes the absolute value of `self`. Returns `FloatCore::nan()` if the
+ /// number is `FloatCore::nan()`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.abs() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, f32::INFINITY);
+ /// check(1.0f32, 1.0);
+ /// check(0.0f64, 0.0);
+ /// check(-0.0f64, 0.0);
+ /// check(-1.0f64, 1.0);
+ /// check(f64::MIN, f64::MAX);
+ /// ```
+ #[inline]
+ fn abs(self) -> Self {
+ if self.is_sign_positive() {
+ return self;
+ }
+ if self.is_sign_negative() {
+ return -self;
+ }
+ Self::nan()
+ }
-// Used for default implementation of `epsilon`
-#[cfg(feature = "std")]
-use std::f32;
+ /// Returns a number that represents the sign of `self`.
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `FloatCore::infinity()`
+ /// - `-1.0` if the number is negative, `-0.0` or `FloatCore::neg_infinity()`
+ /// - `FloatCore::nan()` if the number is `FloatCore::nan()`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.signum() == y);
+ /// }
+ ///
+ /// check(f32::INFINITY, 1.0);
+ /// check(3.0f32, 1.0);
+ /// check(0.0f32, 1.0);
+ /// check(-0.0f64, -1.0);
+ /// check(-3.0f64, -1.0);
+ /// check(f64::MIN, -1.0);
+ /// ```
+ #[inline]
+ fn signum(self) -> Self {
+ if self.is_nan() {
+ Self::nan()
+ } else if self.is_sign_negative() {
+ -Self::one()
+ } else {
+ Self::one()
+ }
+ }
+
+ /// Returns `true` if `self` is positive, including `+0.0` and
+ /// `FloatCore::infinity()`, and since Rust 1.20 also
+ /// `FloatCore::nan()`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_sign_positive() == p);
+ /// }
+ ///
+ /// check(f32::INFINITY, true);
+ /// check(f32::MAX, true);
+ /// check(0.0f32, true);
+ /// check(-0.0f64, false);
+ /// check(f64::NEG_INFINITY, false);
+ /// check(f64::MIN_POSITIVE, true);
+ /// check(-f64::NAN, false);
+ /// ```
+ #[inline]
+ fn is_sign_positive(self) -> bool {
+ !self.is_sign_negative()
+ }
+
+ /// Returns `true` if `self` is negative, including `-0.0` and
+ /// `FloatCore::neg_infinity()`, and since Rust 1.20 also
+ /// `-FloatCore::nan()`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, p: bool) {
+ /// assert!(x.is_sign_negative() == p);
+ /// }
+ ///
+ /// check(f32::INFINITY, false);
+ /// check(f32::MAX, false);
+ /// check(0.0f32, false);
+ /// check(-0.0f64, true);
+ /// check(f64::NEG_INFINITY, true);
+ /// check(f64::MIN_POSITIVE, false);
+ /// check(f64::NAN, false);
+ /// ```
+ #[inline]
+ fn is_sign_negative(self) -> bool {
+ let (_, _, sign) = self.integer_decode();
+ sign < 0
+ }
+
+ /// Returns the minimum of the two numbers.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T, min: T) {
+ /// assert!(x.min(y) == min);
+ /// }
+ ///
+ /// check(1.0f32, 2.0, 1.0);
+ /// check(f32::NAN, 2.0, 2.0);
+ /// check(1.0f64, -2.0, -2.0);
+ /// check(1.0f64, f64::NAN, 1.0);
+ /// ```
+ #[inline]
+ fn min(self, other: Self) -> Self {
+ if self.is_nan() {
+ return other;
+ }
+ if other.is_nan() {
+ return self;
+ }
+ if self < other {
+ self
+ } else {
+ other
+ }
+ }
+
+ /// Returns the maximum of the two numbers.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T, max: T) {
+ /// assert!(x.max(y) == max);
+ /// }
+ ///
+ /// check(1.0f32, 2.0, 2.0);
+ /// check(1.0f32, f32::NAN, 1.0);
+ /// check(-1.0f64, 2.0, 2.0);
+ /// check(-1.0f64, f64::NAN, -1.0);
+ /// ```
+ #[inline]
+ fn max(self, other: Self) -> Self {
+ if self.is_nan() {
+ return other;
+ }
+ if other.is_nan() {
+ return self;
+ }
+ if self > other {
+ self
+ } else {
+ other
+ }
+ }
+
+ /// Returns the reciprocal (multiplicative inverse) of the number.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, y: T) {
+ /// assert!(x.recip() == y);
+ /// assert!(y.recip() == x);
+ /// }
+ ///
+ /// check(f32::INFINITY, 0.0);
+ /// check(2.0f32, 0.5);
+ /// check(-0.25f64, -4.0);
+ /// check(-0.0f64, f64::NEG_INFINITY);
+ /// ```
+ #[inline]
+ fn recip(self) -> Self {
+ Self::one() / self
+ }
+
+ /// Raise a number to an integer power.
+ ///
+ /// Using this function is generally faster than using `powf`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ ///
+ /// fn check<T: FloatCore>(x: T, exp: i32, powi: T) {
+ /// assert!(x.powi(exp) == powi);
+ /// }
+ ///
+ /// check(9.0f32, 2, 81.0);
+ /// check(1.0f32, -2, 1.0);
+ /// check(10.0f64, 20, 1e20);
+ /// check(4.0f64, -2, 0.0625);
+ /// check(-1.0f64, std::i32::MIN, 1.0);
+ /// ```
+ #[inline]
+ fn powi(mut self, mut exp: i32) -> Self {
+ if exp < 0 {
+ exp = exp.wrapping_neg();
+ self = self.recip();
+ }
+ // It should always be possible to convert a positive `i32` to a `usize`.
+ // Note, `i32::MIN` will wrap and still be negative, so we need to convert
+ // to `u32` without sign-extension before growing to `usize`.
+ super::pow(self, (exp as u32).to_usize().unwrap())
+ }
+
+ /// Converts to degrees, assuming the number is in radians.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(rad: T, deg: T) {
+ /// assert!(rad.to_degrees() == deg);
+ /// }
+ ///
+ /// check(0.0f32, 0.0);
+ /// check(f32::consts::PI, 180.0);
+ /// check(f64::consts::FRAC_PI_4, 45.0);
+ /// check(f64::INFINITY, f64::INFINITY);
+ /// ```
+ fn to_degrees(self) -> Self;
-#[cfg(feature = "std")]
-use {Num, NumCast};
+ /// Converts to radians, assuming the number is in degrees.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(deg: T, rad: T) {
+ /// assert!(deg.to_radians() == rad);
+ /// }
+ ///
+ /// check(0.0f32, 0.0);
+ /// check(180.0, f32::consts::PI);
+ /// check(45.0, f64::consts::FRAC_PI_4);
+ /// check(f64::INFINITY, f64::INFINITY);
+ /// ```
+ fn to_radians(self) -> Self;
+
+ /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
+ /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::float::FloatCore;
+ /// use std::{f32, f64};
+ ///
+ /// fn check<T: FloatCore>(x: T, m: u64, e: i16, s:i8) {
+ /// let (mantissa, exponent, sign) = x.integer_decode();
+ /// assert_eq!(mantissa, m);
+ /// assert_eq!(exponent, e);
+ /// assert_eq!(sign, s);
+ /// }
+ ///
+ /// check(2.0f32, 1 << 23, -22, 1);
+ /// check(-2.0f32, 1 << 23, -22, -1);
+ /// check(f32::INFINITY, 1 << 23, 105, 1);
+ /// check(f64::NEG_INFINITY, 1 << 52, 972, -1);
+ /// ```
+ fn integer_decode(self) -> (u64, i16, i8);
+}
+
+impl FloatCore for f32 {
+ constant! {
+ infinity() -> f32::INFINITY;
+ neg_infinity() -> f32::NEG_INFINITY;
+ nan() -> f32::NAN;
+ neg_zero() -> -0.0;
+ min_value() -> f32::MIN;
+ min_positive_value() -> f32::MIN_POSITIVE;
+ epsilon() -> f32::EPSILON;
+ max_value() -> f32::MAX;
+ }
+
+ #[inline]
+ fn integer_decode(self) -> (u64, i16, i8) {
+ integer_decode_f32(self)
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn classify(self) -> FpCategory {
+ const EXP_MASK: u32 = 0x7f800000;
+ const MAN_MASK: u32 = 0x007fffff;
+
+ // Safety: this identical to the implementation of f32::to_bits(),
+ // which is only available starting at Rust 1.20
+ let bits: u32 = unsafe { mem::transmute(self) };
+ match (bits & MAN_MASK, bits & EXP_MASK) {
+ (0, 0) => FpCategory::Zero,
+ (_, 0) => FpCategory::Subnormal,
+ (0, EXP_MASK) => FpCategory::Infinite,
+ (_, EXP_MASK) => FpCategory::Nan,
+ _ => FpCategory::Normal,
+ }
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn is_sign_negative(self) -> bool {
+ const SIGN_MASK: u32 = 0x80000000;
+
+ // Safety: this identical to the implementation of f32::to_bits(),
+ // which is only available starting at Rust 1.20
+ let bits: u32 = unsafe { mem::transmute(self) };
+ bits & SIGN_MASK != 0
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn to_degrees(self) -> Self {
+ // Use a constant for better precision.
+ const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
+ self * PIS_IN_180
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn to_radians(self) -> Self {
+ self * (f32::consts::PI / 180.0)
+ }
+
+ #[cfg(feature = "std")]
+ forward! {
+ Self::is_nan(self) -> bool;
+ Self::is_infinite(self) -> bool;
+ Self::is_finite(self) -> bool;
+ Self::is_normal(self) -> bool;
+ Self::classify(self) -> FpCategory;
+ Self::floor(self) -> Self;
+ Self::ceil(self) -> Self;
+ Self::round(self) -> Self;
+ Self::trunc(self) -> Self;
+ Self::fract(self) -> Self;
+ Self::abs(self) -> Self;
+ Self::signum(self) -> Self;
+ Self::is_sign_positive(self) -> bool;
+ Self::is_sign_negative(self) -> bool;
+ Self::min(self, other: Self) -> Self;
+ Self::max(self, other: Self) -> Self;
+ Self::recip(self) -> Self;
+ Self::powi(self, n: i32) -> Self;
+ Self::to_degrees(self) -> Self;
+ Self::to_radians(self) -> Self;
+ }
+
+ #[cfg(all(not(feature = "std"), feature = "libm"))]
+ forward! {
+ libm::floorf as floor(self) -> Self;
+ libm::ceilf as ceil(self) -> Self;
+ libm::roundf as round(self) -> Self;
+ libm::truncf as trunc(self) -> Self;
+ libm::fabsf as abs(self) -> Self;
+ libm::fminf as min(self, other: Self) -> Self;
+ libm::fmaxf as max(self, other: Self) -> Self;
+ }
+
+ #[cfg(all(not(feature = "std"), feature = "libm"))]
+ #[inline]
+ fn fract(self) -> Self {
+ self - libm::truncf(self)
+ }
+}
+
+impl FloatCore for f64 {
+ constant! {
+ infinity() -> f64::INFINITY;
+ neg_infinity() -> f64::NEG_INFINITY;
+ nan() -> f64::NAN;
+ neg_zero() -> -0.0;
+ min_value() -> f64::MIN;
+ min_positive_value() -> f64::MIN_POSITIVE;
+ epsilon() -> f64::EPSILON;
+ max_value() -> f64::MAX;
+ }
+
+ #[inline]
+ fn integer_decode(self) -> (u64, i16, i8) {
+ integer_decode_f64(self)
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn classify(self) -> FpCategory {
+ const EXP_MASK: u64 = 0x7ff0000000000000;
+ const MAN_MASK: u64 = 0x000fffffffffffff;
+
+ // Safety: this identical to the implementation of f64::to_bits(),
+ // which is only available starting at Rust 1.20
+ let bits: u64 = unsafe { mem::transmute(self) };
+ match (bits & MAN_MASK, bits & EXP_MASK) {
+ (0, 0) => FpCategory::Zero,
+ (_, 0) => FpCategory::Subnormal,
+ (0, EXP_MASK) => FpCategory::Infinite,
+ (_, EXP_MASK) => FpCategory::Nan,
+ _ => FpCategory::Normal,
+ }
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn is_sign_negative(self) -> bool {
+ const SIGN_MASK: u64 = 0x8000000000000000;
+
+ // Safety: this identical to the implementation of f64::to_bits(),
+ // which is only available starting at Rust 1.20
+ let bits: u64 = unsafe { mem::transmute(self) };
+ bits & SIGN_MASK != 0
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn to_degrees(self) -> Self {
+ // The division here is correctly rounded with respect to the true
+ // value of 180/π. (This differs from f32, where a constant must be
+ // used to ensure a correctly rounded result.)
+ self * (180.0 / f64::consts::PI)
+ }
+
+ #[inline]
+ #[cfg(not(feature = "std"))]
+ fn to_radians(self) -> Self {
+ self * (f64::consts::PI / 180.0)
+ }
+
+ #[cfg(feature = "std")]
+ forward! {
+ Self::is_nan(self) -> bool;
+ Self::is_infinite(self) -> bool;
+ Self::is_finite(self) -> bool;
+ Self::is_normal(self) -> bool;
+ Self::classify(self) -> FpCategory;
+ Self::floor(self) -> Self;
+ Self::ceil(self) -> Self;
+ Self::round(self) -> Self;
+ Self::trunc(self) -> Self;
+ Self::fract(self) -> Self;
+ Self::abs(self) -> Self;
+ Self::signum(self) -> Self;
+ Self::is_sign_positive(self) -> bool;
+ Self::is_sign_negative(self) -> bool;
+ Self::min(self, other: Self) -> Self;
+ Self::max(self, other: Self) -> Self;
+ Self::recip(self) -> Self;
+ Self::powi(self, n: i32) -> Self;
+ Self::to_degrees(self) -> Self;
+ Self::to_radians(self) -> Self;
+ }
+
+ #[cfg(all(not(feature = "std"), feature = "libm"))]
+ forward! {
+ libm::floor as floor(self) -> Self;
+ libm::ceil as ceil(self) -> Self;
+ libm::round as round(self) -> Self;
+ libm::trunc as trunc(self) -> Self;
+ libm::fabs as abs(self) -> Self;
+ libm::fmin as min(self, other: Self) -> Self;
+ libm::fmax as max(self, other: Self) -> Self;
+ }
+
+ #[cfg(all(not(feature = "std"), feature = "libm"))]
+ #[inline]
+ fn fract(self) -> Self {
+ self - libm::trunc(self)
+ }
+}
// FIXME: these doctests aren't actually helpful, because they're using and
// testing the inherent methods directly, not going through `Float`.
/// Generic trait for floating point numbers
///
-/// This trait is only available with the `std` feature.
-#[cfg(feature = "std")]
-pub trait Float
- : Num
- + Copy
- + NumCast
- + PartialOrd
- + Neg<Output = Self>
-{
+/// This trait is only available with the `std` feature, or with the `libm` feature otherwise.
+#[cfg(any(feature = "std", feature = "libm"))]
+pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
/// Returns the `NaN` value.
///
/// ```
/// use num_traits::Float;
///
/// let nan: f32 = Float::nan();
///
/// assert!(nan.is_nan());
@@ -328,17 +1261,17 @@ pub trait Float
/// assert_eq!(f.signum(), 1.0);
/// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
///
/// assert!(f64::NAN.signum().is_nan());
/// ```
fn signum(self) -> Self;
/// Returns `true` if `self` is positive, including `+0.0`,
- /// `Float::infinity()`, and with newer versions of Rust `f64::NAN`.
+ /// `Float::infinity()`, and since Rust 1.20 also `Float::nan()`.
///
/// ```
/// use num_traits::Float;
/// use std::f64;
///
/// let neg_nan: f64 = -f64::NAN;
///
/// let f = 7.0;
@@ -346,17 +1279,17 @@ pub trait Float
///
/// assert!(f.is_sign_positive());
/// assert!(!g.is_sign_positive());
/// assert!(!neg_nan.is_sign_positive());
/// ```
fn is_sign_positive(self) -> bool;
/// Returns `true` if `self` is negative, including `-0.0`,
- /// `Float::neg_infinity()`, and with newer versions of Rust `-f64::NAN`.
+ /// `Float::neg_infinity()`, and since Rust 1.20 also `-Float::nan()`.
///
/// ```
/// use num_traits::Float;
/// use std::f64;
///
/// let nan: f64 = f64::NAN;
///
/// let f = 7.0;
@@ -364,18 +1297,20 @@ pub trait Float
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// assert!(!nan.is_sign_negative());
/// ```
fn is_sign_negative(self) -> bool;
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
- /// error. This produces a more accurate result with better performance than
- /// a separate multiplication operation followed by an add.
+ /// error, yielding a more accurate result than an unfused multiply-add.
+ ///
+ /// Using `mul_add` can be more performant than an unfused multiply-add if
+ /// the target architecture has a dedicated `fma` CPU instruction.
///
/// ```
/// use num_traits::Float;
///
/// let m = 10.0;
/// let x = 4.0;
/// let b = 60.0;
///
@@ -902,20 +1837,18 @@ pub trait Float
/// let f = e.tanh().atanh();
///
/// let abs_difference = (f - e).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
fn atanh(self) -> Self;
-
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
- /// The floating point encoding is documented in the [Reference][floating-point].
///
/// ```
/// use num_traits::Float;
///
/// let num = 2.0f32;
///
/// // (8388608, -22, 1)
/// let (mantissa, exponent, sign) = Float::integer_decode(num);
@@ -923,377 +1856,344 @@ pub trait Float
/// let mantissa_f = mantissa as f32;
/// let exponent_f = num.powf(exponent as f32);
///
/// // 1 * 8388608 * 2^(-22) == 2
/// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
- /// [floating-point]: ../../../../../reference.html#machine-types
fn integer_decode(self) -> (u64, i16, i8);
+
+ /// Returns a number composed of the magnitude of `self` and the sign of
+ /// `sign`.
+ ///
+ /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
+ /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
+ /// `sign` is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::Float;
+ ///
+ /// let f = 3.5_f32;
+ ///
+ /// assert_eq!(f.copysign(0.42), 3.5_f32);
+ /// assert_eq!(f.copysign(-0.42), -3.5_f32);
+ /// assert_eq!((-f).copysign(0.42), 3.5_f32);
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
+ ///
+ /// assert!(f32::nan().copysign(1.0).is_nan());
+ /// ```
+ fn copysign(self, sign: Self) -> Self {
+ if self.is_sign_negative() == sign.is_sign_negative() {
+ self
+ } else {
+ self.neg()
+ }
+ }
}
#[cfg(feature = "std")]
-macro_rules! float_impl {
- ($T:ident $decode:ident) => (
+macro_rules! float_impl_std {
+ ($T:ident $decode:ident) => {
impl Float for $T {
- #[inline]
- fn nan() -> Self {
- ::std::$T::NAN
- }
-
- #[inline]
- fn infinity() -> Self {
- ::std::$T::INFINITY
- }
-
- #[inline]
- fn neg_infinity() -> Self {
- ::std::$T::NEG_INFINITY
- }
-
- #[inline]
- fn neg_zero() -> Self {
- -0.0
- }
-
- #[inline]
- fn min_value() -> Self {
- ::std::$T::MIN
- }
-
- #[inline]
- fn min_positive_value() -> Self {
- ::std::$T::MIN_POSITIVE
- }
-
- #[inline]
- fn epsilon() -> Self {
- ::std::$T::EPSILON
- }
-
- #[inline]
- fn max_value() -> Self {
- ::std::$T::MAX
- }
-
- #[inline]
- fn is_nan(self) -> bool {
- <$T>::is_nan(self)
- }
-
- #[inline]
- fn is_infinite(self) -> bool {
- <$T>::is_infinite(self)
- }
-
- #[inline]
- fn is_finite(self) -> bool {
- <$T>::is_finite(self)
- }
-
- #[inline]
- fn is_normal(self) -> bool {
- <$T>::is_normal(self)
- }
-
- #[inline]
- fn classify(self) -> FpCategory {
- <$T>::classify(self)
- }
-
- #[inline]
- fn floor(self) -> Self {
- <$T>::floor(self)
- }
-
- #[inline]
- fn ceil(self) -> Self {
- <$T>::ceil(self)
- }
-
- #[inline]
- fn round(self) -> Self {
- <$T>::round(self)
- }
-
- #[inline]
- fn trunc(self) -> Self {
- <$T>::trunc(self)
- }
-
- #[inline]
- fn fract(self) -> Self {
- <$T>::fract(self)
- }
-
- #[inline]
- fn abs(self) -> Self {
- <$T>::abs(self)
- }
-
- #[inline]
- fn signum(self) -> Self {
- <$T>::signum(self)
- }
-
- #[inline]
- fn is_sign_positive(self) -> bool {
- <$T>::is_sign_positive(self)
- }
-
- #[inline]
- fn is_sign_negative(self) -> bool {
- <$T>::is_sign_negative(self)
- }
-
- #[inline]
- fn mul_add(self, a: Self, b: Self) -> Self {
- <$T>::mul_add(self, a, b)
- }
-
- #[inline]
- fn recip(self) -> Self {
- <$T>::recip(self)
- }
-
- #[inline]
- fn powi(self, n: i32) -> Self {
- <$T>::powi(self, n)
- }
-
- #[inline]
- fn powf(self, n: Self) -> Self {
- <$T>::powf(self, n)
- }
-
- #[inline]
- fn sqrt(self) -> Self {
- <$T>::sqrt(self)
- }
-
- #[inline]
- fn exp(self) -> Self {
- <$T>::exp(self)
- }
-
- #[inline]
- fn exp2(self) -> Self {
- <$T>::exp2(self)
- }
-
- #[inline]
- fn ln(self) -> Self {
- <$T>::ln(self)
- }
-
- #[inline]
- fn log(self, base: Self) -> Self {
- <$T>::log(self, base)
- }
-
- #[inline]
- fn log2(self) -> Self {
- <$T>::log2(self)
- }
-
- #[inline]
- fn log10(self) -> Self {
- <$T>::log10(self)
- }
-
- #[inline]
- fn to_degrees(self) -> Self {
- // NB: `f32` didn't stabilize this until 1.7
- // <$T>::to_degrees(self)
- self * (180. / ::std::$T::consts::PI)
- }
-
- #[inline]
- fn to_radians(self) -> Self {
- // NB: `f32` didn't stabilize this until 1.7
- // <$T>::to_radians(self)
- self * (::std::$T::consts::PI / 180.)
- }
-
- #[inline]
- fn max(self, other: Self) -> Self {
- <$T>::max(self, other)
- }
-
- #[inline]
- fn min(self, other: Self) -> Self {
- <$T>::min(self, other)
+ constant! {
+ nan() -> $T::NAN;
+ infinity() -> $T::INFINITY;
+ neg_infinity() -> $T::NEG_INFINITY;
+ neg_zero() -> -0.0;
+ min_value() -> $T::MIN;
+ min_positive_value() -> $T::MIN_POSITIVE;
+ epsilon() -> $T::EPSILON;
+ max_value() -> $T::MAX;
}
#[inline]
#[allow(deprecated)]
fn abs_sub(self, other: Self) -> Self {
<$T>::abs_sub(self, other)
}
#[inline]
- fn cbrt(self) -> Self {
- <$T>::cbrt(self)
- }
-
- #[inline]
- fn hypot(self, other: Self) -> Self {
- <$T>::hypot(self, other)
- }
-
- #[inline]
- fn sin(self) -> Self {
- <$T>::sin(self)
- }
-
- #[inline]
- fn cos(self) -> Self {
- <$T>::cos(self)
- }
-
- #[inline]
- fn tan(self) -> Self {
- <$T>::tan(self)
- }
-
- #[inline]
- fn asin(self) -> Self {
- <$T>::asin(self)
- }
-
- #[inline]
- fn acos(self) -> Self {
- <$T>::acos(self)
- }
-
- #[inline]
- fn atan(self) -> Self {
- <$T>::atan(self)
- }
-
- #[inline]
- fn atan2(self, other: Self) -> Self {
- <$T>::atan2(self, other)
- }
-
- #[inline]
- fn sin_cos(self) -> (Self, Self) {
- <$T>::sin_cos(self)
- }
-
- #[inline]
- fn exp_m1(self) -> Self {
- <$T>::exp_m1(self)
- }
-
- #[inline]
- fn ln_1p(self) -> Self {
- <$T>::ln_1p(self)
- }
-
- #[inline]
- fn sinh(self) -> Self {
- <$T>::sinh(self)
- }
-
- #[inline]
- fn cosh(self) -> Self {
- <$T>::cosh(self)
- }
-
- #[inline]
- fn tanh(self) -> Self {
- <$T>::tanh(self)
- }
-
- #[inline]
- fn asinh(self) -> Self {
- <$T>::asinh(self)
- }
-
- #[inline]
- fn acosh(self) -> Self {
- <$T>::acosh(self)
- }
-
- #[inline]
- fn atanh(self) -> Self {
- <$T>::atanh(self)
- }
-
- #[inline]
fn integer_decode(self) -> (u64, i16, i8) {
$decode(self)
}
+
+ forward! {
+ Self::is_nan(self) -> bool;
+ Self::is_infinite(self) -> bool;
+ Self::is_finite(self) -> bool;
+ Self::is_normal(self) -> bool;
+ Self::classify(self) -> FpCategory;
+ Self::floor(self) -> Self;
+ Self::ceil(self) -> Self;
+ Self::round(self) -> Self;
+ Self::trunc(self) -> Self;
+ Self::fract(self) -> Self;
+ Self::abs(self) -> Self;
+ Self::signum(self) -> Self;
+ Self::is_sign_positive(self) -> bool;
+ Self::is_sign_negative(self) -> bool;
+ Self::mul_add(self, a: Self, b: Self) -> Self;
+ Self::recip(self) -> Self;
+ Self::powi(self, n: i32) -> Self;
+ Self::powf(self, n: Self) -> Self;
+ Self::sqrt(self) -> Self;
+ Self::exp(self) -> Self;
+ Self::exp2(self) -> Self;
+ Self::ln(self) -> Self;
+ Self::log(self, base: Self) -> Self;
+ Self::log2(self) -> Self;
+ Self::log10(self) -> Self;
+ Self::to_degrees(self) -> Self;
+ Self::to_radians(self) -> Self;
+ Self::max(self, other: Self) -> Self;
+ Self::min(self, other: Self) -> Self;
+ Self::cbrt(self) -> Self;
+ Self::hypot(self, other: Self) -> Self;
+ Self::sin(self) -> Self;
+ Self::cos(self) -> Self;
+ Self::tan(self) -> Self;
+ Self::asin(self) -> Self;
+ Self::acos(self) -> Self;
+ Self::atan(self) -> Self;
+ Self::atan2(self, other: Self) -> Self;
+ Self::sin_cos(self) -> (Self, Self);
+ Self::exp_m1(self) -> Self;
+ Self::ln_1p(self) -> Self;
+ Self::sinh(self) -> Self;
+ Self::cosh(self) -> Self;
+ Self::tanh(self) -> Self;
+ Self::asinh(self) -> Self;
+ Self::acosh(self) -> Self;
+ Self::atanh(self) -> Self;
+ }
+
+ #[cfg(has_copysign)]
+ #[inline]
+ fn copysign(self, sign: Self) -> Self {
+ Self::copysign(self, sign)
+ }
}
- )
+ };
}
-#[cfg(feature = "std")]
+#[cfg(all(not(feature = "std"), feature = "libm"))]
+macro_rules! float_impl_libm {
+ ($T:ident $decode:ident) => {
+ constant! {
+ nan() -> $T::NAN;
+ infinity() -> $T::INFINITY;
+ neg_infinity() -> $T::NEG_INFINITY;
+ neg_zero() -> -0.0;
+ min_value() -> $T::MIN;
+ min_positive_value() -> $T::MIN_POSITIVE;
+ epsilon() -> $T::EPSILON;
+ max_value() -> $T::MAX;
+ }
+
+ #[inline]
+ fn integer_decode(self) -> (u64, i16, i8) {
+ $decode(self)
+ }
+
+ #[inline]
+ fn fract(self) -> Self {
+ self - Float::trunc(self)
+ }
+
+ #[inline]
+ fn log(self, base: Self) -> Self {
+ self.ln() / base.ln()
+ }
+
+ forward! {
+ FloatCore::is_nan(self) -> bool;
+ FloatCore::is_infinite(self) -> bool;
+ FloatCore::is_finite(self) -> bool;
+ FloatCore::is_normal(self) -> bool;
+ FloatCore::classify(self) -> FpCategory;
+ FloatCore::signum(self) -> Self;
+ FloatCore::is_sign_positive(self) -> bool;
+ FloatCore::is_sign_negative(self) -> bool;
+ FloatCore::recip(self) -> Self;
+ FloatCore::powi(self, n: i32) -> Self;
+ FloatCore::to_degrees(self) -> Self;
+ FloatCore::to_radians(self) -> Self;
+ }
+ };
+}
+
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
+ // Safety: this identical to the implementation of f32::to_bits(),
+ // which is only available starting at Rust 1.20
let bits: u32 = unsafe { mem::transmute(f) };
- let sign: i8 = if bits >> 31 == 0 {
- 1
- } else {
- -1
- };
+ let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
let mantissa = if exponent == 0 {
(bits & 0x7fffff) << 1
} else {
(bits & 0x7fffff) | 0x800000
};
// Exponent bias + mantissa shift
exponent -= 127 + 23;
(mantissa as u64, exponent, sign)
}
-#[cfg(feature = "std")]
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
+ // Safety: this identical to the implementation of f64::to_bits(),
+ // which is only available starting at Rust 1.20
let bits: u64 = unsafe { mem::transmute(f) };
- let sign: i8 = if bits >> 63 == 0 {
- 1
- } else {
- -1
- };
+ let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
let mantissa = if exponent == 0 {
(bits & 0xfffffffffffff) << 1
} else {
(bits & 0xfffffffffffff) | 0x10000000000000
};
// Exponent bias + mantissa shift
exponent -= 1023 + 52;
(mantissa, exponent, sign)
}
#[cfg(feature = "std")]
-float_impl!(f32 integer_decode_f32);
+float_impl_std!(f32 integer_decode_f32);
#[cfg(feature = "std")]
-float_impl!(f64 integer_decode_f64);
+float_impl_std!(f64 integer_decode_f64);
+
+#[cfg(all(not(feature = "std"), feature = "libm"))]
+impl Float for f32 {
+ float_impl_libm!(f32 integer_decode_f32);
+
+ #[inline]
+ #[allow(deprecated)]
+ fn abs_sub(self, other: Self) -> Self {
+ libm::fdimf(self, other)
+ }
+
+ forward! {
+ libm::floorf as floor(self) -> Self;
+ libm::ceilf as ceil(self) -> Self;
+ libm::roundf as round(self) -> Self;
+ libm::truncf as trunc(self) -> Self;
+ libm::fabsf as abs(self) -> Self;
+ libm::fmaf as mul_add(self, a: Self, b: Self) -> Self;
+ libm::powf as powf(self, n: Self) -> Self;
+ libm::sqrtf as sqrt(self) -> Self;
+ libm::expf as exp(self) -> Self;
+ libm::exp2f as exp2(self) -> Self;
+ libm::logf as ln(self) -> Self;
+ libm::log2f as log2(self) -> Self;
+ libm::log10f as log10(self) -> Self;
+ libm::cbrtf as cbrt(self) -> Self;
+ libm::hypotf as hypot(self, other: Self) -> Self;
+ libm::sinf as sin(self) -> Self;
+ libm::cosf as cos(self) -> Self;
+ libm::tanf as tan(self) -> Self;
+ libm::asinf as asin(self) -> Self;
+ libm::acosf as acos(self) -> Self;
+ libm::atanf as atan(self) -> Self;
+ libm::atan2f as atan2(self, other: Self) -> Self;
+ libm::sincosf as sin_cos(self) -> (Self, Self);
+ libm::expm1f as exp_m1(self) -> Self;
+ libm::log1pf as ln_1p(self) -> Self;
+ libm::sinhf as sinh(self) -> Self;
+ libm::coshf as cosh(self) -> Self;
+ libm::tanhf as tanh(self) -> Self;
+ libm::asinhf as asinh(self) -> Self;
+ libm::acoshf as acosh(self) -> Self;
+ libm::atanhf as atanh(self) -> Self;
+ libm::fmaxf as max(self, other: Self) -> Self;
+ libm::fminf as min(self, other: Self) -> Self;
+ libm::copysignf as copysign(self, other: Self) -> Self;
+ }
+}
+
+#[cfg(all(not(feature = "std"), feature = "libm"))]
+impl Float for f64 {
+ float_impl_libm!(f64 integer_decode_f64);
+
+ #[inline]
+ #[allow(deprecated)]
+ fn abs_sub(self, other: Self) -> Self {
+ libm::fdim(self, other)
+ }
+
+ forward! {
+ libm::floor as floor(self) -> Self;
+ libm::ceil as ceil(self) -> Self;
+ libm::round as round(self) -> Self;
+ libm::trunc as trunc(self) -> Self;
+ libm::fabs as abs(self) -> Self;
+ libm::fma as mul_add(self, a: Self, b: Self) -> Self;
+ libm::pow as powf(self, n: Self) -> Self;
+ libm::sqrt as sqrt(self) -> Self;
+ libm::exp as exp(self) -> Self;
+ libm::exp2 as exp2(self) -> Self;
+ libm::log as ln(self) -> Self;
+ libm::log2 as log2(self) -> Self;
+ libm::log10 as log10(self) -> Self;
+ libm::cbrt as cbrt(self) -> Self;
+ libm::hypot as hypot(self, other: Self) -> Self;
+ libm::sin as sin(self) -> Self;
+ libm::cos as cos(self) -> Self;
+ libm::tan as tan(self) -> Self;
+ libm::asin as asin(self) -> Self;
+ libm::acos as acos(self) -> Self;
+ libm::atan as atan(self) -> Self;
+ libm::atan2 as atan2(self, other: Self) -> Self;
+ libm::sincos as sin_cos(self) -> (Self, Self);
+ libm::expm1 as exp_m1(self) -> Self;
+ libm::log1p as ln_1p(self) -> Self;
+ libm::sinh as sinh(self) -> Self;
+ libm::cosh as cosh(self) -> Self;
+ libm::tanh as tanh(self) -> Self;
+ libm::asinh as asinh(self) -> Self;
+ libm::acosh as acosh(self) -> Self;
+ libm::atanh as atanh(self) -> Self;
+ libm::fmax as max(self, other: Self) -> Self;
+ libm::fmin as min(self, other: Self) -> Self;
+ libm::copysign as copysign(self, sign: Self) -> Self;
+ }
+}
macro_rules! float_const_impl {
($(#[$doc:meta] $constant:ident,)+) => (
#[allow(non_snake_case)]
pub trait FloatConst {
$(#[$doc] fn $constant() -> Self;)+
+ #[doc = "Return the full circle constant `τ`."]
+ #[inline]
+ fn TAU() -> Self where Self: Sized + Add<Self, Output = Self> {
+ Self::PI() + Self::PI()
+ }
+ #[doc = "Return `log10(2.0)`."]
+ #[inline]
+ fn LOG10_2() -> Self where Self: Sized + Div<Self, Output = Self> {
+ Self::LN_2() / Self::LN_10()
+ }
+ #[doc = "Return `log2(10.0)`."]
+ #[inline]
+ fn LOG2_10() -> Self where Self: Sized + Div<Self, Output = Self> {
+ Self::LN_10() / Self::LN_2()
+ }
}
float_const_impl! { @float f32, $($constant,)+ }
float_const_impl! { @float f64, $($constant,)+ }
);
(@float $T:ident, $($constant:ident,)+) => (
impl FloatConst for $T {
- $(
- #[inline]
- fn $constant() -> Self {
- ::core::$T::consts::$constant
- }
- )+
+ constant! {
+ $( $constant() -> $T::consts::$constant; )+
+ TAU() -> 6.28318530717958647692528676655900577;
+ LOG10_2() -> 0.301029995663981195213738894724493027;
+ LOG2_10() -> 3.32192809488736234787031942948939018;
+ }
}
);
}
float_const_impl! {
#[doc = "Return Eulers number."]
E,
#[doc = "Return `1.0 / π`."]
@@ -1317,42 +2217,135 @@ float_const_impl! {
#[doc = "Return `ln(10.0)`."]
LN_10,
#[doc = "Return `ln(2.0)`."]
LN_2,
#[doc = "Return `log10(e)`."]
LOG10_E,
#[doc = "Return `log2(e)`."]
LOG2_E,
- #[doc = "Return Archimedes constant."]
+ #[doc = "Return Archimedes constant `π`."]
PI,
#[doc = "Return `sqrt(2.0)`."]
SQRT_2,
}
-#[cfg(all(test, feature = "std"))]
+#[cfg(test)]
mod tests {
- use Float;
+ use core::f64::consts;
+
+ const DEG_RAD_PAIRS: [(f64, f64); 7] = [
+ (0.0, 0.),
+ (22.5, consts::FRAC_PI_8),
+ (30.0, consts::FRAC_PI_6),
+ (45.0, consts::FRAC_PI_4),
+ (60.0, consts::FRAC_PI_3),
+ (90.0, consts::FRAC_PI_2),
+ (180.0, consts::PI),
+ ];
#[test]
fn convert_deg_rad() {
- use core::f64::consts;
-
- const DEG_RAD_PAIRS: [(f64, f64); 7] = [
- (0.0, 0.),
- (22.5, consts::FRAC_PI_8),
- (30.0, consts::FRAC_PI_6),
- (45.0, consts::FRAC_PI_4),
- (60.0, consts::FRAC_PI_3),
- (90.0, consts::FRAC_PI_2),
- (180.0, consts::PI),
- ];
+ use float::FloatCore;
for &(deg, rad) in &DEG_RAD_PAIRS {
+ assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-6);
+ assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-6);
+
+ let (deg, rad) = (deg as f32, rad as f32);
+ assert!((FloatCore::to_degrees(rad) - deg).abs() < 1e-5);
+ assert!((FloatCore::to_radians(deg) - rad).abs() < 1e-5);
+ }
+ }
+
+ #[cfg(any(feature = "std", feature = "libm"))]
+ #[test]
+ fn convert_deg_rad_std() {
+ for &(deg, rad) in &DEG_RAD_PAIRS {
+ use Float;
+
assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
let (deg, rad) = (deg as f32, rad as f32);
- assert!((Float::to_degrees(rad) - deg).abs() < 1e-6);
- assert!((Float::to_radians(deg) - rad).abs() < 1e-6);
+ assert!((Float::to_degrees(rad) - deg).abs() < 1e-5);
+ assert!((Float::to_radians(deg) - rad).abs() < 1e-5);
}
}
+
+ #[test]
+ // This fails with the forwarded `std` implementation in Rust 1.8.
+ // To avoid the failure, the test is limited to `no_std` builds.
+ #[cfg(not(feature = "std"))]
+ fn to_degrees_rounding() {
+ use float::FloatCore;
+
+ assert_eq!(
+ FloatCore::to_degrees(1_f32),
+ 57.2957795130823208767981548141051703
+ );
+ }
+
+ #[test]
+ #[cfg(any(feature = "std", feature = "libm"))]
+ fn extra_logs() {
+ use float::{Float, FloatConst};
+
+ fn check<F: Float + FloatConst>(diff: F) {
+ let _2 = F::from(2.0).unwrap();
+ assert!((F::LOG10_2() - F::log10(_2)).abs() < diff);
+ assert!((F::LOG10_2() - F::LN_2() / F::LN_10()).abs() < diff);
+
+ let _10 = F::from(10.0).unwrap();
+ assert!((F::LOG2_10() - F::log2(_10)).abs() < diff);
+ assert!((F::LOG2_10() - F::LN_10() / F::LN_2()).abs() < diff);
+ }
+
+ check::<f32>(1e-6);
+ check::<f64>(1e-12);
+ }
+
+ #[test]
+ #[cfg(any(feature = "std", feature = "libm"))]
+ fn copysign() {
+ use float::Float;
+ test_copysign_generic(2.0_f32, -2.0_f32, f32::nan());
+ test_copysign_generic(2.0_f64, -2.0_f64, f64::nan());
+ test_copysignf(2.0_f32, -2.0_f32, f32::nan());
+ }
+
+ #[cfg(any(feature = "std", feature = "libm"))]
+ fn test_copysignf(p: f32, n: f32, nan: f32) {
+ use core::ops::Neg;
+ use float::Float;
+
+ assert!(p.is_sign_positive());
+ assert!(n.is_sign_negative());
+ assert!(nan.is_nan());
+
+ assert_eq!(p, Float::copysign(p, p));
+ assert_eq!(p.neg(), Float::copysign(p, n));
+
+ assert_eq!(n, Float::copysign(n, n));
+ assert_eq!(n.neg(), Float::copysign(n, p));
+
+ // FIXME: is_sign... only works on NaN starting in Rust 1.20
+ // assert!(Float::copysign(nan, p).is_sign_positive());
+ // assert!(Float::copysign(nan, n).is_sign_negative());
+ }
+
+ #[cfg(any(feature = "std", feature = "libm"))]
+ fn test_copysign_generic<F: ::float::Float + ::core::fmt::Debug>(p: F, n: F, nan: F) {
+ assert!(p.is_sign_positive());
+ assert!(n.is_sign_negative());
+ assert!(nan.is_nan());
+
+ assert_eq!(p, p.copysign(p));
+ assert_eq!(p.neg(), p.copysign(n));
+
+ assert_eq!(n, n.copysign(n));
+ assert_eq!(n.neg(), n.copysign(p));
+
+ // FIXME: is_sign... only works on NaN starting in Rust 1.20
+ // assert!(nan.copysign(p).is_sign_positive());
+ // assert!(nan.copysign(n).is_sign_negative());
+ }
}
diff --git a/third_party/rust/num-traits/src/identities.rs b/third_party/rust/num-traits/src/identities.rs
--- a/third_party/rust/num-traits/src/identities.rs
+++ b/third_party/rust/num-traits/src/identities.rs
@@ -1,129 +1,187 @@
+use core::num::Wrapping;
use core::ops::{Add, Mul};
-use core::num::Wrapping;
/// Defines an additive identity element for `Self`.
+///
+/// # Laws
+///
+/// ```{.text}
+/// a + 0 = a ∀ a ∈ Self
+/// 0 + a = a ∀ a ∈ Self
+/// ```
pub trait Zero: Sized + Add<Self, Output = Self> {
/// Returns the additive identity element of `Self`, `0`.
- ///
- /// # Laws
- ///
- /// ```{.text}
- /// a + 0 = a ∀ a ∈ Self
- /// 0 + a = a ∀ a ∈ Self
- /// ```
- ///
/// # Purity
///
/// This function should return the same result at all times regardless of
/// external mutable state, for example values stored in TLS or in
/// `static mut`s.
- // FIXME (#5527): This should be an associated constant
+ // This cannot be an associated constant, because of bignums.
fn zero() -> Self;
+ /// Sets `self` to the additive identity element of `Self`, `0`.
+ fn set_zero(&mut self) {
+ *self = Zero::zero();
+ }
+
/// Returns `true` if `self` is equal to the additive identity.
- #[inline]
fn is_zero(&self) -> bool;
}
macro_rules! zero_impl {
($t:ty, $v:expr) => {
impl Zero for $t {
#[inline]
- fn zero() -> $t { $v }
+ fn zero() -> $t {
+ $v
+ }
#[inline]
- fn is_zero(&self) -> bool { *self == $v }
+ fn is_zero(&self) -> bool {
+ *self == $v
+ }
}
- }
+ };
}
-zero_impl!(usize, 0usize);
-zero_impl!(u8, 0u8);
-zero_impl!(u16, 0u16);
-zero_impl!(u32, 0u32);
-zero_impl!(u64, 0u64);
+zero_impl!(usize, 0);
+zero_impl!(u8, 0);
+zero_impl!(u16, 0);
+zero_impl!(u32, 0);
+zero_impl!(u64, 0);
+#[cfg(has_i128)]
+zero_impl!(u128, 0);
-zero_impl!(isize, 0isize);
-zero_impl!(i8, 0i8);
-zero_impl!(i16, 0i16);
-zero_impl!(i32, 0i32);
-zero_impl!(i64, 0i64);
+zero_impl!(isize, 0);
+zero_impl!(i8, 0);
+zero_impl!(i16, 0);
+zero_impl!(i32, 0);
+zero_impl!(i64, 0);
+#[cfg(has_i128)]
+zero_impl!(i128, 0);
-zero_impl!(f32, 0.0f32);
-zero_impl!(f64, 0.0f64);
+zero_impl!(f32, 0.0);
+zero_impl!(f64, 0.0);
-impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
+impl<T: Zero> Zero for Wrapping<T>
+where
+ Wrapping<T>: Add<Output = Wrapping<T>>,
+{
fn is_zero(&self) -> bool {
self.0.is_zero()
}
+
+ fn set_zero(&mut self) {
+ self.0.set_zero();
+ }
+
fn zero() -> Self {
Wrapping(T::zero())
}
}
-
/// Defines a multiplicative identity element for `Self`.
+///
+/// # Laws
+///
+/// ```{.text}
+/// a * 1 = a ∀ a ∈ Self
+/// 1 * a = a ∀ a ∈ Self
+/// ```
pub trait One: Sized + Mul<Self, Output = Self> {
/// Returns the multiplicative identity element of `Self`, `1`.
///
- /// # Laws
- ///
- /// ```{.text}
- /// a * 1 = a ∀ a ∈ Self
- /// 1 * a = a ∀ a ∈ Self
- /// ```
- ///
/// # Purity
///
/// This function should return the same result at all times regardless of
/// external mutable state, for example values stored in TLS or in
/// `static mut`s.
- // FIXME (#5527): This should be an associated constant
+ // This cannot be an associated constant, because of bignums.
fn one() -> Self;
+
+ /// Sets `self` to the multiplicative identity element of `Self`, `1`.
+ fn set_one(&mut self) {
+ *self = One::one();
+ }
+
+ /// Returns `true` if `self` is equal to the multiplicative identity.
+ ///
+ /// For performance reasons, it's best to implement this manually.
+ /// After a semver bump, this method will be required, and the
+ /// `where Self: PartialEq` bound will be removed.
+ #[inline]
+ fn is_one(&self) -> bool
+ where
+ Self: PartialEq,
+ {
+ *self == Self::one()
+ }
}
macro_rules! one_impl {
($t:ty, $v:expr) => {
impl One for $t {
#[inline]
- fn one() -> $t { $v }
+ fn one() -> $t {
+ $v
+ }
+ #[inline]
+ fn is_one(&self) -> bool {
+ *self == $v
+ }
}
- }
+ };
}
-one_impl!(usize, 1usize);
-one_impl!(u8, 1u8);
-one_impl!(u16, 1u16);
-one_impl!(u32, 1u32);
-one_impl!(u64, 1u64);
+one_impl!(usize, 1);
+one_impl!(u8, 1);
+one_impl!(u16, 1);
+one_impl!(u32, 1);
+one_impl!(u64, 1);
+#[cfg(has_i128)]
+one_impl!(u128, 1);
-one_impl!(isize, 1isize);
-one_impl!(i8, 1i8);
-one_impl!(i16, 1i16);
-one_impl!(i32, 1i32);
-one_impl!(i64, 1i64);
+one_impl!(isize, 1);
+one_impl!(i8, 1);
+one_impl!(i16, 1);
+one_impl!(i32, 1);
+one_impl!(i64, 1);
+#[cfg(has_i128)]
+one_impl!(i128, 1);
-one_impl!(f32, 1.0f32);
-one_impl!(f64, 1.0f64);
+one_impl!(f32, 1.0);
+one_impl!(f64, 1.0);
-impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
+impl<T: One> One for Wrapping<T>
+where
+ Wrapping<T>: Mul<Output = Wrapping<T>>,
+{
+ fn set_one(&mut self) {
+ self.0.set_one();
+ }
+
fn one() -> Self {
Wrapping(T::one())
}
}
// Some helper functions provided for backwards compatibility.
/// Returns the additive identity, `0`.
-#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
+#[inline(always)]
+pub fn zero<T: Zero>() -> T {
+ Zero::zero()
+}
/// Returns the multiplicative identity, `1`.
-#[inline(always)] pub fn one<T: One>() -> T { One::one() }
-
+#[inline(always)]
+pub fn one<T: One>() -> T {
+ One::one()
+}
#[test]
fn wrapping_identities() {
macro_rules! test_wrapping_identities {
($($t:ty)+) => {
$(
assert_eq!(zero::<$t>(), zero::<Wrapping<$t>>().0);
assert_eq!(one::<$t>(), one::<Wrapping<$t>>().0);
diff --git a/third_party/rust/num-traits/src/int.rs b/third_party/rust/num-traits/src/int.rs
--- a/third_party/rust/num-traits/src/int.rs
+++ b/third_party/rust/num-traits/src/int.rs
@@ -1,31 +1,60 @@
-use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
+use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
-use {Num, NumCast};
use bounds::Bounded;
use ops::checked::*;
use ops::saturating::Saturating;
+use {Num, NumCast};
-pub trait PrimInt
- : Sized
+/// Generic trait for primitive integers.
+///
+/// The `PrimInt` trait is an abstraction over the builtin primitive integer types (e.g., `u8`,
+/// `u32`, `isize`, `i128`, ...). It inherits the basic numeric traits and extends them with
+/// bitwise operators and non-wrapping arithmetic.
+///
+/// The trait explicitly inherits `Copy`, `Eq`, `Ord`, and `Sized`. The intention is that all
+/// types implementing this trait behave like primitive types that are passed by value by default
+/// and behave like builtin integers. Furthermore, the types are expected to expose the integer
+/// value in binary representation and support bitwise operators. The standard bitwise operations
+/// (e.g., bitwise-and, bitwise-or, right-shift, left-shift) are inherited and the trait extends
+/// these with introspective queries (e.g., `PrimInt::count_ones()`, `PrimInt::leading_zeros()`),
+/// bitwise combinators (e.g., `PrimInt::rotate_left()`), and endianness converters (e.g.,
+/// `PrimInt::to_be()`).
+///
+/// All `PrimInt` types are expected to be fixed-width binary integers. The width can be queried
+/// via `T::zero().count_zeros()`. The trait currently lacks a way to query the width at
+/// compile-time.
+///
+/// While a default implementation for all builtin primitive integers is provided, the trait is in
+/// no way restricted to these. Other integer types that fulfil the requirements are free to
+/// implement the trait was well.
+///
+/// This trait and many of the method names originate in the unstable `core::num::Int` trait from
+/// the rust standard library. The original trait was never stabilized and thus removed from the
+/// standard library.
+pub trait PrimInt:
+ Sized
+ Copy
- + Num + NumCast
+ + Num
+ + NumCast
+ Bounded
- + PartialOrd + Ord + Eq
- + Not<Output=Self>
- + BitAnd<Output=Self>
- + BitOr<Output=Self>
- + BitXor<Output=Self>
- + Shl<usize, Output=Self>
- + Shr<usize, Output=Self>
- + CheckedAdd<Output=Self>
- + CheckedSub<Output=Self>
- + CheckedMul<Output=Self>
- + CheckedDiv<Output=Self>
+ + PartialOrd
+ + Ord
+ + Eq
+ + Not<Output = Self>
+ + BitAnd<Output = Self>
+ + BitOr<Output = Self>
+ + BitXor<Output = Self>
+ + Shl<usize, Output = Self>
+ + Shr<usize, Output = Self>
+ + CheckedAdd<Output = Self>
+ + CheckedSub<Output = Self>
+ + CheckedMul<Output = Self>
+ + CheckedDiv<Output = Self>
+ Saturating
{
/// Returns the number of ones in the binary representation of `self`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
@@ -44,139 +73,171 @@ pub trait PrimInt
/// use num_traits::PrimInt;
///
/// let n = 0b01001100u8;
///
/// assert_eq!(n.count_zeros(), 5);
/// ```
fn count_zeros(self) -> u32;
+ /// Returns the number of leading ones in the binary representation
+ /// of `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::PrimInt;
+ ///
+ /// let n = 0xF00Du16;
+ ///
+ /// assert_eq!(n.leading_ones(), 4);
+ /// ```
+ fn leading_ones(self) -> u32 {
+ (!self).leading_zeros()
+ }
+
/// Returns the number of leading zeros in the binary representation
/// of `self`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.leading_zeros(), 10);
/// ```
fn leading_zeros(self) -> u32;
+ /// Returns the number of trailing ones in the binary representation
+ /// of `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::PrimInt;
+ ///
+ /// let n = 0xBEEFu16;
+ ///
+ /// assert_eq!(n.trailing_ones(), 4);
+ /// ```
+ fn trailing_ones(self) -> u32 {
+ (!self).trailing_zeros()
+ }
+
/// Returns the number of trailing zeros in the binary representation
/// of `self`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.trailing_zeros(), 3);
/// ```
fn trailing_zeros(self) -> u32;
- /// Shifts the bits to the left by a specified amount amount, `n`, wrapping
+ /// Shifts the bits to the left by a specified amount, `n`, wrapping
/// the truncated bits to the end of the resulting integer.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0x3456789ABCDEF012u64;
///
/// assert_eq!(n.rotate_left(12), m);
/// ```
fn rotate_left(self, n: u32) -> Self;
- /// Shifts the bits to the right by a specified amount amount, `n`, wrapping
+ /// Shifts the bits to the right by a specified amount, `n`, wrapping
/// the truncated bits to the beginning of the resulting integer.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xDEF0123456789ABCu64;
///
/// assert_eq!(n.rotate_right(12), m);
/// ```
fn rotate_right(self, n: u32) -> Self;
- /// Shifts the bits to the left by a specified amount amount, `n`, filling
+ /// Shifts the bits to the left by a specified amount, `n`, filling
/// zeros in the least significant bits.
///
/// This is bitwise equivalent to signed `Shl`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0x3456789ABCDEF000u64;
///
/// assert_eq!(n.signed_shl(12), m);
/// ```
fn signed_shl(self, n: u32) -> Self;
- /// Shifts the bits to the right by a specified amount amount, `n`, copying
+ /// Shifts the bits to the right by a specified amount, `n`, copying
/// the "sign bit" in the most significant bits even for unsigned types.
///
/// This is bitwise equivalent to signed `Shr`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0xFEDCBA9876543210u64;
/// let m = 0xFFFFEDCBA9876543u64;
///
/// assert_eq!(n.signed_shr(12), m);
/// ```
fn signed_shr(self, n: u32) -> Self;
- /// Shifts the bits to the left by a specified amount amount, `n`, filling
+ /// Shifts the bits to the left by a specified amount, `n`, filling
/// zeros in the least significant bits.
///
/// This is bitwise equivalent to unsigned `Shl`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0x0123456789ABCDEFi64;
/// let m = 0x3456789ABCDEF000i64;
///
/// assert_eq!(n.unsigned_shl(12), m);
/// ```
fn unsigned_shl(self, n: u32) -> Self;
- /// Shifts the bits to the right by a specified amount amount, `n`, filling
+ /// Shifts the bits to the right by a specified amount, `n`, filling
/// zeros in the most significant bits.
///
/// This is bitwise equivalent to unsigned `Shr`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
- /// let n = 0xFEDCBA9876543210i64;
- /// let m = 0x000FEDCBA9876543i64;
+ /// let n = -8i8; // 0b11111000
+ /// let m = 62i8; // 0b00111110
///
- /// assert_eq!(n.unsigned_shr(12), m);
+ /// assert_eq!(n.unsigned_shr(2), m);
/// ```
fn unsigned_shr(self, n: u32) -> Self;
/// Reverses the byte order of the integer.
///
/// # Examples
///
/// ```
@@ -184,16 +245,36 @@ pub trait PrimInt
///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xEFCDAB8967452301u64;
///
/// assert_eq!(n.swap_bytes(), m);
/// ```
fn swap_bytes(self) -> Self;
+ /// Reverses the order of bits in the integer.
+ ///
+ /// The least significant bit becomes the most significant bit, second least-significant bit
+ /// becomes second most-significant bit, etc.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::PrimInt;
+ ///
+ /// let n = 0x12345678u32;
+ /// let m = 0x1e6a2c48u32;
+ ///
+ /// assert_eq!(n.reverse_bits(), m);
+ /// assert_eq!(0u32.reverse_bits(), 0);
+ /// ```
+ fn reverse_bits(self) -> Self {
+ reverse_bits_fallback(self)
+ }
+
/// Convert an integer from big endian to the target's endianness.
///
/// On big endian this is a no-op. On little endian the bytes are swapped.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
@@ -272,34 +353,79 @@ pub trait PrimInt
/// ```
/// use num_traits::PrimInt;
///
/// assert_eq!(2i32.pow(4), 16);
/// ```
fn pow(self, exp: u32) -> Self;
}
+fn one_per_byte<P: PrimInt>() -> P {
+ // i8, u8: return 0x01
+ // i16, u16: return 0x0101 = (0x01 << 8) | 0x01
+ // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101
+ // ...
+ let mut ret = P::one();
+ let mut shift = 8;
+ let mut b = ret.count_zeros() >> 3;
+ while b != 0 {
+ ret = (ret << shift) | ret;
+ shift <<= 1;
+ b >>= 1;
+ }
+ ret
+}
+
+fn reverse_bits_fallback<P: PrimInt>(i: P) -> P {
+ let rep_01: P = one_per_byte();
+ let rep_03 = (rep_01 << 1) | rep_01;
+ let rep_05 = (rep_01 << 2) | rep_01;
+ let rep_0f = (rep_03 << 2) | rep_03;
+ let rep_33 = (rep_03 << 4) | rep_03;
+ let rep_55 = (rep_05 << 4) | rep_05;
+
+ // code above only used to determine rep_0f, rep_33, rep_55;
+ // optimizer should be able to do it in compile time
+ let mut ret = i.swap_bytes();
+ ret = ((ret & rep_0f) << 4) | ((ret >> 4) & rep_0f);
+ ret = ((ret & rep_33) << 2) | ((ret >> 2) & rep_33);
+ ret = ((ret & rep_55) << 1) | ((ret >> 1) & rep_55);
+ ret
+}
+
macro_rules! prim_int_impl {
- ($T:ty, $S:ty, $U:ty) => (
+ ($T:ty, $S:ty, $U:ty) => {
impl PrimInt for $T {
#[inline]
fn count_ones(self) -> u32 {
<$T>::count_ones(self)
}
#[inline]
fn count_zeros(self) -> u32 {
<$T>::count_zeros(self)
}
+ #[cfg(has_leading_trailing_ones)]
+ #[inline]
+ fn leading_ones(self) -> u32 {
+ <$T>::leading_ones(self)
+ }
+
#[inline]
fn leading_zeros(self) -> u32 {
<$T>::leading_zeros(self)
}
+ #[cfg(has_leading_trailing_ones)]
+ #[inline]
+ fn trailing_ones(self) -> u32 {
+ <$T>::trailing_ones(self)
+ }
+
#[inline]
fn trailing_zeros(self) -> u32 {
<$T>::trailing_zeros(self)
}
#[inline]
fn rotate_left(self, n: u32) -> Self {
<$T>::rotate_left(self, n)
@@ -330,16 +456,22 @@ macro_rules! prim_int_impl {
((self as $U) >> n) as $T
}
#[inline]
fn swap_bytes(self) -> Self {
<$T>::swap_bytes(self)
}
+ #[cfg(has_reverse_bits)]
+ #[inline]
+ fn reverse_bits(self) -> Self {
+ <$T>::reverse_bits(self)
+ }
+
#[inline]
fn from_be(x: Self) -> Self {
<$T>::from_be(x)
}
#[inline]
fn from_le(x: Self) -> Self {
<$T>::from_le(x)
@@ -355,22 +487,82 @@ macro_rules! prim_int_impl {
<$T>::to_le(self)
}
#[inline]
fn pow(self, exp: u32) -> Self {
<$T>::pow(self, exp)
}
}
- )
+ };
}
// prim_int_impl!(type, signed, unsigned);
-prim_int_impl!(u8, i8, u8);
-prim_int_impl!(u16, i16, u16);
-prim_int_impl!(u32, i32, u32);
-prim_int_impl!(u64, i64, u64);
+prim_int_impl!(u8, i8, u8);
+prim_int_impl!(u16, i16, u16);
+prim_int_impl!(u32, i32, u32);
+prim_int_impl!(u64, i64, u64);
+#[cfg(has_i128)]
+prim_int_impl!(u128, i128, u128);
prim_int_impl!(usize, isize, usize);
-prim_int_impl!(i8, i8, u8);
-prim_int_impl!(i16, i16, u16);
-prim_int_impl!(i32, i32, u32);
-prim_int_impl!(i64, i64, u64);
+prim_int_impl!(i8, i8, u8);
+prim_int_impl!(i16, i16, u16);
+prim_int_impl!(i32, i32, u32);
+prim_int_impl!(i64, i64, u64);
+#[cfg(has_i128)]
+prim_int_impl!(i128, i128, u128);
prim_int_impl!(isize, isize, usize);
+
+#[cfg(test)]
+mod tests {
+ use int::PrimInt;
+
+ #[test]
+ pub fn reverse_bits() {
+ use core::{i16, i32, i64, i8};
+
+ assert_eq!(
+ PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64),
+ 0xf7b3_d591_e6a2_c480
+ );
+
+ assert_eq!(PrimInt::reverse_bits(0i8), 0);
+ assert_eq!(PrimInt::reverse_bits(-1i8), -1);
+ assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN);
+ assert_eq!(PrimInt::reverse_bits(i8::MIN), 1);
+ assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX);
+ assert_eq!(PrimInt::reverse_bits(i8::MAX), -2);
+
+ assert_eq!(PrimInt::reverse_bits(0i16), 0);
+ assert_eq!(PrimInt::reverse_bits(-1i16), -1);
+ assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN);
+ assert_eq!(PrimInt::reverse_bits(i16::MIN), 1);
+ assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX);
+ assert_eq!(PrimInt::reverse_bits(i16::MAX), -2);
+
+ assert_eq!(PrimInt::reverse_bits(0i32), 0);
+ assert_eq!(PrimInt::reverse_bits(-1i32), -1);
+ assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN);
+ assert_eq!(PrimInt::reverse_bits(i32::MIN), 1);
+ assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX);
+ assert_eq!(PrimInt::reverse_bits(i32::MAX), -2);
+
+ assert_eq!(PrimInt::reverse_bits(0i64), 0);
+ assert_eq!(PrimInt::reverse_bits(-1i64), -1);
+ assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN);
+ assert_eq!(PrimInt::reverse_bits(i64::MIN), 1);
+ assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX);
+ assert_eq!(PrimInt::reverse_bits(i64::MAX), -2);
+ }
+
+ #[test]
+ #[cfg(has_i128)]
+ pub fn reverse_bits_i128() {
+ use core::i128;
+
+ assert_eq!(PrimInt::reverse_bits(0i128), 0);
+ assert_eq!(PrimInt::reverse_bits(-1i128), -1);
+ assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN);
+ assert_eq!(PrimInt::reverse_bits(i128::MIN), 1);
+ assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX);
+ assert_eq!(PrimInt::reverse_bits(i128::MAX), -2);
+ }
+}
diff --git a/third_party/rust/num-traits/src/lib.rs b/third_party/rust/num-traits/src/lib.rs
--- a/third_party/rust/num-traits/src/lib.rs
+++ b/third_party/rust/num-traits/src/lib.rs
@@ -10,168 +10,187 @@
//! Numeric traits for generic mathematics
//!
//! ## Compatibility
//!
//! The `num-traits` crate is tested for rustc 1.8 and greater.
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
-
#![deny(unconditional_recursion)]
-
-#![cfg_attr(not(feature = "std"), no_std)]
+#![no_std]
#[cfg(feature = "std")]
-extern crate core;
+extern crate std;
-use core::ops::{Add, Sub, Mul, Div, Rem};
-use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
+// Only `no_std` builds actually use `libm`.
+#[cfg(all(not(feature = "std"), feature = "libm"))]
+extern crate libm;
+
+use core::fmt;
use core::num::Wrapping;
-use core::fmt;
+use core::ops::{Add, Div, Mul, Rem, Sub};
+use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
pub use bounds::Bounded;
-#[cfg(feature = "std")]
+#[cfg(any(feature = "std", feature = "libm"))]
pub use float::Float;
pub use float::FloatConst;
-// pub use real::Real; // NOTE: Don't do this, it breaks `use num_traits::*;`.
-pub use identities::{Zero, One, zero, one};
-pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr};
-pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub};
-pub use ops::saturating::Saturating;
-pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
-pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
+// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
+pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
+pub use identities::{one, zero, One, Zero};
pub use int::PrimInt;
-pub use pow::{pow, checked_pow};
+pub use ops::checked::{
+ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
+};
+pub use ops::euclid::{CheckedEuclid, Euclid};
+pub use ops::inv::Inv;
+pub use ops::mul_add::{MulAdd, MulAddAssign};
+pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub};
+pub use ops::wrapping::{
+ WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub,
+};
+pub use pow::{checked_pow, pow, Pow};
+pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
-pub mod identities;
-pub mod sign;
-pub mod ops;
+#[macro_use]
+mod macros;
+
pub mod bounds;
+pub mod cast;
pub mod float;
-#[cfg(feature = "std")]
+pub mod identities;
+pub mod int;
+pub mod ops;
+pub mod pow;
pub mod real;
-pub mod cast;
-pub mod int;
-pub mod pow;
+pub mod sign;
/// The base trait for numeric types, covering `0` and `1` values,
/// comparisons, basic numeric operations, and string conversion.
-pub trait Num: PartialEq + Zero + One + NumOps
-{
+pub trait Num: PartialEq + Zero + One + NumOps {
type FromStrRadixErr;
- /// Convert from a string and radix <= 36.
+ /// Convert from a string and radix (typically `2..=36`).
///
/// # Examples
///
/// ```rust
/// use num_traits::Num;
///
/// let result = <i32 as Num>::from_str_radix("27", 10);
/// assert_eq!(result, Ok(27));
///
/// let result = <i32 as Num>::from_str_radix("foo", 10);
/// assert!(result.is_err());
/// ```
+ ///
+ /// # Supported radices
+ ///
+ /// The exact range of supported radices is at the discretion of each type implementation. For
+ /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the
+ /// standard library, which **panic** if the radix is not in the range from 2 to 36. The
+ /// implementation in this crate for primitive floats is similar.
+ ///
+ /// For third-party types, it is suggested that implementations should follow suit and at least
+ /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix.
+ /// It's possible that a type might not even support the common radix 10, nor any, if string
+ /// parsing doesn't make sense for that type.
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
}
-/// The trait for types implementing basic numeric operations
+/// Generic trait for types implementing basic numeric operations
///
/// This is automatically implemented for types which implement the operators.
-pub trait NumOps<Rhs = Self, Output = Self>
- : Add<Rhs, Output = Output>
+pub trait NumOps<Rhs = Self, Output = Self>:
+ Add<Rhs, Output = Output>
+ Sub<Rhs, Output = Output>
+ Mul<Rhs, Output = Output>
+ Div<Rhs, Output = Output>
+ Rem<Rhs, Output = Output>
-{}
+{
+}
-impl<T, Rhs, Output> NumOps<Rhs, Output> for T
-where T: Add<Rhs, Output = Output>
- + Sub<Rhs, Output = Output>
- + Mul<Rhs, Output = Output>
- + Div<Rhs, Output = Output>
- + Rem<Rhs, Output = Output>
-{}
+impl<T, Rhs, Output> NumOps<Rhs, Output> for T where
+ T: Add<Rhs, Output = Output>
+ + Sub<Rhs, Output = Output>
+ + Mul<Rhs, Output = Output>
+ + Div<Rhs, Output = Output>
+ + Rem<Rhs, Output = Output>
+{
+}
/// The trait for `Num` types which also implement numeric operations taking
/// the second operand by reference.
///
/// This is automatically implemented for types which implement the operators.
pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
-/// The trait for references which implement numeric operations, taking the
+/// The trait for `Num` references which implement numeric operations, taking the
/// second operand either by value or by reference.
///
-/// This is automatically implemented for types which implement the operators.
+/// This is automatically implemented for all types which implement the operators. It covers
+/// every type implementing the operations though, regardless of it being a reference or
+/// related to `Num`.
pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
-/// The trait for types implementing numeric assignment operators (like `+=`).
+/// Generic trait for types implementing numeric assignment operators (like `+=`).
///
/// This is automatically implemented for types which implement the operators.
-pub trait NumAssignOps<Rhs = Self>
- : AddAssign<Rhs>
- + SubAssign<Rhs>
- + MulAssign<Rhs>
- + DivAssign<Rhs>
- + RemAssign<Rhs>
-{}
+pub trait NumAssignOps<Rhs = Self>:
+ AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
+{
+}
-impl<T, Rhs> NumAssignOps<Rhs> for T
-where T: AddAssign<Rhs>
- + SubAssign<Rhs>
- + MulAssign<Rhs>
- + DivAssign<Rhs>
- + RemAssign<Rhs>
-{}
+impl<T, Rhs> NumAssignOps<Rhs> for T where
+ T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
+{
+}
/// The trait for `Num` types which also implement assignment operators.
///
/// This is automatically implemented for types which implement the operators.
pub trait NumAssign: Num + NumAssignOps {}
impl<T> NumAssign for T where T: Num + NumAssignOps {}
/// The trait for `NumAssign` types which also implement assignment operations
/// taking the second operand by reference.
///
/// This is automatically implemented for types which implement the operators.
pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
-
macro_rules! int_trait_impl {
($name:ident for $($t:ty)*) => ($(
impl $name for $t {
type FromStrRadixErr = ::core::num::ParseIntError;
#[inline]
fn from_str_radix(s: &str, radix: u32)
-> Result<Self, ::core::num::ParseIntError>
{
<$t>::from_str_radix(s, radix)
}
}
)*)
}
int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
+#[cfg(has_i128)]
+int_trait_impl!(Num for u128 i128);
impl<T: Num> Num for Wrapping<T>
- where Wrapping<T>:
- Add<Output = Wrapping<T>> + Sub<Output = Wrapping<T>>
- + Mul<Output = Wrapping<T>> + Div<Output = Wrapping<T>> + Rem<Output = Wrapping<T>>
+where
+ Wrapping<T>: NumOps,
{
type FromStrRadixErr = T::FromStrRadixErr;
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
T::from_str_radix(str, radix).map(Wrapping)
}
}
-
#[derive(Debug)]
pub enum FloatErrorKind {
Empty,
Invalid,
}
// FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
// so there's not really any way for us to reuse it.
#[derive(Debug)]
@@ -185,40 +204,67 @@ impl fmt::Display for ParseFloatError {
FloatErrorKind::Empty => "cannot parse float from empty string",
FloatErrorKind::Invalid => "invalid float literal",
};
description.fmt(f)
}
}
+fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool {
+ a.len() == b.len()
+ && a.bytes().zip(b.bytes()).all(|(a, b)| {
+ let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5);
+ a_to_ascii_lower == b
+ })
+}
+
// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
macro_rules! float_trait_impl {
($name:ident for $($t:ident)*) => ($(
impl $name for $t {
type FromStrRadixErr = ParseFloatError;
fn from_str_radix(src: &str, radix: u32)
-> Result<Self, Self::FromStrRadixErr>
{
use self::FloatErrorKind::*;
use self::ParseFloatError as PFE;
+ // Special case radix 10 to use more accurate standard library implementation
+ if radix == 10 {
+ return src.parse().map_err(|_| PFE {
+ kind: if src.is_empty() { Empty } else { Invalid },
+ });
+ }
+
// Special values
- match src {
- "inf" => return Ok(core::$t::INFINITY),
- "-inf" => return Ok(core::$t::NEG_INFINITY),
- "NaN" => return Ok(core::$t::NAN),
- _ => {},
+ if str_to_ascii_lower_eq_str(src, "inf")
+ || str_to_ascii_lower_eq_str(src, "infinity")
+ {
+ return Ok(core::$t::INFINITY);
+ } else if str_to_ascii_lower_eq_str(src, "-inf")
+ || str_to_ascii_lower_eq_str(src, "-infinity")
+ {
+ return Ok(core::$t::NEG_INFINITY);
+ } else if str_to_ascii_lower_eq_str(src, "nan") {
+ return Ok(core::$t::NAN);
+ } else if str_to_ascii_lower_eq_str(src, "-nan") {
+ return Ok(-core::$t::NAN);
}
fn slice_shift_char(src: &str) -> Option<(char, &str)> {
- src.chars().nth(0).map(|ch| (ch, &src[1..]))
+ let mut chars = src.chars();
+ if let Some(ch) = chars.next() {
+ Some((ch, chars.as_str()))
+ } else {
+ None
+ }
}
let (is_positive, src) = match slice_shift_char(src) {
None => return Err(PFE { kind: Empty }),
Some(('-', "")) => return Err(PFE { kind: Empty }),
Some(('-', src)) => (false, src),
Some((_, _)) => (true, src),
};
@@ -351,53 +397,166 @@ macro_rules! float_trait_impl {
}
float_trait_impl!(Num for f32 f64);
/// A value bounded by a minimum and a maximum
///
/// If input is less than min then this returns min.
/// If input is greater than max then this returns max.
/// Otherwise this returns input.
+///
+/// **Panics** in debug mode if `!(min <= max)`.
#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
debug_assert!(min <= max, "min must be less than or equal to max");
if input < min {
min
} else if input > max {
max
} else {
input
}
}
+/// A value bounded by a minimum value
+///
+/// If input is less than min then this returns min.
+/// Otherwise this returns input.
+/// `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`.
+///
+/// **Panics** in debug mode if `!(min == min)`. (This occurs if `min` is `NAN`.)
+#[inline]
+pub fn clamp_min<T: PartialOrd>(input: T, min: T) -> T {
+ debug_assert!(min == min, "min must not be NAN");
+ if input < min {
+ min
+ } else {
+ input
+ }
+}
+
+/// A value bounded by a maximum value
+///
+/// If input is greater than max then this returns max.
+/// Otherwise this returns input.
+/// `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`.
+///
+/// **Panics** in debug mode if `!(max == max)`. (This occurs if `max` is `NAN`.)
+#[inline]
+pub fn clamp_max<T: PartialOrd>(input: T, max: T) -> T {
+ debug_assert!(max == max, "max must not be NAN");
+ if input > max {
+ max
+ } else {
+ input
+ }
+}
+
#[test]
fn clamp_test() {
// Int test
assert_eq!(1, clamp(1, -1, 2));
assert_eq!(-1, clamp(-2, -1, 2));
assert_eq!(2, clamp(3, -1, 2));
+ assert_eq!(1, clamp_min(1, -1));
+ assert_eq!(-1, clamp_min(-2, -1));
+ assert_eq!(-1, clamp_max(1, -1));
+ assert_eq!(-2, clamp_max(-2, -1));
// Float test
assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
+ assert_eq!(1.0, clamp_min(1.0, -1.0));
+ assert_eq!(-1.0, clamp_min(-2.0, -1.0));
+ assert_eq!(-1.0, clamp_max(1.0, -1.0));
+ assert_eq!(-2.0, clamp_max(-2.0, -1.0));
+ assert!(clamp(::core::f32::NAN, -1.0, 1.0).is_nan());
+ assert!(clamp_min(::core::f32::NAN, 1.0).is_nan());
+ assert!(clamp_max(::core::f32::NAN, 1.0).is_nan());
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+fn clamp_nan_min() {
+ clamp(0., ::core::f32::NAN, 1.);
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+fn clamp_nan_max() {
+ clamp(0., -1., ::core::f32::NAN);
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+fn clamp_nan_min_max() {
+ clamp(0., ::core::f32::NAN, ::core::f32::NAN);
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+fn clamp_min_nan_min() {
+ clamp_min(0., ::core::f32::NAN);
+}
+
+#[test]
+#[should_panic]
+#[cfg(debug_assertions)]
+fn clamp_max_nan_max() {
+ clamp_max(0., ::core::f32::NAN);
}
#[test]
fn from_str_radix_unwrap() {
// The Result error must impl Debug to allow unwrap()
let i: i32 = Num::from_str_radix("0", 10).unwrap();
assert_eq!(i, 0);
let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
assert_eq!(f, 0.0);
}
#[test]
+fn from_str_radix_multi_byte_fail() {
+ // Ensure parsing doesn't panic, even on invalid sign characters
+ assert!(f32::from_str_radix("™0.2", 10).is_err());
+
+ // Even when parsing the exponent sign
+ assert!(f32::from_str_radix("0.2E™1", 10).is_err());
+}
+
+#[test]
+fn from_str_radix_ignore_case() {
+ assert_eq!(
+ f32::from_str_radix("InF", 16).unwrap(),
+ ::core::f32::INFINITY
+ );
+ assert_eq!(
+ f32::from_str_radix("InfinitY", 16).unwrap(),
+ ::core::f32::INFINITY
+ );
+ assert_eq!(
+ f32::from_str_radix("-InF", 8).unwrap(),
+ ::core::f32::NEG_INFINITY
+ );
+ assert_eq!(
+ f32::from_str_radix("-InfinitY", 8).unwrap(),
+ ::core::f32::NEG_INFINITY
+ );
+ assert!(f32::from_str_radix("nAn", 4).unwrap().is_nan());
+ assert!(f32::from_str_radix("-nAn", 4).unwrap().is_nan());
+}
+
+#[test]
fn wrapping_is_num() {
fn require_num<T: Num>(_: &T) {}
require_num(&Wrapping(42_u32));
require_num(&Wrapping(-42));
}
#[test]
fn wrapping_from_str_radix() {
@@ -429,27 +588,29 @@ fn check_numref_ops() {
x * y / y % y + y - y
}
assert_eq!(compute(1, &2), 1)
}
#[test]
fn check_refnum_ops() {
fn compute<T: Copy>(x: &T, y: T) -> T
- where for<'a> &'a T: RefNum<T>
+ where
+ for<'a> &'a T: RefNum<T>,
{
&(&(&(&(x * y) / y) % y) + y) - y
}
assert_eq!(compute(&1, 2), 1)
}
#[test]
fn check_refref_ops() {
fn compute<T>(x: &T, y: &T) -> T
- where for<'a> &'a T: RefNum<T>
+ where
+ for<'a> &'a T: RefNum<T>,
{
&(&(&(&(x * y) / y) % y) + y) - y
}
assert_eq!(compute(&1, &2), 1)
}
#[test]
fn check_numassign_ops() {
@@ -459,10 +620,21 @@ fn check_numassign_ops() {
x %= y;
x += y;
x -= y;
x
}
assert_eq!(compute(1, 2), 1)
}
-// TODO test `NumAssignRef`, but even the standard numeric types don't
-// implement this yet. (see rust pr41336)
+#[cfg(has_int_assignop_ref)]
+#[test]
+fn check_numassignref_ops() {
+ fn compute<T: NumAssignRef + Copy>(mut x: T, y: &T) -> T {
+ x *= y;
+ x /= y;
+ x %= y;
+ x += y;
+ x -= y;
+ x
+ }
+ assert_eq!(compute(1, &2), 1)
+}
diff --git a/third_party/rust/num-traits/src/macros.rs b/third_party/rust/num-traits/src/macros.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/src/macros.rs
@@ -0,0 +1,44 @@
+// not all are used in all features configurations
+#![allow(unused)]
+
+/// Forward a method to an inherent method or a base trait method.
+macro_rules! forward {
+ ($( Self :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+ => {$(
+ #[inline]
+ fn $method(self $( , $arg : $ty )* ) -> $ret {
+ Self::$method(self $( , $arg )* )
+ }
+ )*};
+ ($( $base:ident :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+ => {$(
+ #[inline]
+ fn $method(self $( , $arg : $ty )* ) -> $ret {
+ <Self as $base>::$method(self $( , $arg )* )
+ }
+ )*};
+ ($( $base:ident :: $method:ident ( $( $arg:ident : $ty:ty ),* ) -> $ret:ty ; )*)
+ => {$(
+ #[inline]
+ fn $method( $( $arg : $ty ),* ) -> $ret {
+ <Self as $base>::$method( $( $arg ),* )
+ }
+ )*};
+ ($( $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
+ => {$(
+ #[inline]
+ fn $method(self $( , $arg : $ty )* ) -> $ret {
+ $imp(self $( , $arg )* )
+ }
+ )*};
+}
+
+macro_rules! constant {
+ ($( $method:ident () -> $ret:expr ; )*)
+ => {$(
+ #[inline]
+ fn $method() -> Self {
+ $ret
+ }
+ )*};
+}
diff --git a/third_party/rust/num-traits/src/ops/checked.rs b/third_party/rust/num-traits/src/ops/checked.rs
--- a/third_party/rust/num-traits/src/ops/checked.rs
+++ b/third_party/rust/num-traits/src/ops/checked.rs
@@ -1,104 +1,210 @@
-use core::ops::{Add, Sub, Mul, Div, Shl, Shr};
+use core::ops::{Add, Div, Mul, Rem, Shl, Shr, Sub};
/// Performs addition that returns `None` instead of wrapping around on
/// overflow.
-pub trait CheckedAdd: Sized + Add<Self, Output=Self> {
+pub trait CheckedAdd: Sized + Add<Self, Output = Self> {
/// Adds two numbers, checking for overflow. If overflow happens, `None` is
/// returned.
fn checked_add(&self, v: &Self) -> Option<Self>;
}
macro_rules! checked_impl {
($trait_name:ident, $method:ident, $t:ty) => {
impl $trait_name for $t {
#[inline]
fn $method(&self, v: &$t) -> Option<$t> {
<$t>::$method(*self, *v)
}
}
- }
+ };
}
checked_impl!(CheckedAdd, checked_add, u8);
checked_impl!(CheckedAdd, checked_add, u16);
checked_impl!(CheckedAdd, checked_add, u32);
checked_impl!(CheckedAdd, checked_add, u64);
checked_impl!(CheckedAdd, checked_add, usize);
+#[cfg(has_i128)]
+checked_impl!(CheckedAdd, checked_add, u128);
checked_impl!(CheckedAdd, checked_add, i8);
checked_impl!(CheckedAdd, checked_add, i16);
checked_impl!(CheckedAdd, checked_add, i32);
checked_impl!(CheckedAdd, checked_add, i64);
checked_impl!(CheckedAdd, checked_add, isize);
+#[cfg(has_i128)]
+checked_impl!(CheckedAdd, checked_add, i128);
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
-pub trait CheckedSub: Sized + Sub<Self, Output=Self> {
+pub trait CheckedSub: Sized + Sub<Self, Output = Self> {
/// Subtracts two numbers, checking for underflow. If underflow happens,
/// `None` is returned.
fn checked_sub(&self, v: &Self) -> Option<Self>;
}
checked_impl!(CheckedSub, checked_sub, u8);
checked_impl!(CheckedSub, checked_sub, u16);
checked_impl!(CheckedSub, checked_sub, u32);
checked_impl!(CheckedSub, checked_sub, u64);
checked_impl!(CheckedSub, checked_sub, usize);
+#[cfg(has_i128)]
+checked_impl!(CheckedSub, checked_sub, u128);
checked_impl!(CheckedSub, checked_sub, i8);
checked_impl!(CheckedSub, checked_sub, i16);
checked_impl!(CheckedSub, checked_sub, i32);
checked_impl!(CheckedSub, checked_sub, i64);
checked_impl!(CheckedSub, checked_sub, isize);
+#[cfg(has_i128)]
+checked_impl!(CheckedSub, checked_sub, i128);
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
/// overflow.
-pub trait CheckedMul: Sized + Mul<Self, Output=Self> {
+pub trait CheckedMul: Sized + Mul<Self, Output = Self> {
/// Multiplies two numbers, checking for underflow or overflow. If underflow
/// or overflow happens, `None` is returned.
fn checked_mul(&self, v: &Self) -> Option<Self>;
}
checked_impl!(CheckedMul, checked_mul, u8);
checked_impl!(CheckedMul, checked_mul, u16);
checked_impl!(CheckedMul, checked_mul, u32);
checked_impl!(CheckedMul, checked_mul, u64);
checked_impl!(CheckedMul, checked_mul, usize);
+#[cfg(has_i128)]
+checked_impl!(CheckedMul, checked_mul, u128);
checked_impl!(CheckedMul, checked_mul, i8);
checked_impl!(CheckedMul, checked_mul, i16);
checked_impl!(CheckedMul, checked_mul, i32);
checked_impl!(CheckedMul, checked_mul, i64);
checked_impl!(CheckedMul, checked_mul, isize);
+#[cfg(has_i128)]
+checked_impl!(CheckedMul, checked_mul, i128);
/// Performs division that returns `None` instead of panicking on division by zero and instead of
/// wrapping around on underflow and overflow.
-pub trait CheckedDiv: Sized + Div<Self, Output=Self> {
+pub trait CheckedDiv: Sized + Div<Self, Output = Self> {
/// Divides two numbers, checking for underflow, overflow and division by
/// zero. If any of that happens, `None` is returned.
fn checked_div(&self, v: &Self) -> Option<Self>;
}
checked_impl!(CheckedDiv, checked_div, u8);
checked_impl!(CheckedDiv, checked_div, u16);
checked_impl!(CheckedDiv, checked_div, u32);
checked_impl!(CheckedDiv, checked_div, u64);
checked_impl!(CheckedDiv, checked_div, usize);
+#[cfg(has_i128)]
+checked_impl!(CheckedDiv, checked_div, u128);
checked_impl!(CheckedDiv, checked_div, i8);
checked_impl!(CheckedDiv, checked_div, i16);
checked_impl!(CheckedDiv, checked_div, i32);
checked_impl!(CheckedDiv, checked_div, i64);
checked_impl!(CheckedDiv, checked_div, isize);
+#[cfg(has_i128)]
+checked_impl!(CheckedDiv, checked_div, i128);
-/// Performs a left shift that returns `None` on overflow.
-pub trait CheckedShl: Sized + Shl<u32, Output=Self> {
- /// Shifts a number to the left, checking for overflow. If overflow happens,
- /// `None` is returned.
+/// Performs an integral remainder that returns `None` instead of panicking on division by zero and
+/// instead of wrapping around on underflow and overflow.
+pub trait CheckedRem: Sized + Rem<Self, Output = Self> {
+ /// Finds the remainder of dividing two numbers, checking for underflow, overflow and division
+ /// by zero. If any of that happens, `None` is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::CheckedRem;
+ /// use std::i32::MIN;
+ ///
+ /// assert_eq!(CheckedRem::checked_rem(&10, &7), Some(3));
+ /// assert_eq!(CheckedRem::checked_rem(&10, &-7), Some(3));
+ /// assert_eq!(CheckedRem::checked_rem(&-10, &7), Some(-3));
+ /// assert_eq!(CheckedRem::checked_rem(&-10, &-7), Some(-3));
+ ///
+ /// assert_eq!(CheckedRem::checked_rem(&10, &0), None);
+ ///
+ /// assert_eq!(CheckedRem::checked_rem(&MIN, &1), Some(0));
+ /// assert_eq!(CheckedRem::checked_rem(&MIN, &-1), None);
+ /// ```
+ fn checked_rem(&self, v: &Self) -> Option<Self>;
+}
+
+checked_impl!(CheckedRem, checked_rem, u8);
+checked_impl!(CheckedRem, checked_rem, u16);
+checked_impl!(CheckedRem, checked_rem, u32);
+checked_impl!(CheckedRem, checked_rem, u64);
+checked_impl!(CheckedRem, checked_rem, usize);
+#[cfg(has_i128)]
+checked_impl!(CheckedRem, checked_rem, u128);
+
+checked_impl!(CheckedRem, checked_rem, i8);
+checked_impl!(CheckedRem, checked_rem, i16);
+checked_impl!(CheckedRem, checked_rem, i32);
+checked_impl!(CheckedRem, checked_rem, i64);
+checked_impl!(CheckedRem, checked_rem, isize);
+#[cfg(has_i128)]
+checked_impl!(CheckedRem, checked_rem, i128);
+
+macro_rules! checked_impl_unary {
+ ($trait_name:ident, $method:ident, $t:ty) => {
+ impl $trait_name for $t {
+ #[inline]
+ fn $method(&self) -> Option<$t> {
+ <$t>::$method(*self)
+ }
+ }
+ };
+}
+
+/// Performs negation that returns `None` if the result can't be represented.
+pub trait CheckedNeg: Sized {
+ /// Negates a number, returning `None` for results that can't be represented, like signed `MIN`
+ /// values that can't be positive, or non-zero unsigned values that can't be negative.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::CheckedNeg;
+ /// use std::i32::MIN;
+ ///
+ /// assert_eq!(CheckedNeg::checked_neg(&1_i32), Some(-1));
+ /// assert_eq!(CheckedNeg::checked_neg(&-1_i32), Some(1));
+ /// assert_eq!(CheckedNeg::checked_neg(&MIN), None);
+ ///
+ /// assert_eq!(CheckedNeg::checked_neg(&0_u32), Some(0));
+ /// assert_eq!(CheckedNeg::checked_neg(&1_u32), None);
+ /// ```
+ fn checked_neg(&self) -> Option<Self>;
+}
+
+checked_impl_unary!(CheckedNeg, checked_neg, u8);
+checked_impl_unary!(CheckedNeg, checked_neg, u16);
+checked_impl_unary!(CheckedNeg, checked_neg, u32);
+checked_impl_unary!(CheckedNeg, checked_neg, u64);
+checked_impl_unary!(CheckedNeg, checked_neg, usize);
+#[cfg(has_i128)]
+checked_impl_unary!(CheckedNeg, checked_neg, u128);
+
+checked_impl_unary!(CheckedNeg, checked_neg, i8);
+checked_impl_unary!(CheckedNeg, checked_neg, i16);
+checked_impl_unary!(CheckedNeg, checked_neg, i32);
+checked_impl_unary!(CheckedNeg, checked_neg, i64);
+checked_impl_unary!(CheckedNeg, checked_neg, isize);
+#[cfg(has_i128)]
+checked_impl_unary!(CheckedNeg, checked_neg, i128);
+
+/// Performs a left shift that returns `None` on shifts larger than
+/// the type width.
+pub trait CheckedShl: Sized + Shl<u32, Output = Self> {
+ /// Checked shift left. Computes `self << rhs`, returning `None`
+ /// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// ```
/// use num_traits::CheckedShl;
///
/// let x: u16 = 0x0001;
///
/// assert_eq!(CheckedShl::checked_shl(&x, 0), Some(0x0001));
/// assert_eq!(CheckedShl::checked_shl(&x, 1), Some(0x0002));
@@ -111,35 +217,40 @@ pub trait CheckedShl: Sized + Shl<u32, O
macro_rules! checked_shift_impl {
($trait_name:ident, $method:ident, $t:ty) => {
impl $trait_name for $t {
#[inline]
fn $method(&self, rhs: u32) -> Option<$t> {
<$t>::$method(*self, rhs)
}
}
- }
+ };
}
checked_shift_impl!(CheckedShl, checked_shl, u8);
checked_shift_impl!(CheckedShl, checked_shl, u16);
checked_shift_impl!(CheckedShl, checked_shl, u32);
checked_shift_impl!(CheckedShl, checked_shl, u64);
checked_shift_impl!(CheckedShl, checked_shl, usize);
+#[cfg(has_i128)]
+checked_shift_impl!(CheckedShl, checked_shl, u128);
checked_shift_impl!(CheckedShl, checked_shl, i8);
checked_shift_impl!(CheckedShl, checked_shl, i16);
checked_shift_impl!(CheckedShl, checked_shl, i32);
checked_shift_impl!(CheckedShl, checked_shl, i64);
checked_shift_impl!(CheckedShl, checked_shl, isize);
+#[cfg(has_i128)]
+checked_shift_impl!(CheckedShl, checked_shl, i128);
-/// Performs a right shift that returns `None` on overflow.
-pub trait CheckedShr: Sized + Shr<u32, Output=Self> {
- /// Shifts a number to the left, checking for overflow. If overflow happens,
- /// `None` is returned.
+/// Performs a right shift that returns `None` on shifts larger than
+/// the type width.
+pub trait CheckedShr: Sized + Shr<u32, Output = Self> {
+ /// Checked shift right. Computes `self >> rhs`, returning `None`
+ /// if `rhs` is larger than or equal to the number of bits in `self`.
///
/// ```
/// use num_traits::CheckedShr;
///
/// let x: u16 = 0x8000;
///
/// assert_eq!(CheckedShr::checked_shr(&x, 0), Some(0x8000));
/// assert_eq!(CheckedShr::checked_shr(&x, 1), Some(0x4000));
@@ -149,14 +260,18 @@ pub trait CheckedShr: Sized + Shr<u32, O
fn checked_shr(&self, rhs: u32) -> Option<Self>;
}
checked_shift_impl!(CheckedShr, checked_shr, u8);
checked_shift_impl!(CheckedShr, checked_shr, u16);
checked_shift_impl!(CheckedShr, checked_shr, u32);
checked_shift_impl!(CheckedShr, checked_shr, u64);
checked_shift_impl!(CheckedShr, checked_shr, usize);
+#[cfg(has_i128)]
+checked_shift_impl!(CheckedShr, checked_shr, u128);
checked_shift_impl!(CheckedShr, checked_shr, i8);
checked_shift_impl!(CheckedShr, checked_shr, i16);
checked_shift_impl!(CheckedShr, checked_shr, i32);
checked_shift_impl!(CheckedShr, checked_shr, i64);
checked_shift_impl!(CheckedShr, checked_shr, isize);
+#[cfg(has_i128)]
+checked_shift_impl!(CheckedShr, checked_shr, i128);
diff --git a/third_party/rust/num-traits/src/ops/euclid.rs b/third_party/rust/num-traits/src/ops/euclid.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/src/ops/euclid.rs
@@ -0,0 +1,347 @@
+use core::ops::{Div, Rem};
+
+pub trait Euclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
+ /// Calculates Euclidean division, the matching method for `rem_euclid`.
+ ///
+ /// This computes the integer `n` such that
+ /// `self = n * v + self.rem_euclid(v)`.
+ /// In other words, the result is `self / v` rounded to the integer `n`
+ /// such that `self >= n * v`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::Euclid;
+ ///
+ /// let a: i32 = 7;
+ /// let b: i32 = 4;
+ /// assert_eq!(Euclid::div_euclid(&a, &b), 1); // 7 > 4 * 1
+ /// assert_eq!(Euclid::div_euclid(&-a, &b), -2); // -7 >= 4 * -2
+ /// assert_eq!(Euclid::div_euclid(&a, &-b), -1); // 7 >= -4 * -1
+ /// assert_eq!(Euclid::div_euclid(&-a, &-b), 2); // -7 >= -4 * 2
+ /// ```
+ fn div_euclid(&self, v: &Self) -> Self;
+
+ /// Calculates the least nonnegative remainder of `self (mod v)`.
+ ///
+ /// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in
+ /// most cases. However, due to a floating point round-off error it can
+ /// result in `r == v.abs()`, violating the mathematical definition, if
+ /// `self` is much smaller than `v.abs()` in magnitude and `self < 0.0`.
+ /// This result is not an element of the function's codomain, but it is the
+ /// closest floating point number in the real numbers and thus fulfills the
+ /// property `self == self.div_euclid(v) * v + self.rem_euclid(v)`
+ /// approximatively.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::Euclid;
+ ///
+ /// let a: i32 = 7;
+ /// let b: i32 = 4;
+ /// assert_eq!(Euclid::rem_euclid(&a, &b), 3);
+ /// assert_eq!(Euclid::rem_euclid(&-a, &b), 1);
+ /// assert_eq!(Euclid::rem_euclid(&a, &-b), 3);
+ /// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1);
+ /// ```
+ fn rem_euclid(&self, v: &Self) -> Self;
+}
+
+macro_rules! euclid_forward_impl {
+ ($($t:ty)*) => {$(
+ #[cfg(has_div_euclid)]
+ impl Euclid for $t {
+ #[inline]
+ fn div_euclid(&self, v: &$t) -> Self {
+ <$t>::div_euclid(*self, *v)
+ }
+
+ #[inline]
+ fn rem_euclid(&self, v: &$t) -> Self {
+ <$t>::rem_euclid(*self, *v)
+ }
+ }
+ )*}
+}
+
+macro_rules! euclid_int_impl {
+ ($($t:ty)*) => {$(
+ euclid_forward_impl!($t);
+
+ #[cfg(not(has_div_euclid))]
+ impl Euclid for $t {
+ #[inline]
+ fn div_euclid(&self, v: &$t) -> Self {
+ let q = self / v;
+ if self % v < 0 {
+ return if *v > 0 { q - 1 } else { q + 1 }
+ }
+ q
+ }
+
+ #[inline]
+ fn rem_euclid(&self, v: &$t) -> Self {
+ let r = self % v;
+ if r < 0 {
+ if *v < 0 {
+ r - v
+ } else {
+ r + v
+ }
+ } else {
+ r
+ }
+ }
+ }
+ )*}
+}
+
+macro_rules! euclid_uint_impl {
+ ($($t:ty)*) => {$(
+ euclid_forward_impl!($t);
+
+ #[cfg(not(has_div_euclid))]
+ impl Euclid for $t {
+ #[inline]
+ fn div_euclid(&self, v: &$t) -> Self {
+ self / v
+ }
+
+ #[inline]
+ fn rem_euclid(&self, v: &$t) -> Self {
+ self % v
+ }
+ }
+ )*}
+}
+
+euclid_int_impl!(isize i8 i16 i32 i64);
+euclid_uint_impl!(usize u8 u16 u32 u64);
+#[cfg(has_i128)]
+euclid_int_impl!(i128);
+#[cfg(has_i128)]
+euclid_uint_impl!(u128);
+
+#[cfg(all(has_div_euclid, feature = "std"))]
+euclid_forward_impl!(f32 f64);
+
+#[cfg(not(all(has_div_euclid, feature = "std")))]
+impl Euclid for f32 {
+ #[inline]
+ fn div_euclid(&self, v: &f32) -> f32 {
+ let q = <f32 as ::float::FloatCore>::trunc(self / v);
+ if self % v < 0.0 {
+ return if *v > 0.0 { q - 1.0 } else { q + 1.0 };
+ }
+ q
+ }
+
+ #[inline]
+ fn rem_euclid(&self, v: &f32) -> f32 {
+ let r = self % v;
+ if r < 0.0 {
+ r + <f32 as ::float::FloatCore>::abs(*v)
+ } else {
+ r
+ }
+ }
+}
+
+#[cfg(not(all(has_div_euclid, feature = "std")))]
+impl Euclid for f64 {
+ #[inline]
+ fn div_euclid(&self, v: &f64) -> f64 {
+ let q = <f64 as ::float::FloatCore>::trunc(self / v);
+ if self % v < 0.0 {
+ return if *v > 0.0 { q - 1.0 } else { q + 1.0 };
+ }
+ q
+ }
+
+ #[inline]
+ fn rem_euclid(&self, v: &f64) -> f64 {
+ let r = self % v;
+ if r < 0.0 {
+ r + <f64 as ::float::FloatCore>::abs(*v)
+ } else {
+ r
+ }
+ }
+}
+
+pub trait CheckedEuclid: Euclid {
+ /// Performs euclid division that returns `None` instead of panicking on division by zero
+ /// and instead of wrapping around on underflow and overflow.
+ fn checked_div_euclid(&self, v: &Self) -> Option<Self>;
+
+ /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
+ /// division by zero. If any of that happens, `None` is returned.
+ fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
+}
+
+macro_rules! checked_euclid_forward_impl {
+ ($($t:ty)*) => {$(
+ #[cfg(has_div_euclid)]
+ impl CheckedEuclid for $t {
+ #[inline]
+ fn checked_div_euclid(&self, v: &$t) -> Option<Self> {
+ <$t>::checked_div_euclid(*self, *v)
+ }
+
+ #[inline]
+ fn checked_rem_euclid(&self, v: &$t) -> Option<Self> {
+ <$t>::checked_rem_euclid(*self, *v)
+ }
+ }
+ )*}
+}
+
+macro_rules! checked_euclid_int_impl {
+ ($($t:ty)*) => {$(
+ checked_euclid_forward_impl!($t);
+
+ #[cfg(not(has_div_euclid))]
+ impl CheckedEuclid for $t {
+ #[inline]
+ fn checked_div_euclid(&self, v: &$t) -> Option<$t> {
+ if *v == 0 || (*self == Self::min_value() && *v == -1) {
+ None
+ } else {
+ Some(Euclid::div_euclid(self, v))
+ }
+ }
+
+ #[inline]
+ fn checked_rem_euclid(&self, v: &$t) -> Option<$t> {
+ if *v == 0 || (*self == Self::min_value() && *v == -1) {
+ None
+ } else {
+ Some(Euclid::rem_euclid(self, v))
+ }
+ }
+ }
+ )*}
+}
+
+macro_rules! checked_euclid_uint_impl {
+ ($($t:ty)*) => {$(
+ checked_euclid_forward_impl!($t);
+
+ #[cfg(not(has_div_euclid))]
+ impl CheckedEuclid for $t {
+ #[inline]
+ fn checked_div_euclid(&self, v: &$t) -> Option<$t> {
+ if *v == 0 {
+ None
+ } else {
+ Some(Euclid::div_euclid(self, v))
+ }
+ }
+
+ #[inline]
+ fn checked_rem_euclid(&self, v: &$t) -> Option<$t> {
+ if *v == 0 {
+ None
+ } else {
+ Some(Euclid::rem_euclid(self, v))
+ }
+ }
+ }
+ )*}
+}
+
+checked_euclid_int_impl!(isize i8 i16 i32 i64);
+checked_euclid_uint_impl!(usize u8 u16 u32 u64);
+#[cfg(has_i128)]
+checked_euclid_int_impl!(i128);
+#[cfg(has_i128)]
+checked_euclid_uint_impl!(u128);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn euclid_unsigned() {
+ macro_rules! test_euclid {
+ ($($t:ident)+) => {
+ $(
+ {
+ let x: $t = 10;
+ let y: $t = 3;
+ assert_eq!(Euclid::div_euclid(&x, &y), 3);
+ assert_eq!(Euclid::rem_euclid(&x, &y), 1);
+ }
+ )+
+ };
+ }
+
+ test_euclid!(usize u8 u16 u32 u64);
+ }
+
+ #[test]
+ fn euclid_signed() {
+ macro_rules! test_euclid {
+ ($($t:ident)+) => {
+ $(
+ {
+ let x: $t = 10;
+ let y: $t = -3;
+ assert_eq!(Euclid::div_euclid(&x, &y), -3);
+ assert_eq!(Euclid::div_euclid(&-x, &y), 4);
+ assert_eq!(Euclid::rem_euclid(&x, &y), 1);
+ assert_eq!(Euclid::rem_euclid(&-x, &y), 2);
+ let x: $t = $t::min_value() + 1;
+ let y: $t = -1;
+ assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value());
+ }
+ )+
+ };
+ }
+
+ test_euclid!(isize i8 i16 i32 i64);
+ }
+
+ #[test]
+ fn euclid_float() {
+ macro_rules! test_euclid {
+ ($($t:ident)+) => {
+ $(
+ {
+ let x: $t = 12.1;
+ let y: $t = 3.2;
+ assert!(Euclid::div_euclid(&x, &y) * y + Euclid::rem_euclid(&x, &y) - x
+ <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+ assert!(Euclid::div_euclid(&x, &-y) * -y + Euclid::rem_euclid(&x, &-y) - x
+ <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+ assert!(Euclid::div_euclid(&-x, &y) * y + Euclid::rem_euclid(&-x, &y) + x
+ <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+ assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x
+ <= 46.4 * <$t as ::float::FloatCore>::epsilon());
+ }
+ )+
+ };
+ }
+
+ test_euclid!(f32 f64);
+ }
+
+ #[test]
+ fn euclid_checked() {
+ macro_rules! test_euclid_checked {
+ ($($t:ident)+) => {
+ $(
+ {
+ assert_eq!(CheckedEuclid::checked_div_euclid(&$t::min_value(), &-1), None);
+ assert_eq!(CheckedEuclid::checked_rem_euclid(&$t::min_value(), &-1), None);
+ assert_eq!(CheckedEuclid::checked_div_euclid(&1, &0), None);
+ assert_eq!(CheckedEuclid::checked_rem_euclid(&1, &0), None);
+ }
+ )+
+ };
+ }
+
+ test_euclid_checked!(isize i8 i16 i32 i64);
+ }
+}
diff --git a/third_party/rust/num-traits/src/ops/inv.rs b/third_party/rust/num-traits/src/ops/inv.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/src/ops/inv.rs
@@ -0,0 +1,47 @@
+/// Unary operator for retrieving the multiplicative inverse, or reciprocal, of a value.
+pub trait Inv {
+ /// The result after applying the operator.
+ type Output;
+
+ /// Returns the multiplicative inverse of `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::f64::INFINITY;
+ /// use num_traits::Inv;
+ ///
+ /// assert_eq!(7.0.inv() * 7.0, 1.0);
+ /// assert_eq!((-0.0).inv(), -INFINITY);
+ /// ```
+ fn inv(self) -> Self::Output;
+}
+
+impl Inv for f32 {
+ type Output = f32;
+ #[inline]
+ fn inv(self) -> f32 {
+ 1.0 / self
+ }
+}
+impl Inv for f64 {
+ type Output = f64;
+ #[inline]
+ fn inv(self) -> f64 {
+ 1.0 / self
+ }
+}
+impl<'a> Inv for &'a f32 {
+ type Output = f32;
+ #[inline]
+ fn inv(self) -> f32 {
+ 1.0 / *self
+ }
+}
+impl<'a> Inv for &'a f64 {
+ type Output = f64;
+ #[inline]
+ fn inv(self) -> f64 {
+ 1.0 / *self
+ }
+}
diff --git a/third_party/rust/num-traits/src/ops/mod.rs b/third_party/rust/num-traits/src/ops/mod.rs
--- a/third_party/rust/num-traits/src/ops/mod.rs
+++ b/third_party/rust/num-traits/src/ops/mod.rs
@@ -1,3 +1,7 @@
+pub mod checked;
+pub mod euclid;
+pub mod inv;
+pub mod mul_add;
+pub mod overflowing;
pub mod saturating;
-pub mod checked;
pub mod wrapping;
diff --git a/third_party/rust/num-traits/src/ops/mul_add.rs b/third_party/rust/num-traits/src/ops/mul_add.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/src/ops/mul_add.rs
@@ -0,0 +1,151 @@
+/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+/// error, yielding a more accurate result than an unfused multiply-add.
+///
+/// Using `mul_add` can be more performant than an unfused multiply-add if
+/// the target architecture has a dedicated `fma` CPU instruction.
+///
+/// Note that `A` and `B` are `Self` by default, but this is not mandatory.
+///
+/// # Example
+///
+/// ```
+/// use std::f32;
+///
+/// let m = 10.0_f32;
+/// let x = 4.0_f32;
+/// let b = 60.0_f32;
+///
+/// // 100.0
+/// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
+///
+/// assert!(abs_difference <= 100.0 * f32::EPSILON);
+/// ```
+pub trait MulAdd<A = Self, B = Self> {
+ /// The resulting type after applying the fused multiply-add.
+ type Output;
+
+ /// Performs the fused multiply-add operation.
+ fn mul_add(self, a: A, b: B) -> Self::Output;
+}
+
+/// The fused multiply-add assignment operation.
+pub trait MulAddAssign<A = Self, B = Self> {
+ /// Performs the fused multiply-add operation.
+ fn mul_add_assign(&mut self, a: A, b: B);
+}
+
+#[cfg(any(feature = "std", feature = "libm"))]
+impl MulAdd<f32, f32> for f32 {
+ type Output = Self;
+
+ #[inline]
+ fn mul_add(self, a: Self, b: Self) -> Self::Output {
+ <Self as ::Float>::mul_add(self, a, b)
+ }
+}
+
+#[cfg(any(feature = "std", feature = "libm"))]
+impl MulAdd<f64, f64> for f64 {
+ type Output = Self;
+
+ #[inline]
+ fn mul_add(self, a: Self, b: Self) -> Self::Output {
+ <Self as ::Float>::mul_add(self, a, b)
+ }
+}
+
+macro_rules! mul_add_impl {
+ ($trait_name:ident for $($t:ty)*) => {$(
+ impl $trait_name for $t {
+ type Output = Self;
+
+ #[inline]
+ fn mul_add(self, a: Self, b: Self) -> Self::Output {
+ (self * a) + b
+ }
+ }
+ )*}
+}
+
+mul_add_impl!(MulAdd for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+#[cfg(has_i128)]
+mul_add_impl!(MulAdd for i128 u128);
+
+#[cfg(any(feature = "std", feature = "libm"))]
+impl MulAddAssign<f32, f32> for f32 {
+ #[inline]
+ fn mul_add_assign(&mut self, a: Self, b: Self) {
+ *self = <Self as ::Float>::mul_add(*self, a, b)
+ }
+}
+
+#[cfg(any(feature = "std", feature = "libm"))]
+impl MulAddAssign<f64, f64> for f64 {
+ #[inline]
+ fn mul_add_assign(&mut self, a: Self, b: Self) {
+ *self = <Self as ::Float>::mul_add(*self, a, b)
+ }
+}
+
+macro_rules! mul_add_assign_impl {
+ ($trait_name:ident for $($t:ty)*) => {$(
+ impl $trait_name for $t {
+ #[inline]
+ fn mul_add_assign(&mut self, a: Self, b: Self) {
+ *self = (*self * a) + b
+ }
+ }
+ )*}
+}
+
+mul_add_assign_impl!(MulAddAssign for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+#[cfg(has_i128)]
+mul_add_assign_impl!(MulAddAssign for i128 u128);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn mul_add_integer() {
+ macro_rules! test_mul_add {
+ ($($t:ident)+) => {
+ $(
+ {
+ let m: $t = 2;
+ let x: $t = 3;
+ let b: $t = 4;
+
+ assert_eq!(MulAdd::mul_add(m, x, b), (m*x + b));
+ }
+ )+
+ };
+ }
+
+ test_mul_add!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn mul_add_float() {
+ macro_rules! test_mul_add {
+ ($($t:ident)+) => {
+ $(
+ {
+ use core::$t;
+
+ let m: $t = 12.0;
+ let x: $t = 3.4;
+ let b: $t = 5.6;
+
+ let abs_difference = (MulAdd::mul_add(m, x, b) - (m*x + b)).abs();
+
+ assert!(abs_difference <= 46.4 * $t::EPSILON);
+ }
+ )+
+ };
+ }
+
+ test_mul_add!(f32 f64);
+ }
+}
diff --git a/third_party/rust/num-traits/src/ops/overflowing.rs b/third_party/rust/num-traits/src/ops/overflowing.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/src/ops/overflowing.rs
@@ -0,0 +1,104 @@
+use core::ops::{Add, Mul, Sub};
+#[cfg(has_i128)]
+use core::{i128, u128};
+use core::{i16, i32, i64, i8, isize};
+use core::{u16, u32, u64, u8, usize};
+
+macro_rules! overflowing_impl {
+ ($trait_name:ident, $method:ident, $t:ty) => {
+ impl $trait_name for $t {
+ #[inline]
+ fn $method(&self, v: &Self) -> (Self, bool) {
+ <$t>::$method(*self, *v)
+ }
+ }
+ };
+}
+
+/// Performs addition with a flag for overflow.
+pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
+ /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur.
+ /// If an overflow would have occurred then the wrapped value is returned.
+ fn overflowing_add(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingAdd, overflowing_add, u8);
+overflowing_impl!(OverflowingAdd, overflowing_add, u16);
+overflowing_impl!(OverflowingAdd, overflowing_add, u32);
+overflowing_impl!(OverflowingAdd, overflowing_add, u64);
+overflowing_impl!(OverflowingAdd, overflowing_add, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingAdd, overflowing_add, u128);
+
+overflowing_impl!(OverflowingAdd, overflowing_add, i8);
+overflowing_impl!(OverflowingAdd, overflowing_add, i16);
+overflowing_impl!(OverflowingAdd, overflowing_add, i32);
+overflowing_impl!(OverflowingAdd, overflowing_add, i64);
+overflowing_impl!(OverflowingAdd, overflowing_add, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingAdd, overflowing_add, i128);
+
+/// Performs substraction with a flag for overflow.
+pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
+ /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur.
+ /// If an overflow would have occurred then the wrapped value is returned.
+ fn overflowing_sub(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingSub, overflowing_sub, u8);
+overflowing_impl!(OverflowingSub, overflowing_sub, u16);
+overflowing_impl!(OverflowingSub, overflowing_sub, u32);
+overflowing_impl!(OverflowingSub, overflowing_sub, u64);
+overflowing_impl!(OverflowingSub, overflowing_sub, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingSub, overflowing_sub, u128);
+
+overflowing_impl!(OverflowingSub, overflowing_sub, i8);
+overflowing_impl!(OverflowingSub, overflowing_sub, i16);
+overflowing_impl!(OverflowingSub, overflowing_sub, i32);
+overflowing_impl!(OverflowingSub, overflowing_sub, i64);
+overflowing_impl!(OverflowingSub, overflowing_sub, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingSub, overflowing_sub, i128);
+
+/// Performs multiplication with a flag for overflow.
+pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
+ /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur.
+ /// If an overflow would have occurred then the wrapped value is returned.
+ fn overflowing_mul(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingMul, overflowing_mul, u8);
+overflowing_impl!(OverflowingMul, overflowing_mul, u16);
+overflowing_impl!(OverflowingMul, overflowing_mul, u32);
+overflowing_impl!(OverflowingMul, overflowing_mul, u64);
+overflowing_impl!(OverflowingMul, overflowing_mul, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingMul, overflowing_mul, u128);
+
+overflowing_impl!(OverflowingMul, overflowing_mul, i8);
+overflowing_impl!(OverflowingMul, overflowing_mul, i16);
+overflowing_impl!(OverflowingMul, overflowing_mul, i32);
+overflowing_impl!(OverflowingMul, overflowing_mul, i64);
+overflowing_impl!(OverflowingMul, overflowing_mul, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingMul, overflowing_mul, i128);
+
+#[test]
+fn test_overflowing_traits() {
+ fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
+ a.overflowing_add(&b)
+ }
+ fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
+ a.overflowing_sub(&b)
+ }
+ fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
+ a.overflowing_mul(&b)
+ }
+ assert_eq!(overflowing_add(5i16, 2), (7, false));
+ assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
+ assert_eq!(overflowing_sub(5i16, 2), (3, false));
+ assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
+ assert_eq!(overflowing_mul(5i16, 2), (10, false));
+ assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
+}
diff --git a/third_party/rust/num-traits/src/ops/saturating.rs b/third_party/rust/num-traits/src/ops/saturating.rs
--- a/third_party/rust/num-traits/src/ops/saturating.rs
+++ b/third_party/rust/num-traits/src/ops/saturating.rs
@@ -1,28 +1,137 @@
-/// Saturating math operations
+use core::ops::{Add, Mul, Sub};
+
+/// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and
+/// `SaturatingMul` instead.
pub trait Saturating {
/// Saturating addition operator.
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
fn saturating_add(self, v: Self) -> Self;
/// Saturating subtraction operator.
/// Returns a-b, saturating at the numeric bounds instead of overflowing.
fn saturating_sub(self, v: Self) -> Self;
}
-macro_rules! saturating_impl {
+macro_rules! deprecated_saturating_impl {
($trait_name:ident for $($t:ty)*) => {$(
impl $trait_name for $t {
#[inline]
fn saturating_add(self, v: Self) -> Self {
Self::saturating_add(self, v)
}
#[inline]
fn saturating_sub(self, v: Self) -> Self {
Self::saturating_sub(self, v)
}
}
)*}
}
-saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+#[cfg(has_i128)]
+deprecated_saturating_impl!(Saturating for i128 u128);
+
+macro_rules! saturating_impl {
+ ($trait_name:ident, $method:ident, $t:ty) => {
+ impl $trait_name for $t {
+ #[inline]
+ fn $method(&self, v: &Self) -> Self {
+ <$t>::$method(*self, *v)
+ }
+ }
+ };
+}
+
+/// Performs addition that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingAdd: Sized + Add<Self, Output = Self> {
+ /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of
+ /// the type.
+ fn saturating_add(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingAdd, saturating_add, u8);
+saturating_impl!(SaturatingAdd, saturating_add, u16);
+saturating_impl!(SaturatingAdd, saturating_add, u32);
+saturating_impl!(SaturatingAdd, saturating_add, u64);
+saturating_impl!(SaturatingAdd, saturating_add, usize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingAdd, saturating_add, u128);
+
+saturating_impl!(SaturatingAdd, saturating_add, i8);
+saturating_impl!(SaturatingAdd, saturating_add, i16);
+saturating_impl!(SaturatingAdd, saturating_add, i32);
+saturating_impl!(SaturatingAdd, saturating_add, i64);
+saturating_impl!(SaturatingAdd, saturating_add, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingAdd, saturating_add, i128);
+
+/// Performs subtraction that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingSub: Sized + Sub<Self, Output = Self> {
+ /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of
+ /// the type.
+ fn saturating_sub(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingSub, saturating_sub, u8);
+saturating_impl!(SaturatingSub, saturating_sub, u16);
+saturating_impl!(SaturatingSub, saturating_sub, u32);
+saturating_impl!(SaturatingSub, saturating_sub, u64);
+saturating_impl!(SaturatingSub, saturating_sub, usize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingSub, saturating_sub, u128);
+
+saturating_impl!(SaturatingSub, saturating_sub, i8);
+saturating_impl!(SaturatingSub, saturating_sub, i16);
+saturating_impl!(SaturatingSub, saturating_sub, i32);
+saturating_impl!(SaturatingSub, saturating_sub, i64);
+saturating_impl!(SaturatingSub, saturating_sub, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingSub, saturating_sub, i128);
+
+/// Performs multiplication that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingMul: Sized + Mul<Self, Output = Self> {
+ /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of
+ /// the type.
+ fn saturating_mul(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingMul, saturating_mul, u8);
+saturating_impl!(SaturatingMul, saturating_mul, u16);
+saturating_impl!(SaturatingMul, saturating_mul, u32);
+saturating_impl!(SaturatingMul, saturating_mul, u64);
+saturating_impl!(SaturatingMul, saturating_mul, usize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingMul, saturating_mul, u128);
+
+saturating_impl!(SaturatingMul, saturating_mul, i8);
+saturating_impl!(SaturatingMul, saturating_mul, i16);
+saturating_impl!(SaturatingMul, saturating_mul, i32);
+saturating_impl!(SaturatingMul, saturating_mul, i64);
+saturating_impl!(SaturatingMul, saturating_mul, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingMul, saturating_mul, i128);
+
+// TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable.
+
+#[test]
+fn test_saturating_traits() {
+ fn saturating_add<T: SaturatingAdd>(a: T, b: T) -> T {
+ a.saturating_add(&b)
+ }
+ fn saturating_sub<T: SaturatingSub>(a: T, b: T) -> T {
+ a.saturating_sub(&b)
+ }
+ fn saturating_mul<T: SaturatingMul>(a: T, b: T) -> T {
+ a.saturating_mul(&b)
+ }
+ assert_eq!(saturating_add(255, 1), 255u8);
+ assert_eq!(saturating_add(127, 1), 127i8);
+ assert_eq!(saturating_add(-128, -1), -128i8);
+ assert_eq!(saturating_sub(0, 1), 0u8);
+ assert_eq!(saturating_sub(-128, 1), -128i8);
+ assert_eq!(saturating_sub(127, -1), 127i8);
+ assert_eq!(saturating_mul(255, 2), 255u8);
+ assert_eq!(saturating_mul(127, 2), 127i8);
+ assert_eq!(saturating_mul(-128, 2), -128i8);
+}
diff --git a/third_party/rust/num-traits/src/ops/wrapping.rs b/third_party/rust/num-traits/src/ops/wrapping.rs
--- a/third_party/rust/num-traits/src/ops/wrapping.rs
+++ b/third_party/rust/num-traits/src/ops/wrapping.rs
@@ -1,10 +1,10 @@
-use core::ops::{Add, Sub, Mul};
use core::num::Wrapping;
+use core::ops::{Add, Mul, Neg, Shl, Shr, Sub};
macro_rules! wrapping_impl {
($trait_name:ident, $method:ident, $t:ty) => {
impl $trait_name for $t {
#[inline]
fn $method(&self, v: &Self) -> Self {
<$t>::$method(*self, *v)
}
@@ -12,105 +12,300 @@ macro_rules! wrapping_impl {
};
($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
impl $trait_name<$rhs> for $t {
#[inline]
fn $method(&self, v: &$rhs) -> Self {
<$t>::$method(*self, *v)
}
}
- }
+ };
}
/// Performs addition that wraps around on overflow.
-pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
+pub trait WrappingAdd: Sized + Add<Self, Output = Self> {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
/// the type.
fn wrapping_add(&self, v: &Self) -> Self;
}
wrapping_impl!(WrappingAdd, wrapping_add, u8);
wrapping_impl!(WrappingAdd, wrapping_add, u16);
wrapping_impl!(WrappingAdd, wrapping_add, u32);
wrapping_impl!(WrappingAdd, wrapping_add, u64);
wrapping_impl!(WrappingAdd, wrapping_add, usize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingAdd, wrapping_add, u128);
wrapping_impl!(WrappingAdd, wrapping_add, i8);
wrapping_impl!(WrappingAdd, wrapping_add, i16);
wrapping_impl!(WrappingAdd, wrapping_add, i32);
wrapping_impl!(WrappingAdd, wrapping_add, i64);
wrapping_impl!(WrappingAdd, wrapping_add, isize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingAdd, wrapping_add, i128);
/// Performs subtraction that wraps around on overflow.
-pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
+pub trait WrappingSub: Sized + Sub<Self, Output = Self> {
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
/// of the type.
fn wrapping_sub(&self, v: &Self) -> Self;
}
wrapping_impl!(WrappingSub, wrapping_sub, u8);
wrapping_impl!(WrappingSub, wrapping_sub, u16);
wrapping_impl!(WrappingSub, wrapping_sub, u32);
wrapping_impl!(WrappingSub, wrapping_sub, u64);
wrapping_impl!(WrappingSub, wrapping_sub, usize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingSub, wrapping_sub, u128);
wrapping_impl!(WrappingSub, wrapping_sub, i8);
wrapping_impl!(WrappingSub, wrapping_sub, i16);
wrapping_impl!(WrappingSub, wrapping_sub, i32);
wrapping_impl!(WrappingSub, wrapping_sub, i64);
wrapping_impl!(WrappingSub, wrapping_sub, isize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingSub, wrapping_sub, i128);
/// Performs multiplication that wraps around on overflow.
-pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
+pub trait WrappingMul: Sized + Mul<Self, Output = Self> {
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
/// of the type.
fn wrapping_mul(&self, v: &Self) -> Self;
}
wrapping_impl!(WrappingMul, wrapping_mul, u8);
wrapping_impl!(WrappingMul, wrapping_mul, u16);
wrapping_impl!(WrappingMul, wrapping_mul, u32);
wrapping_impl!(WrappingMul, wrapping_mul, u64);
wrapping_impl!(WrappingMul, wrapping_mul, usize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingMul, wrapping_mul, u128);
wrapping_impl!(WrappingMul, wrapping_mul, i8);
wrapping_impl!(WrappingMul, wrapping_mul, i16);
wrapping_impl!(WrappingMul, wrapping_mul, i32);
wrapping_impl!(WrappingMul, wrapping_mul, i64);
wrapping_impl!(WrappingMul, wrapping_mul, isize);
+#[cfg(has_i128)]
+wrapping_impl!(WrappingMul, wrapping_mul, i128);
+
+macro_rules! wrapping_unary_impl {
+ ($trait_name:ident, $method:ident, $t:ty) => {
+ impl $trait_name for $t {
+ #[inline]
+ fn $method(&self) -> $t {
+ <$t>::$method(*self)
+ }
+ }
+ };
+}
+
+/// Performs a negation that does not panic.
+pub trait WrappingNeg: Sized {
+ /// Wrapping (modular) negation. Computes `-self`,
+ /// wrapping around at the boundary of the type.
+ ///
+ /// Since unsigned types do not have negative equivalents
+ /// all applications of this function will wrap (except for `-0`).
+ /// For values smaller than the corresponding signed type's maximum
+ /// the result is the same as casting the corresponding signed value.
+ /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where
+ /// `MAX` is the corresponding signed type's maximum.
+ ///
+ /// ```
+ /// use num_traits::WrappingNeg;
+ ///
+ /// assert_eq!(100i8.wrapping_neg(), -100);
+ /// assert_eq!((-100i8).wrapping_neg(), 100);
+ /// assert_eq!((-128i8).wrapping_neg(), -128); // wrapped!
+ /// ```
+ fn wrapping_neg(&self) -> Self;
+}
+
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, usize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u128);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, isize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128);
+
+macro_rules! wrapping_shift_impl {
+ ($trait_name:ident, $method:ident, $t:ty) => {
+ impl $trait_name for $t {
+ #[inline]
+ fn $method(&self, rhs: u32) -> $t {
+ <$t>::$method(*self, rhs)
+ }
+ }
+ };
+}
+
+/// Performs a left shift that does not panic.
+pub trait WrappingShl: Sized + Shl<usize, Output = Self> {
+ /// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
+ /// where `mask` removes any high order bits of `rhs` that would
+ /// cause the shift to exceed the bitwidth of the type.
+ ///
+ /// ```
+ /// use num_traits::WrappingShl;
+ ///
+ /// let x: u16 = 0x0001;
+ ///
+ /// assert_eq!(WrappingShl::wrapping_shl(&x, 0), 0x0001);
+ /// assert_eq!(WrappingShl::wrapping_shl(&x, 1), 0x0002);
+ /// assert_eq!(WrappingShl::wrapping_shl(&x, 15), 0x8000);
+ /// assert_eq!(WrappingShl::wrapping_shl(&x, 16), 0x0001);
+ /// ```
+ fn wrapping_shl(&self, rhs: u32) -> Self;
+}
+
+wrapping_shift_impl!(WrappingShl, wrapping_shl, u8);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, u16);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, u32);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, u64);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, usize);
+#[cfg(has_i128)]
+wrapping_shift_impl!(WrappingShl, wrapping_shl, u128);
+
+wrapping_shift_impl!(WrappingShl, wrapping_shl, i8);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, i16);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, i32);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, i64);
+wrapping_shift_impl!(WrappingShl, wrapping_shl, isize);
+#[cfg(has_i128)]
+wrapping_shift_impl!(WrappingShl, wrapping_shl, i128);
+
+/// Performs a right shift that does not panic.
+pub trait WrappingShr: Sized + Shr<usize, Output = Self> {
+ /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
+ /// where `mask` removes any high order bits of `rhs` that would
+ /// cause the shift to exceed the bitwidth of the type.
+ ///
+ /// ```
+ /// use num_traits::WrappingShr;
+ ///
+ /// let x: u16 = 0x8000;
+ ///
+ /// assert_eq!(WrappingShr::wrapping_shr(&x, 0), 0x8000);
+ /// assert_eq!(WrappingShr::wrapping_shr(&x, 1), 0x4000);
+ /// assert_eq!(WrappingShr::wrapping_shr(&x, 15), 0x0001);
+ /// assert_eq!(WrappingShr::wrapping_shr(&x, 16), 0x8000);
+ /// ```
+ fn wrapping_shr(&self, rhs: u32) -> Self;
+}
+
+wrapping_shift_impl!(WrappingShr, wrapping_shr, u8);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, u16);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, u32);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, u64);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, usize);
+#[cfg(has_i128)]
+wrapping_shift_impl!(WrappingShr, wrapping_shr, u128);
+
+wrapping_shift_impl!(WrappingShr, wrapping_shr, i8);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, i16);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, i32);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, i64);
+wrapping_shift_impl!(WrappingShr, wrapping_shr, isize);
+#[cfg(has_i128)]
+wrapping_shift_impl!(WrappingShr, wrapping_shr, i128);
// Well this is a bit funny, but all the more appropriate.
-impl<T: WrappingAdd> WrappingAdd for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {
+impl<T: WrappingAdd> WrappingAdd for Wrapping<T>
+where
+ Wrapping<T>: Add<Output = Wrapping<T>>,
+{
fn wrapping_add(&self, v: &Self) -> Self {
Wrapping(self.0.wrapping_add(&v.0))
}
}
-impl<T: WrappingSub> WrappingSub for Wrapping<T> where Wrapping<T>: Sub<Output = Wrapping<T>> {
+impl<T: WrappingSub> WrappingSub for Wrapping<T>
+where
+ Wrapping<T>: Sub<Output = Wrapping<T>>,
+{
fn wrapping_sub(&self, v: &Self) -> Self {
Wrapping(self.0.wrapping_sub(&v.0))
}
}
-impl<T: WrappingMul> WrappingMul for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {
+impl<T: WrappingMul> WrappingMul for Wrapping<T>
+where
+ Wrapping<T>: Mul<Output = Wrapping<T>>,
+{
fn wrapping_mul(&self, v: &Self) -> Self {
Wrapping(self.0.wrapping_mul(&v.0))
}
}
-
+impl<T: WrappingNeg> WrappingNeg for Wrapping<T>
+where
+ Wrapping<T>: Neg<Output = Wrapping<T>>,
+{
+ fn wrapping_neg(&self) -> Self {
+ Wrapping(self.0.wrapping_neg())
+ }
+}
+impl<T: WrappingShl> WrappingShl for Wrapping<T>
+where
+ Wrapping<T>: Shl<usize, Output = Wrapping<T>>,
+{
+ fn wrapping_shl(&self, rhs: u32) -> Self {
+ Wrapping(self.0.wrapping_shl(rhs))
+ }
+}
+impl<T: WrappingShr> WrappingShr for Wrapping<T>
+where
+ Wrapping<T>: Shr<usize, Output = Wrapping<T>>,
+{
+ fn wrapping_shr(&self, rhs: u32) -> Self {
+ Wrapping(self.0.wrapping_shr(rhs))
+ }
+}
#[test]
fn test_wrapping_traits() {
- fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
- fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
- fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
+ fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T {
+ a.wrapping_add(&b)
+ }
+ fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T {
+ a.wrapping_sub(&b)
+ }
+ fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
+ a.wrapping_mul(&b)
+ }
+ fn wrapping_neg<T: WrappingNeg>(a: T) -> T {
+ a.wrapping_neg()
+ }
+ fn wrapping_shl<T: WrappingShl>(a: T, b: u32) -> T {
+ a.wrapping_shl(b)
+ }
+ fn wrapping_shr<T: WrappingShr>(a: T, b: u32) -> T {
+ a.wrapping_shr(b)
+ }
assert_eq!(wrapping_add(255, 1), 0u8);
assert_eq!(wrapping_sub(0, 1), 255u8);
assert_eq!(wrapping_mul(255, 2), 254u8);
+ assert_eq!(wrapping_neg(255), 1u8);
+ assert_eq!(wrapping_shl(255, 8), 255u8);
+ assert_eq!(wrapping_shr(255, 8), 255u8);
assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
+ // TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was
+ // only added to core::num::Wrapping<_> in Rust 1.10.
+ assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0);
+ assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0);
}
#[test]
fn wrapping_is_wrappingadd() {
fn require_wrappingadd<T: WrappingAdd>(_: &T) {}
require_wrappingadd(&Wrapping(42));
}
@@ -120,8 +315,23 @@ fn wrapping_is_wrappingsub() {
require_wrappingsub(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingmul() {
fn require_wrappingmul<T: WrappingMul>(_: &T) {}
require_wrappingmul(&Wrapping(42));
}
+
+// TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was
+// only added to core::num::Wrapping<_> in Rust 1.10.
+
+#[test]
+fn wrapping_is_wrappingshl() {
+ fn require_wrappingshl<T: WrappingShl>(_: &T) {}
+ require_wrappingshl(&Wrapping(42));
+}
+
+#[test]
+fn wrapping_is_wrappingshr() {
+ fn require_wrappingshr<T: WrappingShr>(_: &T) {}
+ require_wrappingshr(&Wrapping(42));
+}
diff --git a/third_party/rust/num-traits/src/pow.rs b/third_party/rust/num-traits/src/pow.rs
--- a/third_party/rust/num-traits/src/pow.rs
+++ b/third_party/rust/num-traits/src/pow.rs
@@ -1,70 +1,259 @@
+use core::num::Wrapping;
use core::ops::Mul;
-use {One, CheckedMul};
+use {CheckedMul, One};
+
+/// Binary operator for raising a value to a power.
+pub trait Pow<RHS> {
+ /// The result after applying the operator.
+ type Output;
+
+ /// Returns `self` to the power `rhs`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use num_traits::Pow;
+ /// assert_eq!(Pow::pow(10u32, 2u32), 100);
+ /// ```
+ fn pow(self, rhs: RHS) -> Self::Output;
+}
+
+macro_rules! pow_impl {
+ ($t:ty) => {
+ pow_impl!($t, u8);
+ pow_impl!($t, usize);
+
+ // FIXME: these should be possible
+ // pow_impl!($t, u16);
+ // pow_impl!($t, u32);
+ // pow_impl!($t, u64);
+ };
+ ($t:ty, $rhs:ty) => {
+ pow_impl!($t, $rhs, usize, pow);
+ };
+ ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => {
+ impl Pow<$rhs> for $t {
+ type Output = $t;
+ #[inline]
+ fn pow(self, rhs: $rhs) -> $t {
+ ($method)(self, <$desired_rhs>::from(rhs))
+ }
+ }
+
+ impl<'a> Pow<&'a $rhs> for $t {
+ type Output = $t;
+ #[inline]
+ fn pow(self, rhs: &'a $rhs) -> $t {
+ ($method)(self, <$desired_rhs>::from(*rhs))
+ }
+ }
+
+ impl<'a> Pow<$rhs> for &'a $t {
+ type Output = $t;
+ #[inline]
+ fn pow(self, rhs: $rhs) -> $t {
+ ($method)(*self, <$desired_rhs>::from(rhs))
+ }
+ }
+
+ impl<'a, 'b> Pow<&'a $rhs> for &'b $t {
+ type Output = $t;
+ #[inline]
+ fn pow(self, rhs: &'a $rhs) -> $t {
+ ($method)(*self, <$desired_rhs>::from(*rhs))
+ }
+ }
+ };
+}
+
+pow_impl!(u8, u8, u32, u8::pow);
+pow_impl!(u8, u16, u32, u8::pow);
+pow_impl!(u8, u32, u32, u8::pow);
+pow_impl!(u8, usize);
+pow_impl!(i8, u8, u32, i8::pow);
+pow_impl!(i8, u16, u32, i8::pow);
+pow_impl!(i8, u32, u32, i8::pow);
+pow_impl!(i8, usize);
+pow_impl!(u16, u8, u32, u16::pow);
+pow_impl!(u16, u16, u32, u16::pow);
+pow_impl!(u16, u32, u32, u16::pow);
+pow_impl!(u16, usize);
+pow_impl!(i16, u8, u32, i16::pow);
+pow_impl!(i16, u16, u32, i16::pow);
+pow_impl!(i16, u32, u32, i16::pow);
+pow_impl!(i16, usize);
+pow_impl!(u32, u8, u32, u32::pow);
+pow_impl!(u32, u16, u32, u32::pow);
+pow_impl!(u32, u32, u32, u32::pow);
+pow_impl!(u32, usize);
+pow_impl!(i32, u8, u32, i32::pow);
+pow_impl!(i32, u16, u32, i32::pow);
+pow_impl!(i32, u32, u32, i32::pow);
+pow_impl!(i32, usize);
+pow_impl!(u64, u8, u32, u64::pow);
+pow_impl!(u64, u16, u32, u64::pow);
+pow_impl!(u64, u32, u32, u64::pow);
+pow_impl!(u64, usize);
+pow_impl!(i64, u8, u32, i64::pow);
+pow_impl!(i64, u16, u32, i64::pow);
+pow_impl!(i64, u32, u32, i64::pow);
+pow_impl!(i64, usize);
+
+#[cfg(has_i128)]
+pow_impl!(u128, u8, u32, u128::pow);
+#[cfg(has_i128)]
+pow_impl!(u128, u16, u32, u128::pow);
+#[cfg(has_i128)]
+pow_impl!(u128, u32, u32, u128::pow);
+#[cfg(has_i128)]
+pow_impl!(u128, usize);
+
+#[cfg(has_i128)]
+pow_impl!(i128, u8, u32, i128::pow);
+#[cfg(has_i128)]
+pow_impl!(i128, u16, u32, i128::pow);
+#[cfg(has_i128)]
+pow_impl!(i128, u32, u32, i128::pow);
+#[cfg(has_i128)]
+pow_impl!(i128, usize);
+
+pow_impl!(usize, u8, u32, usize::pow);
+pow_impl!(usize, u16, u32, usize::pow);
+pow_impl!(usize, u32, u32, usize::pow);
+pow_impl!(usize, usize);
+pow_impl!(isize, u8, u32, isize::pow);
+pow_impl!(isize, u16, u32, isize::pow);
+pow_impl!(isize, u32, u32, isize::pow);
+pow_impl!(isize, usize);
+pow_impl!(Wrapping<u8>);
+pow_impl!(Wrapping<i8>);
+pow_impl!(Wrapping<u16>);
+pow_impl!(Wrapping<i16>);
+pow_impl!(Wrapping<u32>);
+pow_impl!(Wrapping<i32>);
+pow_impl!(Wrapping<u64>);
+pow_impl!(Wrapping<i64>);
+#[cfg(has_i128)]
+pow_impl!(Wrapping<u128>);
+#[cfg(has_i128)]
+pow_impl!(Wrapping<i128>);
+pow_impl!(Wrapping<usize>);
+pow_impl!(Wrapping<isize>);
+
+// FIXME: these should be possible
+// pow_impl!(u8, u64);
+// pow_impl!(i16, u64);
+// pow_impl!(i8, u64);
+// pow_impl!(u16, u64);
+// pow_impl!(u32, u64);
+// pow_impl!(i32, u64);
+// pow_impl!(u64, u64);
+// pow_impl!(i64, u64);
+// pow_impl!(usize, u64);
+// pow_impl!(isize, u64);
+
+#[cfg(any(feature = "std", feature = "libm"))]
+mod float_impls {
+ use super::Pow;
+ use Float;
+
+ pow_impl!(f32, i8, i32, <f32 as Float>::powi);
+ pow_impl!(f32, u8, i32, <f32 as Float>::powi);
+ pow_impl!(f32, i16, i32, <f32 as Float>::powi);
+ pow_impl!(f32, u16, i32, <f32 as Float>::powi);
+ pow_impl!(f32, i32, i32, <f32 as Float>::powi);
+ pow_impl!(f64, i8, i32, <f64 as Float>::powi);
+ pow_impl!(f64, u8, i32, <f64 as Float>::powi);
+ pow_impl!(f64, i16, i32, <f64 as Float>::powi);
+ pow_impl!(f64, u16, i32, <f64 as Float>::powi);
+ pow_impl!(f64, i32, i32, <f64 as Float>::powi);
+ pow_impl!(f32, f32, f32, <f32 as Float>::powf);
+ pow_impl!(f64, f32, f64, <f64 as Float>::powf);
+ pow_impl!(f64, f64, f64, <f64 as Float>::powf);
+}
/// Raises a value to the power of exp, using exponentiation by squaring.
///
+/// Note that `0⁰` (`pow(0, 0)`) returns `1`. Mathematically this is undefined.
+///
/// # Example
///
/// ```rust
/// use num_traits::pow;
///
/// assert_eq!(pow(2i8, 4), 16);
/// assert_eq!(pow(6u8, 3), 216);
+/// assert_eq!(pow(0u8, 0), 1); // Be aware if this case affects you
/// ```
#[inline]
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
- if exp == 0 { return T::one() }
+ if exp == 0 {
+ return T::one();
+ }
while exp & 1 == 0 {
base = base.clone() * base;
exp >>= 1;
}
- if exp == 1 { return base }
+ if exp == 1 {
+ return base;
+ }
let mut acc = base.clone();
while exp > 1 {
exp >>= 1;
base = base.clone() * base;
if exp & 1 == 1 {
acc = acc * base.clone();
}
}
acc
}
/// Raises a value to the power of exp, returning `None` if an overflow occurred.
///
+/// Note that `0⁰` (`checked_pow(0, 0)`) returns `Some(1)`. Mathematically this is undefined.
+///
/// Otherwise same as the `pow` function.
///
/// # Example
///
/// ```rust
/// use num_traits::checked_pow;
///
/// assert_eq!(checked_pow(2i8, 4), Some(16));
/// assert_eq!(checked_pow(7i8, 8), None);
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
+/// assert_eq!(checked_pow(0u32, 0), Some(1)); // Be aware if this case affect you
/// ```
#[inline]
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
- if exp == 0 { return Some(T::one()) }
+ if exp == 0 {
+ return Some(T::one());
+ }
macro_rules! optry {
- ( $ expr : expr ) => {
- if let Some(val) = $expr { val } else { return None }
- }
+ ($expr:expr) => {
+ if let Some(val) = $expr {
+ val
+ } else {
+ return None;
+ }
+ };
}
while exp & 1 == 0 {
base = optry!(base.checked_mul(&base));
exp >>= 1;
}
- if exp == 1 { return Some(base) }
+ if exp == 1 {
+ return Some(base);
+ }
let mut acc = base.clone();
while exp > 1 {
exp >>= 1;
base = optry!(base.checked_mul(&base));
if exp & 1 == 1 {
acc = optry!(acc.checked_mul(&base));
}
diff --git a/third_party/rust/num-traits/src/real.rs b/third_party/rust/num-traits/src/real.rs
--- a/third_party/rust/num-traits/src/real.rs
+++ b/third_party/rust/num-traits/src/real.rs
@@ -1,29 +1,25 @@
-use std::ops::Neg;
+#![cfg(any(feature = "std", feature = "libm"))]
-use {Num, NumCast, Float};
+use core::ops::Neg;
+
+use {Float, Num, NumCast};
// NOTE: These doctests have the same issue as those in src/float.rs.
// They're testing the inherent methods directly, and not those of `Real`.
/// A trait for real number types that do not necessarily have
/// floating-point-specific characteristics such as NaN and infinity.
///
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
/// for a list of data types that could meaningfully implement this trait.
///
-/// This trait is only available with the `std` feature.
-pub trait Real
- : Num
- + Copy
- + NumCast
- + PartialOrd
- + Neg<Output = Self>
-{
+/// This trait is only available with the `std` feature, or with the `libm` feature otherwise.
+pub trait Real: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
/// Returns the smallest finite value that this type can represent.
///
/// ```
/// use num_traits::real::Real;
/// use std::f64;
///
/// let x: f64 = Real::min_value();
///
@@ -210,18 +206,20 @@ pub trait Real
///
/// assert!(!f.is_sign_negative());
/// assert!(g.is_sign_negative());
/// assert!(!nan.is_sign_negative());
/// ```
fn is_sign_negative(self) -> bool;
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
- /// error. This produces a more accurate result with better performance than
- /// a separate multiplication operation followed by an add.
+ /// error, yielding a more accurate result than an unfused multiply-add.
+ ///
+ /// Using `mul_add` can be more performant than an unfused multiply-add if
+ /// the target architecture has a dedicated `fma` CPU instruction.
///
/// ```
/// use num_traits::real::Real;
///
/// let m = 10.0;
/// let x = 4.0;
/// let b = 60.0;
///
@@ -777,150 +775,60 @@ pub trait Real
/// let abs_difference = (f - e).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
fn atanh(self) -> Self;
}
impl<T: Float> Real for T {
- fn min_value() -> Self {
- Self::min_value()
- }
- fn min_positive_value() -> Self {
- Self::min_positive_value()
- }
- fn epsilon() -> Self {
- Self::epsilon()
- }
- fn max_value() -> Self {
- Self::max_value()
- }
- fn floor(self) -> Self {
- self.floor()
- }
- fn ceil(self) -> Self {
- self.ceil()
- }
- fn round(self) -> Self {
- self.round()
- }
- fn trunc(self) -> Self {
- self.trunc()
- }
- fn fract(self) -> Self {
- self.fract()
- }
- fn abs(self) -> Self {
- self.abs()
- }
- fn signum(self) -> Self {
- self.signum()
- }
- fn is_sign_positive(self) -> bool {
- self.is_sign_positive()
- }
- fn is_sign_negative(self) -> bool {
- self.is_sign_negative()
- }
- fn mul_add(self, a: Self, b: Self) -> Self {
- self.mul_add(a, b)
- }
- fn recip(self) -> Self {
- self.recip()
- }
- fn powi(self, n: i32) -> Self {
- self.powi(n)
- }
- fn powf(self, n: Self) -> Self {
- self.powf(n)
- }
- fn sqrt(self) -> Self {
- self.sqrt()
- }
- fn exp(self) -> Self {
- self.exp()
- }
- fn exp2(self) -> Self {
- self.exp2()
- }
- fn ln(self) -> Self {
- self.ln()
- }
- fn log(self, base: Self) -> Self {
- self.log(base)
- }
- fn log2(self) -> Self {
- self.log2()
+ forward! {
+ Float::min_value() -> Self;
+ Float::min_positive_value() -> Self;
+ Float::epsilon() -> Self;
+ Float::max_value() -> Self;
}
- fn log10(self) -> Self {
- self.log10()
- }
- fn to_degrees(self) -> Self {
- self.to_degrees()
- }
- fn to_radians(self) -> Self {
- self.to_radians()
- }
- fn max(self, other: Self) -> Self {
- self.max(other)
- }
- fn min(self, other: Self) -> Self {
- self.min(other)
- }
- fn abs_sub(self, other: Self) -> Self {
- self.abs_sub(other)
- }
- fn cbrt(self) -> Self {
- self.cbrt()
- }
- fn hypot(self, other: Self) -> Self {
- self.hypot(other)
- }
- fn sin(self) -> Self {
- self.sin()
- }
- fn cos(self) -> Self {
- self.cos()
- }
- fn tan(self) -> Self {
- self.tan()
- }
- fn asin(self) -> Self {
- self.asin()
- }
- fn acos(self) -> Self {
- self.acos()
- }
- fn atan(self) -> Self {
- self.atan()
- }
- fn atan2(self, other: Self) -> Self {
- self.atan2(other)
- }
- fn sin_cos(self) -> (Self, Self) {
- self.sin_cos()
- }
- fn exp_m1(self) -> Self {
- self.exp_m1()
- }
- fn ln_1p(self) -> Self {
- self.ln_1p()
- }
- fn sinh(self) -> Self {
- self.sinh()
- }
- fn cosh(self) -> Self {
- self.cosh()
- }
- fn tanh(self) -> Self {
- self.tanh()
- }
- fn asinh(self) -> Self {
- self.asinh()
- }
- fn acosh(self) -> Self {
- self.acosh()
- }
- fn atanh(self) -> Self {
- self.atanh()
+ forward! {
+ Float::floor(self) -> Self;
+ Float::ceil(self) -> Self;
+ Float::round(self) -> Self;
+ Float::trunc(self) -> Self;
+ Float::fract(self) -> Self;
+ Float::abs(self) -> Self;
+ Float::signum(self) -> Self;
+ Float::is_sign_positive(self) -> bool;
+ Float::is_sign_negative(self) -> bool;
+ Float::mul_add(self, a: Self, b: Self) -> Self;
+ Float::recip(self) -> Self;
+ Float::powi(self, n: i32) -> Self;
+ Float::powf(self, n: Self) -> Self;
+ Float::sqrt(self) -> Self;
+ Float::exp(self) -> Self;
+ Float::exp2(self) -> Self;
+ Float::ln(self) -> Self;
+ Float::log(self, base: Self) -> Self;
+ Float::log2(self) -> Self;
+ Float::log10(self) -> Self;
+ Float::to_degrees(self) -> Self;
+ Float::to_radians(self) -> Self;
+ Float::max(self, other: Self) -> Self;
+ Float::min(self, other: Self) -> Self;
+ Float::abs_sub(self, other: Self) -> Self;
+ Float::cbrt(self) -> Self;
+ Float::hypot(self, other: Self) -> Self;
+ Float::sin(self) -> Self;
+ Float::cos(self) -> Self;
+ Float::tan(self) -> Self;
+ Float::asin(self) -> Self;
+ Float::acos(self) -> Self;
+ Float::atan(self) -> Self;
+ Float::atan2(self, other: Self) -> Self;
+ Float::sin_cos(self) -> (Self, Self);
+ Float::exp_m1(self) -> Self;
+ Float::ln_1p(self) -> Self;
+ Float::sinh(self) -> Self;
+ Float::cosh(self) -> Self;
+ Float::tanh(self) -> Self;
+ Float::asinh(self) -> Self;
+ Float::acosh(self) -> Self;
+ Float::atanh(self) -> Self;
}
}
diff --git a/third_party/rust/num-traits/src/sign.rs b/third_party/rust/num-traits/src/sign.rs
--- a/third_party/rust/num-traits/src/sign.rs
+++ b/third_party/rust/num-traits/src/sign.rs
@@ -1,12 +1,12 @@
+use core::num::Wrapping;
use core::ops::Neg;
-use core::{f32, f64};
-use core::num::Wrapping;
+use float::FloatCore;
use Num;
/// Useful functions for signed numbers (i.e. numbers that can be negative).
pub trait Signed: Sized + Num + Neg<Output = Self> {
/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
///
@@ -69,17 +69,22 @@ macro_rules! signed_impl {
#[inline]
fn is_negative(&self) -> bool { *self < 0 }
}
)*)
}
signed_impl!(isize i8 i16 i32 i64);
-impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
+#[cfg(has_i128)]
+signed_impl!(i128);
+
+impl<T: Signed> Signed for Wrapping<T>
+where
+ Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
{
#[inline]
fn abs(&self) -> Self {
Wrapping(self.0.abs())
}
#[inline]
fn abs_sub(&self, other: &Self) -> Self {
@@ -87,95 +92,74 @@ impl<T: Signed> Signed for Wrapping<T> w
}
#[inline]
fn signum(&self) -> Self {
Wrapping(self.0.signum())
}
#[inline]
- fn is_positive(&self) -> bool { self.0.is_positive() }
+ fn is_positive(&self) -> bool {
+ self.0.is_positive()
+ }
#[inline]
- fn is_negative(&self) -> bool { self.0.is_negative() }
+ fn is_negative(&self) -> bool {
+ self.0.is_negative()
+ }
}
macro_rules! signed_float_impl {
- ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
+ ($t:ty) => {
impl Signed for $t {
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
#[inline]
- #[cfg(feature = "std")]
fn abs(&self) -> $t {
- (*self).abs()
- }
-
- /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
- #[inline]
- #[cfg(not(feature = "std"))]
- fn abs(&self) -> $t {
- if self.is_positive() {
- *self
- } else if self.is_negative() {
- -*self
- } else {
- $nan
- }
+ FloatCore::abs(*self)
}
/// The positive difference of two numbers. Returns `0.0` if the number is
/// less than or equal to `other`, otherwise the difference between`self`
/// and `other` is returned.
#[inline]
fn abs_sub(&self, other: &$t) -> $t {
- if *self <= *other { 0. } else { *self - *other }
+ if *self <= *other {
+ 0.
+ } else {
+ *self - *other
+ }
}
/// # Returns
///
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// - `NAN` if the number is NaN
#[inline]
- #[cfg(feature = "std")]
fn signum(&self) -> $t {
- use Float;
- Float::signum(*self)
- }
-
- /// # Returns
- ///
- /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
- /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
- /// - `NAN` if the number is NaN
- #[inline]
- #[cfg(not(feature = "std"))]
- fn signum(&self) -> $t {
- if self.is_positive() {
- 1.0
- } else if self.is_negative() {
- -1.0
- } else {
- $nan
- }
+ FloatCore::signum(*self)
}
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
#[inline]
- fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }
+ fn is_positive(&self) -> bool {
+ FloatCore::is_sign_positive(*self)
+ }
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
#[inline]
- fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
+ fn is_negative(&self) -> bool {
+ FloatCore::is_sign_negative(*self)
+ }
}
- }
+ };
}
-signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
-signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);
+signed_float_impl!(f32);
+signed_float_impl!(f64);
/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
///
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
@@ -199,38 +183,42 @@ pub fn abs_sub<T: Signed>(x: T, y: T) ->
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// * `NaN` if the number is `NaN`
///
/// For signed integers:
///
/// * `0` if the number is zero
/// * `1` if the number is positive
/// * `-1` if the number is negative
-#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
+#[inline(always)]
+pub fn signum<T: Signed>(value: T) -> T {
+ value.signum()
+}
/// A trait for values which cannot be negative
pub trait Unsigned: Num {}
macro_rules! empty_trait_impl {
($name:ident for $($t:ty)*) => ($(
impl $name for $t {}
)*)
}
empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);
+#[cfg(has_i128)]
+empty_trait_impl!(Unsigned for u128);
impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}
#[test]
fn unsigned_wrapping_is_unsigned() {
fn require_unsigned<T: Unsigned>(_: &T) {}
require_unsigned(&Wrapping(42_u32));
}
-/*
+
// Commenting this out since it doesn't compile on Rust 1.8,
// because on this version Wrapping doesn't implement Neg and therefore can't
// implement Signed.
-#[test]
-fn signed_wrapping_is_signed() {
- fn require_signed<T: Signed>(_: &T) {}
- require_signed(&Wrapping(-42));
-}
-*/
+// #[test]
+// fn signed_wrapping_is_signed() {
+// fn require_signed<T: Signed>(_: &T) {}
+// require_signed(&Wrapping(-42));
+// }
diff --git a/third_party/rust/num-traits/tests/cast.rs b/third_party/rust/num-traits/tests/cast.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/num-traits/tests/cast.rs
@@ -0,0 +1,397 @@
+//! Tests of `num_traits::cast`.
+
+#![no_std]
+
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate std;
+
+extern crate num_traits;
+
+use num_traits::cast::*;
+use num_traits::Bounded;
+
+use core::{f32, f64};
+#[cfg(has_i128)]
+use core::{i128, u128};
+use core::{i16, i32, i64, i8, isize};
+use core::{u16, u32, u64, u8, usize};
+
+use core::fmt::Debug;
+use core::mem;
+use core::num::Wrapping;
+
+#[test]
+fn to_primitive_float() {
+ let f32_toolarge = 1e39f64;
+ assert_eq!(f32_toolarge.to_f32(), Some(f32::INFINITY));
+ assert_eq!((-f32_toolarge).to_f32(), Some(f32::NEG_INFINITY));
+ assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX));
+ assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX));
+ assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY));
+ assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY));
+ assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan()));
+}
+
+#[test]
+fn wrapping_to_primitive() {
+ macro_rules! test_wrapping_to_primitive {
+ ($($t:ty)+) => {
+ $({
+ let i: $t = 0;
+ let w = Wrapping(i);
+ assert_eq!(i.to_u8(), w.to_u8());
+ assert_eq!(i.to_u16(), w.to_u16());
+ assert_eq!(i.to_u32(), w.to_u32());
+ assert_eq!(i.to_u64(), w.to_u64());
+ assert_eq!(i.to_usize(), w.to_usize());
+ assert_eq!(i.to_i8(), w.to_i8());
+ assert_eq!(i.to_i16(), w.to_i16());
+ assert_eq!(i.to_i32(), w.to_i32());
+ assert_eq!(i.to_i64(), w.to_i64());
+ assert_eq!(i.to_isize(), w.to_isize());
+ assert_eq!(i.to_f32(), w.to_f32());
+ assert_eq!(i.to_f64(), w.to_f64());
+ })+
+ };
+ }
+
+ test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
+}
+
+#[test]
+fn wrapping_is_toprimitive() {
+ fn require_toprimitive<T: ToPrimitive>(_: &T) {}
+ require_toprimitive(&Wrapping(42));
+}
+
+#[test]
+fn wrapping_is_fromprimitive() {
+ fn require_fromprimitive<T: FromPrimitive>(_: &T) {}
+ require_fromprimitive(&Wrapping(42));
+}
+
+#[test]
+fn wrapping_is_numcast() {
+ fn require_numcast<T: NumCast>(_: &T) {}
+ require_numcast(&Wrapping(42));
+}
+
+#[test]
+fn as_primitive() {
+ let x: f32 = (1.625f64).as_();
+ assert_eq!(x, 1.625f32);
+
+ let x: f32 = (3.14159265358979323846f64).as_();
+ assert_eq!(x, 3.1415927f32);
+
+ let x: u8 = (768i16).as_();
+ assert_eq!(x, 0);
+}
+
+#[test]
+fn float_to_integer_checks_overflow() {
+ // This will overflow an i32
+ let source: f64 = 1.0e+123f64;
+
+ // Expect the overflow to be caught
+ assert_eq!(cast::<f64, i32>(source), None);
+}
+
+#[test]
+fn cast_to_int_checks_overflow() {
+ let big_f: f64 = 1.0e123;
+ let normal_f: f64 = 1.0;
+ let small_f: f64 = -1.0e123;
+ assert_eq!(None, cast::<f64, isize>(big_f));
+ assert_eq!(None, cast::<f64, i8>(big_f));
+ assert_eq!(None, cast::<f64, i16>(big_f));
+ assert_eq!(None, cast::<f64, i32>(big_f));
+ assert_eq!(None, cast::<f64, i64>(big_f));
+
+ assert_eq!(Some(normal_f as isize), cast::<f64, isize>(normal_f));
+ assert_eq!(Some(normal_f as i8), cast::<f64, i8>(normal_f));
+ assert_eq!(Some(normal_f as i16), cast::<f64, i16>(normal_f));
+ assert_eq!(Some(normal_f as i32), cast::<f64, i32>(normal_f));
+ assert_eq!(Some(normal_f as i64), cast::<f64, i64>(normal_f));
+
+ assert_eq!(None, cast::<f64, isize>(small_f));
+ assert_eq!(None, cast::<f64, i8>(small_f));
+ assert_eq!(None, cast::<f64, i16>(small_f));
+ assert_eq!(None, cast::<f64, i32>(small_f));
+ assert_eq!(None, cast::<f64, i64>(small_f));
+}
+
+#[test]
+fn cast_to_unsigned_int_checks_overflow() {
+ let big_f: f64 = 1.0e123;
+ let normal_f: f64 = 1.0;
+ let small_f: f64 = -1.0e123;
+ assert_eq!(None, cast::<f64, usize>(big_f));
+ assert_eq!(None, cast::<f64, u8>(big_f));
+ assert_eq!(None, cast::<f64, u16>(big_f));
+ assert_eq!(None, cast::<f64, u32>(big_f));
+ assert_eq!(None, cast::<f64, u64>(big_f));
+
+ assert_eq!(Some(normal_f as usize), cast::<f64, usize>(normal_f));
+ assert_eq!(Some(normal_f as u8), cast::<f64, u8>(normal_f));
+ assert_eq!(Some(normal_f as u16), cast::<f64, u16>(normal_f));
+ assert_eq!(Some(normal_f as u32), cast::<f64, u32>(normal_f));
+ assert_eq!(Some(normal_f as u64), cast::<f64, u64>(normal_f));
+
+ assert_eq!(None, cast::<f64, usize>(small_f));
+ assert_eq!(None, cast::<f64, u8>(small_f));
+ assert_eq!(None, cast::<f64, u16>(small_f));
+ assert_eq!(None, cast::<f64, u32>(small_f));
+ assert_eq!(None, cast::<f64, u64>(small_f));
+}
+
+#[test]
+#[cfg(has_i128)]
+fn cast_to_i128_checks_overflow() {
+ let big_f: f64 = 1.0e123;
+ let normal_f: f64 = 1.0;
+ let small_f: f64 = -1.0e123;
+ assert_eq!(None, cast::<f64, i128>(big_f));
+ assert_eq!(None, cast::<f64, u128>(big_f));
+
+ assert_eq!(Some(normal_f as i128), cast::<f64, i128>(normal_f));
+ assert_eq!(Some(normal_f as u128), cast::<f64, u128>(normal_f));
+
+ assert_eq!(None, cast::<f64, i128>(small_f));
+ assert_eq!(None, cast::<f64, u128>(small_f));
+}
+
+#[cfg(feature = "std")]
+fn dbg(args: ::core::fmt::Arguments) {
+ println!("{}", args);
+}
+
+#[cfg(not(feature = "std"))]
+fn dbg(_: ::core::fmt::Arguments) {}
+
+// Rust 1.8 doesn't handle cfg on macros correctly
+macro_rules! dbg { ($($tok:tt)*) => { dbg(format_args!($($tok)*)) } }
+
+macro_rules! float_test_edge {
+ ($f:ident -> $($t:ident)+) => { $({
+ dbg!("testing cast edge cases for {} -> {}", stringify!($f), stringify!($t));
+
+ let small = if $t::MIN == 0 || mem::size_of::<$t>() < mem::size_of::<$f>() {
+ $t::MIN as $f - 1.0
+ } else {
+ ($t::MIN as $f).raw_offset(1).floor()
+ };
+ let fmin = small.raw_offset(-1);
+ dbg!(" testing min {}\n\tvs. {:.0}\n\tand {:.0}", $t::MIN, fmin, small);
+ assert_eq!(Some($t::MIN), cast::<$f, $t>($t::MIN as $f));
+ assert_eq!(Some($t::MIN), cast::<$f, $t>(fmin));
+ assert_eq!(None, cast::<$f, $t>(small));
+
+ let (max, large) = if mem::size_of::<$t>() < mem::size_of::<$f>() {
+ ($t::MAX, $t::MAX as $f + 1.0)
+ } else {
+ let large = $t::MAX as $f; // rounds up!
+ let max = large.raw_offset(-1) as $t; // the next smallest possible
+ assert_eq!(max.count_ones(), $f::MANTISSA_DIGITS);
+ (max, large)
+ };
+ let fmax = large.raw_offset(-1);
+ dbg!(" testing max {}\n\tvs. {:.0}\n\tand {:.0}", max, fmax, large);
+ assert_eq!(Some(max), cast::<$f, $t>(max as $f));
+ assert_eq!(Some(max), cast::<$f, $t>(fmax));
+ assert_eq!(None, cast::<$f, $t>(large));
+
+ dbg!(" testing non-finite values");
+ assert_eq!(None, cast::<$f, $t>($f::NAN));
+ assert_eq!(None, cast::<$f, $t>($f::INFINITY));
+ assert_eq!(None, cast::<$f, $t>($f::NEG_INFINITY));
+ })+}
+}
+
+trait RawOffset: Sized {
+ type Raw;
+ fn raw_offset(self, offset: Self::Raw) -> Self;
+}
+
+impl RawOffset for f32 {
+ type Raw = i32;
+ fn raw_offset(self, offset: Self::Raw) -> Self {
+ unsafe {
+ let raw: Self::Raw = mem::transmute(self);
+ mem::transmute(raw + offset)
+ }
+ }
+}
+
+impl RawOffset for f64 {
+ type Raw = i64;
+ fn raw_offset(self, offset: Self::Raw) -> Self {
+ unsafe {
+ let raw: Self::Raw = mem::transmute(self);
+ mem::transmute(raw + offset)
+ }
+ }
+}
+
+#[test]
+fn cast_float_to_int_edge_cases() {
+ float_test_edge!(f32 -> isize i8 i16 i32 i64);
+ float_test_edge!(f32 -> usize u8 u16 u32 u64);
+ float_test_edge!(f64 -> isize i8 i16 i32 i64);
+ float_test_edge!(f64 -> usize u8 u16 u32 u64);
+}
+
+#[test]
+#[cfg(has_i128)]
+fn cast_float_to_i128_edge_cases() {
+ float_test_edge!(f32 -> i128 u128);
+ float_test_edge!(f64 -> i128 u128);
+}
+
+macro_rules! int_test_edge {
+ ($f:ident -> { $($t:ident)+ } with $BigS:ident $BigU:ident ) => { $({
+ fn test_edge() {
+ dbg!("testing cast edge cases for {} -> {}", stringify!($f), stringify!($t));
+
+ match ($f::MIN as $BigS).cmp(&($t::MIN as $BigS)) {
+ Greater => {
+ assert_eq!(Some($f::MIN as $t), cast::<$f, $t>($f::MIN));
+ }
+ Equal => {
+ assert_eq!(Some($t::MIN), cast::<$f, $t>($f::MIN));
+ }
+ Less => {
+ let min = $t::MIN as $f;
+ assert_eq!(Some($t::MIN), cast::<$f, $t>(min));
+ assert_eq!(None, cast::<$f, $t>(min - 1));
+ }
+ }
+
+ match ($f::MAX as $BigU).cmp(&($t::MAX as $BigU)) {
+ Greater => {
+ let max = $t::MAX as $f;
+ assert_eq!(Some($t::MAX), cast::<$f, $t>(max));
+ assert_eq!(None, cast::<$f, $t>(max + 1));
+ }
+ Equal => {
+ assert_eq!(Some($t::MAX), cast::<$f, $t>($f::MAX));
+ }
+ Less => {
+ assert_eq!(Some($f::MAX as $t), cast::<$f, $t>($f::MAX));
+ }
+ }
+ }
+ test_edge();
+ })+}
+}
+
+#[test]
+fn cast_int_to_int_edge_cases() {
+ use core::cmp::Ordering::*;
+
+ macro_rules! test_edge {
+ ($( $from:ident )+) => { $({
+ int_test_edge!($from -> { isize i8 i16 i32 i64 } with i64 u64);
+ int_test_edge!($from -> { usize u8 u16 u32 u64 } with i64 u64);
+ })+}
+ }
+
+ test_edge!(isize i8 i16 i32 i64);
+ test_edge!(usize u8 u16 u32 u64);
+}
+
+#[test]
+#[cfg(has_i128)]
+fn cast_int_to_128_edge_cases() {
+ use core::cmp::Ordering::*;
+
+ macro_rules! test_edge {
+ ($( $t:ident )+) => {
+ $(
+ int_test_edge!($t -> { i128 u128 } with i128 u128);
+ )+
+ int_test_edge!(i128 -> { $( $t )+ } with i128 u128);
+ int_test_edge!(u128 -> { $( $t )+ } with i128 u128);
+ }
+ }
+
+ test_edge!(isize i8 i16 i32 i64 i128);
+ test_edge!(usize u8 u16 u32 u64 u128);
+}
+
+#[test]
+fn newtype_from_primitive() {
+ #[derive(PartialEq, Debug)]
+ struct New<T>(T);
+
+ // minimal impl
+ impl<T: FromPrimitive> FromPrimitive for New<T> {
+ fn from_i64(n: i64) -> Option<Self> {
+ T::from_i64(n).map(New)
+ }
+
+ fn from_u64(n: u64) -> Option<Self> {
+ T::from_u64(n).map(New)
+ }
+ }
+
+ macro_rules! assert_eq_from {
+ ($( $from:ident )+) => {$(
+ assert_eq!(T::$from(Bounded::min_value()).map(New),
+ New::<T>::$from(Bounded::min_value()));
+ assert_eq!(T::$from(Bounded::max_value()).map(New),
+ New::<T>::$from(Bounded::max_value()));
+ )+}
+ }
+
+ fn check<T: PartialEq + Debug + FromPrimitive>() {
+ assert_eq_from!(from_i8 from_i16 from_i32 from_i64 from_isize);
+ assert_eq_from!(from_u8 from_u16 from_u32 from_u64 from_usize);
+ assert_eq_from!(from_f32 from_f64);
+ }
+
+ macro_rules! check {
+ ($( $ty:ty )+) => {$( check::<$ty>(); )+}
+ }
+ check!(i8 i16 i32 i64 isize);
+ check!(u8 u16 u32 u64 usize);
+}
+
+#[test]
+fn newtype_to_primitive() {
+ #[derive(PartialEq, Debug)]
+ struct New<T>(T);
+
+ // minimal impl
+ impl<T: ToPrimitive> ToPrimitive for New<T> {
+ fn to_i64(&self) -> Option<i64> {
+ self.0.to_i64()
+ }
+
+ fn to_u64(&self) -> Option<u64> {
+ self.0.to_u64()
+ }
+ }
+
+ macro_rules! assert_eq_to {
+ ($( $to:ident )+) => {$(
+ assert_eq!(T::$to(&Bounded::min_value()),
+ New::<T>::$to(&New(Bounded::min_value())));
+ assert_eq!(T::$to(&Bounded::max_value()),
+ New::<T>::$to(&New(Bounded::max_value())));
+ )+}
+ }
+
+ fn check<T: PartialEq + Debug + Bounded + ToPrimitive>() {
+ assert_eq_to!(to_i8 to_i16 to_i32 to_i64 to_isize);
+ assert_eq_to!(to_u8 to_u16 to_u32 to_u64 to_usize);
+ assert_eq_to!(to_f32 to_f64);
+ }
+
+ macro_rules! check {
+ ($( $ty:ty )+) => {$( check::<$ty>(); )+}
+ }
+ check!(i8 i16 i32 i64 isize);
+ check!(u8 u16 u32 u64 usize);
+}
diff --git a/third_party/rust/packed_simd/.cargo-checksum.json b/third_party/rust/packed_simd/.cargo-checksum.json
--- a/third_party/rust/packed_simd/.cargo-checksum.json
+++ b/third_party/rust/packed_simd/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"ae219b55eab1f8cd8c3497d7327ea0e5426dba23d2446f7981ca799ad80b6a52","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c4ac7027a9ab7d7858aa8957d7454dbfcdbb81e605b6a171f05310cc3cad3762","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"019ed29c43989782d8eec3a961654cfc172d7a7898da4eca8f654700af7e1988","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"bdcf93ba9043ac1184e2c504a3d40c47c6c1601d882e0f0a27a8eb56fbabcb5f","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"ae8274309928620a5dd232a46264e05399bb746288ebee3843a71c4162208cc3","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"ba5fbc4bf3bb91cd50b407248da31225681efc8f2be7618f4a0ab1219b389508","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"53f97f8b9b5aca7534b9bf9ea48f35175052cd2a560a107e01ad270731c032fc","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"89f5421cf06d817ae94092987e914472ef384ad2d1fff2735be3d8786ba11214","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"83eba19576486f9d10d7c037d669d72b31a65565a479f30b22aab36aaa2ff8dc","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"b982b421c70db476900df5b60e19ef8815e6c7dae22687225002780cab7b0a76","ci/docker/x86_64-linux-android/Dockerfile":"a17ebdb186ce2dd6b62100b5a439e05a1ab9adab113e2508843e121aaea52992","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/lld-shim.rs":"3d7f71ec23a49e2b67f694a0168786f9a954dda15f5a138815d966643fd3fcc3","ci/max_line_width.sh":"0a1518bba4c9ecaa55694cb2e9930d0e19c265baabf73143f17f9cf285aaa5bb","ci/run-docker.sh":"92e036390ad9b0d16f109579df1b5ced2e72e9afea40c7d011400ebd3a2a90de","ci/run.sh":"9afabc961e0ee83b87201f3fd554c19e5b0c36f3a95d013595e276c9882dd0a4","ci/run_examples.sh":"d1a23c6c35374a0678ba5114b9b8fefd8be0a79e774872a8bf0898d1baca18d0","ci/runtest-android.rs":"145a8e9799a5223975061fe7e586ade5669ee4877a7d7a4cf6b4ab48e8e36c7c","ci/setup_benchmarks.sh":"fae3960023f6f3d1388cd2ad22fdbab4b075f1f29dd4292d7994a20783beb6cf","ci/test-runner-linux":"c8aa6025cff5306f4f31d0c61dc5f9d4dd5a1d189ab613ef8d4c367c694d9ccd","contributing.md":"2d2629310ad4d464c482bdbb5819f0d6ce223c576aeef2cdce6a1f6857085ea5","perf-guide/book.toml":"115a98284126c6b180178b44713314cc494f08a71662ee2ce15cf67f17a51064","perf-guide/src/SUMMARY.md":"3e03bffc991fdc2050f3d51842d72d9d21ea6abab56a3baf3b2d5973a78b89e1","perf-guide/src/ascii.css":"29afb08833b2fe2250f0412e1fa1161a2432a0820a14953c87124407417c741a","perf-guide/src/bound_checks.md":"5e4991ff58a183ef0cd9fdc1feb4cd12d083b44bdf87393bbb0927808ef3ce7d","perf-guide/src/float-math/approx.md":"8c09032fa2d795a0c5db1775826c850d28eb2627846d0965c60ee72de63735ad","perf-guide/src/float-math/fma.md":"311076ba4b741d604a82e74b83a8d7e8c318fcbd7f64c4392d1cf5af95c60243","perf-guide/src/float-math/fp.md":"04153e775ab6e4f0d7837bcc515230d327b04edfa34c84ce9c9e10ebaeef2be8","perf-guide/src/float-math/svml.md":"0798873b8eedaeda5fed62dc91645b57c20775a02d3cd74d8bd06958f1516506","perf-guide/src/introduction.md":"9f5a19e9e6751f25d2daad39891a0cc600974527ec4c8305843f9618910671bd","perf-guide/src/prof/linux.md":"447731eb5de7d69166728fdbc5ecb0c0c9db678ea493b45a592d67dd002184c0","perf-guide/src/prof/mca.md":"f56d54f3d20e7aa4d32052186e8237b03d65971eb5d112802b442570ff11d344","perf-guide/src/prof/profiling.md":"8a650c0fd6ede0964789bb6577557eeef1d8226a896788602ce61528e260e43c","perf-guide/src/target-feature/attribute.md":"615f88dca0a707b6c416fa605435dd6e1fb5361cc639429cbf68cd87624bd78b","perf-guide/src/target-feature/features.md":"17077760ff24c006b606dd21889c53d87228f4311f3ba3a574f9afdeacd86165","perf-guide/src/target-feature/inlining.md":"7ed1d7068d8173a00d84c16cfe5871cd68b9f04f8d0cca2d01ebc84957ebf2f6","perf-guide/src/target-feature/practice.md":"c4b371842e0086df178488fec97f20def8f0c62ee588bcd25fd948b9b1fa227e","perf-guide/src/target-feature/runtime.md":"835425f5ee597fb3e51d36e725a81ebee29f4561231d19563cd4da81dbb1cfcb","perf-guide/src/target-feature/rustflags.md":"01197acf6f0adec8db32b8591811f69cecb6555a2b05dc5d5ec27d0e3f7b065e","perf-guide/src/vert-hor-ops.md":"c6211c0ee91e60552ec592d89d9d957eedc21dee3cbd89e1ad6765ea06a27471","rust-toolchain":"58bea07cb6d97f9cfcd5c8f98b1feca0fb81cce5b0bf29a8e70ed2641956e9a6","rustfmt.toml":"d99a43f3f8ef9e425cf01c333fba9f0051f888f5d87ab4e8f63c2f7d0fe6620f","src/api.rs":"45508c6c0241519fc01a7f00c9105554c24c312c4e46900ef9c75139ea438305","src/api/bit_manip.rs":"27f3097fc0a11e3c4107049d9779e680dcd67407a066704008a6b9c4fd529e05","src/api/bitmask.rs":"058ebc38a2e0363f07a441d3e9a4775aaec57ccb170a0e5d5efa5dc4743ab07b","src/api/cast.rs":"03b94a3d316ac7b7be7068810044911e965e889a0ace7bae762749ca74a92747","src/api/cast/macros.rs":"b0a14d0c83ad2ebb7a275180f6d9e3f2bc312ba57a7d3d6c39fad4e0f20f9408","src/api/cast/v128.rs":"edd0994efac4379dff26e178423a52dbb3ffeb38b1fc97cae975d744c00b4fb6","src/api/cast/v16.rs":"96bd98c2d21b0663abe6c0ab33005b1fa693f3db7ee6795351391343863484da","src/api/cast/v256.rs":"8c31fe91f5e78ef737dfba6979cc1240210cb094a89d284fe459bf8a991ca24b","src/api/cast/v32.rs":"a99a79dd84d2a5e6adf9db98705675915bd03fd1287d489c7fe38e84d7e4a086","src/api/cast/v512.rs":"c0dd526f41ed7b8a71c3743d91267554ec0a0c75834ccc2e3ecb0ef3004af642","src/api/cast/v64.rs":"6572fdba2a1241a6cd666d3f0cce3306cd2cb7e5e236172e59d5d4351c8a88af","src/api/cmp.rs":"357c3a2a09c6d4611c32dd7fa95be2fae933d513e229026ec9b44451a77b884e","src/api/cmp/eq.rs":"60f70f355bae4cb5b17db53204cacc3890f70670611c17df638d4c04f7cc8075","src/api/cmp/ord.rs":"589f7234761c294fa5df8f525bc4acd5a47cdb602207d524a0d4e19804cd9695","src/api/cmp/partial_eq.rs":"902ccb8aa01fd5738b30ba0b712669c21d4801958907e03bad23432c7dba0198","src/api/cmp/partial_ord.rs":"9db0c37d7434cdfc62d8d66912e972fa3d8c115ab2af051a6f45e414bd3e4f1c","src/api/cmp/vertical.rs":"de3d62f38eba817299aa16f1e1939954c9a447e316509397465c2830852ba053","src/api/default.rs":"67bf21c134127d12a7028c8b88a57f0ceee8ccbd74976da8ca74eb9f16a174d5","src/api/fmt.rs":"67fb804bb86b6cd77cf8cd492b5733ce437071b66fe3297278b8a6552c325dda","src/api/fmt/binary.rs":"02b2b287f7404f8a983813cf70c87108c8da3835578b63ab303116885f609413","src/api/fmt/debug.rs":"56e1c3bdc092747344fffaafff9da7163ee7827857f6fb7cb1c9923eca4f6fa0","src/api/fmt/lower_hex.rs":"558fd592f7f485712fb051509cecc7174a21e6bf62e5ce64766e75afc97bb8e1","src/api/fmt/octal.rs":"3b2e70877a4f368c7704f8e254236c014c365c74d93371c1feb5f030e6c66422","src/api/fmt/upper_hex.rs":"2a442f666bc80e22d41f903f881238fe114dd49344c3ed69849250e853cafc5d","src/api/from.rs":"2e599d8329cb05eaf06224cc441355c4b7b51254fc19256619333be8c149d444","src/api/from/from_array.rs":"5d2cc700568376bf6ee1fe5e406da3bc2d488ff155644bf73d06a1349b73fc53","src/api/from/from_vector.rs":"9764371aa9e6005aace74dea14f59e5611a095b7cf42707940924749282c52f0","src/api/hash.rs":"5076ece87969592c876486f5b1ea8affbeaec379d1a14a30859e0aa5592019de","src/api/into_bits.rs":"8f8011627250e23e66b5c0ca641afb079d8232674bb1354140b536bdbea63e55","src/api/into_bits/arch_specific.rs":"e7445021f3908326bfee758835e5fc5ad56aa1baa77fc1c58abe4350c66c670a","src/api/into_bits/macros.rs":"bb4fe99be2af6a21d805efab44c8e4e61a7b2adb42a65504a0cf26d13efdadcd","src/api/into_bits/v128.rs":"145a44922b09a5ca5b62d88a461d327d399a997a15db4b11d7b17e554a9fa4c0","src/api/into_bits/v16.rs":"f4f4f61ba88aa51b158ec56ca3dce234349aea0daf2b3029a14ab5125d1e41e5","src/api/into_bits/v256.rs":"8cea9c5d9809f11323cb7cdc53b83df593fd17caf926251e412ae9777bed547f","src/api/into_bits/v32.rs":"905ba683d342fa32f4202b80bb46530807bd0a5b588f6c2e8c9f475223c47775","src/api/into_bits/v512.rs":"e25afa1fbf088a5d58e7d75d197b6cd4c56637ea28542ba18e46a451f29d04e7","src/api/into_bits/v64.rs":"d6238022ccff7b92e55b3f6017fc269acb6f36330a6d7e8fb389853a0f1b6478","src/api/math.rs":"8b2a2fc651917a850539f993aa0b9e5bf4da67b11685285b8de8cdca311719ec","src/api/math/float.rs":"969a75cdb3743c5ac7cde653d1a7f659ac65f2a5afb004c9928a7b34b79c3e39","src/api/math/float/abs.rs":"5b6b2701e2e11135b7ce58a05052ea8120e10e4702c95d046b9d21b827b26bf8","src/api/math/float/consts.rs":"6302c9261da4291d144d5bb53493cdd073498feb40955fb6860ea3c4d06c978a","src/api/math/float/cos.rs":"4c2dd7173728ef189314f1576c9486e03be21b7da98843b2f9011282a7979e31","src/api/math/float/exp.rs":"7c6d5f1e304f498a01cfa23b92380c815d7da0ad94eae3483783bc377d287eef","src/api/math/float/ln.rs":"54c7583f3df793b39ff57534fade27b41bb992439e5dc178252f5ca3190a3e54","src/api/math/float/mul_add.rs":"62cac77660d20159276d4c9ef066eb90c81cbddb808e8e157182c607625ad2eb","src/api/math/float/mul_adde.rs":"bae056ee9f3a70df39ec3c3b2f6437c65303888a7b843ef1a5bcf1f5aca0e602","src/api/math/float/powf.rs":"9ddb938984b36d39d82a82f862f80df8f7fb013f1d222d45698d41d88472f568","src/api/math/float/recpre.rs":"589225794ff1dbf31158dff660e6d4509ecc8befbb57c633900dea5ac0b840d6","src/api/math/float/rsqrte.rs":"a32abdcc318d7ccc8448231f54d75b884b7cbeb03a7d595713ab6243036f4dbf","src/api/math/float/sin.rs":"cbd3622b7df74f19691743001c8cf747a201f8977ad90542fee915f37dcd1e49","src/api/math/float/sqrt.rs":"0c66d5d63fb08e4d99c6b82a8828e41173aff1ac9fa1a2764a11fac217ccf2ac","src/api/math/float/sqrte.rs":"731e1c9f321b662accdd27dacb3aac2e8043b7aecb2f2161dde733bd9f025362","src/api/math/float/tanh.rs":"e57940434cc05981b086f0f3b92d32caceb38d67b90aebce5d3ed8e07c80538f","src/api/minimal.rs":"1f22bcc528555444e76de569ec0ae2029b9ae9d04805efeafa93369c8098036b","src/api/minimal/iuf.rs":"819cff26d3e196f807645bcc1d79eb27d9f175edb89910f2274d52a1e913cd11","src/api/minimal/mask.rs":"0cae10ae1fc65f5070e686c0c79bfba27b86b33d6c399367bd4848fb367dcec4","src/api/minimal/ptr.rs":"f74d7a4925d7209faebc26ea8315259cb2c08ec65789a70869e595649a9bc39a","src/api/ops.rs":"3e273b277a0f3019d42c3c59ca94a5afd4885d5ae6d2182e5089bbeec9de42ee","src/api/ops/scalar_arithmetic.rs":"d2d5ad897a59dd0787544f927e0e7ca4072c3e58b0f4a2324083312b0d5a21d7","src/api/ops/scalar_bitwise.rs":"482204e459ca6be79568e1c9f70adbe2d2151412ddf122fb2161be8ebb51c40c","src/api/ops/scalar_mask_bitwise.rs":"c250f52042e37b22d57256c80d4604104cfd2fbe2a2e127c676267270ca5d350","src/api/ops/scalar_shifts.rs":"c4773d435c3f9da4454327e6fbb2b5b41a1c0ebb1cca7372e69dc7a344a1b6e4","src/api/ops/vector_arithmetic.rs":"ddca15d09ddeef502c2ed66117a62300ca65d87e959e8b622d767bdf1c307910","src/api/ops/vector_bitwise.rs":"b3968f7005b649edcc22a54e2379b14d5ee19045f2e784029805781ae043b5ee","src/api/ops/vector_float_min_max.rs":"76bf8cb607e2c442923c1da1061a6b80d742d607408033c2a3761161114cf2a0","src/api/ops/vector_int_min_max.rs":"a378789c6ff9b32a51fbd0a97ffd36ed102cd1fe6a067d2b02017c1df342def6","src/api/ops/vector_mask_bitwise.rs":"5052d18517d765415d40327e6e8e55a312daaca0a5e2aec959bfa54b1675f9c8","src/api/ops/vector_neg.rs":"5c62f6b0221983cdbd23cd0a3af3672e6ba1255f0dfe8b19aae6fbd6503e231b","src/api/ops/vector_rotates.rs":"6c3f761d9d551f6365a8a95539ceace4b1a02e0b12d144f34ed68db94e88cff4","src/api/ops/vector_shifts.rs":"e510be14127c0ffd58a2573a39701da3557d66bedec09837ac8bbd44d579da00","src/api/ptr.rs":"8a793251bed6130dcfb2f1519ceaa18b751bbb15875928d0fb6deb5a5e07523a","src/api/ptr/gather_scatter.rs":"3d614f9d5b4ca201a9f7e46af4405e1d2c28ecee1620297c23b52e37b92cc0ea","src/api/reductions.rs":"ae5baca81352ecd44526d6c30c0a1feeda475ec73ddd3c3ec6b14e944e5448ee","src/api/reductions/bitwise.rs":"8bf910ae226188bd15fc7e125f058cd2566b6186fcd0cd8fd020f352c39ce139","src/api/reductions/float_arithmetic.rs":"47a5679896db2cbb56c31372fe42143da015b6beae7db5d2f3a0309ddf427ae1","src/api/reductions/integer_arithmetic.rs":"c2df3cf7493cca4174f2c65aea422a3d20d8a23af03f8d57cef72c19fee8f20d","src/api/reductions/mask.rs":"db83327a950e33a317f37fd33ca4e20c347fb415975ec024f3e23da8509425af","src/api/reductions/min_max.rs":"6af8c9aa45c69961b1b6fc205395f4767d4421869fb105fb3d563c5605fc13cd","src/api/select.rs":"6b07e7e8026df561f7307221a896f0fbb272536f41b9109040ac094c24c69331","src/api/shuffle.rs":"be7faff9b59654926df12897b2f98a4baa7d6acf2af1aaf93d388ba6e96f83ec","src/api/shuffle1_dyn.rs":"bfea5a91905b31444e9ef7ca6eddb7a9606b7e22d3f71bb842eb2795a0346620","src/api/slice.rs":"ee87484e8af329547b9a5d4f2a69e8bed6ea10bbd96270d706083843d4eea2ac","src/api/slice/from_slice.rs":"3735363000737104a8fc5f394ad8c31ec14e885952bd57647dd2a84001aee0a6","src/api/slice/write_to_slice.rs":"79d09c64d00724783c77c42e4583eeec97b18db94cf2ae146b564c3f85cfefd6","src/api/swap_bytes.rs":"05b4262eaade2f63e6cd3b780c19a03aecd2459d4cc4360051fc088887179a6e","src/codegen.rs":"db4f232fb9f5728db310b87dc8c4733be48afacab1053798c06106bef9a42b05","src/codegen/bit_manip.rs":"525ea6ff7ad1e043b6f6136992166f1803ed5563b7f6fc292c1c40257d20e264","src/codegen/llvm.rs":"12e748b4928c3be6cc12b4165c3041a3d0efccf6195338ecd3d88b8fdb0bbcc7","src/codegen/math.rs":"dfcf02ad34e2fdfe22c3f1cc2822001cc895e65031b4d06e585e5047839febb7","src/codegen/math/float.rs":"b2f31f479c5c70a6ff9ad33872c1e65506f72882b77a2e3f9e71c42e92af9355","src/codegen/math/float/abs.rs":"d5aaadcf540bdb9b4264dca6471a255fd7bf509e763bef0239c0144a68466fea","src/codegen/math/float/cos.rs":"17f28d2900c852dca221fa9c92a9cd5fe7fd2df8d427bbc60216c749b2be013d","src/codegen/math/float/cos_pi.rs":"dbaf9f443f9846a491d4ec52210a7b5835dd593b03366e3135b05c37d70f9d6c","src/codegen/math/float/exp.rs":"d300058a4bcc7ae7976f216f81902cd73a9e603ad63880dff3bbc866c27a9f37","src/codegen/math/float/ln.rs":"c851e211e43f8256093ba75b03ae0c307c9962ee66d94f09b4dd80068190cbdf","src/codegen/math/float/macros.rs":"fc9924869ed85e4795983af228cacf23158f4f35919adce16c920ad4a3f0a009","src/codegen/math/float/mul_add.rs":"041a5b69d5991d93ef795351b17560c10faf80b78fd26ad7df42a239b32cf9de","src/codegen/math/float/mul_adde.rs":"d71d5f0f3333b62a7439b823cb7adf5340ea1555ce820fb4a3f4cb922f73f5f5","src/codegen/math/float/powf.rs":"9742c3877f1a5509ca5c9492a40884b6579ba6dd11c26b7112e63f70666b395d","src/codegen/math/float/sin.rs":"0e9868d35531566509f3a01d85d5253045eb4afa8525d8407dcc1f5f33c56036","src/codegen/math/float/sin_cos_pi.rs":"8e6b6142d7dd240cdb36669722e82ab9810a2261e86e659f7d97a942ad8b1258","src/codegen/math/float/sin_pi.rs":"bb6d39db8f921e03a301fc5206ac1a61a97def8a2cb83b87ccf189f3fc48d548","src/codegen/math/float/sqrt.rs":"e6ebb0c5f428efad1f672b9a8fe4e58534dbf1ea5a8fe092ce5ce76b52fe89cb","src/codegen/math/float/sqrte.rs":"23acfaea38d0e081a6d9021c1094e813d0cfd12c58c1eca9662aade5e625d51c","src/codegen/math/float/tanh.rs":"816fd107f134920fb1a21cd792029d4b89306f6cf16d6f030cc1136823b033e7","src/codegen/pointer_sized_int.rs":"6ca13c214b6cf7e0929dbe18e96a16fc0bb7d8799608df29c4c8115490f99e01","src/codegen/reductions.rs":"8eb18ebac76985d2aa30262a2edd8cb004230b511a765d657525f677a585c12c","src/codegen/reductions/mask.rs":"e67f35a1f4d156a4894a2d6ea5a935b4d898cf70eefb2715f5c1cc165e776c11","src/codegen/reductions/mask/aarch64.rs":"84b101c17cad1ede4eb6d38cada0ac7da239dba8cea3badd3829b967e558431f","src/codegen/reductions/mask/arm.rs":"aaa07129bd078ae7e677cf8b8e67ec9f30536606a0c7ed1baaa18fd1793bb218","src/codegen/reductions/mask/fallback.rs":"3eb9319d2c7cf19216b607b8459612c4e027b643cf11b036937d36896bf76786","src/codegen/reductions/mask/fallback_impl.rs":"76547f396e55ef403327c77c314cf8db8c7a5c9b9819bfb925abeacf130249e5","src/codegen/reductions/mask/x86.rs":"36dcd8af4ab99730a078ed113d3955f74eb1a2876e2e6d9f224e0ff462c216d1","src/codegen/reductions/mask/x86/avx.rs":"3a40868b38c86e35aefb96d7578de6322efe89d8135e0366359b54ddd06f861a","src/codegen/reductions/mask/x86/avx2.rs":"677aed3f056285285daa3adff8bc65e739630b4424defa6d9665e160f027507e","src/codegen/reductions/mask/x86/sse.rs":"8522f6ed03f6c32dd577d4298df477c08aeaaa38563706f29096e1911ed731f2","src/codegen/reductions/mask/x86/sse2.rs":"54ec56e49b0c6841eccb719e4f310d65fe767c04136b2ec20bd8b9d7d9897b9e","src/codegen/shuffle.rs":"1ec2930f4e1acc43ac30b518af298d466a79e9e75734a51c380b7810efd1a27f","src/codegen/shuffle1_dyn.rs":"3f13ca1597378758d05106bf5ff3715eee531f3cb6d88f48b9182bd6c9386b51","src/codegen/swap_bytes.rs":"c67c86e91ca3fc77539e0efcea081a3c62548cccf503963ae408f2e86f4e6a21","src/codegen/v128.rs":"94226b31ec403d18d9d2fe06713f147c9c79e9b5f9105089088266313f843185","src/codegen/v16.rs":"ddec4ffb66b6f7aaffb9a1780c5ddba82557abd74f45073d335047e04cf74924","src/codegen/v256.rs":"6b63917f0444118d6b1595bff2045e59b97c4d24012bd575f69f1f0efc5a0241","src/codegen/v32.rs":"3477b3c5540aed86e61e2f5807dd31db947413cec9181c587d93ed6ec74f0eba","src/codegen/v512.rs":"5854f99d3aabc4cd42b28a20d9ce447756dc2ba024a409a69b6a8ae1f1842fc5","src/codegen/v64.rs":"e9e89caebfe63d10c0cbca61e4dfdba3b7e02ee0989170f80beed23237ddd950","src/codegen/vPtr.rs":"f0753b405cdc865bdf8e82c6505f299ea1f96136239ebbaf7f9ce93d310764b8","src/codegen/vSize.rs":"c89f5fdeb28ac4c8272ed1816fce03d9d95308cc32bb2533bd8b20cd5ac102ac","src/lib.rs":"05048c6a85ec65cf902d9dd8f757a3f76392b703a6794ea71f0d41500a89f78f","src/masks.rs":"70fc0abe4c2907ce2a491c574e1cfb9f3423385da2e1a923a48c9c13f8ba6ed8","src/sealed.rs":"ae7fdeaf5d84cd7710ed730ca72ca7eaba93df6cb0acb183e5c0a7327acf197f","src/testing.rs":"896669c08d8c801448a4d2fadc9d633eda0fbe879d229997e2a182e31278e469","src/testing/macros.rs":"403bbc5ecb7c786fe36156df302d0c07a8122408dbb15f7474d7682224ba1106","src/testing/utils.rs":"41912a92266dfe884647fc035e4242fd746100df8e839808ae0397af3759a3c8","src/v128.rs":"16cf9a8e7156b899ee9b9cd3f2dba9d13ec63289bea8c3ee9ae2e43ad9510288","src/v16.rs":"cb6465cf1e00bf530183af1819b9fe3d7eec978f8765d5e85d9b58a39a4b4045","src/v256.rs":"fe235017da18c7f3c361831c60e3173ad304d8ea1e95d64ebebc79da2d708511","src/v32.rs":"145d347855bac59b2de6508f9e594654e6c330423af9edc0e2ac8f4d1abdf45e","src/v512.rs":"f372f277f3e62eb5c945bb1c460333fdb17b6974fcc876633788ff53bded9599","src/v64.rs":"0b8079881b71575e3414be0b7f8f7eaba65281ba6732f2b2f61f73e95b6f48f7","src/vPtr.rs":"8b3e433d487180bb4304ff71245ecad90f0010f43e139a72027b672abe58facc","src/vSize.rs":"eda5aa020706cbf94d15bada41a0c2a35fc8f3f37cb7c2cd6f34d201399a495e","tests/endianness.rs":"5147f86d224c4c540b772033da2f994cad9bc9c035f38ec21e23bc4e55f8a759"},"package":"1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d"}
\ No newline at end of file
+{"files":{".appveyor.yml":"f1ed01850e0d725f9498f52a1a63ddf40702ad6e0bf5b2d7c4c04d76e96794a3",".github/workflows/benchmarks.yml":"d049f016dc53830a3fcc735833eca168df2e491f33b6b44ce7e4d5d1dd453854",".github/workflows/ci.yml":"170a2074add57ddc8f88b780149e4930162c6ee4718add4369dca8e3fd6c022a",".github/workflows/docs.yml":"86f7eb652c900624e4deb76320cd92175db1fa7295a76f28f30336ff0fad1604",".github/workflows/run-ci-script.yml":"d847be293f9ec17038e450652b1eb7bdc20b805c18c5dbab34d1d9ff7a9c8940",".travis.yml":"30a61a5ec53355fc1f3585e1690280308c2b7961701abc11e8389b235b647178","Cargo.toml":"2298b95db733423c8dfe684e28086fc50ef48cac43d0c5192abd876495eacfba","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c4ac7027a9ab7d7858aa8957d7454dbfcdbb81e605b6a171f05310cc3cad3762","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"019ed29c43989782d8eec3a961654cfc172d7a7898da4eca8f654700af7e1988","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"bdcf93ba9043ac1184e2c504a3d40c47c6c1601d882e0f0a27a8eb56fbabcb5f","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"ae8274309928620a5dd232a46264e05399bb746288ebee3843a71c4162208cc3","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"ba5fbc4bf3bb91cd50b407248da31225681efc8f2be7618f4a0ab1219b389508","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"53f97f8b9b5aca7534b9bf9ea48f35175052cd2a560a107e01ad270731c032fc","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"89f5421cf06d817ae94092987e914472ef384ad2d1fff2735be3d8786ba11214","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"83eba19576486f9d10d7c037d669d72b31a65565a479f30b22aab36aaa2ff8dc","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"b982b421c70db476900df5b60e19ef8815e6c7dae22687225002780cab7b0a76","ci/docker/x86_64-linux-android/Dockerfile":"a17ebdb186ce2dd6b62100b5a439e05a1ab9adab113e2508843e121aaea52992","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab7ad3b7a344833ee726aba6b647cf5952e56f0ad1ba420b13325","ci/lld-shim.rs":"3d7f71ec23a49e2b67f694a0168786f9a954dda15f5a138815d966643fd3fcc3","ci/max_line_width.sh":"0a1518bba4c9ecaa55694cb2e9930d0e19c265baabf73143f17f9cf285aaa5bb","ci/run-docker.sh":"92e036390ad9b0d16f109579df1b5ced2e72e9afea40c7d011400ebd3a2a90de","ci/run.sh":"9afabc961e0ee83b87201f3fd554c19e5b0c36f3a95d013595e276c9882dd0a4","ci/run_examples.sh":"d1a23c6c35374a0678ba5114b9b8fefd8be0a79e774872a8bf0898d1baca18d0","ci/runtest-android.rs":"145a8e9799a5223975061fe7e586ade5669ee4877a7d7a4cf6b4ab48e8e36c7c","ci/setup_benchmarks.sh":"fae3960023f6f3d1388cd2ad22fdbab4b075f1f29dd4292d7994a20783beb6cf","ci/test-runner-linux":"c8aa6025cff5306f4f31d0c61dc5f9d4dd5a1d189ab613ef8d4c367c694d9ccd","contributing.md":"2d2629310ad4d464c482bdbb5819f0d6ce223c576aeef2cdce6a1f6857085ea5","perf-guide/.gitignore":"fe82c7da551079d832cf74200b0b359b4df9828cb4a0416fa7384f07a2ae6a13","perf-guide/book.toml":"115a98284126c6b180178b44713314cc494f08a71662ee2ce15cf67f17a51064","perf-guide/src/SUMMARY.md":"3e03bffc991fdc2050f3d51842d72d9d21ea6abab56a3baf3b2d5973a78b89e1","perf-guide/src/ascii.css":"29afb08833b2fe2250f0412e1fa1161a2432a0820a14953c87124407417c741a","perf-guide/src/bound_checks.md":"5e4991ff58a183ef0cd9fdc1feb4cd12d083b44bdf87393bbb0927808ef3ce7d","perf-guide/src/float-math/approx.md":"8c09032fa2d795a0c5db1775826c850d28eb2627846d0965c60ee72de63735ad","perf-guide/src/float-math/fma.md":"311076ba4b741d604a82e74b83a8d7e8c318fcbd7f64c4392d1cf5af95c60243","perf-guide/src/float-math/fp.md":"04153e775ab6e4f0d7837bcc515230d327b04edfa34c84ce9c9e10ebaeef2be8","perf-guide/src/float-math/svml.md":"0798873b8eedaeda5fed62dc91645b57c20775a02d3cd74d8bd06958f1516506","perf-guide/src/introduction.md":"9f5a19e9e6751f25d2daad39891a0cc600974527ec4c8305843f9618910671bd","perf-guide/src/prof/linux.md":"447731eb5de7d69166728fdbc5ecb0c0c9db678ea493b45a592d67dd002184c0","perf-guide/src/prof/mca.md":"f56d54f3d20e7aa4d32052186e8237b03d65971eb5d112802b442570ff11d344","perf-guide/src/prof/profiling.md":"8a650c0fd6ede0964789bb6577557eeef1d8226a896788602ce61528e260e43c","perf-guide/src/target-feature/attribute.md":"615f88dca0a707b6c416fa605435dd6e1fb5361cc639429cbf68cd87624bd78b","perf-guide/src/target-feature/features.md":"17077760ff24c006b606dd21889c53d87228f4311f3ba3a574f9afdeacd86165","perf-guide/src/target-feature/inlining.md":"7ed1d7068d8173a00d84c16cfe5871cd68b9f04f8d0cca2d01ebc84957ebf2f6","perf-guide/src/target-feature/practice.md":"c4b371842e0086df178488fec97f20def8f0c62ee588bcd25fd948b9b1fa227e","perf-guide/src/target-feature/runtime.md":"835425f5ee597fb3e51d36e725a81ebee29f4561231d19563cd4da81dbb1cfcb","perf-guide/src/target-feature/rustflags.md":"01197acf6f0adec8db32b8591811f69cecb6555a2b05dc5d5ec27d0e3f7b065e","perf-guide/src/vert-hor-ops.md":"c6211c0ee91e60552ec592d89d9d957eedc21dee3cbd89e1ad6765ea06a27471","rustfmt.toml":"d99a43f3f8ef9e425cf01c333fba9f0051f888f5d87ab4e8f63c2f7d0fe6620f","src/api.rs":"bb1795e9657a8298d37d2349b45443f08e9e455399ad4b727018600728478c10","src/api/bit_manip.rs":"27f3097fc0a11e3c4107049d9779e680dcd67407a066704008a6b9c4fd529e05","src/api/bitmask.rs":"058ebc38a2e0363f07a441d3e9a4775aaec57ccb170a0e5d5efa5dc4743ab07b","src/api/cast.rs":"03b94a3d316ac7b7be7068810044911e965e889a0ace7bae762749ca74a92747","src/api/cast/macros.rs":"b0a14d0c83ad2ebb7a275180f6d9e3f2bc312ba57a7d3d6c39fad4e0f20f9408","src/api/cast/v128.rs":"edd0994efac4379dff26e178423a52dbb3ffeb38b1fc97cae975d744c00b4fb6","src/api/cast/v16.rs":"96bd98c2d21b0663abe6c0ab33005b1fa693f3db7ee6795351391343863484da","src/api/cast/v256.rs":"8c31fe91f5e78ef737dfba6979cc1240210cb094a89d284fe459bf8a991ca24b","src/api/cast/v32.rs":"a99a79dd84d2a5e6adf9db98705675915bd03fd1287d489c7fe38e84d7e4a086","src/api/cast/v512.rs":"c0dd526f41ed7b8a71c3743d91267554ec0a0c75834ccc2e3ecb0ef3004af642","src/api/cast/v64.rs":"6572fdba2a1241a6cd666d3f0cce3306cd2cb7e5e236172e59d5d4351c8a88af","src/api/cmp.rs":"357c3a2a09c6d4611c32dd7fa95be2fae933d513e229026ec9b44451a77b884e","src/api/cmp/eq.rs":"60f70f355bae4cb5b17db53204cacc3890f70670611c17df638d4c04f7cc8075","src/api/cmp/ord.rs":"589f7234761c294fa5df8f525bc4acd5a47cdb602207d524a0d4e19804cd9695","src/api/cmp/partial_eq.rs":"902ccb8aa01fd5738b30ba0b712669c21d4801958907e03bad23432c7dba0198","src/api/cmp/partial_ord.rs":"9db0c37d7434cdfc62d8d66912e972fa3d8c115ab2af051a6f45e414bd3e4f1c","src/api/cmp/vertical.rs":"de3d62f38eba817299aa16f1e1939954c9a447e316509397465c2830852ba053","src/api/default.rs":"67bf21c134127d12a7028c8b88a57f0ceee8ccbd74976da8ca74eb9f16a174d5","src/api/fmt.rs":"67fb804bb86b6cd77cf8cd492b5733ce437071b66fe3297278b8a6552c325dda","src/api/fmt/binary.rs":"02b2b287f7404f8a983813cf70c87108c8da3835578b63ab303116885f609413","src/api/fmt/debug.rs":"56e1c3bdc092747344fffaafff9da7163ee7827857f6fb7cb1c9923eca4f6fa0","src/api/fmt/lower_hex.rs":"558fd592f7f485712fb051509cecc7174a21e6bf62e5ce64766e75afc97bb8e1","src/api/fmt/octal.rs":"3b2e70877a4f368c7704f8e254236c014c365c74d93371c1feb5f030e6c66422","src/api/fmt/upper_hex.rs":"2a442f666bc80e22d41f903f881238fe114dd49344c3ed69849250e853cafc5d","src/api/from.rs":"2e599d8329cb05eaf06224cc441355c4b7b51254fc19256619333be8c149d444","src/api/from/from_array.rs":"5d2cc700568376bf6ee1fe5e406da3bc2d488ff155644bf73d06a1349b73fc53","src/api/from/from_vector.rs":"9764371aa9e6005aace74dea14f59e5611a095b7cf42707940924749282c52f0","src/api/hash.rs":"5076ece87969592c876486f5b1ea8affbeaec379d1a14a30859e0aa5592019de","src/api/into_bits.rs":"8f8011627250e23e66b5c0ca641afb079d8232674bb1354140b536bdbea63e55","src/api/into_bits/arch_specific.rs":"e7445021f3908326bfee758835e5fc5ad56aa1baa77fc1c58abe4350c66c670a","src/api/into_bits/macros.rs":"bb4fe99be2af6a21d805efab44c8e4e61a7b2adb42a65504a0cf26d13efdadcd","src/api/into_bits/v128.rs":"145a44922b09a5ca5b62d88a461d327d399a997a15db4b11d7b17e554a9fa4c0","src/api/into_bits/v16.rs":"f4f4f61ba88aa51b158ec56ca3dce234349aea0daf2b3029a14ab5125d1e41e5","src/api/into_bits/v256.rs":"8cea9c5d9809f11323cb7cdc53b83df593fd17caf926251e412ae9777bed547f","src/api/into_bits/v32.rs":"905ba683d342fa32f4202b80bb46530807bd0a5b588f6c2e8c9f475223c47775","src/api/into_bits/v512.rs":"e25afa1fbf088a5d58e7d75d197b6cd4c56637ea28542ba18e46a451f29d04e7","src/api/into_bits/v64.rs":"d6238022ccff7b92e55b3f6017fc269acb6f36330a6d7e8fb389853a0f1b6478","src/api/math.rs":"8b2a2fc651917a850539f993aa0b9e5bf4da67b11685285b8de8cdca311719ec","src/api/math/float.rs":"61d2794d68262a1090ae473bd30793b5f65cf732f32a6694a3af2ce5d9225616","src/api/math/float/abs.rs":"5b6b2701e2e11135b7ce58a05052ea8120e10e4702c95d046b9d21b827b26bf8","src/api/math/float/consts.rs":"6302c9261da4291d144d5bb53493cdd073498feb40955fb6860ea3c4d06c978a","src/api/math/float/cos.rs":"4c2dd7173728ef189314f1576c9486e03be21b7da98843b2f9011282a7979e31","src/api/math/float/exp.rs":"7c6d5f1e304f498a01cfa23b92380c815d7da0ad94eae3483783bc377d287eef","src/api/math/float/ln.rs":"54c7583f3df793b39ff57534fade27b41bb992439e5dc178252f5ca3190a3e54","src/api/math/float/mul_add.rs":"62cac77660d20159276d4c9ef066eb90c81cbddb808e8e157182c607625ad2eb","src/api/math/float/mul_adde.rs":"bae056ee9f3a70df39ec3c3b2f6437c65303888a7b843ef1a5bcf1f5aca0e602","src/api/math/float/powf.rs":"9ddb938984b36d39d82a82f862f80df8f7fb013f1d222d45698d41d88472f568","src/api/math/float/recpre.rs":"589225794ff1dbf31158dff660e6d4509ecc8befbb57c633900dea5ac0b840d6","src/api/math/float/rsqrte.rs":"a32abdcc318d7ccc8448231f54d75b884b7cbeb03a7d595713ab6243036f4dbf","src/api/math/float/sin.rs":"cbd3622b7df74f19691743001c8cf747a201f8977ad90542fee915f37dcd1e49","src/api/math/float/sqrt.rs":"0c66d5d63fb08e4d99c6b82a8828e41173aff1ac9fa1a2764a11fac217ccf2ac","src/api/math/float/sqrte.rs":"731e1c9f321b662accdd27dacb3aac2e8043b7aecb2f2161dde733bd9f025362","src/api/minimal.rs":"1f22bcc528555444e76de569ec0ae2029b9ae9d04805efeafa93369c8098036b","src/api/minimal/iuf.rs":"819cff26d3e196f807645bcc1d79eb27d9f175edb89910f2274d52a1e913cd11","src/api/minimal/mask.rs":"0cae10ae1fc65f5070e686c0c79bfba27b86b33d6c399367bd4848fb367dcec4","src/api/minimal/ptr.rs":"f74d7a4925d7209faebc26ea8315259cb2c08ec65789a70869e595649a9bc39a","src/api/ops.rs":"3e273b277a0f3019d42c3c59ca94a5afd4885d5ae6d2182e5089bbeec9de42ee","src/api/ops/scalar_arithmetic.rs":"d2d5ad897a59dd0787544f927e0e7ca4072c3e58b0f4a2324083312b0d5a21d7","src/api/ops/scalar_bitwise.rs":"482204e459ca6be79568e1c9f70adbe2d2151412ddf122fb2161be8ebb51c40c","src/api/ops/scalar_mask_bitwise.rs":"c250f52042e37b22d57256c80d4604104cfd2fbe2a2e127c676267270ca5d350","src/api/ops/scalar_shifts.rs":"c4773d435c3f9da4454327e6fbb2b5b41a1c0ebb1cca7372e69dc7a344a1b6e4","src/api/ops/vector_arithmetic.rs":"ddca15d09ddeef502c2ed66117a62300ca65d87e959e8b622d767bdf1c307910","src/api/ops/vector_bitwise.rs":"b3968f7005b649edcc22a54e2379b14d5ee19045f2e784029805781ae043b5ee","src/api/ops/vector_float_min_max.rs":"76bf8cb607e2c442923c1da1061a6b80d742d607408033c2a3761161114cf2a0","src/api/ops/vector_int_min_max.rs":"a378789c6ff9b32a51fbd0a97ffd36ed102cd1fe6a067d2b02017c1df342def6","src/api/ops/vector_mask_bitwise.rs":"5052d18517d765415d40327e6e8e55a312daaca0a5e2aec959bfa54b1675f9c8","src/api/ops/vector_neg.rs":"5c62f6b0221983cdbd23cd0a3af3672e6ba1255f0dfe8b19aae6fbd6503e231b","src/api/ops/vector_rotates.rs":"6c3f761d9d551f6365a8a95539ceace4b1a02e0b12d144f34ed68db94e88cff4","src/api/ops/vector_shifts.rs":"e510be14127c0ffd58a2573a39701da3557d66bedec09837ac8bbd44d579da00","src/api/ptr.rs":"8a793251bed6130dcfb2f1519ceaa18b751bbb15875928d0fb6deb5a5e07523a","src/api/ptr/gather_scatter.rs":"3d614f9d5b4ca201a9f7e46af4405e1d2c28ecee1620297c23b52e37b92cc0ea","src/api/reductions.rs":"ae5baca81352ecd44526d6c30c0a1feeda475ec73ddd3c3ec6b14e944e5448ee","src/api/reductions/bitwise.rs":"8bf910ae226188bd15fc7e125f058cd2566b6186fcd0cd8fd020f352c39ce139","src/api/reductions/float_arithmetic.rs":"47a5679896db2cbb56c31372fe42143da015b6beae7db5d2f3a0309ddf427ae1","src/api/reductions/integer_arithmetic.rs":"c2df3cf7493cca4174f2c65aea422a3d20d8a23af03f8d57cef72c19fee8f20d","src/api/reductions/mask.rs":"db83327a950e33a317f37fd33ca4e20c347fb415975ec024f3e23da8509425af","src/api/reductions/min_max.rs":"6af8c9aa45c69961b1b6fc205395f4767d4421869fb105fb3d563c5605fc13cd","src/api/select.rs":"6b07e7e8026df561f7307221a896f0fbb272536f41b9109040ac094c24c69331","src/api/shuffle.rs":"be7faff9b59654926df12897b2f98a4baa7d6acf2af1aaf93d388ba6e96f83ec","src/api/shuffle1_dyn.rs":"bfea5a91905b31444e9ef7ca6eddb7a9606b7e22d3f71bb842eb2795a0346620","src/api/slice.rs":"ee87484e8af329547b9a5d4f2a69e8bed6ea10bbd96270d706083843d4eea2ac","src/api/slice/from_slice.rs":"3735363000737104a8fc5f394ad8c31ec14e885952bd57647dd2a84001aee0a6","src/api/slice/write_to_slice.rs":"79d09c64d00724783c77c42e4583eeec97b18db94cf2ae146b564c3f85cfefd6","src/api/swap_bytes.rs":"05b4262eaade2f63e6cd3b780c19a03aecd2459d4cc4360051fc088887179a6e","src/codegen.rs":"db4f232fb9f5728db310b87dc8c4733be48afacab1053798c06106bef9a42b05","src/codegen/bit_manip.rs":"525ea6ff7ad1e043b6f6136992166f1803ed5563b7f6fc292c1c40257d20e264","src/codegen/llvm.rs":"12e748b4928c3be6cc12b4165c3041a3d0efccf6195338ecd3d88b8fdb0bbcc7","src/codegen/math.rs":"dfcf02ad34e2fdfe22c3f1cc2822001cc895e65031b4d06e585e5047839febb7","src/codegen/math/float.rs":"2c1cbce155bc527ce34d472c0fef6bc3dadb79cd7a357dd7aa5b1ebeb1d77a13","src/codegen/math/float/abs.rs":"d5aaadcf540bdb9b4264dca6471a255fd7bf509e763bef0239c0144a68466fea","src/codegen/math/float/cos.rs":"17f28d2900c852dca221fa9c92a9cd5fe7fd2df8d427bbc60216c749b2be013d","src/codegen/math/float/cos_pi.rs":"dbaf9f443f9846a491d4ec52210a7b5835dd593b03366e3135b05c37d70f9d6c","src/codegen/math/float/exp.rs":"d300058a4bcc7ae7976f216f81902cd73a9e603ad63880dff3bbc866c27a9f37","src/codegen/math/float/ln.rs":"c851e211e43f8256093ba75b03ae0c307c9962ee66d94f09b4dd80068190cbdf","src/codegen/math/float/macros.rs":"fc9924869ed85e4795983af228cacf23158f4f35919adce16c920ad4a3f0a009","src/codegen/math/float/mul_add.rs":"041a5b69d5991d93ef795351b17560c10faf80b78fd26ad7df42a239b32cf9de","src/codegen/math/float/mul_adde.rs":"d71d5f0f3333b62a7439b823cb7adf5340ea1555ce820fb4a3f4cb922f73f5f5","src/codegen/math/float/powf.rs":"9742c3877f1a5509ca5c9492a40884b6579ba6dd11c26b7112e63f70666b395d","src/codegen/math/float/sin.rs":"0e9868d35531566509f3a01d85d5253045eb4afa8525d8407dcc1f5f33c56036","src/codegen/math/float/sin_cos_pi.rs":"8e6b6142d7dd240cdb36669722e82ab9810a2261e86e659f7d97a942ad8b1258","src/codegen/math/float/sin_pi.rs":"bb6d39db8f921e03a301fc5206ac1a61a97def8a2cb83b87ccf189f3fc48d548","src/codegen/math/float/sqrt.rs":"e6ebb0c5f428efad1f672b9a8fe4e58534dbf1ea5a8fe092ce5ce76b52fe89cb","src/codegen/math/float/sqrte.rs":"23acfaea38d0e081a6d9021c1094e813d0cfd12c58c1eca9662aade5e625d51c","src/codegen/pointer_sized_int.rs":"6ca13c214b6cf7e0929dbe18e96a16fc0bb7d8799608df29c4c8115490f99e01","src/codegen/reductions.rs":"8eb18ebac76985d2aa30262a2edd8cb004230b511a765d657525f677a585c12c","src/codegen/reductions/mask.rs":"e67f35a1f4d156a4894a2d6ea5a935b4d898cf70eefb2715f5c1cc165e776c11","src/codegen/reductions/mask/aarch64.rs":"84b101c17cad1ede4eb6d38cada0ac7da239dba8cea3badd3829b967e558431f","src/codegen/reductions/mask/arm.rs":"aaa07129bd078ae7e677cf8b8e67ec9f30536606a0c7ed1baaa18fd1793bb218","src/codegen/reductions/mask/fallback.rs":"3eb9319d2c7cf19216b607b8459612c4e027b643cf11b036937d36896bf76786","src/codegen/reductions/mask/fallback_impl.rs":"76547f396e55ef403327c77c314cf8db8c7a5c9b9819bfb925abeacf130249e5","src/codegen/reductions/mask/x86.rs":"36dcd8af4ab99730a078ed113d3955f74eb1a2876e2e6d9f224e0ff462c216d1","src/codegen/reductions/mask/x86/avx.rs":"3a40868b38c86e35aefb96d7578de6322efe89d8135e0366359b54ddd06f861a","src/codegen/reductions/mask/x86/avx2.rs":"677aed3f056285285daa3adff8bc65e739630b4424defa6d9665e160f027507e","src/codegen/reductions/mask/x86/sse.rs":"8522f6ed03f6c32dd577d4298df477c08aeaaa38563706f29096e1911ed731f2","src/codegen/reductions/mask/x86/sse2.rs":"54ec56e49b0c6841eccb719e4f310d65fe767c04136b2ec20bd8b9d7d9897b9e","src/codegen/shuffle.rs":"1ec2930f4e1acc43ac30b518af298d466a79e9e75734a51c380b7810efd1a27f","src/codegen/shuffle1_dyn.rs":"3f13ca1597378758d05106bf5ff3715eee531f3cb6d88f48b9182bd6c9386b51","src/codegen/swap_bytes.rs":"c67c86e91ca3fc77539e0efcea081a3c62548cccf503963ae408f2e86f4e6a21","src/codegen/v128.rs":"94226b31ec403d18d9d2fe06713f147c9c79e9b5f9105089088266313f843185","src/codegen/v16.rs":"ddec4ffb66b6f7aaffb9a1780c5ddba82557abd74f45073d335047e04cf74924","src/codegen/v256.rs":"6b63917f0444118d6b1595bff2045e59b97c4d24012bd575f69f1f0efc5a0241","src/codegen/v32.rs":"3477b3c5540aed86e61e2f5807dd31db947413cec9181c587d93ed6ec74f0eba","src/codegen/v512.rs":"5854f99d3aabc4cd42b28a20d9ce447756dc2ba024a409a69b6a8ae1f1842fc5","src/codegen/v64.rs":"e9e89caebfe63d10c0cbca61e4dfdba3b7e02ee0989170f80beed23237ddd950","src/codegen/vPtr.rs":"f0753b405cdc865bdf8e82c6505f299ea1f96136239ebbaf7f9ce93d310764b8","src/codegen/vSize.rs":"c89f5fdeb28ac4c8272ed1816fce03d9d95308cc32bb2533bd8b20cd5ac102ac","src/lib.rs":"05048c6a85ec65cf902d9dd8f757a3f76392b703a6794ea71f0d41500a89f78f","src/masks.rs":"70fc0abe4c2907ce2a491c574e1cfb9f3423385da2e1a923a48c9c13f8ba6ed8","src/sealed.rs":"ae7fdeaf5d84cd7710ed730ca72ca7eaba93df6cb0acb183e5c0a7327acf197f","src/testing.rs":"896669c08d8c801448a4d2fadc9d633eda0fbe879d229997e2a182e31278e469","src/testing/macros.rs":"403bbc5ecb7c786fe36156df302d0c07a8122408dbb15f7474d7682224ba1106","src/testing/utils.rs":"41912a92266dfe884647fc035e4242fd746100df8e839808ae0397af3759a3c8","src/v128.rs":"16cf9a8e7156b899ee9b9cd3f2dba9d13ec63289bea8c3ee9ae2e43ad9510288","src/v16.rs":"cb6465cf1e00bf530183af1819b9fe3d7eec978f8765d5e85d9b58a39a4b4045","src/v256.rs":"fe235017da18c7f3c361831c60e3173ad304d8ea1e95d64ebebc79da2d708511","src/v32.rs":"145d347855bac59b2de6508f9e594654e6c330423af9edc0e2ac8f4d1abdf45e","src/v512.rs":"f372f277f3e62eb5c945bb1c460333fdb17b6974fcc876633788ff53bded9599","src/v64.rs":"0b8079881b71575e3414be0b7f8f7eaba65281ba6732f2b2f61f73e95b6f48f7","src/vPtr.rs":"8b3e433d487180bb4304ff71245ecad90f0010f43e139a72027b672abe58facc","src/vSize.rs":"eda5aa020706cbf94d15bada41a0c2a35fc8f3f37cb7c2cd6f34d201399a495e","tests/endianness.rs":"5147f86d224c4c540b772033da2f994cad9bc9c035f38ec21e23bc4e55f8a759"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/packed_simd/Cargo.toml b/third_party/rust/packed_simd/Cargo.toml
--- a/third_party/rust/packed_simd/Cargo.toml
+++ b/third_party/rust/packed_simd/Cargo.toml
@@ -1,83 +1,46 @@
-# 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 are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
[package]
-edition = "2018"
name = "packed_simd"
version = "0.3.9"
-build = "build.rs"
description = "Portable Packed SIMD vectors"
-homepage = "https://github.com/rust-lang/packed_simd"
documentation = "https://docs.rs/crate/packed_simd/"
-readme = "README.md"
-keywords = [
- "simd",
- "vector",
- "portability",
-]
-categories = [
- "hardware-support",
- "concurrency",
- "no-std",
- "data-structures",
-]
+homepage = "https://github.com/rust-lang/packed_simd"
+repository = "https://github.com/rust-lang/packed_simd"
+keywords = ["simd", "vector", "portability"]
+categories = ["hardware-support", "concurrency", "no-std", "data-structures"]
license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/packed_simd"
+build = "build.rs"
+edition = "2018"
[package.metadata.docs.rs]
features = ["into_bits"]
-rustdoc-args = [
- "--cfg",
- "doc_cfg",
-]
-
-[dependencies.cfg-if]
-version = "1.0.0"
-
-[dependencies.core_arch]
-version = "0.1.5"
-optional = true
+rustdoc-args = ["--cfg", "doc_cfg"]
+# To build locally:
+# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --features into_bits --no-deps --open
-[dependencies.num-traits]
-version = "0.2.14"
-features = ["libm"]
-default-features = false
+[badges]
+is-it-maintained-issue-resolution = { repository = "rust-lang/packed_simd" }
+is-it-maintained-open-issues = { repository = "rust-lang/packed_simd" }
+maintenance = { status = "experimental" }
-[dev-dependencies.arrayvec]
-version = "^0.5"
-default-features = false
-
-[dev-dependencies.paste]
-version = "^1"
+[dependencies]
+cfg-if = "1.0.0"
+core_arch = { version = "0.1.5", optional = true }
+num-traits = { version = "0.2.14", default-features = false }
[features]
default = []
into_bits = []
libcore_neon = []
-[target."cfg(target_arch = \"x86_64\")".dependencies.sleef-sys]
+[dev-dependencies]
+paste = "^1"
+arrayvec = { version = "^0.5", default-features = false }
+
+[target.'cfg(target_arch = "x86_64")'.dependencies.sleef-sys]
version = "0.1.2"
optional = true
-[target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen]
-version = "=0.2.87"
-
-[target.wasm32-unknown-unknown.dev-dependencies.wasm-bindgen-test]
-version = "=0.3.37"
-
-[badges.is-it-maintained-issue-resolution]
-repository = "rust-lang/packed_simd"
-
-[badges.is-it-maintained-open-issues]
-repository = "rust-lang/packed_simd"
-
-[badges.maintenance]
-status = "experimental"
+[target.wasm32-unknown-unknown.dev-dependencies]
+# Keep in sync with the version on Dockerfile.
+wasm-bindgen = "=0.2.87"
+wasm-bindgen-test = "=0.3.37"
diff --git a/third_party/rust/packed_simd/rust-toolchain b/third_party/rust/packed_simd/rust-toolchain
deleted file mode 100644
--- a/third_party/rust/packed_simd/rust-toolchain
+++ /dev/null
@@ -1,1 +0,0 @@
-nightly
diff --git a/third_party/rust/packed_simd/src/api.rs b/third_party/rust/packed_simd/src/api.rs
--- a/third_party/rust/packed_simd/src/api.rs
+++ b/third_party/rust/packed_simd/src/api.rs
@@ -208,17 +208,16 @@ macro_rules! impl_f {
impl_math_float_mul_add!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_mul_adde!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_powf!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_recpre!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_rsqrte!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_sin!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_sqrt!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_math_float_sqrte!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
- impl_math_float_tanh!([$elem_ty; $elem_n]: $tuple_id | $test_tt);
impl_cmp_vertical!(
[$elem_ty; $elem_n]: $tuple_id, $mask_ty, false, (1., 0.)
| $test_tt
);
test_select!($elem_ty, $mask_ty, $tuple_id, (1., 2.) | $test_tt);
test_reduction_float_min_max!(
[$elem_ty; $elem_n]: $tuple_id | $test_tt
diff --git a/third_party/rust/packed_simd/src/api/math/float.rs b/third_party/rust/packed_simd/src/api/math/float.rs
--- a/third_party/rust/packed_simd/src/api/math/float.rs
+++ b/third_party/rust/packed_simd/src/api/math/float.rs
@@ -34,19 +34,16 @@ mod rsqrte;
mod sin;
#[macro_use]
mod sqrt;
#[macro_use]
mod sqrte;
-#[macro_use]
-mod tanh;
-
macro_rules! impl_float_category {
([$elem_ty:ident; $elem_count:expr]: $id:ident, $mask_ty:ident) => {
impl $id {
#[inline]
pub fn is_nan(self) -> $mask_ty {
self.ne(self)
}
diff --git a/third_party/rust/packed_simd/src/api/math/float/tanh.rs b/third_party/rust/packed_simd/src/api/math/float/tanh.rs
deleted file mode 100644
--- a/third_party/rust/packed_simd/src/api/math/float/tanh.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//! Implements vertical (lane-wise) floating-point `tanh`.
-
-macro_rules! impl_math_float_tanh {
- ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
- impl $id {
- /// Tanh.
- #[inline]
- pub fn tanh(self) -> Self {
- use crate::codegen::math::float::tanh::Tanh;
- Tanh::tanh(self)
- }
- }
-
- test_if!{
- $test_tt:
- paste::item! {
- pub mod [<$id _math_tanh>] {
- use super::*;
- #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
- fn tanh() {
- let z = $id::splat(0 as $elem_ty);
-
- assert_eq!(z, z.tanh());
- }
- }
- }
- }
- };
-}
diff --git a/third_party/rust/packed_simd/src/codegen/math/float.rs b/third_party/rust/packed_simd/src/codegen/math/float.rs
--- a/third_party/rust/packed_simd/src/codegen/math/float.rs
+++ b/third_party/rust/packed_simd/src/codegen/math/float.rs
@@ -11,9 +11,8 @@ pub(crate) mod ln;
pub(crate) mod mul_add;
pub(crate) mod mul_adde;
pub(crate) mod powf;
pub(crate) mod sin;
pub(crate) mod sin_cos_pi;
pub(crate) mod sin_pi;
pub(crate) mod sqrt;
pub(crate) mod sqrte;
-pub(crate) mod tanh;
diff --git a/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs b/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs
deleted file mode 100644
--- a/third_party/rust/packed_simd/src/codegen/math/float/tanh.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-//! Vertical floating-point `tanh`
-#![allow(unused)]
-
-// FIXME 64-bit 1 elem vectors tanh
-
-#[cfg(not(feature = "std"))]
-use num_traits::Float;
-
-use crate::*;
-
-pub(crate) trait Tanh {
- fn tanh(self) -> Self;
-}
-
-macro_rules! define_tanh {
- ($name:ident, $basetype:ty, $simdtype:ty, $lanes:expr, $trait:path) => {
- fn $name(x: $simdtype) -> $simdtype {
- use core::intrinsics::transmute;
- let mut buf: [$basetype; $lanes] = unsafe { transmute(x) };
- for elem in &mut buf {
- *elem = <$basetype as $trait>::tanh(*elem);
- }
- unsafe { transmute(buf) }
- }
- };
-
- (f32 => $name:ident, $type:ty, $lanes:expr) => {
- define_tanh!($name, f32, $type, $lanes, Float);
- };
-
- (f64 => $name:ident, $type:ty, $lanes:expr) => {
- define_tanh!($name, f64, $type, $lanes, Float);
- };
-}
-
-// llvm does not seem to expose the hyperbolic versions of trigonometric
-// functions; we thus call the classical rust versions on all of them (which
-// stem from cmath).
-define_tanh!(f32 => tanh_v2f32, f32x2, 2);
-define_tanh!(f32 => tanh_v4f32, f32x4, 4);
-define_tanh!(f32 => tanh_v8f32, f32x8, 8);
-define_tanh!(f32 => tanh_v16f32, f32x16, 16);
-
-define_tanh!(f64 => tanh_v2f64, f64x2, 2);
-define_tanh!(f64 => tanh_v4f64, f64x4, 4);
-define_tanh!(f64 => tanh_v8f64, f64x8, 8);
-
-fn tanh_f32(x: f32) -> f32 {
- Float::tanh(x)
-}
-
-fn tanh_f64(x: f64) -> f64 {
- Float::tanh(x)
-}
-
-gen_unary_impl_table!(Tanh, tanh);
-
-cfg_if! {
- if #[cfg(target_arch = "s390x")] {
- // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/14
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x4[f32; 4]: tanh_f32);
- impl_unary!(f32x8[f32; 8]: tanh_f32);
- impl_unary!(f32x16[f32; 16]: tanh_f32);
-
- impl_unary!(f64x2[f64; 2]: tanh_f64);
- impl_unary!(f64x4[f64; 4]: tanh_f64);
- impl_unary!(f64x8[f64; 8]: tanh_f64);
- } else if #[cfg(all(target_arch = "x86_64", feature = "sleef-sys"))] {
- use sleef_sys::*;
- cfg_if! {
- if #[cfg(target_feature = "avx2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10avx2128);
- impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx2);
- impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx2);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10avx2128);
- impl_unary!(f32x8: Sleef_tanhf8_u10avx2);
- impl_unary!(f64x2: Sleef_tanhd2_u10avx2128);
- impl_unary!(f64x4: Sleef_tanhd4_u10avx2);
- } else if #[cfg(target_feature = "avx")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x16[h => f32x8]: Sleef_tanhf8_u10avx);
- impl_unary!(f64x8[h => f64x4]: Sleef_tanhd4_u10avx);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x8: Sleef_tanhf8_u10avx);
- impl_unary!(f64x2: Sleef_tanhd2_u10sse4);
- impl_unary!(f64x4: Sleef_tanhd4_u10avx);
- } else if #[cfg(target_feature = "sse4.2")] {
- impl_unary!(f32x2[t => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x16[q => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f64x8[q => f64x2]: Sleef_tanhd2_u10sse4);
-
- impl_unary!(f32x4: Sleef_tanhf4_u10sse4);
- impl_unary!(f32x8[h => f32x4]: Sleef_tanhf4_u10sse4);
- impl_unary!(f64x2: Sleef_tanhd2_u10sse4);
- impl_unary!(f64x4[h => f64x2]: Sleef_tanhd2_u10sse4);
- } else {
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x16: tanh_v16f32);
- impl_unary!(f64x8: tanh_v8f64);
-
- impl_unary!(f32x4: tanh_v4f32);
- impl_unary!(f32x8: tanh_v8f32);
- impl_unary!(f64x2: tanh_v2f64);
- impl_unary!(f64x4: tanh_v4f64);
- }
- }
- } else {
- impl_unary!(f32x2[f32; 2]: tanh_f32);
- impl_unary!(f32x4: tanh_v4f32);
- impl_unary!(f32x8: tanh_v8f32);
- impl_unary!(f32x16: tanh_v16f32);
-
- impl_unary!(f64x2: tanh_v2f64);
- impl_unary!(f64x4: tanh_v4f64);
- impl_unary!(f64x8: tanh_v8f64);
- }
-}