num-traits-0.2.19/.cargo_vcs_info.json0000644000000001360000000000100132300ustar { "git": { "sha1": "7ec3d41d39b28190ec1d42db38021107b3951f3a" }, "path_in_vcs": "" }num-traits-0.2.19/.gitignore000064400000000000000000000000221046102023000140020ustar 00000000000000Cargo.lock target num-traits-0.2.19/Cargo.toml0000644000000024200000000000100112240ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60" name = "num-traits" version = "0.2.19" authors = ["The Rust Project Developers"] build = "build.rs" exclude = [ "/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"] rustdoc-args = ["--generate-link-to-definition"] [dependencies.libm] version = "0.2.0" optional = true [build-dependencies.autocfg] version = "1" [features] default = ["std"] i128 = [] libm = ["dep:libm"] std = [] num-traits-0.2.19/Cargo.toml.orig000064400000000000000000000015031046102023000147060ustar 00000000000000[package] authors = ["The Rust Project Developers"] description = "Numeric traits for generic mathematics" documentation = "https://docs.rs/num-traits" homepage = "https://github.com/rust-num/num-traits" keywords = ["mathematics", "numerics"] categories = ["algorithms", "science", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-num/num-traits" name = "num-traits" version = "0.2.19" readme = "README.md" build = "build.rs" exclude = ["/ci/*", "/.github/*"] edition = "2021" rust-version = "1.60" [package.metadata.docs.rs] features = ["std"] rustdoc-args = ["--generate-link-to-definition"] [dependencies] libm = { version = "0.2.0", optional = true } [features] default = ["std"] libm = ["dep:libm"] std = [] # vestigial features, now always in effect i128 = [] [build-dependencies] autocfg = "1" num-traits-0.2.19/LICENSE-APACHE000064400000000000000000000251371046102023000137540ustar 00000000000000 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. num-traits-0.2.19/LICENSE-MIT000064400000000000000000000020571046102023000134600ustar 00000000000000Copyright (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. num-traits-0.2.19/README.md000064400000000000000000000034021046102023000132760ustar 00000000000000# 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.60](https://img.shields.io/badge/rustc-1.60+-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 `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`. ## Releases Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility The `num-traits` crate is tested for rustc 1.60 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. num-traits-0.2.19/RELEASES.md000064400000000000000000000307221046102023000135510ustar 00000000000000# Release 0.2.19 (2024-05-03) - [Upgrade to 2021 edition, **MSRV 1.60**][310] - [The new `Float::clamp` limits values by minimum and maximum][305] **Contributors**: @cuviper, @michaelciraci [305]: https://github.com/rust-num/num-traits/pull/305 [310]: https://github.com/rust-num/num-traits/pull/310 # Release 0.2.18 (2024-02-07) - [The new `Euclid::div_rem_euclid` and `CheckedEuclid::checked_div_rem_euclid` methods][291] compute and return the quotient and remainder at the same time. - [The new `TotalOrder` trait implements the IEEE 754 `totalOrder` predicate.][295] - [The new `ConstZero` and `ConstOne` traits offered associated constants][303], extending the non-const `Zero` and `One` traits for types that have constant values. **Contributors**: @andrewjradcliffe, @cuviper, @tarcieri, @tdelabro, @waywardmonkeys [291]: https://github.com/rust-num/num-traits/pull/291 [295]: https://github.com/rust-num/num-traits/pull/295 [303]: https://github.com/rust-num/num-traits/pull/303 # Release 0.2.17 (2023-10-07) - [Fix a doc warning about custom classes with newer rustdoc.][286] **Contributors**: @robamu [286]: https://github.com/rust-num/num-traits/pull/286 # Release 0.2.16 (2023-07-20) - [Upgrade to 2018 edition, **MSRV 1.31**][240] - [The new `ToBytes` and `FromBytes` traits][224] convert to and from byte representations of a value, with little, big, and native-endian options. - [The new `Float::is_subnormal` method checks for subnormal values][279], with a non-zero magnitude that is less than the normal minimum positive value. - Several other improvements to documentation and testing. **Contributors**: @ctrlcctrlv, @cuviper, @flier, @GuillaumeGomez, @kaidokert, @rs017991, @vicsn [224]: https://github.com/rust-num/num-traits/pull/224 [240]: https://github.com/rust-num/num-traits/pull/240 [279]: https://github.com/rust-num/num-traits/pull/279 # 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! num-traits-0.2.19/build.rs000064400000000000000000000002401046102023000134610ustar 00000000000000fn main() { let ac = autocfg::new(); ac.emit_expression_cfg("1f64.total_cmp(&2f64)", "has_total_cmp"); // 1.62 autocfg::rerun_path("build.rs"); } num-traits-0.2.19/src/bounds.rs000064400000000000000000000074361046102023000144610ustar 00000000000000use core::num::Wrapping; use core::{f32, f64}; use core::{i128, i16, i32, i64, i8, isize}; use core::{u128, 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 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 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); bounded_impl!(u128, u128::MIN, u128::MAX); bounded_impl!(isize, isize::MIN, isize::MAX); bounded_impl!(i8, i8::MIN, i8::MAX); bounded_impl!(i16, i16::MIN, i16::MAX); bounded_impl!(i32, i32::MIN, i32::MAX); bounded_impl!(i64, i64::MIN, i64::MAX); bounded_impl!(i128, i128::MIN, i128::MAX); impl Bounded for Wrapping { 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!( as Bounded>::min_value().0, <$t>::min_value()); assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); )+ }; } test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); } #[test] fn wrapping_bounded_i128() { macro_rules! test_wrapping_bounded { ($($t:ty)+) => { $( assert_eq!( as Bounded>::min_value().0, <$t>::min_value()); assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); )+ }; } test_wrapping_bounded!(u128 i128); } #[test] fn wrapping_is_bounded() { fn require_bounded(_: &T) {} require_bounded(&Wrapping(42_u32)); require_bounded(&Wrapping(-42)); } num-traits-0.2.19/src/cast.rs000064400000000000000000000624601046102023000141170ustar 00000000000000use core::mem::size_of; use core::num::Wrapping; use core::{f32, f64}; use core::{i128, i16, i32, i64, i8, isize}; use core::{u128, 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 { 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 { 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 { 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 { 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; /// 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. /// /// The default implementation converts through `to_i64()`. Types implementing /// this trait should override this method if they can represent a greater range. #[inline] fn to_i128(&self) -> Option { 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 { 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 { 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 { 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 { 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; /// 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. /// /// The default implementation converts through `to_u64()`. Types implementing /// this trait should override this method if they can represent a greater range. #[inline] fn to_u128(&self) -> Option { 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 { 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 { 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; 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; fn to_u128 -> u128; } #[inline] fn to_f32(&self) -> Option { Some(*self as f32) } #[inline] fn to_f64(&self) -> Option { 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); 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; 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; fn to_u128 -> u128; } #[inline] fn to_f32(&self) -> Option { Some(*self as f32) } #[inline] fn to_f64(&self) -> Option { 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); 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) } )*} } 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>() } }; } 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; 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; 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 { 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 { 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 { 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 { 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; /// Converts an `i128` to return an optional value of this type. If the /// value cannot be represented by this type, then `None` is returned. /// /// The default implementation converts through `from_i64()`. Types implementing /// this trait should override this method if they can represent a greater range. #[inline] fn from_i128(n: i128) -> Option { 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 { 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 { 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 { 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 { 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; /// Converts an `u128` to return an optional value of this type. If the /// value cannot be represented by this type, then `None` is returned. /// /// The default implementation converts through `from_u64()`. Types implementing /// this trait should override this method if they can represent a greater range. #[inline] fn from_u128(n: u128) -> Option { 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 { 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 { 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() } #[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() } #[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); impl_from_primitive!(i128, to_i128); impl_from_primitive!(usize, to_usize); impl_from_primitive!(u8, to_u8); impl_from_primitive!(u16, to_u16); impl_from_primitive!(u32, to_u32); impl_from_primitive!(u64, to_u64); impl_from_primitive!(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 ToPrimitive for Wrapping { impl_to_primitive_wrapping! { fn to_isize -> isize; fn to_i8 -> i8; fn to_i16 -> i16; fn to_i32 -> i32; fn to_i64 -> i64; fn to_i128 -> i128; fn to_usize -> usize; fn to_u8 -> u8; fn to_u16 -> u16; fn to_u32 -> u32; fn to_u64 -> u64; 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 { T::$method(n).map(Wrapping) } )*} } impl FromPrimitive for Wrapping { impl_from_primitive_wrapping! { fn from_isize(isize); fn from_i8(i8); fn from_i16(i16); fn from_i32(i32); fn from_i64(i64); fn from_i128(i128); fn from_usize(usize); fn from_u8(u8); fn from_u16(u16); fn from_u32(u32); fn from_u64(u64); 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(n: T) -> Option { 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(n: T) -> Option; } macro_rules! impl_num_cast { ($T:ty, $conv:ident) => { impl NumCast for $T { #[inline] #[allow(deprecated)] fn from(n: N) -> Option<$T> { // `$conv` could be generated using `concat_idents!`, but that // macro seems to be broken at the moment n.$conv() } } }; } impl_num_cast!(u8, to_u8); impl_num_cast!(u16, to_u16); impl_num_cast!(u32, to_u32); impl_num_cast!(u64, to_u64); impl_num_cast!(u128, to_u128); impl_num_cast!(usize, to_usize); impl_num_cast!(i8, to_i8); impl_num_cast!(i16, to_i16); impl_num_cast!(i32, to_i32); impl_num_cast!(i64, to_i64); impl_num_cast!(i128, to_i128); impl_num_cast!(isize, to_isize); impl_num_cast!(f32, to_f32); impl_num_cast!(f64, to_f64); impl NumCast for Wrapping { fn from(n: U) -> Option { 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: '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, u128, usize }); impl_as_primitive!(@ $T => { i8, i16, i32, i64, i128, isize }); }; } 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 }); impl_as_primitive!(u128 => { f32, f64 }); 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 => {}); num-traits-0.2.19/src/float.rs000064400000000000000000002112421046102023000142640ustar 00000000000000use core::cmp::Ordering; use core::num::FpCategory; use core::ops::{Add, Div, Neg}; use core::f32; use core::f64; use crate::{Num, NumCast, ToPrimitive}; /// 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 + PartialOrd + Copy { /// Returns positive infinity. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// /// fn check(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(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() { /// let n = T::nan(); /// assert!(n != n); /// } /// /// check::(); /// check::(); /// ``` fn nan() -> Self; /// Returns `-0.0`. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// /// fn check(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(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(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(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(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(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] #[allow(clippy::eq_op)] 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(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(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(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 `true` if the number is [subnormal]. /// /// ``` /// use num_traits::float::FloatCore; /// use std::f64; /// /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64 /// let max = f64::MAX; /// let lower_than_min = 1.0e-308_f64; /// let zero = 0.0_f64; /// /// assert!(!min.is_subnormal()); /// assert!(!max.is_subnormal()); /// /// assert!(!zero.is_subnormal()); /// assert!(!f64::NAN.is_subnormal()); /// assert!(!f64::INFINITY.is_subnormal()); /// // Values between `0` and `min` are Subnormal. /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Subnormal_number #[inline] fn is_subnormal(self) -> bool { self.classify() == FpCategory::Subnormal } /// 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(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(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(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(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(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(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(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(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 `FloatCore::nan()`. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// /// fn check(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, 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 `-FloatCore::nan()`. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// /// fn check(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); /// check(-f64::NAN, true); /// ``` #[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(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(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 } } /// 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)`. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// /// fn check(val: T, min: T, max: T, expected: T) { /// assert!(val.clamp(min, max) == expected); /// } /// /// /// check(1.0f32, 0.0, 2.0, 1.0); /// check(1.0f32, 2.0, 3.0, 2.0); /// check(3.0f32, 0.0, 2.0, 2.0); /// /// check(1.0f64, 0.0, 2.0, 1.0); /// check(1.0f64, 2.0, 3.0, 2.0); /// check(3.0f64, 0.0, 2.0, 2.0); /// ``` fn clamp(self, min: Self, max: Self) -> Self { crate::clamp(self, min, max) } /// Returns the reciprocal (multiplicative inverse) of the number. /// /// # Examples /// /// ``` /// use num_traits::float::FloatCore; /// use std::{f32, f64}; /// /// fn check(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(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(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(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(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) } forward! { Self::is_nan(self) -> bool; Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; Self::is_subnormal(self) -> bool; Self::clamp(self, min: Self, max: Self) -> Self; Self::classify(self) -> FpCategory; 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::to_degrees(self) -> Self; Self::to_radians(self) -> Self; } #[cfg(feature = "std")] forward! { 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::powi(self, n: i32) -> 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; } #[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) } forward! { Self::is_nan(self) -> bool; Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; Self::is_subnormal(self) -> bool; Self::clamp(self, min: Self, max: Self) -> Self; Self::classify(self) -> FpCategory; 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::to_degrees(self) -> Self; Self::to_radians(self) -> Self; } #[cfg(feature = "std")] forward! { 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::powi(self, n: i32) -> 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; } #[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 { /// 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/Subnormal_number fn is_normal(self) -> bool; /// Returns `true` if the number is [subnormal]. /// /// ``` /// use num_traits::Float; /// use std::f64; /// /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64 /// let max = f64::MAX; /// let lower_than_min = 1.0e-308_f64; /// let zero = 0.0_f64; /// /// assert!(!min.is_subnormal()); /// assert!(!max.is_subnormal()); /// /// assert!(!zero.is_subnormal()); /// assert!(!f64::NAN.is_subnormal()); /// assert!(!f64::INFINITY.is_subnormal()); /// // Values between `0` and `min` are Subnormal. /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Subnormal_number #[inline] fn is_subnormal(self) -> bool { self.classify() == FpCategory::Subnormal } /// 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 `Float::nan()`. /// /// ``` /// use num_traits::Float; /// use std::f64; /// /// let nan: f64 = f64::NAN; /// 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!(nan.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 `-Float::nan()`. /// /// ``` /// use num_traits::Float; /// use std::f64; /// /// let nan: f64 = f64::NAN; /// let neg_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()); /// assert!(neg_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; /// Clamps a value between a min and max. /// /// **Panics** in debug mode if `!(min <= max)`. /// /// ``` /// use num_traits::Float; /// /// let x = 1.0; /// let y = 2.0; /// let z = 3.0; /// /// assert_eq!(x.clamp(y, z), 2.0); /// ``` fn clamp(self, min: Self, max: Self) -> Self { crate::clamp(self, min, max) } /// 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::is_subnormal(self) -> bool; Self::classify(self) -> FpCategory; Self::clamp(self, min: Self, max: Self) -> Self; 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; Self::copysign(self, sign: Self) -> Self; } } }; } #[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! { Self::is_nan(self) -> bool; Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; Self::is_subnormal(self) -> bool; Self::clamp(self, min: Self, max: Self) -> Self; Self::classify(self) -> FpCategory; 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::to_degrees(self) -> Self; Self::to_radians(self) -> Self; } forward! { FloatCore::signum(self) -> Self; FloatCore::powi(self, n: i32) -> Self; } }; } fn integer_decode_f32(f: f32) -> (u64, i16, i8) { let bits: u32 = f.to_bits(); 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) { let bits: u64 = f.to_bits(); 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::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::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::PI() + Self::PI() } #[doc = "Return `log10(2.0)`."] #[inline] fn LOG10_2() -> Self where Self: Sized + Div { Self::LN_2() / Self::LN_10() } #[doc = "Return `log2(10.0)`."] #[inline] fn LOG2_10() -> Self where Self: Sized + Div { 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, } /// Trait for floating point numbers that provide an implementation /// of the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) /// floating point standard. pub trait TotalOrder { /// Return the ordering between `self` and `other`. /// /// Unlike the standard partial comparison between floating point numbers, /// this comparison always produces an ordering in accordance to /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) /// floating point standard. The values are ordered in the following sequence: /// /// - negative quiet NaN /// - negative signaling NaN /// - negative infinity /// - negative numbers /// - negative subnormal numbers /// - negative zero /// - positive zero /// - positive subnormal numbers /// - positive numbers /// - positive infinity /// - positive signaling NaN /// - positive quiet NaN. /// /// The ordering established by this function does not always agree with the /// [`PartialOrd`] and [`PartialEq`] implementations. For example, /// they consider negative and positive zero equal, while `total_cmp` /// doesn't. /// /// The interpretation of the signaling NaN bit follows the definition in /// the IEEE 754 standard, which may not match the interpretation by some of /// the older, non-conformant (e.g. MIPS) hardware implementations. /// /// # Examples /// ``` /// use num_traits::float::TotalOrder; /// use std::cmp::Ordering; /// use std::{f32, f64}; /// /// fn check_eq(x: T, y: T) { /// assert_eq!(x.total_cmp(&y), Ordering::Equal); /// } /// /// check_eq(f64::NAN, f64::NAN); /// check_eq(f32::NAN, f32::NAN); /// /// fn check_lt(x: T, y: T) { /// assert_eq!(x.total_cmp(&y), Ordering::Less); /// } /// /// check_lt(-f64::NAN, f64::NAN); /// check_lt(f64::INFINITY, f64::NAN); /// check_lt(-0.0_f64, 0.0_f64); /// ``` fn total_cmp(&self, other: &Self) -> Ordering; } macro_rules! totalorder_impl { ($T:ident, $I:ident, $U:ident, $bits:expr) => { impl TotalOrder for $T { #[inline] #[cfg(has_total_cmp)] fn total_cmp(&self, other: &Self) -> Ordering { // Forward to the core implementation Self::total_cmp(&self, other) } #[inline] #[cfg(not(has_total_cmp))] fn total_cmp(&self, other: &Self) -> Ordering { // Backport the core implementation (since 1.62) let mut left = self.to_bits() as $I; let mut right = other.to_bits() as $I; left ^= (((left >> ($bits - 1)) as $U) >> 1) as $I; right ^= (((right >> ($bits - 1)) as $U) >> 1) as $I; left.cmp(&right) } } }; } totalorder_impl!(f64, i64, u64, 64); totalorder_impl!(f32, i32, u32, 32); #[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 crate::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 crate::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] fn to_degrees_rounding() { use crate::float::FloatCore; assert_eq!( FloatCore::to_degrees(1_f32), 57.2957795130823208767981548141051703 ); } #[test] #[cfg(any(feature = "std", feature = "libm"))] fn extra_logs() { use crate::float::{Float, FloatConst}; fn check(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::(1e-6); check::(1e-12); } #[test] #[cfg(any(feature = "std", feature = "libm"))] fn copysign() { use crate::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 crate::float::Float; use core::ops::Neg; 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)); 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(p: F, n: F, nan: F) { assert!(p.is_sign_positive()); assert!(n.is_sign_negative()); assert!(nan.is_nan()); assert!(!nan.is_subnormal()); 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)); assert!(nan.copysign(p).is_sign_positive()); assert!(nan.copysign(n).is_sign_negative()); } #[cfg(any(feature = "std", feature = "libm"))] fn test_subnormal() { let min_positive = F::min_positive_value(); let lower_than_min = min_positive / F::from(2.0f32).unwrap(); assert!(!min_positive.is_subnormal()); assert!(lower_than_min.is_subnormal()); } #[test] #[cfg(any(feature = "std", feature = "libm"))] fn subnormal() { test_subnormal::(); test_subnormal::(); } #[test] fn total_cmp() { use crate::float::TotalOrder; use core::cmp::Ordering; use core::{f32, f64}; fn check_eq(x: T, y: T) { assert_eq!(x.total_cmp(&y), Ordering::Equal); } fn check_lt(x: T, y: T) { assert_eq!(x.total_cmp(&y), Ordering::Less); } fn check_gt(x: T, y: T) { assert_eq!(x.total_cmp(&y), Ordering::Greater); } check_eq(f64::NAN, f64::NAN); check_eq(f32::NAN, f32::NAN); check_lt(-0.0_f64, 0.0_f64); check_lt(-0.0_f32, 0.0_f32); // x87 registers don't preserve the exact value of signaling NaN: // https://github.com/rust-lang/rust/issues/115567 #[cfg(not(target_arch = "x86"))] { let s_nan = f64::from_bits(0x7ff4000000000000); let q_nan = f64::from_bits(0x7ff8000000000000); check_lt(s_nan, q_nan); let neg_s_nan = f64::from_bits(0xfff4000000000000); let neg_q_nan = f64::from_bits(0xfff8000000000000); check_lt(neg_q_nan, neg_s_nan); let s_nan = f32::from_bits(0x7fa00000); let q_nan = f32::from_bits(0x7fc00000); check_lt(s_nan, q_nan); let neg_s_nan = f32::from_bits(0xffa00000); let neg_q_nan = f32::from_bits(0xffc00000); check_lt(neg_q_nan, neg_s_nan); } check_lt(-f64::NAN, f64::NEG_INFINITY); check_gt(1.0_f64, -f64::NAN); check_lt(f64::INFINITY, f64::NAN); check_gt(f64::NAN, 1.0_f64); check_lt(-f32::NAN, f32::NEG_INFINITY); check_gt(1.0_f32, -f32::NAN); check_lt(f32::INFINITY, f32::NAN); check_gt(f32::NAN, 1.0_f32); } } num-traits-0.2.19/src/identities.rs000064400000000000000000000125001046102023000153140ustar 00000000000000use 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 { /// 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; } /// Defines an associated constant representing the additive identity element /// for `Self`. pub trait ConstZero: Zero { /// The additive identity element of `Self`, `0`. const ZERO: Self; } 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 } } impl ConstZero for $t { const ZERO: Self = $v; } }; } zero_impl!(usize, 0); zero_impl!(u8, 0); zero_impl!(u16, 0); zero_impl!(u32, 0); zero_impl!(u64, 0); zero_impl!(u128, 0); zero_impl!(isize, 0); zero_impl!(i8, 0); zero_impl!(i16, 0); zero_impl!(i32, 0); zero_impl!(i64, 0); zero_impl!(i128, 0); zero_impl!(f32, 0.0); zero_impl!(f64, 0.0); impl Zero for Wrapping where Wrapping: Add>, { fn is_zero(&self) -> bool { self.0.is_zero() } fn set_zero(&mut self) { self.0.set_zero(); } fn zero() -> Self { Wrapping(T::zero()) } } impl ConstZero for Wrapping where Wrapping: Add>, { const 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 { /// 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() } } /// Defines an associated constant representing the multiplicative identity /// element for `Self`. pub trait ConstOne: One { /// The multiplicative identity element of `Self`, `1`. const ONE: Self; } 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 } } impl ConstOne for $t { const ONE: Self = $v; } }; } one_impl!(usize, 1); one_impl!(u8, 1); one_impl!(u16, 1); one_impl!(u32, 1); one_impl!(u64, 1); one_impl!(u128, 1); one_impl!(isize, 1); one_impl!(i8, 1); one_impl!(i16, 1); one_impl!(i32, 1); one_impl!(i64, 1); one_impl!(i128, 1); one_impl!(f32, 1.0); one_impl!(f64, 1.0); impl One for Wrapping where Wrapping: Mul>, { fn set_one(&mut self) { self.0.set_one(); } fn one() -> Self { Wrapping(T::one()) } } impl ConstOne for Wrapping where Wrapping: Mul>, { const ONE: Self = Wrapping(T::ONE); } // Some helper functions provided for backwards compatibility. /// Returns the additive identity, `0`. #[inline(always)] pub fn zero() -> T { Zero::zero() } /// Returns the multiplicative identity, `1`. #[inline(always)] pub fn one() -> T { One::one() } #[test] fn wrapping_identities() { macro_rules! test_wrapping_identities { ($($t:ty)+) => { $( assert_eq!(zero::<$t>(), zero::>().0); assert_eq!(one::<$t>(), one::>().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) {} require_zero(&Wrapping(42)); } #[test] fn wrapping_is_one() { fn require_one(_: &T) {} require_one(&Wrapping(42)); } num-traits-0.2.19/src/int.rs000064400000000000000000000366521046102023000137630ustar 00000000000000use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use crate::bounds::Bounded; use crate::ops::checked::*; use crate::ops::saturating::Saturating; use crate::{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 + BitAnd + BitOr + BitXor + Shl + Shr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + 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 { // 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(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) } #[inline] fn leading_ones(self) -> u32 { <$T>::leading_ones(self) } #[inline] fn leading_zeros(self) -> u32 { <$T>::leading_zeros(self) } #[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) } #[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); prim_int_impl!(u128, i128, u128); prim_int_impl!(usize, isize, usize); prim_int_impl!(i8, i8, u8); prim_int_impl!(i16, i16, u16); prim_int_impl!(i32, i32, u32); prim_int_impl!(i64, i64, u64); prim_int_impl!(i128, i128, u128); prim_int_impl!(isize, isize, usize); #[cfg(test)] mod tests { use crate::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] 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); } } num-traits-0.2.19/src/lib.rs000064400000000000000000000524201046102023000137260ustar 00000000000000// 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 or the MIT license // , 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.60 and greater. #![doc(html_root_url = "https://docs.rs/num-traits/0.2")] #![deny(unconditional_recursion)] #![no_std] // Need to explicitly bring the crate in for inherent float methods #[cfg(feature = "std")] extern crate std; 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 crate::bounds::Bounded; #[cfg(any(feature = "std", feature = "libm"))] pub use crate::float::Float; pub use crate::float::FloatConst; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use crate::cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; pub use crate::identities::{one, zero, ConstOne, ConstZero, One, Zero}; pub use crate::int::PrimInt; pub use crate::ops::bytes::{FromBytes, ToBytes}; pub use crate::ops::checked::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, }; pub use crate::ops::euclid::{CheckedEuclid, Euclid}; pub use crate::ops::inv::Inv; pub use crate::ops::mul_add::{MulAdd, MulAddAssign}; pub use crate::ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; pub use crate::ops::wrapping::{ WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, }; pub use crate::pow::{checked_pow, pow, Pow}; pub use crate::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 = ::from_str_radix("27", 10); /// assert_eq!(result, Ok(27)); /// /// let result = ::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; } /// Generic trait for types implementing basic numeric operations /// /// This is automatically implemented for types which implement the operators. pub trait NumOps: Add + Sub + Mul + Div + Rem { } impl NumOps for T where T: Add + Sub + Mul + Div + Rem { } /// 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 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: NumOps + for<'r> NumOps<&'r Base, Base> {} impl RefNum for T where T: NumOps + 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: AddAssign + SubAssign + MulAssign + DivAssign + RemAssign { } impl NumAssignOps for T where T: AddAssign + SubAssign + MulAssign + DivAssign + RemAssign { } /// 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 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 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 { <$t>::from_str_radix(s, radix) } } )*) } int_trait_impl!(Num for usize u8 u16 u32 u64 u128); int_trait_impl!(Num for isize i8 i16 i32 i64 i128); impl Num for Wrapping where Wrapping: NumOps, { type FromStrRadixErr = T::FromStrRadixErr; fn from_str_radix(str: &str, radix: u32) -> Result { 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 { 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(); Some((chars.next()?, chars.as_str())) } 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 *= radix as $t; // add/subtract current digit depending on sign if is_positive { sig += (digit as isize) as $t; } else { 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 /= 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::()), Some(('+', src)) => (true, src.parse::()), Some((_, _)) => (true, src.parse::()), 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(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] #[allow(clippy::eq_op)] pub fn clamp_min(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] #[allow(clippy::eq_op)] pub fn clamp_max(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) {} 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(x: T, y: T) -> T { x * y / y % y + y - y } assert_eq!(compute(1, 2), 1) } #[test] fn check_numref_ops() { fn compute(x: T, y: &T) -> T { x * y / y % y + y - y } assert_eq!(compute(1, &2), 1) } #[test] fn check_refnum_ops() { fn compute(x: &T, y: T) -> T where for<'a> &'a T: RefNum, { &(&(&(&(x * y) / y) % y) + y) - y } assert_eq!(compute(&1, 2), 1) } #[test] fn check_refref_ops() { fn compute(x: &T, y: &T) -> T where for<'a> &'a T: RefNum, { &(&(&(&(x * y) / y) % y) + y) - y } assert_eq!(compute(&1, &2), 1) } #[test] fn check_numassign_ops() { fn compute(mut x: T, y: T) -> T { x *= y; x /= y; x %= y; x += y; x -= y; x } assert_eq!(compute(1, 2), 1) } #[test] fn check_numassignref_ops() { fn compute(mut x: T, y: &T) -> T { x *= y; x /= y; x %= y; x += y; x -= y; x } assert_eq!(compute(1, &2), 1) } num-traits-0.2.19/src/macros.rs000064400000000000000000000025651046102023000144510ustar 00000000000000// 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 { ::$method(self $( , $arg )* ) } )*}; ($( $base:ident :: $method:ident ( $( $arg:ident : $ty:ty ),* ) -> $ret:ty ; )*) => {$( #[inline] fn $method( $( $arg : $ty ),* ) -> $ret { ::$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 } )*}; } num-traits-0.2.19/src/ops/bytes.rs000064400000000000000000000212011046102023000151000ustar 00000000000000use core::borrow::{Borrow, BorrowMut}; use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; use core::fmt::Debug; use core::hash::Hash; pub trait NumBytes: Debug + AsRef<[u8]> + AsMut<[u8]> + PartialEq + Eq + PartialOrd + Ord + Hash + Borrow<[u8]> + BorrowMut<[u8]> { } impl NumBytes for T where T: Debug + AsRef<[u8]> + AsMut<[u8]> + PartialEq + Eq + PartialOrd + Ord + Hash + Borrow<[u8]> + BorrowMut<[u8]> + ?Sized { } pub trait ToBytes { type Bytes: NumBytes; /// Return the memory representation of this number as a byte array in big-endian byte order. /// /// # Examples /// /// ``` /// use num_traits::ToBytes; /// /// let bytes = ToBytes::to_be_bytes(&0x12345678u32); /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); /// ``` fn to_be_bytes(&self) -> Self::Bytes; /// Return the memory representation of this number as a byte array in little-endian byte order. /// /// # Examples /// /// ``` /// use num_traits::ToBytes; /// /// let bytes = ToBytes::to_le_bytes(&0x12345678u32); /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); /// ``` fn to_le_bytes(&self) -> Self::Bytes; /// Return the memory representation of this number as a byte array in native byte order. /// /// As the target platform's native endianness is used, /// portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. /// /// [`to_be_bytes`]: #method.to_be_bytes /// [`to_le_bytes`]: #method.to_le_bytes /// /// # Examples /// /// ``` /// use num_traits::ToBytes; /// /// #[cfg(target_endian = "big")] /// let expected = [0x12, 0x34, 0x56, 0x78]; /// /// #[cfg(target_endian = "little")] /// let expected = [0x78, 0x56, 0x34, 0x12]; /// /// let bytes = ToBytes::to_ne_bytes(&0x12345678u32); /// assert_eq!(bytes, expected) /// ``` fn to_ne_bytes(&self) -> Self::Bytes { #[cfg(target_endian = "big")] let bytes = self.to_be_bytes(); #[cfg(target_endian = "little")] let bytes = self.to_le_bytes(); bytes } } pub trait FromBytes: Sized { type Bytes: NumBytes + ?Sized; /// Create a number from its representation as a byte array in big endian. /// /// # Examples /// /// ``` /// use num_traits::FromBytes; /// /// let value: u32 = FromBytes::from_be_bytes(&[0x12, 0x34, 0x56, 0x78]); /// assert_eq!(value, 0x12345678); /// ``` fn from_be_bytes(bytes: &Self::Bytes) -> Self; /// Create a number from its representation as a byte array in little endian. /// /// # Examples /// /// ``` /// use num_traits::FromBytes; /// /// let value: u32 = FromBytes::from_le_bytes(&[0x78, 0x56, 0x34, 0x12]); /// assert_eq!(value, 0x12345678); /// ``` fn from_le_bytes(bytes: &Self::Bytes) -> Self; /// Create a number from its memory representation as a byte array in native endianness. /// /// As the target platform's native endianness is used, /// portable code likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as appropriate instead. /// /// [`from_be_bytes`]: #method.from_be_bytes /// [`from_le_bytes`]: #method.from_le_bytes /// /// # Examples /// /// ``` /// use num_traits::FromBytes; /// /// #[cfg(target_endian = "big")] /// let bytes = [0x12, 0x34, 0x56, 0x78]; /// /// #[cfg(target_endian = "little")] /// let bytes = [0x78, 0x56, 0x34, 0x12]; /// /// let value: u32 = FromBytes::from_ne_bytes(&bytes); /// assert_eq!(value, 0x12345678) /// ``` fn from_ne_bytes(bytes: &Self::Bytes) -> Self { #[cfg(target_endian = "big")] let this = Self::from_be_bytes(bytes); #[cfg(target_endian = "little")] let this = Self::from_le_bytes(bytes); this } } macro_rules! float_to_from_bytes_impl { ($T:ty, $L:expr) => { impl ToBytes for $T { type Bytes = [u8; $L]; #[inline] fn to_be_bytes(&self) -> Self::Bytes { <$T>::to_be_bytes(*self) } #[inline] fn to_le_bytes(&self) -> Self::Bytes { <$T>::to_le_bytes(*self) } #[inline] fn to_ne_bytes(&self) -> Self::Bytes { <$T>::to_ne_bytes(*self) } } impl FromBytes for $T { type Bytes = [u8; $L]; #[inline] fn from_be_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_be_bytes(*bytes) } #[inline] fn from_le_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_le_bytes(*bytes) } #[inline] fn from_ne_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_ne_bytes(*bytes) } } }; } macro_rules! int_to_from_bytes_impl { ($T:ty, $L:expr) => { impl ToBytes for $T { type Bytes = [u8; $L]; #[inline] fn to_be_bytes(&self) -> Self::Bytes { <$T>::to_be_bytes(*self) } #[inline] fn to_le_bytes(&self) -> Self::Bytes { <$T>::to_le_bytes(*self) } #[inline] fn to_ne_bytes(&self) -> Self::Bytes { <$T>::to_ne_bytes(*self) } } impl FromBytes for $T { type Bytes = [u8; $L]; #[inline] fn from_be_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_be_bytes(*bytes) } #[inline] fn from_le_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_le_bytes(*bytes) } #[inline] fn from_ne_bytes(bytes: &Self::Bytes) -> Self { <$T>::from_ne_bytes(*bytes) } } }; } int_to_from_bytes_impl!(u8, 1); int_to_from_bytes_impl!(u16, 2); int_to_from_bytes_impl!(u32, 4); int_to_from_bytes_impl!(u64, 8); int_to_from_bytes_impl!(u128, 16); #[cfg(target_pointer_width = "64")] int_to_from_bytes_impl!(usize, 8); #[cfg(target_pointer_width = "32")] int_to_from_bytes_impl!(usize, 4); int_to_from_bytes_impl!(i8, 1); int_to_from_bytes_impl!(i16, 2); int_to_from_bytes_impl!(i32, 4); int_to_from_bytes_impl!(i64, 8); int_to_from_bytes_impl!(i128, 16); #[cfg(target_pointer_width = "64")] int_to_from_bytes_impl!(isize, 8); #[cfg(target_pointer_width = "32")] int_to_from_bytes_impl!(isize, 4); float_to_from_bytes_impl!(f32, 4); float_to_from_bytes_impl!(f64, 8); #[cfg(test)] mod tests { use super::*; macro_rules! check_to_from_bytes { ($( $ty:ty )+) => {$({ let n = 1; let be = <$ty as ToBytes>::to_be_bytes(&n); let le = <$ty as ToBytes>::to_le_bytes(&n); let ne = <$ty as ToBytes>::to_ne_bytes(&n); assert_eq!(*be.last().unwrap(), 1); assert_eq!(*le.first().unwrap(), 1); if cfg!(target_endian = "big") { assert_eq!(*ne.last().unwrap(), 1); } else { assert_eq!(*ne.first().unwrap(), 1); } assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n); assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n); if cfg!(target_endian = "big") { assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n); } else { assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n); } })+} } #[test] fn convert_between_int_and_bytes() { check_to_from_bytes!(u8 u16 u32 u64 u128 usize); check_to_from_bytes!(i8 i16 i32 i64 i128 isize); } #[test] fn convert_between_float_and_bytes() { macro_rules! check_to_from_bytes { ($( $ty:ty )+) => {$( let n: $ty = 3.14; let be = <$ty as ToBytes>::to_be_bytes(&n); let le = <$ty as ToBytes>::to_le_bytes(&n); let ne = <$ty as ToBytes>::to_ne_bytes(&n); assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n); assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n); if cfg!(target_endian = "big") { assert_eq!(ne, be); assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n); } else { assert_eq!(ne, le); assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n); } )+} } check_to_from_bytes!(f32 f64); } } num-traits-0.2.19/src/ops/checked.rs000064400000000000000000000234701046102023000153520ustar 00000000000000use 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 { /// Adds two numbers, checking for overflow. If overflow happens, `None` is /// returned. fn checked_add(&self, v: &Self) -> Option; } 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); 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); checked_impl!(CheckedAdd, checked_add, i128); /// Performs subtraction that returns `None` instead of wrapping around on underflow. pub trait CheckedSub: Sized + Sub { /// Subtracts two numbers, checking for underflow. If underflow happens, /// `None` is returned. fn checked_sub(&self, v: &Self) -> Option; } 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); 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); checked_impl!(CheckedSub, checked_sub, i128); /// Performs multiplication that returns `None` instead of wrapping around on underflow or /// overflow. pub trait CheckedMul: Sized + Mul { /// Multiplies two numbers, checking for underflow or overflow. If underflow /// or overflow happens, `None` is returned. fn checked_mul(&self, v: &Self) -> Option; } 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); 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); 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 { /// 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; } 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); 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); 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 { /// 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; } 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); 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); 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; } 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); 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); checked_impl_unary!(CheckedNeg, checked_neg, i128); /// Performs a left shift that returns `None` on shifts larger than /// or equal to the type width. pub trait CheckedShl: Sized + Shl { /// 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; } 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); 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); checked_shift_impl!(CheckedShl, checked_shl, i128); /// Performs a right shift that returns `None` on shifts larger than /// or equal to the type width. pub trait CheckedShr: Sized + Shr { /// 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; } 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); 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); checked_shift_impl!(CheckedShr, checked_shr, i128); num-traits-0.2.19/src/ops/euclid.rs000064400000000000000000000222401046102023000152230ustar 00000000000000use core::ops::{Div, Rem}; pub trait Euclid: Sized + Div + Rem { /// 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; /// Returns both the quotient and remainder from Euclidean division. /// /// By default, it internally calls both `Euclid::div_euclid` and `Euclid::rem_euclid`, /// but it can be overridden in order to implement some optimization. /// /// # Examples /// /// ``` /// # use num_traits::Euclid; /// let x = 5u8; /// let y = 3u8; /// /// let div = Euclid::div_euclid(&x, &y); /// let rem = Euclid::rem_euclid(&x, &y); /// /// assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y)); /// ``` fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { (self.div_euclid(v), self.rem_euclid(v)) } } macro_rules! euclid_forward_impl { ($($t:ty)*) => {$( 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) } } )*} } euclid_forward_impl!(isize i8 i16 i32 i64 i128); euclid_forward_impl!(usize u8 u16 u32 u64 u128); #[cfg(feature = "std")] euclid_forward_impl!(f32 f64); #[cfg(not(feature = "std"))] impl Euclid for f32 { #[inline] fn div_euclid(&self, v: &f32) -> f32 { let q = ::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 + ::abs(*v) } else { r } } } #[cfg(not(feature = "std"))] impl Euclid for f64 { #[inline] fn div_euclid(&self, v: &f64) -> f64 { let q = ::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 + ::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; /// 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; /// Returns both the quotient and remainder from checked Euclidean division. /// /// By default, it internally calls both `CheckedEuclid::checked_div_euclid` and `CheckedEuclid::checked_rem_euclid`, /// but it can be overridden in order to implement some optimization. /// # Examples /// /// ``` /// # use num_traits::CheckedEuclid; /// let x = 5u8; /// let y = 3u8; /// /// let div = CheckedEuclid::checked_div_euclid(&x, &y); /// let rem = CheckedEuclid::checked_rem_euclid(&x, &y); /// /// assert_eq!(Some((div.unwrap(), rem.unwrap())), CheckedEuclid::checked_div_rem_euclid(&x, &y)); /// ``` fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { Some((self.checked_div_euclid(v)?, self.checked_rem_euclid(v)?)) } } macro_rules! checked_euclid_forward_impl { ($($t:ty)*) => {$( impl CheckedEuclid for $t { #[inline] fn checked_div_euclid(&self, v: &$t) -> Option { <$t>::checked_div_euclid(*self, *v) } #[inline] fn checked_rem_euclid(&self, v: &$t) -> Option { <$t>::checked_rem_euclid(*self, *v) } } )*} } checked_euclid_forward_impl!(isize i8 i16 i32 i64 i128); checked_euclid_forward_impl!(usize u8 u16 u32 u64 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; let div = Euclid::div_euclid(&x, &y); let rem = Euclid::rem_euclid(&x, &y); assert_eq!(div, 3); assert_eq!(rem, 1); assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y)); } )+ }; } 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); assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y)); 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 i128); } #[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 crate::float::FloatCore>::epsilon()); assert!(Euclid::div_euclid(&x, &-y) * -y + Euclid::rem_euclid(&x, &-y) - x <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); assert!(Euclid::div_euclid(&-x, &y) * y + Euclid::rem_euclid(&-x, &y) + x <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y)); } )+ }; } 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 i128); } } num-traits-0.2.19/src/ops/inv.rs000064400000000000000000000016431046102023000145560ustar 00000000000000/// 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 } } num-traits-0.2.19/src/ops/mod.rs000064400000000000000000000002111046102023000145270ustar 00000000000000pub mod bytes; pub mod checked; pub mod euclid; pub mod inv; pub mod mul_add; pub mod overflowing; pub mod saturating; pub mod wrapping; num-traits-0.2.19/src/ops/mul_add.rs000064400000000000000000000076171046102023000153760ustar 00000000000000/// 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 { /// The resulting type after applying the fused multiply-add. type Output; /// Performs the fused multiply-add operation `(self * a) + b` fn mul_add(self, a: A, b: B) -> Self::Output; } /// The fused multiply-add assignment operation `*self = (*self * a) + b` pub trait MulAddAssign { /// Performs the fused multiply-add assignment operation `*self = (*self * a) + b` fn mul_add_assign(&mut self, a: A, b: B); } #[cfg(any(feature = "std", feature = "libm"))] impl MulAdd for f32 { type Output = Self; #[inline] fn mul_add(self, a: Self, b: Self) -> Self::Output { ::mul_add(self, a, b) } } #[cfg(any(feature = "std", feature = "libm"))] impl MulAdd for f64 { type Output = Self; #[inline] fn mul_add(self, a: Self, b: Self) -> Self::Output { ::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 i8 i16 i32 i64 i128); mul_add_impl!(MulAdd for usize u8 u16 u32 u64 u128); #[cfg(any(feature = "std", feature = "libm"))] impl MulAddAssign for f32 { #[inline] fn mul_add_assign(&mut self, a: Self, b: Self) { *self = ::mul_add(*self, a, b) } } #[cfg(any(feature = "std", feature = "libm"))] impl MulAddAssign for f64 { #[inline] fn mul_add_assign(&mut self, a: Self, b: Self) { *self = ::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 i8 i16 i32 i64 i128); mul_add_assign_impl!(MulAddAssign for usize u8 u16 u32 u64 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); } } num-traits-0.2.19/src/ops/overflowing.rs000064400000000000000000000102731046102023000163220ustar 00000000000000use core::ops::{Add, Mul, Sub}; use core::{i128, i16, i32, i64, i8, isize}; use core::{u128, 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 { /// 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); 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); overflowing_impl!(OverflowingAdd, overflowing_add, i128); /// Performs substraction with a flag for overflow. pub trait OverflowingSub: Sized + Sub { /// 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); 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); overflowing_impl!(OverflowingSub, overflowing_sub, i128); /// Performs multiplication with a flag for overflow. pub trait OverflowingMul: Sized + Mul { /// 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); 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); overflowing_impl!(OverflowingMul, overflowing_mul, i128); #[test] fn test_overflowing_traits() { fn overflowing_add(a: T, b: T) -> (T, bool) { a.overflowing_add(&b) } fn overflowing_sub(a: T, b: T) -> (T, bool) { a.overflowing_sub(&b) } fn overflowing_mul(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)); } num-traits-0.2.19/src/ops/saturating.rs000064400000000000000000000117571046102023000161520ustar 00000000000000use 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 i8 i16 i32 i64 i128); deprecated_saturating_impl!(Saturating for usize u8 u16 u32 u64 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 { /// 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); 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); saturating_impl!(SaturatingAdd, saturating_add, i128); /// Performs subtraction that saturates at the numeric bounds instead of overflowing. pub trait SaturatingSub: Sized + Sub { /// 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); 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); saturating_impl!(SaturatingSub, saturating_sub, i128); /// Performs multiplication that saturates at the numeric bounds instead of overflowing. pub trait SaturatingMul: Sized + Mul { /// 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); 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); 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(a: T, b: T) -> T { a.saturating_add(&b) } fn saturating_sub(a: T, b: T) -> T { a.saturating_sub(&b) } fn saturating_mul(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); } num-traits-0.2.19/src/ops/wrapping.rs000064400000000000000000000257741046102023000156240ustar 00000000000000use 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 { /// 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); 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); wrapping_impl!(WrappingAdd, wrapping_add, i128); /// Performs subtraction that wraps around on overflow. pub trait WrappingSub: Sized + Sub { /// 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); 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); wrapping_impl!(WrappingSub, wrapping_sub, i128); /// Performs multiplication that wraps around on overflow. pub trait WrappingMul: Sized + Mul { /// 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); 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); 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); 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); 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 { /// 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); 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); wrapping_shift_impl!(WrappingShl, wrapping_shl, i128); /// Performs a right shift that does not panic. pub trait WrappingShr: Sized + Shr { /// 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); 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); wrapping_shift_impl!(WrappingShr, wrapping_shr, i128); // Well this is a bit funny, but all the more appropriate. impl WrappingAdd for Wrapping where Wrapping: Add>, { fn wrapping_add(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_add(&v.0)) } } impl WrappingSub for Wrapping where Wrapping: Sub>, { fn wrapping_sub(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_sub(&v.0)) } } impl WrappingMul for Wrapping where Wrapping: Mul>, { fn wrapping_mul(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_mul(&v.0)) } } impl WrappingNeg for Wrapping where Wrapping: Neg>, { fn wrapping_neg(&self) -> Self { Wrapping(self.0.wrapping_neg()) } } impl WrappingShl for Wrapping where Wrapping: Shl>, { fn wrapping_shl(&self, rhs: u32) -> Self { Wrapping(self.0.wrapping_shl(rhs)) } } impl WrappingShr for Wrapping where Wrapping: Shr>, { fn wrapping_shr(&self, rhs: u32) -> Self { Wrapping(self.0.wrapping_shr(rhs)) } } #[test] fn test_wrapping_traits() { fn wrapping_add(a: T, b: T) -> T { a.wrapping_add(&b) } fn wrapping_sub(a: T, b: T) -> T { a.wrapping_sub(&b) } fn wrapping_mul(a: T, b: T) -> T { a.wrapping_mul(&b) } fn wrapping_neg(a: T) -> T { a.wrapping_neg() } fn wrapping_shl(a: T, b: u32) -> T { a.wrapping_shl(b) } fn wrapping_shr(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); assert_eq!(wrapping_neg(255), (-Wrapping(255u8)).0); 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) {} require_wrappingadd(&Wrapping(42)); } #[test] fn wrapping_is_wrappingsub() { fn require_wrappingsub(_: &T) {} require_wrappingsub(&Wrapping(42)); } #[test] fn wrapping_is_wrappingmul() { fn require_wrappingmul(_: &T) {} require_wrappingmul(&Wrapping(42)); } #[test] fn wrapping_is_wrappingneg() { fn require_wrappingneg(_: &T) {} require_wrappingneg(&Wrapping(42)); } #[test] fn wrapping_is_wrappingshl() { fn require_wrappingshl(_: &T) {} require_wrappingshl(&Wrapping(42)); } #[test] fn wrapping_is_wrappingshr() { fn require_wrappingshr(_: &T) {} require_wrappingshr(&Wrapping(42)); } num-traits-0.2.19/src/pow.rs000064400000000000000000000146561046102023000137760ustar 00000000000000use crate::{CheckedMul, One}; use core::num::Wrapping; use core::ops::Mul; /// Binary operator for raising a value to a power. pub trait Pow { /// 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); pow_impl!(u128, u8, u32, u128::pow); pow_impl!(u128, u16, u32, u128::pow); pow_impl!(u128, u32, u32, u128::pow); pow_impl!(u128, usize); pow_impl!(i128, u8, u32, i128::pow); pow_impl!(i128, u16, u32, i128::pow); pow_impl!(i128, u32, u32, i128::pow); 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); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); pow_impl!(Wrapping); // 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 crate::Float; pow_impl!(f32, i8, i32, ::powi); pow_impl!(f32, u8, i32, ::powi); pow_impl!(f32, i16, i32, ::powi); pow_impl!(f32, u16, i32, ::powi); pow_impl!(f32, i32, i32, ::powi); pow_impl!(f64, i8, i32, ::powi); pow_impl!(f64, u8, i32, ::powi); pow_impl!(f64, i16, i32, ::powi); pow_impl!(f64, u16, i32, ::powi); pow_impl!(f64, i32, i32, ::powi); pow_impl!(f32, f32, f32, ::powf); pow_impl!(f64, f32, f64, ::powf); pow_impl!(f64, f64, f64, ::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>(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(mut base: T, mut exp: usize) -> Option { if exp == 0 { return Some(T::one()); } while exp & 1 == 0 { base = base.checked_mul(&base)?; exp >>= 1; } if exp == 1 { return Some(base); } let mut acc = base.clone(); while exp > 1 { exp >>= 1; base = base.checked_mul(&base)?; if exp & 1 == 1 { acc = acc.checked_mul(&base)?; } } Some(acc) } num-traits-0.2.19/src/real.rs000064400000000000000000000532141046102023000141050ustar 00000000000000#![cfg(any(feature = "std", feature = "libm"))] use core::ops::Neg; use crate::{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 { /// 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 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; } } num-traits-0.2.19/src/sign.rs000064400000000000000000000133651046102023000141250ustar 00000000000000use core::num::Wrapping; use core::ops::Neg; use crate::float::FloatCore; use crate::Num; /// Useful functions for signed numbers (i.e. numbers that can be negative). pub trait Signed: Sized + Num + Neg { /// 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 i128); impl Signed for Wrapping where Wrapping: Num + Neg>, { #[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(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(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(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 u128); impl Unsigned for Wrapping where Wrapping: Num {} #[test] fn unsigned_wrapping_is_unsigned() { fn require_unsigned(_: &T) {} require_unsigned(&Wrapping(42_u32)); } #[test] fn signed_wrapping_is_signed() { fn require_signed(_: &T) {} require_signed(&Wrapping(-42)); } num-traits-0.2.19/tests/cast.rs000064400000000000000000000274601046102023000144730ustar 00000000000000//! Tests of `num_traits::cast`. #![cfg_attr(not(feature = "std"), no_std)] use num_traits::cast::*; use num_traits::Bounded; use core::{f32, f64}; use core::{i128, i16, i32, i64, i8, isize}; use core::{u128, 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) {} require_toprimitive(&Wrapping(42)); } #[test] fn wrapping_is_fromprimitive() { fn require_fromprimitive(_: &T) {} require_fromprimitive(&Wrapping(42)); } #[test] fn wrapping_is_numcast() { fn require_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::(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::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(Some(normal_f as isize), cast::(normal_f)); assert_eq!(Some(normal_f as i8), cast::(normal_f)); assert_eq!(Some(normal_f as i16), cast::(normal_f)); assert_eq!(Some(normal_f as i32), cast::(normal_f)); assert_eq!(Some(normal_f as i64), cast::(normal_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(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::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(Some(normal_f as usize), cast::(normal_f)); assert_eq!(Some(normal_f as u8), cast::(normal_f)); assert_eq!(Some(normal_f as u16), cast::(normal_f)); assert_eq!(Some(normal_f as u32), cast::(normal_f)); assert_eq!(Some(normal_f as u64), cast::(normal_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(small_f)); } #[test] 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::(big_f)); assert_eq!(None, cast::(big_f)); assert_eq!(Some(normal_f as i128), cast::(normal_f)); assert_eq!(Some(normal_f as u128), cast::(normal_f)); assert_eq!(None, cast::(small_f)); assert_eq!(None, cast::(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_inc().floor() }; let fmin = small.raw_dec(); 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_dec() as $t; // the next smallest possible assert_eq!(max.count_ones(), $f::MANTISSA_DIGITS); (max, large) }; let fmax = large.raw_dec(); 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 { fn raw_inc(self) -> Self; fn raw_dec(self) -> Self; } impl RawOffset for f32 { fn raw_inc(self) -> Self { Self::from_bits(self.to_bits() + 1) } fn raw_dec(self) -> Self { Self::from_bits(self.to_bits() - 1) } } impl RawOffset for f64 { fn raw_inc(self) -> Self { Self::from_bits(self.to_bits() + 1) } fn raw_dec(self) -> Self { Self::from_bits(self.to_bits() - 1) } } #[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] 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 ) => { $({ #[allow(arithmetic_overflow)] // https://github.com/rust-lang/rust/issues/109731 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] 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); // minimal impl impl FromPrimitive for New { fn from_i64(n: i64) -> Option { T::from_i64(n).map(New) } fn from_u64(n: u64) -> Option { T::from_u64(n).map(New) } } macro_rules! assert_eq_from { ($( $from:ident )+) => {$( assert_eq!(T::$from(Bounded::min_value()).map(New), New::::$from(Bounded::min_value())); assert_eq!(T::$from(Bounded::max_value()).map(New), New::::$from(Bounded::max_value())); )+} } fn check() { 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); // minimal impl impl ToPrimitive for New { fn to_i64(&self) -> Option { self.0.to_i64() } fn to_u64(&self) -> Option { self.0.to_u64() } } macro_rules! assert_eq_to { ($( $to:ident )+) => {$( assert_eq!(T::$to(&Bounded::min_value()), New::::$to(&New(Bounded::min_value()))); assert_eq!(T::$to(&Bounded::max_value()), New::::$to(&New(Bounded::max_value()))); )+} } fn check() { 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); }