diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/num-traits | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/num-traits')
26 files changed, 8529 insertions, 0 deletions
diff --git a/third_party/rust/num-traits/.cargo-checksum.json b/third_party/rust/num-traits/.cargo-checksum.json new file mode 100644 index 0000000000..82a6d1c2f3 --- /dev/null +++ b/third_party/rust/num-traits/.cargo-checksum.json @@ -0,0 +1 @@ +{"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 new file mode 100644 index 0000000000..b30fca3225 --- /dev/null +++ b/third_party/rust/num-traits/Cargo.toml @@ -0,0 +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. +# +# 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.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", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-num/num-traits" + +[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/LICENSE-APACHE b/third_party/rust/num-traits/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/third_party/rust/num-traits/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/num-traits/LICENSE-MIT b/third_party/rust/num-traits/LICENSE-MIT new file mode 100644 index 0000000000..39d4bdb5ac --- /dev/null +++ b/third_party/rust/num-traits/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +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/num-traits/README.md b/third_party/rust/num-traits/README.md new file mode 100644 index 0000000000..36339622be --- /dev/null +++ b/third_party/rust/num-traits/README.md @@ -0,0 +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)](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" +``` + +## Features + +This crate can be used without the standard library (`#![no_std]`) by disabling +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 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 new file mode 100644 index 0000000000..cd33c044d3 --- /dev/null +++ b/third_party/rust/num-traits/RELEASES.md @@ -0,0 +1,259 @@ +# 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]. + +**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. + - 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 (2018-02-06) + +- All items are now [re-exported from num-traits 0.2][31] for compatibility. + +[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. + +Thanks to @cuviper, @Enet4, @fabianschuiki, @svartalf, and @yoanlcq for their contributions! + +[home]: https://github.com/rust-num/num-traits +[num-356]: https://github.com/rust-num/num/pull/356 +[17]: https://github.com/rust-num/num-traits/pull/17 +[21]: https://github.com/rust-num/num-traits/pull/21 +[22]: https://github.com/rust-num/num-traits/pull/22 +[23]: https://github.com/rust-num/num-traits/pull/23 + + +# Prior releases + +No prior release notes were kept. Thanks all the same to the many +contributors that have made this crate what it is! diff --git a/third_party/rust/num-traits/build.rs b/third_party/rust/num-traits/build.rs new file mode 100644 index 0000000000..c7bf364f1c --- /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/src/bounds.rs b/third_party/rust/num-traits/src/bounds.rs new file mode 100644 index 0000000000..36e1bbdfb0 --- /dev/null +++ b/third_party/rust/num-traits/src/bounds.rs @@ -0,0 +1,153 @@ +use core::num::Wrapping; +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}; + +/// 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 + 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; +} + +// 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 + } + + #[inline] + 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); +#[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); +#[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()) + } +} + +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) => { + 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(),)*) + } + #[inline] + fn max_value() -> Self { + ($($name::max_value(),)*) + } + } + ); +} + +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> 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 new file mode 100644 index 0000000000..d38c338156 --- /dev/null +++ b/third_party/rust/num-traits/src/cast.rs @@ -0,0 +1,814 @@ +use core::mem::size_of; +use core::num::Wrapping; +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`. If the value cannot be + /// represented by an `isize`, then `None` is returned. + #[inline] + fn to_isize(&self) -> Option<isize> { + self.to_i64().as_ref().and_then(ToPrimitive::to_isize) + } + + /// 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().as_ref().and_then(ToPrimitive::to_i8) + } + + /// 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().as_ref().and_then(ToPrimitive::to_i16) + } + + /// 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().as_ref().and_then(ToPrimitive::to_i32) + } + + /// 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 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] + #[cfg(has_i128)] + fn to_i128(&self) -> Option<i128> { + self.to_i64().map(From::from) + } + + /// 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().as_ref().and_then(ToPrimitive::to_u8) + } + + /// 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().as_ref().and_then(ToPrimitive::to_u16) + } + + /// 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().as_ref().and_then(ToPrimitive::to_u32) + } + + /// 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 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().as_ref().and_then(ToPrimitive::to_f32) + } + + /// 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> { + 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: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 { + None + } + } + )*} +} + +macro_rules! impl_to_primitive_int_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 0 <= *self && (size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max) { + Some(*self as $DstT) + } else { + None + } + } + )*} +} + +macro_rules! impl_to_primitive_int { + ($T:ident) => { + impl ToPrimitive for $T { + 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_f32(&self) -> Option<f32> { + Some(*self as f32) + } + #[inline] + 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 { + ($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 { + ($T:ident) => { + impl ToPrimitive for $T { + 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_f32(&self) -> Option<f32> { + Some(*self as f32) + } + #[inline] + 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 : $( 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 { + // 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) => { + impl ToPrimitive for $T { + 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; + } + + 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; + } + + 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 { + /// 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> { + n.to_i64().and_then(FromPrimitive::from_i64) + } + + /// 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(From::from(n)) + } + + /// 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(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)) + } + + /// 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] + #[cfg(has_i128)] + fn from_i128(n: i128) -> Option<Self> { + n.to_i64().and_then(FromPrimitive::from_i64) + } + + /// 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> { + n.to_u64().and_then(FromPrimitive::from_u64) + } + + /// 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(From::from(n)) + } + + /// 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(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)) + } + + /// 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>; + + /// 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(From::from(n)) + } + + /// 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> { + 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) => { + #[allow(deprecated)] + impl FromPrimitive for $T { + #[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_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() + } + } + }; +} + +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); +#[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); +#[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> { + 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(); +/// assert_eq!(twenty, 20f32); +/// ``` +/// +#[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. 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) => { + 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); +#[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); +#[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<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 +/// 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 +/// +/// **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 +/// ``` +/// +pub trait AsPrimitive<T>: 'static + Copy +where + T: 'static + Copy, +{ + /// Convert a value to another, using the `as` operator. + fn as_(self) -> T; +} + +macro_rules! impl_as_primitive { + (@ $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, 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 new file mode 100644 index 0000000000..47bd65431f --- /dev/null +++ b/third_party/rust/num-traits/src/float.rs @@ -0,0 +1,2351 @@ +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() + } + + /// 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; + + /// 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, 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()); + /// ``` + fn nan() -> Self; + /// Returns the infinite value. + /// + /// ``` + /// use num_traits::Float; + /// use std::f32; + /// + /// let infinity: f32 = Float::infinity(); + /// + /// assert!(infinity.is_infinite()); + /// assert!(!infinity.is_finite()); + /// assert!(infinity > f32::MAX); + /// ``` + fn infinity() -> Self; + /// Returns the negative infinite value. + /// + /// ``` + /// use num_traits::Float; + /// use std::f32; + /// + /// let neg_infinity: f32 = Float::neg_infinity(); + /// + /// assert!(neg_infinity.is_infinite()); + /// assert!(!neg_infinity.is_finite()); + /// assert!(neg_infinity < f32::MIN); + /// ``` + fn neg_infinity() -> Self; + /// Returns `-0.0`. + /// + /// ``` + /// use num_traits::{Zero, Float}; + /// + /// let inf: f32 = Float::infinity(); + /// let zero: f32 = Zero::zero(); + /// let neg_zero: f32 = Float::neg_zero(); + /// + /// assert_eq!(zero, neg_zero); + /// assert_eq!(7.0f32/inf, zero); + /// assert_eq!(zero * 10.0, zero); + /// ``` + fn neg_zero() -> Self; + + /// Returns the smallest finite value that this type can represent. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_value(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + fn min_value() -> Self; + + /// Returns the smallest positive, normalized value that this type can represent. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x: f64 = Float::min_positive_value(); + /// + /// assert_eq!(x, f64::MIN_POSITIVE); + /// ``` + fn min_positive_value() -> Self; + + /// Returns epsilon, a small positive value. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x: f64 = Float::epsilon(); + /// + /// assert_eq!(x, f64::EPSILON); + /// ``` + /// + /// # Panics + /// + /// The default implementation will panic if `f32::EPSILON` cannot + /// be cast to `Self`. + fn epsilon() -> Self { + Self::from(f32::EPSILON).expect("Unable to cast from f32::EPSILON") + } + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x: f64 = Float::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + fn max_value() -> Self; + + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + fn is_nan(self) -> bool; + + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use num_traits::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + fn is_infinite(self) -> bool; + + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf: f32 = Float::infinity(); + /// let neg_inf: f32 = Float::neg_infinity(); + /// let nan: f32 = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + fn is_finite(self) -> bool; + + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + fn is_normal(self) -> bool; + + /// 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. + /// + /// ``` + /// use num_traits::Float; + /// use std::num::FpCategory; + /// use std::f32; + /// + /// let num = 12.4f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + fn classify(self) -> FpCategory; + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + fn floor(self) -> Self; + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + fn ceil(self) -> Self; + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + fn round(self) -> Self; + + /// Return the integer part of a number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + fn trunc(self) -> Self; + + /// Returns the fractional part of a number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + fn fract(self) -> Self; + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + fn abs(self) -> Self; + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// 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 since Rust 1.20 also `Float::nan()`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let neg_nan: f64 = -f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// 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 since Rust 1.20 also `-Float::nan()`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// 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, 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; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn mul_add(self, a: Self, b: Self) -> Self; + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn recip(self) -> Self; + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powi(self, n: i32) -> Self; + + /// Raise a number to a floating point power. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powf(self, n: Self) -> Self; + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + fn sqrt(self) -> Self; + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use num_traits::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp(self) -> Self; + + /// Returns `2^(self)`. + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp2(self) -> Self; + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn ln(self) -> Self; + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use num_traits::Float; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + fn log(self, base: Self) -> Self; + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log2(self) -> Self; + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log10(self) -> Self; + + /// Converts radians to degrees. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[inline] + fn to_degrees(self) -> Self { + let halfpi = Self::zero().acos(); + let ninety = Self::from(90u8).unwrap(); + self * ninety / halfpi + } + + /// Converts degrees to radians. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = 180.0_f64; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[inline] + fn to_radians(self) -> Self { + let halfpi = Self::zero().acos(); + let ninety = Self::from(90u8).unwrap(); + self * halfpi / ninety + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + fn max(self, other: Self) -> Self; + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + fn min(self, other: Self) -> Self; + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + fn abs_sub(self, other: Self) -> Self; + + /// Take the cubic root of a number. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cbrt(self) -> Self; + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn hypot(self, other: Self) -> Self; + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sin(self) -> Self; + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cos(self) -> Self; + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + fn tan(self) -> Self; + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn asin(self) -> Self; + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn acos(self) -> Self; + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use num_traits::Float; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn atan(self) -> Self; + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + fn atan2(self, other: Self) -> Self; + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + fn sin_cos(self) -> (Self, Self); + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp_m1(self) -> Self; + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn ln_1p(self) -> Self; + + /// Hyperbolic sine function. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sinh(self) -> Self; + + /// Hyperbolic cosine function. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn cosh(self) -> Self; + + /// Hyperbolic tangent function. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn tanh(self) -> Self; + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn asinh(self) -> Self; + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use num_traits::Float; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn acosh(self) -> Self; + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use num_traits::Float; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// 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`. + /// + /// ``` + /// use num_traits::Float; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = Float::integer_decode(num); + /// let sign_f = sign as f32; + /// 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); + /// ``` + 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_std { + ($T:ident $decode:ident) => { + impl Float for $T { + 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 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(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 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) +} + +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 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_std!(f32 integer_decode_f32); +#[cfg(feature = "std")] +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 { + constant! { + $( $constant() -> $T::consts::$constant; )+ + TAU() -> 6.28318530717958647692528676655900577; + LOG10_2() -> 0.301029995663981195213738894724493027; + LOG2_10() -> 3.32192809488736234787031942948939018; + } + } + ); +} + +float_const_impl! { + #[doc = "Return Euler’s number."] + E, + #[doc = "Return `1.0 / π`."] + FRAC_1_PI, + #[doc = "Return `1.0 / sqrt(2.0)`."] + FRAC_1_SQRT_2, + #[doc = "Return `2.0 / π`."] + FRAC_2_PI, + #[doc = "Return `2.0 / sqrt(π)`."] + FRAC_2_SQRT_PI, + #[doc = "Return `π / 2.0`."] + FRAC_PI_2, + #[doc = "Return `π / 3.0`."] + FRAC_PI_3, + #[doc = "Return `π / 4.0`."] + FRAC_PI_4, + #[doc = "Return `π / 6.0`."] + FRAC_PI_6, + #[doc = "Return `π / 8.0`."] + FRAC_PI_8, + #[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 `π`."] + PI, + #[doc = "Return `sqrt(2.0)`."] + SQRT_2, +} + +#[cfg(test)] +mod tests { + 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 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-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 new file mode 100644 index 0000000000..7a99566d9e --- /dev/null +++ b/third_party/rust/num-traits/src/identities.rs @@ -0,0 +1,206 @@ +use core::num::Wrapping; +use core::ops::{Add, Mul}; + +/// 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`. + /// # 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. + // 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. + fn is_zero(&self) -> bool; +} + +macro_rules! zero_impl { + ($t:ty, $v:expr) => { + impl Zero for $t { + #[inline] + fn zero() -> $t { + $v + } + #[inline] + fn is_zero(&self) -> bool { + *self == $v + } + } + }; +} + +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, 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.0); +zero_impl!(f64, 0.0); + +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`. + /// + /// # 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. + // 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 + } + #[inline] + fn is_one(&self) -> bool { + *self == $v + } + } + }; +} + +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, 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.0); +one_impl!(f64, 1.0); + +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() +} + +/// Returns the multiplicative identity, `1`. +#[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); + assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); + assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); + )+ + }; + } + + test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); +} + +#[test] +fn wrapping_is_zero() { + fn require_zero<T: Zero>(_: &T) {} + require_zero(&Wrapping(42)); +} +#[test] +fn wrapping_is_one() { + fn require_one<T: One>(_: &T) {} + require_one(&Wrapping(42)); +} diff --git a/third_party/rust/num-traits/src/int.rs b/third_party/rust/num-traits/src/int.rs new file mode 100644 index 0000000000..c7dbf12465 --- /dev/null +++ b/third_party/rust/num-traits/src/int.rs @@ -0,0 +1,568 @@ +use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + +use bounds::Bounded; +use ops::checked::*; +use ops::saturating::Saturating; +use {Num, NumCast}; + +/// 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 + + 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> + + Saturating +{ + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + fn count_ones(self) -> u32; + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ``` + /// 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, `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, `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, `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, `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, `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, `n`, filling + /// zeros in the most significant bits. + /// + /// This is bitwise equivalent to unsigned `Shr`. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = -8i8; // 0b11111000 + /// let m = 62i8; // 0b00111110 + /// + /// assert_eq!(n.unsigned_shr(2), m); + /// ``` + fn unsigned_shr(self, n: u32) -> Self; + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ``` + /// use num_traits::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; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(u64::from_be(n), n) + /// } else { + /// assert_eq!(u64::from_be(n), n.swap_bytes()) + /// } + /// ``` + fn from_be(x: Self) -> Self; + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(u64::from_le(n), n) + /// } else { + /// assert_eq!(u64::from_le(n), n.swap_bytes()) + /// } + /// ``` + fn from_le(x: Self) -> Self; + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are swapped. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + fn to_be(self) -> Self; + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are swapped. + /// + /// # Examples + /// + /// ``` + /// use num_traits::PrimInt; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + fn to_le(self) -> Self; + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ``` + /// 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) => { + 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) + } + + #[inline] + fn rotate_right(self, n: u32) -> Self { + <$T>::rotate_right(self, n) + } + + #[inline] + fn signed_shl(self, n: u32) -> Self { + ((self as $S) << n) as $T + } + + #[inline] + fn signed_shr(self, n: u32) -> Self { + ((self as $S) >> n) as $T + } + + #[inline] + fn unsigned_shl(self, n: u32) -> Self { + ((self as $U) << n) as $T + } + + #[inline] + fn unsigned_shr(self, n: u32) -> Self { + ((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) + } + + #[inline] + fn to_be(self) -> Self { + <$T>::to_be(self) + } + + #[inline] + fn to_le(self) -> Self { + <$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); +#[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); +#[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 new file mode 100644 index 0000000000..bed87f3667 --- /dev/null +++ b/third_party/rust/num-traits/src/lib.rs @@ -0,0 +1,640 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! 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)] +#![no_std] +#[cfg(feature = "std")] +extern crate std; + +// 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::ops::{Add, Div, Mul, Rem, Sub}; +use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; + +pub use bounds::Bounded; +#[cfg(any(feature = "std", feature = "libm"))] +pub use float::Float; +pub use float::FloatConst; +// 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 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}; + +#[macro_use] +mod macros; + +pub mod bounds; +pub mod cast; +pub mod float; +pub mod identities; +pub mod int; +pub mod ops; +pub mod pow; +pub mod real; +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 { + type FromStrRadixErr; + + /// 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>; +} + +/// 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> + + 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 `Num` references which implement numeric operations, taking the +/// second operand either by value or by reference. +/// +/// 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> {} + +/// 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> +{ +} + +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>: 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)] +pub struct ParseFloatError { + pub kind: FloatErrorKind, +} + +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let description = match self.kind { + 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 + 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)> { + 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), + }; + + // The significand to accumulate + let mut sig = if is_positive { 0.0 } else { -0.0 }; + // Necessary to detect overflow + let mut prev_sig = sig; + let mut cs = src.chars().enumerate(); + // Exponent prefix and exponent index offset + let mut exp_info = None::<(char, usize)>; + + // Parse the integer part of the significand + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // shift significand one digit left + sig = sig * (radix as $t); + + // add/subtract current digit depending on sign + if is_positive { + sig = sig + ((digit as isize) as $t); + } else { + sig = sig - ((digit as isize) as $t); + } + + // Detect overflow by comparing to last value, except + // if we've not seen any non-zero digits. + if prev_sig != 0.0 { + if is_positive && sig <= prev_sig + { return Ok(core::$t::INFINITY); } + if !is_positive && sig >= prev_sig + { return Ok(core::$t::NEG_INFINITY); } + + // Detect overflow by reversing the shift-and-add process + if is_positive && (prev_sig != (sig - digit as $t) / radix as $t) + { return Ok(core::$t::INFINITY); } + if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t) + { return Ok(core::$t::NEG_INFINITY); } + } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + '.' => { + break; // start of fractional part + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + + // If we are not yet at the exponent parse the fractional + // part of the significand + if exp_info.is_none() { + let mut power = 1.0; + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // Decrease power one order of magnitude + power = power / (radix as $t); + // add/subtract current digit depending on sign + sig = if is_positive { + sig + (digit as $t) * power + } else { + sig - (digit as $t) * power + }; + // Detect overflow by comparing to last value + if is_positive && sig < prev_sig + { return Ok(core::$t::INFINITY); } + if !is_positive && sig > prev_sig + { return Ok(core::$t::NEG_INFINITY); } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + } + + // Parse and calculate the exponent + let exp = match exp_info { + Some((c, offset)) => { + let base = match c { + 'E' | 'e' if radix == 10 => 10.0, + 'P' | 'p' if radix == 16 => 2.0, + _ => return Err(PFE { kind: Invalid }), + }; + + // Parse the exponent as decimal integer + let src = &src[offset..]; + let (is_positive, exp) = match slice_shift_char(src) { + Some(('-', src)) => (false, src.parse::<usize>()), + Some(('+', src)) => (true, src.parse::<usize>()), + Some((_, _)) => (true, src.parse::<usize>()), + None => return Err(PFE { kind: Invalid }), + }; + + #[cfg(feature = "std")] + fn pow(base: $t, exp: usize) -> $t { + Float::powi(base, exp as i32) + } + // otherwise uses the generic `pow` from the root + + match (is_positive, exp) { + (true, Ok(exp)) => pow(base, exp), + (false, Ok(exp)) => 1.0 / pow(base, exp), + (_, Err(_)) => return Err(PFE { kind: Invalid }), + } + }, + None => 1.0, // no exponent + }; + + Ok(sig * exp) + } + } + )*) +} +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() { + macro_rules! test_wrapping_from_str_radix { + ($($t:ty)+) => { + $( + for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { + let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); + assert_eq!(w, <$t as Num>::from_str_radix(s, r)); + } + )+ + }; + } + + test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn check_num_ops() { + fn compute<T: Num + Copy>(x: T, y: T) -> T { + x * y / y % y + y - y + } + assert_eq!(compute(1, 2), 1) +} + +#[test] +fn check_numref_ops() { + fn compute<T: NumRef>(x: T, y: &T) -> T { + 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>, + { + &(&(&(&(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>, + { + &(&(&(&(x * y) / y) % y) + y) - y + } + assert_eq!(compute(&1, &2), 1) +} + +#[test] +fn check_numassign_ops() { + fn compute<T: NumAssign + Copy>(mut x: T, y: T) -> T { + x *= y; + x /= y; + x %= y; + x += y; + x -= y; + x + } + assert_eq!(compute(1, 2), 1) +} + +#[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 index 0000000000..b97758e42c --- /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 new file mode 100644 index 0000000000..3865570038 --- /dev/null +++ b/third_party/rust/num-traits/src/ops/checked.rs @@ -0,0 +1,277 @@ +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> { + /// 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> { + /// 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> { + /// 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> { + /// 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 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)); + /// assert_eq!(CheckedShl::checked_shl(&x, 15), Some(0x8000)); + /// assert_eq!(CheckedShl::checked_shl(&x, 16), None); + /// ``` + fn checked_shl(&self, rhs: u32) -> Option<Self>; +} + +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 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)); + /// assert_eq!(CheckedShr::checked_shr(&x, 15), Some(0x0001)); + /// assert_eq!(CheckedShr::checked_shr(&x, 16), None); + /// ``` + 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 index 0000000000..99b51279f5 --- /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 index 0000000000..7087d09d01 --- /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 new file mode 100644 index 0000000000..585879f6f2 --- /dev/null +++ b/third_party/rust/num-traits/src/ops/mod.rs @@ -0,0 +1,7 @@ +pub mod checked; +pub mod euclid; +pub mod inv; +pub mod mul_add; +pub mod overflowing; +pub mod saturating; +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 index 0000000000..c5835d3d00 --- /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 index 0000000000..56118a032b --- /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 new file mode 100644 index 0000000000..e39cfd7b6c --- /dev/null +++ b/third_party/rust/num-traits/src/ops/saturating.rs @@ -0,0 +1,137 @@ +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! 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) + } + } + )*} +} + +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 new file mode 100644 index 0000000000..265b8f3bbc --- /dev/null +++ b/third_party/rust/num-traits/src/ops/wrapping.rs @@ -0,0 +1,337 @@ +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) + } + } + }; + ($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> { + /// 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> { + /// 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> { + /// 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>>, +{ + 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>>, +{ + 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>>, +{ + 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_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)); +} + +#[test] +fn wrapping_is_wrappingsub() { + fn require_wrappingsub<T: WrappingSub>(_: &T) {} + 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 new file mode 100644 index 0000000000..8addc21121 --- /dev/null +++ b/third_party/rust/num-traits/src/pow.rs @@ -0,0 +1,262 @@ +use core::num::Wrapping; +use core::ops::Mul; +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(); + } + + while exp & 1 == 0 { + base = base.clone() * base; + exp >>= 1; + } + 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()); + } + + macro_rules! optry { + ($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); + } + + 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)); + } + } + Some(acc) +} diff --git a/third_party/rust/num-traits/src/real.rs b/third_party/rust/num-traits/src/real.rs new file mode 100644 index 0000000000..8b31cce3ff --- /dev/null +++ b/third_party/rust/num-traits/src/real.rs @@ -0,0 +1,834 @@ +#![cfg(any(feature = "std", feature = "libm"))] + +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, 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(); + /// + /// assert_eq!(x, f64::MIN); + /// ``` + fn min_value() -> Self; + + /// Returns the smallest positive, normalized value that this type can represent. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x: f64 = Real::min_positive_value(); + /// + /// assert_eq!(x, f64::MIN_POSITIVE); + /// ``` + fn min_positive_value() -> Self; + + /// Returns epsilon, a small positive value. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x: f64 = Real::epsilon(); + /// + /// assert_eq!(x, f64::EPSILON); + /// ``` + /// + /// # Panics + /// + /// The default implementation will panic if `f32::EPSILON` cannot + /// be cast to `Self`. + fn epsilon() -> Self; + + /// Returns the largest finite value that this type can represent. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x: f64 = Real::max_value(); + /// assert_eq!(x, f64::MAX); + /// ``` + fn max_value() -> Self; + + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 3.99; + /// let g = 3.0; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + fn floor(self) -> Self; + + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 3.01; + /// let g = 4.0; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + fn ceil(self) -> Self; + + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 3.3; + /// let g = -3.3; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + fn round(self) -> Self; + + /// Return the integer part of a number. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 3.3; + /// let g = -3.7; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + fn trunc(self) -> Self; + + /// Returns the fractional part of a number. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 3.5; + /// let y = -3.5; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + fn fract(self) -> Self; + + /// Computes the absolute value of `self`. Returns `Float::nan()` if the + /// number is `Float::nan()`. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = 3.5; + /// let y = -3.5; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(::num_traits::Float::is_nan(f64::NAN.abs())); + /// ``` + fn abs(self) -> Self; + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` + /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` + /// - `Float::nan()` if the number is `Float::nan()` + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let f = 3.5; + /// + /// 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`. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let neg_nan: f64 = -f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// 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`. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0; + /// let g = -7.0; + /// + /// 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, 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; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn mul_add(self, a: Self, b: Self) -> Self; + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 2.0; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn recip(self) -> Self; + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 2.0; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powi(self, n: i32) -> Self; + + /// Raise a number to a real number power. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 2.0; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powf(self, n: Self) -> Self; + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative floating-point number. + /// + /// # Panics + /// + /// If the implementing type doesn't support NaN, this method should panic if `self < 0`. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let positive = 4.0; + /// let negative = -4.0; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(::num_traits::Float::is_nan(negative.sqrt())); + /// ``` + fn sqrt(self) -> Self; + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp(self) -> Self; + + /// Returns `2^(self)`. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 2.0; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp2(self) -> Self; + + /// Returns the natural logarithm of the number. + /// + /// # Panics + /// + /// If `self <= 0` and this type does not support a NaN representation, this function should panic. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let one = 1.0; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn ln(self) -> Self; + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// # Panics + /// + /// If `self <= 0` and this type does not support a NaN representation, this function should panic. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let ten = 10.0; + /// let two = 2.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + fn log(self, base: Self) -> Self; + + /// Returns the base 2 logarithm of the number. + /// + /// # Panics + /// + /// If `self <= 0` and this type does not support a NaN representation, this function should panic. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let two = 2.0; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log2(self) -> Self; + + /// Returns the base 10 logarithm of the number. + /// + /// # Panics + /// + /// If `self <= 0` and this type does not support a NaN representation, this function should panic. + /// + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let ten = 10.0; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log10(self) -> Self; + + /// Converts radians to degrees. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn to_degrees(self) -> Self; + + /// Converts degrees to radians. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = 180.0_f64; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn to_radians(self) -> Self; + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.max(y), y); + /// ``` + fn max(self, other: Self) -> Self; + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 1.0; + /// let y = 2.0; + /// + /// assert_eq!(x.min(y), x); + /// ``` + fn min(self, other: Self) -> Self; + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 3.0; + /// let y = -3.0; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + fn abs_sub(self, other: Self) -> Self; + + /// Take the cubic root of a number. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 8.0; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cbrt(self) -> Self; + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 2.0; + /// let y = 3.0; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn hypot(self, other: Self) -> Self; + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sin(self) -> Self; + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cos(self) -> Self; + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + fn tan(self) -> Self; + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// # Panics + /// + /// If this type does not support a NaN representation, this function should panic + /// if the number is outside the range [-1, 1]. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn asin(self) -> Self; + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// # Panics + /// + /// If this type does not support a NaN representation, this function should panic + /// if the number is outside the range [-1, 1]. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn acos(self) -> Self; + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let f = 1.0; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn atan(self) -> Self; + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0; + /// let y1 = -3.0; + /// + /// // 135 deg clockwise + /// let x2 = -3.0; + /// let y2 = 3.0; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + fn atan2(self, other: Self) -> Self; + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + fn sin_cos(self) -> (Self, Self); + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 7.0; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp_m1(self) -> Self; + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// # Panics + /// + /// If this type does not support a NaN representation, this function should panic + /// if `self-1 <= 0`. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn ln_1p(self) -> Self; + + /// Hyperbolic sine function. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sinh(self) -> Self; + + /// Hyperbolic cosine function. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn cosh(self) -> Self; + + /// Hyperbolic tangent function. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn tanh(self) -> Self; + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 1.0; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn asinh(self) -> Self; + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use num_traits::real::Real; + /// + /// let x = 1.0; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn acosh(self) -> Self; + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use num_traits::real::Real; + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn atanh(self) -> Self; +} + +impl<T: Float> Real for T { + forward! { + Float::min_value() -> Self; + Float::min_positive_value() -> Self; + Float::epsilon() -> Self; + Float::max_value() -> Self; + } + 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 new file mode 100644 index 0000000000..5c32071c23 --- /dev/null +++ b/third_party/rust/num-traits/src/sign.rs @@ -0,0 +1,224 @@ +use core::num::Wrapping; +use core::ops::Neg; + +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`. + /// + /// For signed integers, `::MIN` will be returned if the number is `::MIN`. + fn abs(&self) -> Self; + + /// The positive difference of two numbers. + /// + /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference + /// between `self` and `other` is returned. + fn abs_sub(&self, other: &Self) -> Self; + + /// Returns the sign of the number. + /// + /// For `f32` and `f64`: + /// + /// * `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` + /// + /// For signed integers: + /// + /// * `0` if the number is zero + /// * `1` if the number is positive + /// * `-1` if the number is negative + fn signum(&self) -> Self; + + /// Returns true if the number is positive and false if the number is zero or negative. + fn is_positive(&self) -> bool; + + /// Returns true if the number is negative and false if the number is zero or positive. + fn is_negative(&self) -> bool; +} + +macro_rules! signed_impl { + ($($t:ty)*) => ($( + impl Signed for $t { + #[inline] + fn abs(&self) -> $t { + if self.is_negative() { -*self } else { *self } + } + + #[inline] + fn abs_sub(&self, other: &$t) -> $t { + if *self <= *other { 0 } else { *self - *other } + } + + #[inline] + fn signum(&self) -> $t { + match *self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + #[inline] + fn is_positive(&self) -> bool { *self > 0 } + + #[inline] + fn is_negative(&self) -> bool { *self < 0 } + } + )*) +} + +signed_impl!(isize i8 i16 i32 i64); + +#[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 { + Wrapping(self.0.abs_sub(&other.0)) + } + + #[inline] + fn signum(&self) -> Self { + Wrapping(self.0.signum()) + } + + #[inline] + fn is_positive(&self) -> bool { + self.0.is_positive() + } + + #[inline] + fn is_negative(&self) -> bool { + self.0.is_negative() + } +} + +macro_rules! signed_float_impl { + ($t:ty) => { + impl Signed for $t { + /// Computes the absolute value. Returns `NAN` if the number is `NAN`. + #[inline] + fn abs(&self) -> $t { + 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 + } + } + + /// # 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] + fn signum(&self) -> $t { + FloatCore::signum(*self) + } + + /// Returns `true` if the number is positive, including `+0.0` and `INFINITY` + #[inline] + 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 { + FloatCore::is_sign_negative(*self) + } + } + }; +} + +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 { + value.abs() +} + +/// The positive difference of two numbers. +/// +/// Returns zero if `x` is less than or equal to `y`, otherwise the difference +/// between `x` and `y` is returned. +#[inline(always)] +pub fn abs_sub<T: Signed>(x: T, y: T) -> T { + x.abs_sub(&y) +} + +/// Returns the sign of the number. +/// +/// For `f32` and `f64`: +/// +/// * `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` +/// +/// 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() +} + +/// 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)); +// } diff --git a/third_party/rust/num-traits/tests/cast.rs b/third_party/rust/num-traits/tests/cast.rs new file mode 100644 index 0000000000..69310d0748 --- /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); +} |