├── .github └── workflows │ ├── ci.yaml │ ├── master.yaml │ └── pr.yaml ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── RELEASES.md ├── build.rs ├── ci ├── rustup.sh └── test_full.sh ├── src ├── bounds.rs ├── cast.rs ├── float.rs ├── identities.rs ├── int.rs ├── lib.rs ├── macros.rs ├── ops │ ├── bytes.rs │ ├── checked.rs │ ├── euclid.rs │ ├── inv.rs │ ├── mod.rs │ ├── mul_add.rs │ ├── overflowing.rs │ ├── saturating.rs │ └── wrapping.rs ├── pow.rs ├── real.rs └── sign.rs └── tests └── cast.rs /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: merge_group 3 | 4 | jobs: 5 | 6 | test: 7 | name: Test 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | rust: [ 12 | 1.60.0, # MSRV 13 | 1.62.0, # has_total_cmp 14 | stable, 15 | beta, 16 | nightly, 17 | ] 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/cache@v4 21 | if: startsWith(matrix.rust, '1') 22 | with: 23 | path: ~/.cargo/registry/index 24 | key: cargo-${{ matrix.rust }}-git-index 25 | - uses: dtolnay/rust-toolchain@master 26 | with: 27 | toolchain: ${{ matrix.rust }} 28 | - run: cargo build 29 | env: 30 | # https://github.com/rust-lang/cargo/issues/10303 31 | CARGO_NET_GIT_FETCH_WITH_CLI: true 32 | - run: ./ci/test_full.sh 33 | 34 | # i586 presents floating point challenges for lack of SSE/SSE2 35 | i586: 36 | name: Test (i586) 37 | runs-on: ubuntu-latest 38 | steps: 39 | - run: | 40 | sudo apt-get update 41 | sudo apt-get install gcc-multilib 42 | - uses: actions/checkout@v4 43 | - uses: dtolnay/rust-toolchain@stable 44 | with: 45 | target: i586-unknown-linux-gnu 46 | - run: cargo test --target i586-unknown-linux-gnu --all-features 47 | 48 | # try a target that doesn't have std at all 49 | no_std: 50 | name: No Std 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v4 54 | - uses: dtolnay/rust-toolchain@stable 55 | with: 56 | target: thumbv6m-none-eabi 57 | - run: cargo build --target thumbv6m-none-eabi --no-default-features 58 | - run: cargo build --target thumbv6m-none-eabi --no-default-features --features libm 59 | 60 | fmt: 61 | name: Format 62 | runs-on: ubuntu-latest 63 | steps: 64 | - uses: actions/checkout@v4 65 | - uses: dtolnay/rust-toolchain@1.62.0 66 | with: 67 | components: rustfmt 68 | - run: cargo fmt --all --check 69 | 70 | # One job that "summarizes" the success state of this pipeline. This can then be added to branch 71 | # protection, rather than having to add each job separately. 72 | success: 73 | name: Success 74 | runs-on: ubuntu-latest 75 | needs: [test, i586, no_std, fmt] 76 | # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency 77 | # failed" as success. So we have to do some contortions to ensure the job fails if any of its 78 | # dependencies fails. 79 | if: always() # make sure this is never "skipped" 80 | steps: 81 | # Manually check the status of all dependencies. `if: failure()` does not work. 82 | - name: check if any dependency failed 83 | run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' 84 | -------------------------------------------------------------------------------- /.github/workflows/master.yaml: -------------------------------------------------------------------------------- 1 | name: master 2 | on: 3 | push: 4 | branches: 5 | - master 6 | schedule: 7 | - cron: '0 0 * * 0' # 00:00 Sunday 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | rust: [1.60.0, stable] 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/cache@v4 20 | if: startsWith(matrix.rust, '1') 21 | with: 22 | path: ~/.cargo/registry/index 23 | key: cargo-${{ matrix.rust }}-git-index 24 | - uses: dtolnay/rust-toolchain@master 25 | with: 26 | toolchain: ${{ matrix.rust }} 27 | - run: cargo build 28 | - run: ./ci/test_full.sh 29 | -------------------------------------------------------------------------------- /.github/workflows/pr.yaml: -------------------------------------------------------------------------------- 1 | name: PR 2 | on: 3 | pull_request: 4 | 5 | jobs: 6 | 7 | test: 8 | name: Test 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | rust: [1.60.0, stable] 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/cache@v4 16 | if: startsWith(matrix.rust, '1') 17 | with: 18 | path: ~/.cargo/registry/index 19 | key: cargo-${{ matrix.rust }}-git-index 20 | - uses: dtolnay/rust-toolchain@master 21 | with: 22 | toolchain: ${{ matrix.rust }} 23 | - run: cargo build 24 | - run: ./ci/test_full.sh 25 | 26 | fmt: 27 | name: Format 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: dtolnay/rust-toolchain@1.62.0 31 | with: 32 | components: rustfmt 33 | - uses: actions/checkout@v4 34 | - run: cargo fmt --all --check 35 | 36 | # One job that "summarizes" the success state of this pipeline. This can then be added to branch 37 | # protection, rather than having to add each job separately. 38 | success: 39 | name: Success 40 | runs-on: ubuntu-latest 41 | needs: [test, fmt] 42 | # Github branch protection is exceedingly silly and treats "jobs skipped because a dependency 43 | # failed" as success. So we have to do some contortions to ensure the job fails if any of its 44 | # dependencies fails. 45 | if: always() # make sure this is never "skipped" 46 | steps: 47 | # Manually check the status of all dependencies. `if: failure()` does not work. 48 | - name: check if any dependency failed 49 | run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["The Rust Project Developers"] 3 | description = "Numeric traits for generic mathematics" 4 | documentation = "https://docs.rs/num-traits" 5 | homepage = "https://github.com/rust-num/num-traits" 6 | keywords = ["mathematics", "numerics"] 7 | categories = ["algorithms", "science", "no-std"] 8 | license = "MIT OR Apache-2.0" 9 | repository = "https://github.com/rust-num/num-traits" 10 | name = "num-traits" 11 | version = "0.2.19" 12 | readme = "README.md" 13 | build = "build.rs" 14 | exclude = ["/ci/*", "/.github/*"] 15 | edition = "2021" 16 | rust-version = "1.60" 17 | 18 | [package.metadata.docs.rs] 19 | features = ["std"] 20 | rustdoc-args = ["--generate-link-to-definition"] 21 | 22 | [dependencies] 23 | libm = { version = "0.2.0", optional = true } 24 | 25 | [features] 26 | default = ["std"] 27 | libm = ["dep:libm"] 28 | std = [] 29 | 30 | # vestigial features, now always in effect 31 | i128 = [] 32 | 33 | [build-dependencies] 34 | autocfg = "1" 35 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # num-traits 2 | 3 | [![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits) 4 | [![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits) 5 | [![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) 6 | [![build status](https://github.com/rust-num/num-traits/workflows/master/badge.svg)](https://github.com/rust-num/num-traits/actions) 7 | 8 | Numeric traits for generic mathematics in Rust. 9 | 10 | ## Usage 11 | 12 | Add this to your `Cargo.toml`: 13 | 14 | ```toml 15 | [dependencies] 16 | num-traits = "0.2" 17 | ``` 18 | 19 | ## Features 20 | 21 | This crate can be used without the standard library (`#![no_std]`) by disabling 22 | the default `std` feature. Use this in `Cargo.toml`: 23 | 24 | ```toml 25 | [dependencies.num-traits] 26 | version = "0.2" 27 | default-features = false 28 | # features = ["libm"] # <--- Uncomment if you wish to use `Float` and `Real` without `std` 29 | ``` 30 | 31 | The `Float` and `Real` traits are only available when either `std` or `libm` is enabled. 32 | 33 | The `FloatCore` trait is always available. `MulAdd` and `MulAddAssign` for `f32` 34 | and `f64` also require `std` or `libm`, as do implementations of signed and floating- 35 | point exponents in `Pow`. 36 | 37 | ## Releases 38 | 39 | Release notes are available in [RELEASES.md](RELEASES.md). 40 | 41 | ## Compatibility 42 | 43 | The `num-traits` crate is tested for rustc 1.60 and greater. 44 | 45 | ## License 46 | 47 | Licensed under either of 48 | 49 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 50 | * [MIT license](http://opensource.org/licenses/MIT) 51 | 52 | at your option. 53 | 54 | ### Contribution 55 | 56 | Unless you explicitly state otherwise, any contribution intentionally submitted 57 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 58 | dual licensed as above, without any additional terms or conditions. 59 | -------------------------------------------------------------------------------- /RELEASES.md: -------------------------------------------------------------------------------- 1 | # Release 0.2.19 (2024-05-03) 2 | 3 | - [Upgrade to 2021 edition, **MSRV 1.60**][310] 4 | - [The new `Float::clamp` limits values by minimum and maximum][305] 5 | 6 | **Contributors**: @cuviper, @michaelciraci 7 | 8 | [305]: https://github.com/rust-num/num-traits/pull/305 9 | [310]: https://github.com/rust-num/num-traits/pull/310 10 | 11 | # Release 0.2.18 (2024-02-07) 12 | 13 | - [The new `Euclid::div_rem_euclid` and `CheckedEuclid::checked_div_rem_euclid` methods][291] 14 | compute and return the quotient and remainder at the same time. 15 | - [The new `TotalOrder` trait implements the IEEE 754 `totalOrder` predicate.][295] 16 | - [The new `ConstZero` and `ConstOne` traits offered associated constants][303], 17 | extending the non-const `Zero` and `One` traits for types that have constant values. 18 | 19 | **Contributors**: @andrewjradcliffe, @cuviper, @tarcieri, @tdelabro, @waywardmonkeys 20 | 21 | [291]: https://github.com/rust-num/num-traits/pull/291 22 | [295]: https://github.com/rust-num/num-traits/pull/295 23 | [303]: https://github.com/rust-num/num-traits/pull/303 24 | 25 | # Release 0.2.17 (2023-10-07) 26 | 27 | - [Fix a doc warning about custom classes with newer rustdoc.][286] 28 | 29 | **Contributors**: @robamu 30 | 31 | [286]: https://github.com/rust-num/num-traits/pull/286 32 | 33 | # Release 0.2.16 (2023-07-20) 34 | 35 | - [Upgrade to 2018 edition, **MSRV 1.31**][240] 36 | - [The new `ToBytes` and `FromBytes` traits][224] convert to and from byte 37 | representations of a value, with little, big, and native-endian options. 38 | - [The new `Float::is_subnormal` method checks for subnormal values][279], with 39 | a non-zero magnitude that is less than the normal minimum positive value. 40 | - Several other improvements to documentation and testing. 41 | 42 | **Contributors**: @ctrlcctrlv, @cuviper, @flier, @GuillaumeGomez, @kaidokert, 43 | @rs017991, @vicsn 44 | 45 | [224]: https://github.com/rust-num/num-traits/pull/224 46 | [240]: https://github.com/rust-num/num-traits/pull/240 47 | [279]: https://github.com/rust-num/num-traits/pull/279 48 | 49 | # Release 0.2.15 (2022-05-02) 50 | 51 | - [The new `Euclid` trait calculates Euclidean division][195], where the 52 | remainder is always positive or zero. 53 | - [The new `LowerBounded` and `UpperBounded` traits][210] separately describe 54 | types with lower and upper bounds. These traits are automatically implemented 55 | for all fully-`Bounded` types. 56 | - [The new `Float::copysign` method copies the sign of the argument][207] to 57 | to the magnitude of `self`. 58 | - [The new `PrimInt::leading_ones` and `trailing_ones` methods][205] are the 59 | complement of the existing methods that count zero bits. 60 | - [The new `PrimInt::reverse_bits` method reverses the order of all bits][202] 61 | of a primitive integer. 62 | - [Improved `Num::from_str_radix` for floats][201], also [ignoring case][214]. 63 | - [`Float` and `FloatCore` use more from `libm`][196] when that is enabled. 64 | 65 | **Contributors**: @alion02, @clarfonthey, @cuviper, @ElectronicRU, 66 | @ibraheemdev, @SparrowLii, @sshilovsky, @tspiteri, @XAMPPRocky, @Xiretza 67 | 68 | [195]: https://github.com/rust-num/num-traits/pull/195 69 | [196]: https://github.com/rust-num/num-traits/pull/196 70 | [201]: https://github.com/rust-num/num-traits/pull/201 71 | [202]: https://github.com/rust-num/num-traits/pull/202 72 | [205]: https://github.com/rust-num/num-traits/pull/205 73 | [207]: https://github.com/rust-num/num-traits/pull/207 74 | [210]: https://github.com/rust-num/num-traits/pull/210 75 | [214]: https://github.com/rust-num/num-traits/pull/214 76 | 77 | # Release 0.2.14 (2020-10-29) 78 | 79 | - Clarify the license specification as "MIT OR Apache-2.0". 80 | 81 | **Contributors**: @cuviper 82 | 83 | # Release 0.2.13 (2020-10-29) 84 | 85 | - [The new `OverflowingAdd`, `OverflowingSub`, and `OverflowingMul` traits][180] 86 | return a tuple with the operation result and a `bool` indicating overflow. 87 | - [The "i128" feature now overrides compiler probes for that support][185]. 88 | This may fix scenarios where `autocfg` probing doesn't work properly. 89 | - [Casts from large `f64` values to `f32` now saturate to infinity][186]. They 90 | previously returned `None` because that was once thought to be undefined 91 | behavior, but [rust#15536] resolved that such casts are fine. 92 | - [`Num::from_str_radix` documents requirements for radix support][192], which 93 | are now more relaxed than previously implied. It is suggested to accept at 94 | least `2..=36` without panicking, but `Err` may be returned otherwise. 95 | 96 | **Contributors**: @cuviper, @Enet4, @KaczuH, @martin-t, @newpavlov 97 | 98 | [180]: https://github.com/rust-num/num-traits/pull/180 99 | [185]: https://github.com/rust-num/num-traits/pull/185 100 | [186]: https://github.com/rust-num/num-traits/pull/186 101 | [192]: https://github.com/rust-num/num-traits/issues/192 102 | [rust#15536]: https://github.com/rust-lang/rust/issues/15536 103 | 104 | # Release 0.2.12 (2020-06-11) 105 | 106 | - [The new `WrappingNeg` trait][153] will wrap the result if it exceeds the 107 | boundary of the type, e.g. `i32::MIN.wrapping_neg() == i32::MIN`. 108 | - [The new `SaturatingAdd`, `SaturatingSub`, and `SaturatingMul` traits][165] 109 | will saturate at the numeric bounds if the operation would overflow. These 110 | soft-deprecate the existing `Saturating` trait that only has addition and 111 | subtraction methods. 112 | - [Added new constants for logarithms, `FloatConst::{LOG10_2, LOG2_10}`][171]. 113 | 114 | **Contributors**: @cuviper, @ocstl, @trepetti, @vallentin 115 | 116 | [153]: https://github.com/rust-num/num-traits/pull/153 117 | [165]: https://github.com/rust-num/num-traits/pull/165 118 | [171]: https://github.com/rust-num/num-traits/pull/171 119 | 120 | # Release 0.2.11 (2020-01-09) 121 | 122 | - [Added the full circle constant τ as `FloatConst::TAU`][145]. 123 | - [Updated the `autocfg` build dependency to 1.0][148]. 124 | 125 | **Contributors**: @cuviper, @m-ou-se 126 | 127 | [145]: https://github.com/rust-num/num-traits/pull/145 128 | [148]: https://github.com/rust-num/num-traits/pull/148 129 | 130 | # Release 0.2.10 (2019-11-22) 131 | 132 | - [Updated the `libm` dependency to 0.2][144]. 133 | 134 | **Contributors**: @CryZe 135 | 136 | [144]: https://github.com/rust-num/num-traits/pull/144 137 | 138 | # Release 0.2.9 (2019-11-12) 139 | 140 | - [A new optional `libm` dependency][99] enables the `Float` and `Real` traits 141 | in `no_std` builds. 142 | - [The new `clamp_min` and `clamp_max`][122] limit minimum and maximum values 143 | while preserving input `NAN`s. 144 | - [Fixed a panic in floating point `from_str_radix` on invalid signs][126]. 145 | - Miscellaneous documentation updates. 146 | 147 | **Contributors**: @cuviper, @dingelish, @HeroicKatora, @jturner314, @ocstl, 148 | @Shnatsel, @termoshtt, @waywardmonkeys, @yoanlcq 149 | 150 | [99]: https://github.com/rust-num/num-traits/pull/99 151 | [122]: https://github.com/rust-num/num-traits/pull/122 152 | [126]: https://github.com/rust-num/num-traits/pull/126 153 | 154 | # Release 0.2.8 (2019-05-21) 155 | 156 | - [Fixed feature detection on `no_std` targets][116]. 157 | 158 | **Contributors**: @cuviper 159 | 160 | [116]: https://github.com/rust-num/num-traits/pull/116 161 | 162 | # Release 0.2.7 (2019-05-20) 163 | 164 | - [Documented when `CheckedShl` and `CheckedShr` return `None`][90]. 165 | - [The new `Zero::set_zero` and `One::set_one`][104] will set values to their 166 | identities in place, possibly optimized better than direct assignment. 167 | - [Documented general features and intentions of `PrimInt`][108]. 168 | 169 | **Contributors**: @cuviper, @dvdhrm, @ignatenkobrain, @lcnr, @samueltardieu 170 | 171 | [90]: https://github.com/rust-num/num-traits/pull/90 172 | [104]: https://github.com/rust-num/num-traits/pull/104 173 | [108]: https://github.com/rust-num/num-traits/pull/108 174 | 175 | # Release 0.2.6 (2018-09-13) 176 | 177 | - [Documented that `pow(0, 0)` returns `1`][79]. Mathematically, this is not 178 | strictly defined, but the current behavior is a pragmatic choice that has 179 | precedent in Rust `core` for the primitives and in many other languages. 180 | - [The new `WrappingShl` and `WrappingShr` traits][81] will wrap the shift count 181 | if it exceeds the bit size of the type. 182 | 183 | **Contributors**: @cuviper, @edmccard, @meltinglava 184 | 185 | [79]: https://github.com/rust-num/num-traits/pull/79 186 | [81]: https://github.com/rust-num/num-traits/pull/81 187 | 188 | # Release 0.2.5 (2018-06-20) 189 | 190 | - [Documentation for `mul_add` now clarifies that it's not always faster.][70] 191 | - [The default methods in `FromPrimitive` and `ToPrimitive` are more robust.][73] 192 | 193 | **Contributors**: @cuviper, @frewsxcv 194 | 195 | [70]: https://github.com/rust-num/num-traits/pull/70 196 | [73]: https://github.com/rust-num/num-traits/pull/73 197 | 198 | # Release 0.2.4 (2018-05-11) 199 | 200 | - [Support for 128-bit integers is now automatically detected and enabled.][69] 201 | Setting the `i128` crate feature now causes the build script to panic if such 202 | support is not detected. 203 | 204 | **Contributors**: @cuviper 205 | 206 | [69]: https://github.com/rust-num/num-traits/pull/69 207 | 208 | # Release 0.2.3 (2018-05-10) 209 | 210 | - [The new `CheckedNeg` and `CheckedRem` traits][63] perform checked `Neg` and 211 | `Rem`, returning `Some(output)` or `None` on overflow. 212 | - [The `no_std` implementation of `FloatCore::to_degrees` for `f32`][61] now 213 | uses a constant for greater accuracy, mirroring [rust#47919]. (With `std` it 214 | just calls the inherent `f32::to_degrees` in the standard library.) 215 | - [The new `MulAdd` and `MulAddAssign` traits][59] perform a fused multiply- 216 | add. For integer types this is just a convenience, but for floating point 217 | types this produces a more accurate result than the separate operations. 218 | - [All applicable traits are now implemented for 128-bit integers][60] starting 219 | with Rust 1.26, enabled by the new `i128` crate feature. The `FromPrimitive` 220 | and `ToPrimitive` traits now also have corresponding 128-bit methods, which 221 | default to converting via 64-bit integers for compatibility. 222 | 223 | **Contributors**: @cuviper, @LEXUGE, @regexident, @vks 224 | 225 | [59]: https://github.com/rust-num/num-traits/pull/59 226 | [60]: https://github.com/rust-num/num-traits/pull/60 227 | [61]: https://github.com/rust-num/num-traits/pull/61 228 | [63]: https://github.com/rust-num/num-traits/pull/63 229 | [rust#47919]: https://github.com/rust-lang/rust/pull/47919 230 | 231 | # Release 0.2.2 (2018-03-18) 232 | 233 | - [Casting from floating point to integers now returns `None` on overflow][52], 234 | avoiding [rustc's undefined behavior][rust-10184]. This applies to the `cast` 235 | function and the traits `NumCast`, `FromPrimitive`, and `ToPrimitive`. 236 | 237 | **Contributors**: @apopiak, @cuviper, @dbarella 238 | 239 | [52]: https://github.com/rust-num/num-traits/pull/52 240 | [rust-10184]: https://github.com/rust-lang/rust/issues/10184 241 | 242 | 243 | # Release 0.2.1 (2018-03-01) 244 | 245 | - [The new `FloatCore` trait][32] offers a subset of `Float` for `#![no_std]` use. 246 | [This includes everything][41] except the transcendental functions and FMA. 247 | - [The new `Inv` trait][37] returns the multiplicative inverse, or reciprocal. 248 | - [The new `Pow` trait][37] performs exponentiation, much like the existing `pow` 249 | function, but with generic exponent types. 250 | - [The new `One::is_one` method][39] tests if a value equals 1. Implementers 251 | should override this method if there's a more efficient way to check for 1, 252 | rather than comparing with a temporary `one()`. 253 | 254 | **Contributors**: @clarcharr, @cuviper, @vks 255 | 256 | [32]: https://github.com/rust-num/num-traits/pull/32 257 | [37]: https://github.com/rust-num/num-traits/pull/37 258 | [39]: https://github.com/rust-num/num-traits/pull/39 259 | [41]: https://github.com/rust-num/num-traits/pull/41 260 | 261 | 262 | # Release 0.2.0 (2018-02-06) 263 | 264 | - **breaking change**: [There is now a `std` feature][30], enabled by default, along 265 | with the implication that building *without* this feature makes this a 266 | `#![no_std]` crate. 267 | - The `Float` and `Real` traits are only available when `std` is enabled. 268 | - Otherwise, the API is unchanged, and num-traits 0.1.43 now re-exports its 269 | items from num-traits 0.2 for compatibility (the [semver-trick]). 270 | 271 | **Contributors**: @cuviper, @termoshtt, @vks 272 | 273 | [semver-trick]: https://github.com/dtolnay/semver-trick 274 | [30]: https://github.com/rust-num/num-traits/pull/30 275 | 276 | 277 | # Release 0.1.43 (2018-02-06) 278 | 279 | - All items are now [re-exported from num-traits 0.2][31] for compatibility. 280 | 281 | [31]: https://github.com/rust-num/num-traits/pull/31 282 | 283 | 284 | # Release 0.1.42 (2018-01-22) 285 | 286 | - [num-traits now has its own source repository][num-356] at [rust-num/num-traits][home]. 287 | - [`ParseFloatError` now implements `Display`][22]. 288 | - [The new `AsPrimitive` trait][17] implements generic casting with the `as` operator. 289 | - [The new `CheckedShl` and `CheckedShr` traits][21] implement generic 290 | support for the `checked_shl` and `checked_shr` methods on primitive integers. 291 | - [The new `Real` trait][23] offers a subset of `Float` functionality that may be applicable to more 292 | types, with a blanket implementation for all existing `T: Float` types. 293 | 294 | Thanks to @cuviper, @Enet4, @fabianschuiki, @svartalf, and @yoanlcq for their contributions! 295 | 296 | [home]: https://github.com/rust-num/num-traits 297 | [num-356]: https://github.com/rust-num/num/pull/356 298 | [17]: https://github.com/rust-num/num-traits/pull/17 299 | [21]: https://github.com/rust-num/num-traits/pull/21 300 | [22]: https://github.com/rust-num/num-traits/pull/22 301 | [23]: https://github.com/rust-num/num-traits/pull/23 302 | 303 | 304 | # Prior releases 305 | 306 | No prior release notes were kept. Thanks all the same to the many 307 | contributors that have made this crate what it is! 308 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let ac = autocfg::new(); 3 | 4 | ac.emit_expression_cfg("1f64.total_cmp(&2f64)", "has_total_cmp"); // 1.62 5 | 6 | autocfg::rerun_path("build.rs"); 7 | } 8 | -------------------------------------------------------------------------------- /ci/rustup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Use rustup to locally run the same suite of tests as .github/workflows/ 3 | # (You should first install/update all of the versions below.) 4 | 5 | set -ex 6 | 7 | ci=$(dirname $0) 8 | for version in 1.60.0 1.62.0 stable beta nightly; do 9 | rustup run "$version" "$ci/test_full.sh" 10 | done 11 | -------------------------------------------------------------------------------- /ci/test_full.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | CRATE=num-traits 6 | MSRV=1.60 7 | 8 | get_rust_version() { 9 | local array=($(rustc --version)); 10 | echo "${array[1]}"; 11 | return 0; 12 | } 13 | RUST_VERSION=$(get_rust_version) 14 | 15 | check_version() { 16 | IFS=. read -ra rust <<< "$RUST_VERSION" 17 | IFS=. read -ra want <<< "$1" 18 | [[ "${rust[0]}" -gt "${want[0]}" || 19 | ( "${rust[0]}" -eq "${want[0]}" && 20 | "${rust[1]}" -ge "${want[1]}" ) 21 | ]] 22 | } 23 | 24 | echo "Testing $CRATE on rustc $RUST_VERSION" 25 | if ! check_version $MSRV ; then 26 | echo "The minimum for $CRATE is rustc $MSRV" 27 | exit 1 28 | fi 29 | 30 | FEATURES=(libm) 31 | echo "Testing supported features: ${FEATURES[*]}" 32 | 33 | cargo generate-lockfile 34 | check_version 1.63.0 || cargo update -p libm --precise 0.2.9 35 | 36 | set -x 37 | 38 | # test the default 39 | cargo build 40 | cargo test 41 | 42 | # test `no_std` 43 | cargo build --no-default-features 44 | cargo test --no-default-features 45 | 46 | # test each isolated feature, with and without std 47 | for feature in ${FEATURES[*]}; do 48 | cargo build --no-default-features --features="std $feature" 49 | cargo test --no-default-features --features="std $feature" 50 | 51 | cargo build --no-default-features --features="$feature" 52 | cargo test --no-default-features --features="$feature" 53 | done 54 | 55 | # test all supported features, with and without std 56 | cargo build --features="std ${FEATURES[*]}" 57 | cargo test --features="std ${FEATURES[*]}" 58 | 59 | cargo build --features="${FEATURES[*]}" 60 | cargo test --features="${FEATURES[*]}" 61 | -------------------------------------------------------------------------------- /src/bounds.rs: -------------------------------------------------------------------------------- 1 | use core::num::Wrapping; 2 | use core::{f32, f64}; 3 | use core::{i128, i16, i32, i64, i8, isize}; 4 | use core::{u128, u16, u32, u64, u8, usize}; 5 | 6 | /// Numbers which have upper and lower bounds 7 | pub trait Bounded { 8 | // FIXME (#5527): These should be associated constants 9 | /// Returns the smallest finite number this type can represent 10 | fn min_value() -> Self; 11 | /// Returns the largest finite number this type can represent 12 | fn max_value() -> Self; 13 | } 14 | 15 | /// Numbers which have lower bounds 16 | pub trait LowerBounded { 17 | /// Returns the smallest finite number this type can represent 18 | fn min_value() -> Self; 19 | } 20 | 21 | // FIXME: With a major version bump, this should be a supertrait instead 22 | impl LowerBounded for T { 23 | fn min_value() -> T { 24 | Bounded::min_value() 25 | } 26 | } 27 | 28 | /// Numbers which have upper bounds 29 | pub trait UpperBounded { 30 | /// Returns the largest finite number this type can represent 31 | fn max_value() -> Self; 32 | } 33 | 34 | // FIXME: With a major version bump, this should be a supertrait instead 35 | impl UpperBounded for T { 36 | fn max_value() -> T { 37 | Bounded::max_value() 38 | } 39 | } 40 | 41 | macro_rules! bounded_impl { 42 | ($t:ty, $min:expr, $max:expr) => { 43 | impl Bounded for $t { 44 | #[inline] 45 | fn min_value() -> $t { 46 | $min 47 | } 48 | 49 | #[inline] 50 | fn max_value() -> $t { 51 | $max 52 | } 53 | } 54 | }; 55 | } 56 | 57 | bounded_impl!(usize, usize::MIN, usize::MAX); 58 | bounded_impl!(u8, u8::MIN, u8::MAX); 59 | bounded_impl!(u16, u16::MIN, u16::MAX); 60 | bounded_impl!(u32, u32::MIN, u32::MAX); 61 | bounded_impl!(u64, u64::MIN, u64::MAX); 62 | bounded_impl!(u128, u128::MIN, u128::MAX); 63 | 64 | bounded_impl!(isize, isize::MIN, isize::MAX); 65 | bounded_impl!(i8, i8::MIN, i8::MAX); 66 | bounded_impl!(i16, i16::MIN, i16::MAX); 67 | bounded_impl!(i32, i32::MIN, i32::MAX); 68 | bounded_impl!(i64, i64::MIN, i64::MAX); 69 | bounded_impl!(i128, i128::MIN, i128::MAX); 70 | 71 | impl Bounded for Wrapping { 72 | fn min_value() -> Self { 73 | Wrapping(T::min_value()) 74 | } 75 | fn max_value() -> Self { 76 | Wrapping(T::max_value()) 77 | } 78 | } 79 | 80 | bounded_impl!(f32, f32::MIN, f32::MAX); 81 | 82 | macro_rules! for_each_tuple_ { 83 | ( $m:ident !! ) => ( 84 | $m! { } 85 | ); 86 | ( $m:ident !! $h:ident, $($t:ident,)* ) => ( 87 | $m! { $h $($t)* } 88 | for_each_tuple_! { $m !! $($t,)* } 89 | ); 90 | } 91 | macro_rules! for_each_tuple { 92 | ($m:ident) => { 93 | for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, } 94 | }; 95 | } 96 | 97 | macro_rules! bounded_tuple { 98 | ( $($name:ident)* ) => ( 99 | impl<$($name: Bounded,)*> Bounded for ($($name,)*) { 100 | #[inline] 101 | fn min_value() -> Self { 102 | ($($name::min_value(),)*) 103 | } 104 | #[inline] 105 | fn max_value() -> Self { 106 | ($($name::max_value(),)*) 107 | } 108 | } 109 | ); 110 | } 111 | 112 | for_each_tuple!(bounded_tuple); 113 | bounded_impl!(f64, f64::MIN, f64::MAX); 114 | 115 | #[test] 116 | fn wrapping_bounded() { 117 | macro_rules! test_wrapping_bounded { 118 | ($($t:ty)+) => { 119 | $( 120 | assert_eq!( as Bounded>::min_value().0, <$t>::min_value()); 121 | assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); 122 | )+ 123 | }; 124 | } 125 | 126 | test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); 127 | } 128 | 129 | #[test] 130 | fn wrapping_bounded_i128() { 131 | macro_rules! test_wrapping_bounded { 132 | ($($t:ty)+) => { 133 | $( 134 | assert_eq!( as Bounded>::min_value().0, <$t>::min_value()); 135 | assert_eq!( as Bounded>::max_value().0, <$t>::max_value()); 136 | )+ 137 | }; 138 | } 139 | 140 | test_wrapping_bounded!(u128 i128); 141 | } 142 | 143 | #[test] 144 | fn wrapping_is_bounded() { 145 | fn require_bounded(_: &T) {} 146 | require_bounded(&Wrapping(42_u32)); 147 | require_bounded(&Wrapping(-42)); 148 | } 149 | -------------------------------------------------------------------------------- /src/identities.rs: -------------------------------------------------------------------------------- 1 | use core::num::Wrapping; 2 | use core::ops::{Add, Mul}; 3 | 4 | /// Defines an additive identity element for `Self`. 5 | /// 6 | /// # Laws 7 | /// 8 | /// ```text 9 | /// a + 0 = a ∀ a ∈ Self 10 | /// 0 + a = a ∀ a ∈ Self 11 | /// ``` 12 | pub trait Zero: Sized + Add { 13 | /// Returns the additive identity element of `Self`, `0`. 14 | /// # Purity 15 | /// 16 | /// This function should return the same result at all times regardless of 17 | /// external mutable state, for example values stored in TLS or in 18 | /// `static mut`s. 19 | // This cannot be an associated constant, because of bignums. 20 | fn zero() -> Self; 21 | 22 | /// Sets `self` to the additive identity element of `Self`, `0`. 23 | fn set_zero(&mut self) { 24 | *self = Zero::zero(); 25 | } 26 | 27 | /// Returns `true` if `self` is equal to the additive identity. 28 | fn is_zero(&self) -> bool; 29 | } 30 | 31 | /// Defines an associated constant representing the additive identity element 32 | /// for `Self`. 33 | pub trait ConstZero: Zero { 34 | /// The additive identity element of `Self`, `0`. 35 | const ZERO: Self; 36 | } 37 | 38 | macro_rules! zero_impl { 39 | ($t:ty, $v:expr) => { 40 | impl Zero for $t { 41 | #[inline] 42 | fn zero() -> $t { 43 | $v 44 | } 45 | #[inline] 46 | fn is_zero(&self) -> bool { 47 | *self == $v 48 | } 49 | } 50 | 51 | impl ConstZero for $t { 52 | const ZERO: Self = $v; 53 | } 54 | }; 55 | } 56 | 57 | zero_impl!(usize, 0); 58 | zero_impl!(u8, 0); 59 | zero_impl!(u16, 0); 60 | zero_impl!(u32, 0); 61 | zero_impl!(u64, 0); 62 | zero_impl!(u128, 0); 63 | 64 | zero_impl!(isize, 0); 65 | zero_impl!(i8, 0); 66 | zero_impl!(i16, 0); 67 | zero_impl!(i32, 0); 68 | zero_impl!(i64, 0); 69 | zero_impl!(i128, 0); 70 | 71 | zero_impl!(f32, 0.0); 72 | zero_impl!(f64, 0.0); 73 | 74 | impl Zero for Wrapping 75 | where 76 | Wrapping: Add>, 77 | { 78 | fn is_zero(&self) -> bool { 79 | self.0.is_zero() 80 | } 81 | 82 | fn set_zero(&mut self) { 83 | self.0.set_zero(); 84 | } 85 | 86 | fn zero() -> Self { 87 | Wrapping(T::zero()) 88 | } 89 | } 90 | 91 | impl ConstZero for Wrapping 92 | where 93 | Wrapping: Add>, 94 | { 95 | const ZERO: Self = Wrapping(T::ZERO); 96 | } 97 | 98 | /// Defines a multiplicative identity element for `Self`. 99 | /// 100 | /// # Laws 101 | /// 102 | /// ```text 103 | /// a * 1 = a ∀ a ∈ Self 104 | /// 1 * a = a ∀ a ∈ Self 105 | /// ``` 106 | pub trait One: Sized + Mul { 107 | /// Returns the multiplicative identity element of `Self`, `1`. 108 | /// 109 | /// # Purity 110 | /// 111 | /// This function should return the same result at all times regardless of 112 | /// external mutable state, for example values stored in TLS or in 113 | /// `static mut`s. 114 | // This cannot be an associated constant, because of bignums. 115 | fn one() -> Self; 116 | 117 | /// Sets `self` to the multiplicative identity element of `Self`, `1`. 118 | fn set_one(&mut self) { 119 | *self = One::one(); 120 | } 121 | 122 | /// Returns `true` if `self` is equal to the multiplicative identity. 123 | /// 124 | /// For performance reasons, it's best to implement this manually. 125 | /// After a semver bump, this method will be required, and the 126 | /// `where Self: PartialEq` bound will be removed. 127 | #[inline] 128 | fn is_one(&self) -> bool 129 | where 130 | Self: PartialEq, 131 | { 132 | *self == Self::one() 133 | } 134 | } 135 | 136 | /// Defines an associated constant representing the multiplicative identity 137 | /// element for `Self`. 138 | pub trait ConstOne: One { 139 | /// The multiplicative identity element of `Self`, `1`. 140 | const ONE: Self; 141 | } 142 | 143 | macro_rules! one_impl { 144 | ($t:ty, $v:expr) => { 145 | impl One for $t { 146 | #[inline] 147 | fn one() -> $t { 148 | $v 149 | } 150 | #[inline] 151 | fn is_one(&self) -> bool { 152 | *self == $v 153 | } 154 | } 155 | 156 | impl ConstOne for $t { 157 | const ONE: Self = $v; 158 | } 159 | }; 160 | } 161 | 162 | one_impl!(usize, 1); 163 | one_impl!(u8, 1); 164 | one_impl!(u16, 1); 165 | one_impl!(u32, 1); 166 | one_impl!(u64, 1); 167 | one_impl!(u128, 1); 168 | 169 | one_impl!(isize, 1); 170 | one_impl!(i8, 1); 171 | one_impl!(i16, 1); 172 | one_impl!(i32, 1); 173 | one_impl!(i64, 1); 174 | one_impl!(i128, 1); 175 | 176 | one_impl!(f32, 1.0); 177 | one_impl!(f64, 1.0); 178 | 179 | impl One for Wrapping 180 | where 181 | Wrapping: Mul>, 182 | { 183 | fn set_one(&mut self) { 184 | self.0.set_one(); 185 | } 186 | 187 | fn one() -> Self { 188 | Wrapping(T::one()) 189 | } 190 | } 191 | 192 | impl ConstOne for Wrapping 193 | where 194 | Wrapping: Mul>, 195 | { 196 | const ONE: Self = Wrapping(T::ONE); 197 | } 198 | 199 | // Some helper functions provided for backwards compatibility. 200 | 201 | /// Returns the additive identity, `0`. 202 | #[inline(always)] 203 | pub fn zero() -> T { 204 | Zero::zero() 205 | } 206 | 207 | /// Returns the multiplicative identity, `1`. 208 | #[inline(always)] 209 | pub fn one() -> T { 210 | One::one() 211 | } 212 | 213 | #[test] 214 | fn wrapping_identities() { 215 | macro_rules! test_wrapping_identities { 216 | ($($t:ty)+) => { 217 | $( 218 | assert_eq!(zero::<$t>(), zero::>().0); 219 | assert_eq!(one::<$t>(), one::>().0); 220 | assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); 221 | assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); 222 | )+ 223 | }; 224 | } 225 | 226 | test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); 227 | } 228 | 229 | #[test] 230 | fn wrapping_is_zero() { 231 | fn require_zero(_: &T) {} 232 | require_zero(&Wrapping(42)); 233 | } 234 | #[test] 235 | fn wrapping_is_one() { 236 | fn require_one(_: &T) {} 237 | require_one(&Wrapping(42)); 238 | } 239 | -------------------------------------------------------------------------------- /src/int.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; 2 | 3 | use crate::bounds::Bounded; 4 | use crate::ops::checked::*; 5 | use crate::ops::saturating::Saturating; 6 | use crate::{Num, NumCast}; 7 | 8 | /// Generic trait for primitive integers. 9 | /// 10 | /// The `PrimInt` trait is an abstraction over the builtin primitive integer types (e.g., `u8`, 11 | /// `u32`, `isize`, `i128`, ...). It inherits the basic numeric traits and extends them with 12 | /// bitwise operators and non-wrapping arithmetic. 13 | /// 14 | /// The trait explicitly inherits `Copy`, `Eq`, `Ord`, and `Sized`. The intention is that all 15 | /// types implementing this trait behave like primitive types that are passed by value by default 16 | /// and behave like builtin integers. Furthermore, the types are expected to expose the integer 17 | /// value in binary representation and support bitwise operators. The standard bitwise operations 18 | /// (e.g., bitwise-and, bitwise-or, right-shift, left-shift) are inherited and the trait extends 19 | /// these with introspective queries (e.g., `PrimInt::count_ones()`, `PrimInt::leading_zeros()`), 20 | /// bitwise combinators (e.g., `PrimInt::rotate_left()`), and endianness converters (e.g., 21 | /// `PrimInt::to_be()`). 22 | /// 23 | /// All `PrimInt` types are expected to be fixed-width binary integers. The width can be queried 24 | /// via `T::zero().count_zeros()`. The trait currently lacks a way to query the width at 25 | /// compile-time. 26 | /// 27 | /// While a default implementation for all builtin primitive integers is provided, the trait is in 28 | /// no way restricted to these. Other integer types that fulfil the requirements are free to 29 | /// implement the trait was well. 30 | /// 31 | /// This trait and many of the method names originate in the unstable `core::num::Int` trait from 32 | /// the rust standard library. The original trait was never stabilized and thus removed from the 33 | /// standard library. 34 | pub trait PrimInt: 35 | Sized 36 | + Copy 37 | + Num 38 | + NumCast 39 | + Bounded 40 | + PartialOrd 41 | + Ord 42 | + Eq 43 | + Not 44 | + BitAnd 45 | + BitOr 46 | + BitXor 47 | + Shl 48 | + Shr 49 | + CheckedAdd 50 | + CheckedSub 51 | + CheckedMul 52 | + CheckedDiv 53 | + Saturating 54 | { 55 | /// Returns the number of ones in the binary representation of `self`. 56 | /// 57 | /// # Examples 58 | /// 59 | /// ``` 60 | /// use num_traits::PrimInt; 61 | /// 62 | /// let n = 0b01001100u8; 63 | /// 64 | /// assert_eq!(n.count_ones(), 3); 65 | /// ``` 66 | fn count_ones(self) -> u32; 67 | 68 | /// Returns the number of zeros in the binary representation of `self`. 69 | /// 70 | /// # Examples 71 | /// 72 | /// ``` 73 | /// use num_traits::PrimInt; 74 | /// 75 | /// let n = 0b01001100u8; 76 | /// 77 | /// assert_eq!(n.count_zeros(), 5); 78 | /// ``` 79 | fn count_zeros(self) -> u32; 80 | 81 | /// Returns the number of leading ones in the binary representation 82 | /// of `self`. 83 | /// 84 | /// # Examples 85 | /// 86 | /// ``` 87 | /// use num_traits::PrimInt; 88 | /// 89 | /// let n = 0xF00Du16; 90 | /// 91 | /// assert_eq!(n.leading_ones(), 4); 92 | /// ``` 93 | fn leading_ones(self) -> u32 { 94 | (!self).leading_zeros() 95 | } 96 | 97 | /// Returns the number of leading zeros in the binary representation 98 | /// of `self`. 99 | /// 100 | /// # Examples 101 | /// 102 | /// ``` 103 | /// use num_traits::PrimInt; 104 | /// 105 | /// let n = 0b0101000u16; 106 | /// 107 | /// assert_eq!(n.leading_zeros(), 10); 108 | /// ``` 109 | fn leading_zeros(self) -> u32; 110 | 111 | /// Returns the number of trailing ones in the binary representation 112 | /// of `self`. 113 | /// 114 | /// # Examples 115 | /// 116 | /// ``` 117 | /// use num_traits::PrimInt; 118 | /// 119 | /// let n = 0xBEEFu16; 120 | /// 121 | /// assert_eq!(n.trailing_ones(), 4); 122 | /// ``` 123 | fn trailing_ones(self) -> u32 { 124 | (!self).trailing_zeros() 125 | } 126 | 127 | /// Returns the number of trailing zeros in the binary representation 128 | /// of `self`. 129 | /// 130 | /// # Examples 131 | /// 132 | /// ``` 133 | /// use num_traits::PrimInt; 134 | /// 135 | /// let n = 0b0101000u16; 136 | /// 137 | /// assert_eq!(n.trailing_zeros(), 3); 138 | /// ``` 139 | fn trailing_zeros(self) -> u32; 140 | 141 | /// Shifts the bits to the left by a specified amount, `n`, wrapping 142 | /// the truncated bits to the end of the resulting integer. 143 | /// 144 | /// # Examples 145 | /// 146 | /// ``` 147 | /// use num_traits::PrimInt; 148 | /// 149 | /// let n = 0x0123456789ABCDEFu64; 150 | /// let m = 0x3456789ABCDEF012u64; 151 | /// 152 | /// assert_eq!(n.rotate_left(12), m); 153 | /// ``` 154 | fn rotate_left(self, n: u32) -> Self; 155 | 156 | /// Shifts the bits to the right by a specified amount, `n`, wrapping 157 | /// the truncated bits to the beginning of the resulting integer. 158 | /// 159 | /// # Examples 160 | /// 161 | /// ``` 162 | /// use num_traits::PrimInt; 163 | /// 164 | /// let n = 0x0123456789ABCDEFu64; 165 | /// let m = 0xDEF0123456789ABCu64; 166 | /// 167 | /// assert_eq!(n.rotate_right(12), m); 168 | /// ``` 169 | fn rotate_right(self, n: u32) -> Self; 170 | 171 | /// Shifts the bits to the left by a specified amount, `n`, filling 172 | /// zeros in the least significant bits. 173 | /// 174 | /// This is bitwise equivalent to signed `Shl`. 175 | /// 176 | /// # Examples 177 | /// 178 | /// ``` 179 | /// use num_traits::PrimInt; 180 | /// 181 | /// let n = 0x0123456789ABCDEFu64; 182 | /// let m = 0x3456789ABCDEF000u64; 183 | /// 184 | /// assert_eq!(n.signed_shl(12), m); 185 | /// ``` 186 | fn signed_shl(self, n: u32) -> Self; 187 | 188 | /// Shifts the bits to the right by a specified amount, `n`, copying 189 | /// the "sign bit" in the most significant bits even for unsigned types. 190 | /// 191 | /// This is bitwise equivalent to signed `Shr`. 192 | /// 193 | /// # Examples 194 | /// 195 | /// ``` 196 | /// use num_traits::PrimInt; 197 | /// 198 | /// let n = 0xFEDCBA9876543210u64; 199 | /// let m = 0xFFFFEDCBA9876543u64; 200 | /// 201 | /// assert_eq!(n.signed_shr(12), m); 202 | /// ``` 203 | fn signed_shr(self, n: u32) -> Self; 204 | 205 | /// Shifts the bits to the left by a specified amount, `n`, filling 206 | /// zeros in the least significant bits. 207 | /// 208 | /// This is bitwise equivalent to unsigned `Shl`. 209 | /// 210 | /// # Examples 211 | /// 212 | /// ``` 213 | /// use num_traits::PrimInt; 214 | /// 215 | /// let n = 0x0123456789ABCDEFi64; 216 | /// let m = 0x3456789ABCDEF000i64; 217 | /// 218 | /// assert_eq!(n.unsigned_shl(12), m); 219 | /// ``` 220 | fn unsigned_shl(self, n: u32) -> Self; 221 | 222 | /// Shifts the bits to the right by a specified amount, `n`, filling 223 | /// zeros in the most significant bits. 224 | /// 225 | /// This is bitwise equivalent to unsigned `Shr`. 226 | /// 227 | /// # Examples 228 | /// 229 | /// ``` 230 | /// use num_traits::PrimInt; 231 | /// 232 | /// let n = -8i8; // 0b11111000 233 | /// let m = 62i8; // 0b00111110 234 | /// 235 | /// assert_eq!(n.unsigned_shr(2), m); 236 | /// ``` 237 | fn unsigned_shr(self, n: u32) -> Self; 238 | 239 | /// Reverses the byte order of the integer. 240 | /// 241 | /// # Examples 242 | /// 243 | /// ``` 244 | /// use num_traits::PrimInt; 245 | /// 246 | /// let n = 0x0123456789ABCDEFu64; 247 | /// let m = 0xEFCDAB8967452301u64; 248 | /// 249 | /// assert_eq!(n.swap_bytes(), m); 250 | /// ``` 251 | fn swap_bytes(self) -> Self; 252 | 253 | /// Reverses the order of bits in the integer. 254 | /// 255 | /// The least significant bit becomes the most significant bit, second least-significant bit 256 | /// becomes second most-significant bit, etc. 257 | /// 258 | /// # Examples 259 | /// 260 | /// ``` 261 | /// use num_traits::PrimInt; 262 | /// 263 | /// let n = 0x12345678u32; 264 | /// let m = 0x1e6a2c48u32; 265 | /// 266 | /// assert_eq!(n.reverse_bits(), m); 267 | /// assert_eq!(0u32.reverse_bits(), 0); 268 | /// ``` 269 | fn reverse_bits(self) -> Self { 270 | reverse_bits_fallback(self) 271 | } 272 | 273 | /// Convert an integer from big endian to the target's endianness. 274 | /// 275 | /// On big endian this is a no-op. On little endian the bytes are swapped. 276 | /// 277 | /// # Examples 278 | /// 279 | /// ``` 280 | /// use num_traits::PrimInt; 281 | /// 282 | /// let n = 0x0123456789ABCDEFu64; 283 | /// 284 | /// if cfg!(target_endian = "big") { 285 | /// assert_eq!(u64::from_be(n), n) 286 | /// } else { 287 | /// assert_eq!(u64::from_be(n), n.swap_bytes()) 288 | /// } 289 | /// ``` 290 | fn from_be(x: Self) -> Self; 291 | 292 | /// Convert an integer from little endian to the target's endianness. 293 | /// 294 | /// On little endian this is a no-op. On big endian the bytes are swapped. 295 | /// 296 | /// # Examples 297 | /// 298 | /// ``` 299 | /// use num_traits::PrimInt; 300 | /// 301 | /// let n = 0x0123456789ABCDEFu64; 302 | /// 303 | /// if cfg!(target_endian = "little") { 304 | /// assert_eq!(u64::from_le(n), n) 305 | /// } else { 306 | /// assert_eq!(u64::from_le(n), n.swap_bytes()) 307 | /// } 308 | /// ``` 309 | fn from_le(x: Self) -> Self; 310 | 311 | /// Convert `self` to big endian from the target's endianness. 312 | /// 313 | /// On big endian this is a no-op. On little endian the bytes are swapped. 314 | /// 315 | /// # Examples 316 | /// 317 | /// ``` 318 | /// use num_traits::PrimInt; 319 | /// 320 | /// let n = 0x0123456789ABCDEFu64; 321 | /// 322 | /// if cfg!(target_endian = "big") { 323 | /// assert_eq!(n.to_be(), n) 324 | /// } else { 325 | /// assert_eq!(n.to_be(), n.swap_bytes()) 326 | /// } 327 | /// ``` 328 | fn to_be(self) -> Self; 329 | 330 | /// Convert `self` to little endian from the target's endianness. 331 | /// 332 | /// On little endian this is a no-op. On big endian the bytes are swapped. 333 | /// 334 | /// # Examples 335 | /// 336 | /// ``` 337 | /// use num_traits::PrimInt; 338 | /// 339 | /// let n = 0x0123456789ABCDEFu64; 340 | /// 341 | /// if cfg!(target_endian = "little") { 342 | /// assert_eq!(n.to_le(), n) 343 | /// } else { 344 | /// assert_eq!(n.to_le(), n.swap_bytes()) 345 | /// } 346 | /// ``` 347 | fn to_le(self) -> Self; 348 | 349 | /// Raises self to the power of `exp`, using exponentiation by squaring. 350 | /// 351 | /// # Examples 352 | /// 353 | /// ``` 354 | /// use num_traits::PrimInt; 355 | /// 356 | /// assert_eq!(2i32.pow(4), 16); 357 | /// ``` 358 | fn pow(self, exp: u32) -> Self; 359 | } 360 | 361 | fn one_per_byte() -> P { 362 | // i8, u8: return 0x01 363 | // i16, u16: return 0x0101 = (0x01 << 8) | 0x01 364 | // i32, u32: return 0x01010101 = (0x0101 << 16) | 0x0101 365 | // ... 366 | let mut ret = P::one(); 367 | let mut shift = 8; 368 | let mut b = ret.count_zeros() >> 3; 369 | while b != 0 { 370 | ret = (ret << shift) | ret; 371 | shift <<= 1; 372 | b >>= 1; 373 | } 374 | ret 375 | } 376 | 377 | fn reverse_bits_fallback(i: P) -> P { 378 | let rep_01: P = one_per_byte(); 379 | let rep_03 = (rep_01 << 1) | rep_01; 380 | let rep_05 = (rep_01 << 2) | rep_01; 381 | let rep_0f = (rep_03 << 2) | rep_03; 382 | let rep_33 = (rep_03 << 4) | rep_03; 383 | let rep_55 = (rep_05 << 4) | rep_05; 384 | 385 | // code above only used to determine rep_0f, rep_33, rep_55; 386 | // optimizer should be able to do it in compile time 387 | let mut ret = i.swap_bytes(); 388 | ret = ((ret & rep_0f) << 4) | ((ret >> 4) & rep_0f); 389 | ret = ((ret & rep_33) << 2) | ((ret >> 2) & rep_33); 390 | ret = ((ret & rep_55) << 1) | ((ret >> 1) & rep_55); 391 | ret 392 | } 393 | 394 | macro_rules! prim_int_impl { 395 | ($T:ty, $S:ty, $U:ty) => { 396 | impl PrimInt for $T { 397 | #[inline] 398 | fn count_ones(self) -> u32 { 399 | <$T>::count_ones(self) 400 | } 401 | 402 | #[inline] 403 | fn count_zeros(self) -> u32 { 404 | <$T>::count_zeros(self) 405 | } 406 | 407 | #[inline] 408 | fn leading_ones(self) -> u32 { 409 | <$T>::leading_ones(self) 410 | } 411 | 412 | #[inline] 413 | fn leading_zeros(self) -> u32 { 414 | <$T>::leading_zeros(self) 415 | } 416 | 417 | #[inline] 418 | fn trailing_ones(self) -> u32 { 419 | <$T>::trailing_ones(self) 420 | } 421 | 422 | #[inline] 423 | fn trailing_zeros(self) -> u32 { 424 | <$T>::trailing_zeros(self) 425 | } 426 | 427 | #[inline] 428 | fn rotate_left(self, n: u32) -> Self { 429 | <$T>::rotate_left(self, n) 430 | } 431 | 432 | #[inline] 433 | fn rotate_right(self, n: u32) -> Self { 434 | <$T>::rotate_right(self, n) 435 | } 436 | 437 | #[inline] 438 | fn signed_shl(self, n: u32) -> Self { 439 | ((self as $S) << n) as $T 440 | } 441 | 442 | #[inline] 443 | fn signed_shr(self, n: u32) -> Self { 444 | ((self as $S) >> n) as $T 445 | } 446 | 447 | #[inline] 448 | fn unsigned_shl(self, n: u32) -> Self { 449 | ((self as $U) << n) as $T 450 | } 451 | 452 | #[inline] 453 | fn unsigned_shr(self, n: u32) -> Self { 454 | ((self as $U) >> n) as $T 455 | } 456 | 457 | #[inline] 458 | fn swap_bytes(self) -> Self { 459 | <$T>::swap_bytes(self) 460 | } 461 | 462 | #[inline] 463 | fn reverse_bits(self) -> Self { 464 | <$T>::reverse_bits(self) 465 | } 466 | 467 | #[inline] 468 | fn from_be(x: Self) -> Self { 469 | <$T>::from_be(x) 470 | } 471 | 472 | #[inline] 473 | fn from_le(x: Self) -> Self { 474 | <$T>::from_le(x) 475 | } 476 | 477 | #[inline] 478 | fn to_be(self) -> Self { 479 | <$T>::to_be(self) 480 | } 481 | 482 | #[inline] 483 | fn to_le(self) -> Self { 484 | <$T>::to_le(self) 485 | } 486 | 487 | #[inline] 488 | fn pow(self, exp: u32) -> Self { 489 | <$T>::pow(self, exp) 490 | } 491 | } 492 | }; 493 | } 494 | 495 | // prim_int_impl!(type, signed, unsigned); 496 | prim_int_impl!(u8, i8, u8); 497 | prim_int_impl!(u16, i16, u16); 498 | prim_int_impl!(u32, i32, u32); 499 | prim_int_impl!(u64, i64, u64); 500 | prim_int_impl!(u128, i128, u128); 501 | prim_int_impl!(usize, isize, usize); 502 | prim_int_impl!(i8, i8, u8); 503 | prim_int_impl!(i16, i16, u16); 504 | prim_int_impl!(i32, i32, u32); 505 | prim_int_impl!(i64, i64, u64); 506 | prim_int_impl!(i128, i128, u128); 507 | prim_int_impl!(isize, isize, usize); 508 | 509 | #[cfg(test)] 510 | mod tests { 511 | use crate::int::PrimInt; 512 | 513 | #[test] 514 | pub fn reverse_bits() { 515 | use core::{i16, i32, i64, i8}; 516 | 517 | assert_eq!( 518 | PrimInt::reverse_bits(0x0123_4567_89ab_cdefu64), 519 | 0xf7b3_d591_e6a2_c480 520 | ); 521 | 522 | assert_eq!(PrimInt::reverse_bits(0i8), 0); 523 | assert_eq!(PrimInt::reverse_bits(-1i8), -1); 524 | assert_eq!(PrimInt::reverse_bits(1i8), i8::MIN); 525 | assert_eq!(PrimInt::reverse_bits(i8::MIN), 1); 526 | assert_eq!(PrimInt::reverse_bits(-2i8), i8::MAX); 527 | assert_eq!(PrimInt::reverse_bits(i8::MAX), -2); 528 | 529 | assert_eq!(PrimInt::reverse_bits(0i16), 0); 530 | assert_eq!(PrimInt::reverse_bits(-1i16), -1); 531 | assert_eq!(PrimInt::reverse_bits(1i16), i16::MIN); 532 | assert_eq!(PrimInt::reverse_bits(i16::MIN), 1); 533 | assert_eq!(PrimInt::reverse_bits(-2i16), i16::MAX); 534 | assert_eq!(PrimInt::reverse_bits(i16::MAX), -2); 535 | 536 | assert_eq!(PrimInt::reverse_bits(0i32), 0); 537 | assert_eq!(PrimInt::reverse_bits(-1i32), -1); 538 | assert_eq!(PrimInt::reverse_bits(1i32), i32::MIN); 539 | assert_eq!(PrimInt::reverse_bits(i32::MIN), 1); 540 | assert_eq!(PrimInt::reverse_bits(-2i32), i32::MAX); 541 | assert_eq!(PrimInt::reverse_bits(i32::MAX), -2); 542 | 543 | assert_eq!(PrimInt::reverse_bits(0i64), 0); 544 | assert_eq!(PrimInt::reverse_bits(-1i64), -1); 545 | assert_eq!(PrimInt::reverse_bits(1i64), i64::MIN); 546 | assert_eq!(PrimInt::reverse_bits(i64::MIN), 1); 547 | assert_eq!(PrimInt::reverse_bits(-2i64), i64::MAX); 548 | assert_eq!(PrimInt::reverse_bits(i64::MAX), -2); 549 | } 550 | 551 | #[test] 552 | pub fn reverse_bits_i128() { 553 | use core::i128; 554 | 555 | assert_eq!(PrimInt::reverse_bits(0i128), 0); 556 | assert_eq!(PrimInt::reverse_bits(-1i128), -1); 557 | assert_eq!(PrimInt::reverse_bits(1i128), i128::MIN); 558 | assert_eq!(PrimInt::reverse_bits(i128::MIN), 1); 559 | assert_eq!(PrimInt::reverse_bits(-2i128), i128::MAX); 560 | assert_eq!(PrimInt::reverse_bits(i128::MAX), -2); 561 | } 562 | } 563 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | 11 | //! Numeric traits for generic mathematics 12 | //! 13 | //! ## Compatibility 14 | //! 15 | //! The `num-traits` crate is tested for rustc 1.60 and greater. 16 | 17 | #![doc(html_root_url = "https://docs.rs/num-traits/0.2")] 18 | #![deny(unconditional_recursion)] 19 | #![no_std] 20 | 21 | // Need to explicitly bring the crate in for inherent float methods 22 | #[cfg(feature = "std")] 23 | extern crate std; 24 | 25 | use core::fmt; 26 | use core::num::Wrapping; 27 | use core::ops::{Add, Div, Mul, Rem, Sub}; 28 | use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; 29 | 30 | pub use crate::bounds::Bounded; 31 | #[cfg(any(feature = "std", feature = "libm"))] 32 | pub use crate::float::Float; 33 | pub use crate::float::FloatConst; 34 | // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. 35 | pub use crate::cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; 36 | pub use crate::identities::{one, zero, ConstOne, ConstZero, One, Zero}; 37 | pub use crate::int::PrimInt; 38 | pub use crate::ops::bytes::{FromBytes, ToBytes}; 39 | pub use crate::ops::checked::{ 40 | CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, 41 | }; 42 | pub use crate::ops::euclid::{CheckedEuclid, Euclid}; 43 | pub use crate::ops::inv::Inv; 44 | pub use crate::ops::mul_add::{MulAdd, MulAddAssign}; 45 | pub use crate::ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; 46 | pub use crate::ops::wrapping::{ 47 | WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, 48 | }; 49 | pub use crate::pow::{checked_pow, pow, Pow}; 50 | pub use crate::sign::{abs, abs_sub, signum, Signed, Unsigned}; 51 | 52 | #[macro_use] 53 | mod macros; 54 | 55 | pub mod bounds; 56 | pub mod cast; 57 | pub mod float; 58 | pub mod identities; 59 | pub mod int; 60 | pub mod ops; 61 | pub mod pow; 62 | pub mod real; 63 | pub mod sign; 64 | 65 | /// The base trait for numeric types, covering `0` and `1` values, 66 | /// comparisons, basic numeric operations, and string conversion. 67 | pub trait Num: PartialEq + Zero + One + NumOps { 68 | type FromStrRadixErr; 69 | 70 | /// Convert from a string and radix (typically `2..=36`). 71 | /// 72 | /// # Examples 73 | /// 74 | /// ```rust 75 | /// use num_traits::Num; 76 | /// 77 | /// let result = ::from_str_radix("27", 10); 78 | /// assert_eq!(result, Ok(27)); 79 | /// 80 | /// let result = ::from_str_radix("foo", 10); 81 | /// assert!(result.is_err()); 82 | /// ``` 83 | /// 84 | /// # Supported radices 85 | /// 86 | /// The exact range of supported radices is at the discretion of each type implementation. For 87 | /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the 88 | /// standard library, which **panic** if the radix is not in the range from 2 to 36. The 89 | /// implementation in this crate for primitive floats is similar. 90 | /// 91 | /// For third-party types, it is suggested that implementations should follow suit and at least 92 | /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix. 93 | /// It's possible that a type might not even support the common radix 10, nor any, if string 94 | /// parsing doesn't make sense for that type. 95 | fn from_str_radix(str: &str, radix: u32) -> Result; 96 | } 97 | 98 | /// Generic trait for types implementing basic numeric operations 99 | /// 100 | /// This is automatically implemented for types which implement the operators. 101 | pub trait NumOps: 102 | Add 103 | + Sub 104 | + Mul 105 | + Div 106 | + Rem 107 | { 108 | } 109 | 110 | impl NumOps for T where 111 | T: Add 112 | + Sub 113 | + Mul 114 | + Div 115 | + Rem 116 | { 117 | } 118 | 119 | /// The trait for `Num` types which also implement numeric operations taking 120 | /// the second operand by reference. 121 | /// 122 | /// This is automatically implemented for types which implement the operators. 123 | pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} 124 | impl NumRef for T where T: Num + for<'r> NumOps<&'r T> {} 125 | 126 | /// The trait for `Num` references which implement numeric operations, taking the 127 | /// second operand either by value or by reference. 128 | /// 129 | /// This is automatically implemented for all types which implement the operators. It covers 130 | /// every type implementing the operations though, regardless of it being a reference or 131 | /// related to `Num`. 132 | pub trait RefNum: NumOps + for<'r> NumOps<&'r Base, Base> {} 133 | impl RefNum for T where T: NumOps + for<'r> NumOps<&'r Base, Base> {} 134 | 135 | /// Generic trait for types implementing numeric assignment operators (like `+=`). 136 | /// 137 | /// This is automatically implemented for types which implement the operators. 138 | pub trait NumAssignOps: 139 | AddAssign + SubAssign + MulAssign + DivAssign + RemAssign 140 | { 141 | } 142 | 143 | impl NumAssignOps for T where 144 | T: AddAssign + SubAssign + MulAssign + DivAssign + RemAssign 145 | { 146 | } 147 | 148 | /// The trait for `Num` types which also implement assignment operators. 149 | /// 150 | /// This is automatically implemented for types which implement the operators. 151 | pub trait NumAssign: Num + NumAssignOps {} 152 | impl NumAssign for T where T: Num + NumAssignOps {} 153 | 154 | /// The trait for `NumAssign` types which also implement assignment operations 155 | /// taking the second operand by reference. 156 | /// 157 | /// This is automatically implemented for types which implement the operators. 158 | pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} 159 | impl NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} 160 | 161 | macro_rules! int_trait_impl { 162 | ($name:ident for $($t:ty)*) => ($( 163 | impl $name for $t { 164 | type FromStrRadixErr = ::core::num::ParseIntError; 165 | #[inline] 166 | fn from_str_radix(s: &str, radix: u32) 167 | -> Result 168 | { 169 | <$t>::from_str_radix(s, radix) 170 | } 171 | } 172 | )*) 173 | } 174 | int_trait_impl!(Num for usize u8 u16 u32 u64 u128); 175 | int_trait_impl!(Num for isize i8 i16 i32 i64 i128); 176 | 177 | impl Num for Wrapping 178 | where 179 | Wrapping: NumOps, 180 | { 181 | type FromStrRadixErr = T::FromStrRadixErr; 182 | fn from_str_radix(str: &str, radix: u32) -> Result { 183 | T::from_str_radix(str, radix).map(Wrapping) 184 | } 185 | } 186 | 187 | #[derive(Debug)] 188 | pub enum FloatErrorKind { 189 | Empty, 190 | Invalid, 191 | } 192 | // FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us, 193 | // so there's not really any way for us to reuse it. 194 | #[derive(Debug)] 195 | pub struct ParseFloatError { 196 | pub kind: FloatErrorKind, 197 | } 198 | 199 | impl fmt::Display for ParseFloatError { 200 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 201 | let description = match self.kind { 202 | FloatErrorKind::Empty => "cannot parse float from empty string", 203 | FloatErrorKind::Invalid => "invalid float literal", 204 | }; 205 | 206 | description.fmt(f) 207 | } 208 | } 209 | 210 | fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool { 211 | a.len() == b.len() 212 | && a.bytes().zip(b.bytes()).all(|(a, b)| { 213 | let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5); 214 | a_to_ascii_lower == b 215 | }) 216 | } 217 | 218 | // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck 219 | // with this implementation ourselves until we want to make a breaking change. 220 | // (would have to drop it from `Num` though) 221 | macro_rules! float_trait_impl { 222 | ($name:ident for $($t:ident)*) => ($( 223 | impl $name for $t { 224 | type FromStrRadixErr = ParseFloatError; 225 | 226 | fn from_str_radix(src: &str, radix: u32) 227 | -> Result 228 | { 229 | use self::FloatErrorKind::*; 230 | use self::ParseFloatError as PFE; 231 | 232 | // Special case radix 10 to use more accurate standard library implementation 233 | if radix == 10 { 234 | return src.parse().map_err(|_| PFE { 235 | kind: if src.is_empty() { Empty } else { Invalid }, 236 | }); 237 | } 238 | 239 | // Special values 240 | if str_to_ascii_lower_eq_str(src, "inf") 241 | || str_to_ascii_lower_eq_str(src, "infinity") 242 | { 243 | return Ok(core::$t::INFINITY); 244 | } else if str_to_ascii_lower_eq_str(src, "-inf") 245 | || str_to_ascii_lower_eq_str(src, "-infinity") 246 | { 247 | return Ok(core::$t::NEG_INFINITY); 248 | } else if str_to_ascii_lower_eq_str(src, "nan") { 249 | return Ok(core::$t::NAN); 250 | } else if str_to_ascii_lower_eq_str(src, "-nan") { 251 | return Ok(-core::$t::NAN); 252 | } 253 | 254 | fn slice_shift_char(src: &str) -> Option<(char, &str)> { 255 | let mut chars = src.chars(); 256 | Some((chars.next()?, chars.as_str())) 257 | } 258 | 259 | let (is_positive, src) = match slice_shift_char(src) { 260 | None => return Err(PFE { kind: Empty }), 261 | Some(('-', "")) => return Err(PFE { kind: Empty }), 262 | Some(('-', src)) => (false, src), 263 | Some((_, _)) => (true, src), 264 | }; 265 | 266 | // The significand to accumulate 267 | let mut sig = if is_positive { 0.0 } else { -0.0 }; 268 | // Necessary to detect overflow 269 | let mut prev_sig = sig; 270 | let mut cs = src.chars().enumerate(); 271 | // Exponent prefix and exponent index offset 272 | let mut exp_info = None::<(char, usize)>; 273 | 274 | // Parse the integer part of the significand 275 | for (i, c) in cs.by_ref() { 276 | match c.to_digit(radix) { 277 | Some(digit) => { 278 | // shift significand one digit left 279 | sig *= radix as $t; 280 | 281 | // add/subtract current digit depending on sign 282 | if is_positive { 283 | sig += (digit as isize) as $t; 284 | } else { 285 | sig -= (digit as isize) as $t; 286 | } 287 | 288 | // Detect overflow by comparing to last value, except 289 | // if we've not seen any non-zero digits. 290 | if prev_sig != 0.0 { 291 | if is_positive && sig <= prev_sig 292 | { return Ok(core::$t::INFINITY); } 293 | if !is_positive && sig >= prev_sig 294 | { return Ok(core::$t::NEG_INFINITY); } 295 | 296 | // Detect overflow by reversing the shift-and-add process 297 | if is_positive && (prev_sig != (sig - digit as $t) / radix as $t) 298 | { return Ok(core::$t::INFINITY); } 299 | if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t) 300 | { return Ok(core::$t::NEG_INFINITY); } 301 | } 302 | prev_sig = sig; 303 | }, 304 | None => match c { 305 | 'e' | 'E' | 'p' | 'P' => { 306 | exp_info = Some((c, i + 1)); 307 | break; // start of exponent 308 | }, 309 | '.' => { 310 | break; // start of fractional part 311 | }, 312 | _ => { 313 | return Err(PFE { kind: Invalid }); 314 | }, 315 | }, 316 | } 317 | } 318 | 319 | // If we are not yet at the exponent parse the fractional 320 | // part of the significand 321 | if exp_info.is_none() { 322 | let mut power = 1.0; 323 | for (i, c) in cs.by_ref() { 324 | match c.to_digit(radix) { 325 | Some(digit) => { 326 | // Decrease power one order of magnitude 327 | power /= radix as $t; 328 | // add/subtract current digit depending on sign 329 | sig = if is_positive { 330 | sig + (digit as $t) * power 331 | } else { 332 | sig - (digit as $t) * power 333 | }; 334 | // Detect overflow by comparing to last value 335 | if is_positive && sig < prev_sig 336 | { return Ok(core::$t::INFINITY); } 337 | if !is_positive && sig > prev_sig 338 | { return Ok(core::$t::NEG_INFINITY); } 339 | prev_sig = sig; 340 | }, 341 | None => match c { 342 | 'e' | 'E' | 'p' | 'P' => { 343 | exp_info = Some((c, i + 1)); 344 | break; // start of exponent 345 | }, 346 | _ => { 347 | return Err(PFE { kind: Invalid }); 348 | }, 349 | }, 350 | } 351 | } 352 | } 353 | 354 | // Parse and calculate the exponent 355 | let exp = match exp_info { 356 | Some((c, offset)) => { 357 | let base = match c { 358 | 'E' | 'e' if radix == 10 => 10.0, 359 | 'P' | 'p' if radix == 16 => 2.0, 360 | _ => return Err(PFE { kind: Invalid }), 361 | }; 362 | 363 | // Parse the exponent as decimal integer 364 | let src = &src[offset..]; 365 | let (is_positive, exp) = match slice_shift_char(src) { 366 | Some(('-', src)) => (false, src.parse::()), 367 | Some(('+', src)) => (true, src.parse::()), 368 | Some((_, _)) => (true, src.parse::()), 369 | None => return Err(PFE { kind: Invalid }), 370 | }; 371 | 372 | #[cfg(feature = "std")] 373 | fn pow(base: $t, exp: usize) -> $t { 374 | Float::powi(base, exp as i32) 375 | } 376 | // otherwise uses the generic `pow` from the root 377 | 378 | match (is_positive, exp) { 379 | (true, Ok(exp)) => pow(base, exp), 380 | (false, Ok(exp)) => 1.0 / pow(base, exp), 381 | (_, Err(_)) => return Err(PFE { kind: Invalid }), 382 | } 383 | }, 384 | None => 1.0, // no exponent 385 | }; 386 | 387 | Ok(sig * exp) 388 | } 389 | } 390 | )*) 391 | } 392 | float_trait_impl!(Num for f32 f64); 393 | 394 | /// A value bounded by a minimum and a maximum 395 | /// 396 | /// If input is less than min then this returns min. 397 | /// If input is greater than max then this returns max. 398 | /// Otherwise this returns input. 399 | /// 400 | /// **Panics** in debug mode if `!(min <= max)`. 401 | #[inline] 402 | pub fn clamp(input: T, min: T, max: T) -> T { 403 | debug_assert!(min <= max, "min must be less than or equal to max"); 404 | if input < min { 405 | min 406 | } else if input > max { 407 | max 408 | } else { 409 | input 410 | } 411 | } 412 | 413 | /// A value bounded by a minimum value 414 | /// 415 | /// If input is less than min then this returns min. 416 | /// Otherwise this returns input. 417 | /// `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`. 418 | /// 419 | /// **Panics** in debug mode if `!(min == min)`. (This occurs if `min` is `NAN`.) 420 | #[inline] 421 | #[allow(clippy::eq_op)] 422 | pub fn clamp_min(input: T, min: T) -> T { 423 | debug_assert!(min == min, "min must not be NAN"); 424 | if input < min { 425 | min 426 | } else { 427 | input 428 | } 429 | } 430 | 431 | /// A value bounded by a maximum value 432 | /// 433 | /// If input is greater than max then this returns max. 434 | /// Otherwise this returns input. 435 | /// `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`. 436 | /// 437 | /// **Panics** in debug mode if `!(max == max)`. (This occurs if `max` is `NAN`.) 438 | #[inline] 439 | #[allow(clippy::eq_op)] 440 | pub fn clamp_max(input: T, max: T) -> T { 441 | debug_assert!(max == max, "max must not be NAN"); 442 | if input > max { 443 | max 444 | } else { 445 | input 446 | } 447 | } 448 | 449 | #[test] 450 | fn clamp_test() { 451 | // Int test 452 | assert_eq!(1, clamp(1, -1, 2)); 453 | assert_eq!(-1, clamp(-2, -1, 2)); 454 | assert_eq!(2, clamp(3, -1, 2)); 455 | assert_eq!(1, clamp_min(1, -1)); 456 | assert_eq!(-1, clamp_min(-2, -1)); 457 | assert_eq!(-1, clamp_max(1, -1)); 458 | assert_eq!(-2, clamp_max(-2, -1)); 459 | 460 | // Float test 461 | assert_eq!(1.0, clamp(1.0, -1.0, 2.0)); 462 | assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0)); 463 | assert_eq!(2.0, clamp(3.0, -1.0, 2.0)); 464 | assert_eq!(1.0, clamp_min(1.0, -1.0)); 465 | assert_eq!(-1.0, clamp_min(-2.0, -1.0)); 466 | assert_eq!(-1.0, clamp_max(1.0, -1.0)); 467 | assert_eq!(-2.0, clamp_max(-2.0, -1.0)); 468 | assert!(clamp(::core::f32::NAN, -1.0, 1.0).is_nan()); 469 | assert!(clamp_min(::core::f32::NAN, 1.0).is_nan()); 470 | assert!(clamp_max(::core::f32::NAN, 1.0).is_nan()); 471 | } 472 | 473 | #[test] 474 | #[should_panic] 475 | #[cfg(debug_assertions)] 476 | fn clamp_nan_min() { 477 | clamp(0., ::core::f32::NAN, 1.); 478 | } 479 | 480 | #[test] 481 | #[should_panic] 482 | #[cfg(debug_assertions)] 483 | fn clamp_nan_max() { 484 | clamp(0., -1., ::core::f32::NAN); 485 | } 486 | 487 | #[test] 488 | #[should_panic] 489 | #[cfg(debug_assertions)] 490 | fn clamp_nan_min_max() { 491 | clamp(0., ::core::f32::NAN, ::core::f32::NAN); 492 | } 493 | 494 | #[test] 495 | #[should_panic] 496 | #[cfg(debug_assertions)] 497 | fn clamp_min_nan_min() { 498 | clamp_min(0., ::core::f32::NAN); 499 | } 500 | 501 | #[test] 502 | #[should_panic] 503 | #[cfg(debug_assertions)] 504 | fn clamp_max_nan_max() { 505 | clamp_max(0., ::core::f32::NAN); 506 | } 507 | 508 | #[test] 509 | fn from_str_radix_unwrap() { 510 | // The Result error must impl Debug to allow unwrap() 511 | 512 | let i: i32 = Num::from_str_radix("0", 10).unwrap(); 513 | assert_eq!(i, 0); 514 | 515 | let f: f32 = Num::from_str_radix("0.0", 10).unwrap(); 516 | assert_eq!(f, 0.0); 517 | } 518 | 519 | #[test] 520 | fn from_str_radix_multi_byte_fail() { 521 | // Ensure parsing doesn't panic, even on invalid sign characters 522 | assert!(f32::from_str_radix("™0.2", 10).is_err()); 523 | 524 | // Even when parsing the exponent sign 525 | assert!(f32::from_str_radix("0.2E™1", 10).is_err()); 526 | } 527 | 528 | #[test] 529 | fn from_str_radix_ignore_case() { 530 | assert_eq!( 531 | f32::from_str_radix("InF", 16).unwrap(), 532 | ::core::f32::INFINITY 533 | ); 534 | assert_eq!( 535 | f32::from_str_radix("InfinitY", 16).unwrap(), 536 | ::core::f32::INFINITY 537 | ); 538 | assert_eq!( 539 | f32::from_str_radix("-InF", 8).unwrap(), 540 | ::core::f32::NEG_INFINITY 541 | ); 542 | assert_eq!( 543 | f32::from_str_radix("-InfinitY", 8).unwrap(), 544 | ::core::f32::NEG_INFINITY 545 | ); 546 | assert!(f32::from_str_radix("nAn", 4).unwrap().is_nan()); 547 | assert!(f32::from_str_radix("-nAn", 4).unwrap().is_nan()); 548 | } 549 | 550 | #[test] 551 | fn wrapping_is_num() { 552 | fn require_num(_: &T) {} 553 | require_num(&Wrapping(42_u32)); 554 | require_num(&Wrapping(-42)); 555 | } 556 | 557 | #[test] 558 | fn wrapping_from_str_radix() { 559 | macro_rules! test_wrapping_from_str_radix { 560 | ($($t:ty)+) => { 561 | $( 562 | for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { 563 | let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); 564 | assert_eq!(w, <$t as Num>::from_str_radix(s, r)); 565 | } 566 | )+ 567 | }; 568 | } 569 | 570 | test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); 571 | } 572 | 573 | #[test] 574 | fn check_num_ops() { 575 | fn compute(x: T, y: T) -> T { 576 | x * y / y % y + y - y 577 | } 578 | assert_eq!(compute(1, 2), 1) 579 | } 580 | 581 | #[test] 582 | fn check_numref_ops() { 583 | fn compute(x: T, y: &T) -> T { 584 | x * y / y % y + y - y 585 | } 586 | assert_eq!(compute(1, &2), 1) 587 | } 588 | 589 | #[test] 590 | fn check_refnum_ops() { 591 | fn compute(x: &T, y: T) -> T 592 | where 593 | for<'a> &'a T: RefNum, 594 | { 595 | &(&(&(&(x * y) / y) % y) + y) - y 596 | } 597 | assert_eq!(compute(&1, 2), 1) 598 | } 599 | 600 | #[test] 601 | fn check_refref_ops() { 602 | fn compute(x: &T, y: &T) -> T 603 | where 604 | for<'a> &'a T: RefNum, 605 | { 606 | &(&(&(&(x * y) / y) % y) + y) - y 607 | } 608 | assert_eq!(compute(&1, &2), 1) 609 | } 610 | 611 | #[test] 612 | fn check_numassign_ops() { 613 | fn compute(mut x: T, y: T) -> T { 614 | x *= y; 615 | x /= y; 616 | x %= y; 617 | x += y; 618 | x -= y; 619 | x 620 | } 621 | assert_eq!(compute(1, 2), 1) 622 | } 623 | 624 | #[test] 625 | fn check_numassignref_ops() { 626 | fn compute(mut x: T, y: &T) -> T { 627 | x *= y; 628 | x /= y; 629 | x %= y; 630 | x += y; 631 | x -= y; 632 | x 633 | } 634 | assert_eq!(compute(1, &2), 1) 635 | } 636 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | // not all are used in all features configurations 2 | #![allow(unused)] 3 | 4 | /// Forward a method to an inherent method or a base trait method. 5 | macro_rules! forward { 6 | ($( Self :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) 7 | => {$( 8 | #[inline] 9 | fn $method(self $( , $arg : $ty )* ) -> $ret { 10 | Self::$method(self $( , $arg )* ) 11 | } 12 | )*}; 13 | ($( $base:ident :: $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) 14 | => {$( 15 | #[inline] 16 | fn $method(self $( , $arg : $ty )* ) -> $ret { 17 | ::$method(self $( , $arg )* ) 18 | } 19 | )*}; 20 | ($( $base:ident :: $method:ident ( $( $arg:ident : $ty:ty ),* ) -> $ret:ty ; )*) 21 | => {$( 22 | #[inline] 23 | fn $method( $( $arg : $ty ),* ) -> $ret { 24 | ::$method( $( $arg ),* ) 25 | } 26 | )*}; 27 | ($( $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*) 28 | => {$( 29 | #[inline] 30 | fn $method(self $( , $arg : $ty )* ) -> $ret { 31 | $imp(self $( , $arg )* ) 32 | } 33 | )*}; 34 | } 35 | 36 | macro_rules! constant { 37 | ($( $method:ident () -> $ret:expr ; )*) 38 | => {$( 39 | #[inline] 40 | fn $method() -> Self { 41 | $ret 42 | } 43 | )*}; 44 | } 45 | -------------------------------------------------------------------------------- /src/ops/bytes.rs: -------------------------------------------------------------------------------- 1 | use core::borrow::{Borrow, BorrowMut}; 2 | use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; 3 | use core::fmt::Debug; 4 | use core::hash::Hash; 5 | 6 | pub trait NumBytes: 7 | Debug 8 | + AsRef<[u8]> 9 | + AsMut<[u8]> 10 | + PartialEq 11 | + Eq 12 | + PartialOrd 13 | + Ord 14 | + Hash 15 | + Borrow<[u8]> 16 | + BorrowMut<[u8]> 17 | { 18 | } 19 | 20 | impl NumBytes for T where 21 | T: Debug 22 | + AsRef<[u8]> 23 | + AsMut<[u8]> 24 | + PartialEq 25 | + Eq 26 | + PartialOrd 27 | + Ord 28 | + Hash 29 | + Borrow<[u8]> 30 | + BorrowMut<[u8]> 31 | + ?Sized 32 | { 33 | } 34 | 35 | pub trait ToBytes { 36 | type Bytes: NumBytes; 37 | 38 | /// Return the memory representation of this number as a byte array in big-endian byte order. 39 | /// 40 | /// # Examples 41 | /// 42 | /// ``` 43 | /// use num_traits::ToBytes; 44 | /// 45 | /// let bytes = ToBytes::to_be_bytes(&0x12345678u32); 46 | /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); 47 | /// ``` 48 | fn to_be_bytes(&self) -> Self::Bytes; 49 | 50 | /// Return the memory representation of this number as a byte array in little-endian byte order. 51 | /// 52 | /// # Examples 53 | /// 54 | /// ``` 55 | /// use num_traits::ToBytes; 56 | /// 57 | /// let bytes = ToBytes::to_le_bytes(&0x12345678u32); 58 | /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); 59 | /// ``` 60 | fn to_le_bytes(&self) -> Self::Bytes; 61 | 62 | /// Return the memory representation of this number as a byte array in native byte order. 63 | /// 64 | /// As the target platform's native endianness is used, 65 | /// portable code should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. 66 | /// 67 | /// [`to_be_bytes`]: #method.to_be_bytes 68 | /// [`to_le_bytes`]: #method.to_le_bytes 69 | /// 70 | /// # Examples 71 | /// 72 | /// ``` 73 | /// use num_traits::ToBytes; 74 | /// 75 | /// #[cfg(target_endian = "big")] 76 | /// let expected = [0x12, 0x34, 0x56, 0x78]; 77 | /// 78 | /// #[cfg(target_endian = "little")] 79 | /// let expected = [0x78, 0x56, 0x34, 0x12]; 80 | /// 81 | /// let bytes = ToBytes::to_ne_bytes(&0x12345678u32); 82 | /// assert_eq!(bytes, expected) 83 | /// ``` 84 | fn to_ne_bytes(&self) -> Self::Bytes { 85 | #[cfg(target_endian = "big")] 86 | let bytes = self.to_be_bytes(); 87 | #[cfg(target_endian = "little")] 88 | let bytes = self.to_le_bytes(); 89 | bytes 90 | } 91 | } 92 | 93 | pub trait FromBytes: Sized { 94 | type Bytes: NumBytes + ?Sized; 95 | 96 | /// Create a number from its representation as a byte array in big endian. 97 | /// 98 | /// # Examples 99 | /// 100 | /// ``` 101 | /// use num_traits::FromBytes; 102 | /// 103 | /// let value: u32 = FromBytes::from_be_bytes(&[0x12, 0x34, 0x56, 0x78]); 104 | /// assert_eq!(value, 0x12345678); 105 | /// ``` 106 | fn from_be_bytes(bytes: &Self::Bytes) -> Self; 107 | 108 | /// Create a number from its representation as a byte array in little endian. 109 | /// 110 | /// # Examples 111 | /// 112 | /// ``` 113 | /// use num_traits::FromBytes; 114 | /// 115 | /// let value: u32 = FromBytes::from_le_bytes(&[0x78, 0x56, 0x34, 0x12]); 116 | /// assert_eq!(value, 0x12345678); 117 | /// ``` 118 | fn from_le_bytes(bytes: &Self::Bytes) -> Self; 119 | 120 | /// Create a number from its memory representation as a byte array in native endianness. 121 | /// 122 | /// As the target platform's native endianness is used, 123 | /// portable code likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as appropriate instead. 124 | /// 125 | /// [`from_be_bytes`]: #method.from_be_bytes 126 | /// [`from_le_bytes`]: #method.from_le_bytes 127 | /// 128 | /// # Examples 129 | /// 130 | /// ``` 131 | /// use num_traits::FromBytes; 132 | /// 133 | /// #[cfg(target_endian = "big")] 134 | /// let bytes = [0x12, 0x34, 0x56, 0x78]; 135 | /// 136 | /// #[cfg(target_endian = "little")] 137 | /// let bytes = [0x78, 0x56, 0x34, 0x12]; 138 | /// 139 | /// let value: u32 = FromBytes::from_ne_bytes(&bytes); 140 | /// assert_eq!(value, 0x12345678) 141 | /// ``` 142 | fn from_ne_bytes(bytes: &Self::Bytes) -> Self { 143 | #[cfg(target_endian = "big")] 144 | let this = Self::from_be_bytes(bytes); 145 | #[cfg(target_endian = "little")] 146 | let this = Self::from_le_bytes(bytes); 147 | this 148 | } 149 | } 150 | 151 | macro_rules! float_to_from_bytes_impl { 152 | ($T:ty, $L:expr) => { 153 | impl ToBytes for $T { 154 | type Bytes = [u8; $L]; 155 | 156 | #[inline] 157 | fn to_be_bytes(&self) -> Self::Bytes { 158 | <$T>::to_be_bytes(*self) 159 | } 160 | 161 | #[inline] 162 | fn to_le_bytes(&self) -> Self::Bytes { 163 | <$T>::to_le_bytes(*self) 164 | } 165 | 166 | #[inline] 167 | fn to_ne_bytes(&self) -> Self::Bytes { 168 | <$T>::to_ne_bytes(*self) 169 | } 170 | } 171 | 172 | impl FromBytes for $T { 173 | type Bytes = [u8; $L]; 174 | 175 | #[inline] 176 | fn from_be_bytes(bytes: &Self::Bytes) -> Self { 177 | <$T>::from_be_bytes(*bytes) 178 | } 179 | 180 | #[inline] 181 | fn from_le_bytes(bytes: &Self::Bytes) -> Self { 182 | <$T>::from_le_bytes(*bytes) 183 | } 184 | 185 | #[inline] 186 | fn from_ne_bytes(bytes: &Self::Bytes) -> Self { 187 | <$T>::from_ne_bytes(*bytes) 188 | } 189 | } 190 | }; 191 | } 192 | 193 | macro_rules! int_to_from_bytes_impl { 194 | ($T:ty, $L:expr) => { 195 | impl ToBytes for $T { 196 | type Bytes = [u8; $L]; 197 | 198 | #[inline] 199 | fn to_be_bytes(&self) -> Self::Bytes { 200 | <$T>::to_be_bytes(*self) 201 | } 202 | 203 | #[inline] 204 | fn to_le_bytes(&self) -> Self::Bytes { 205 | <$T>::to_le_bytes(*self) 206 | } 207 | 208 | #[inline] 209 | fn to_ne_bytes(&self) -> Self::Bytes { 210 | <$T>::to_ne_bytes(*self) 211 | } 212 | } 213 | 214 | impl FromBytes for $T { 215 | type Bytes = [u8; $L]; 216 | 217 | #[inline] 218 | fn from_be_bytes(bytes: &Self::Bytes) -> Self { 219 | <$T>::from_be_bytes(*bytes) 220 | } 221 | 222 | #[inline] 223 | fn from_le_bytes(bytes: &Self::Bytes) -> Self { 224 | <$T>::from_le_bytes(*bytes) 225 | } 226 | 227 | #[inline] 228 | fn from_ne_bytes(bytes: &Self::Bytes) -> Self { 229 | <$T>::from_ne_bytes(*bytes) 230 | } 231 | } 232 | }; 233 | } 234 | 235 | int_to_from_bytes_impl!(u8, 1); 236 | int_to_from_bytes_impl!(u16, 2); 237 | int_to_from_bytes_impl!(u32, 4); 238 | int_to_from_bytes_impl!(u64, 8); 239 | int_to_from_bytes_impl!(u128, 16); 240 | #[cfg(target_pointer_width = "64")] 241 | int_to_from_bytes_impl!(usize, 8); 242 | #[cfg(target_pointer_width = "32")] 243 | int_to_from_bytes_impl!(usize, 4); 244 | 245 | int_to_from_bytes_impl!(i8, 1); 246 | int_to_from_bytes_impl!(i16, 2); 247 | int_to_from_bytes_impl!(i32, 4); 248 | int_to_from_bytes_impl!(i64, 8); 249 | int_to_from_bytes_impl!(i128, 16); 250 | #[cfg(target_pointer_width = "64")] 251 | int_to_from_bytes_impl!(isize, 8); 252 | #[cfg(target_pointer_width = "32")] 253 | int_to_from_bytes_impl!(isize, 4); 254 | 255 | float_to_from_bytes_impl!(f32, 4); 256 | float_to_from_bytes_impl!(f64, 8); 257 | 258 | #[cfg(test)] 259 | mod tests { 260 | use super::*; 261 | 262 | macro_rules! check_to_from_bytes { 263 | ($( $ty:ty )+) => {$({ 264 | let n = 1; 265 | let be = <$ty as ToBytes>::to_be_bytes(&n); 266 | let le = <$ty as ToBytes>::to_le_bytes(&n); 267 | let ne = <$ty as ToBytes>::to_ne_bytes(&n); 268 | 269 | assert_eq!(*be.last().unwrap(), 1); 270 | assert_eq!(*le.first().unwrap(), 1); 271 | if cfg!(target_endian = "big") { 272 | assert_eq!(*ne.last().unwrap(), 1); 273 | } else { 274 | assert_eq!(*ne.first().unwrap(), 1); 275 | } 276 | 277 | assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n); 278 | assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n); 279 | if cfg!(target_endian = "big") { 280 | assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n); 281 | } else { 282 | assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n); 283 | } 284 | })+} 285 | } 286 | 287 | #[test] 288 | fn convert_between_int_and_bytes() { 289 | check_to_from_bytes!(u8 u16 u32 u64 u128 usize); 290 | check_to_from_bytes!(i8 i16 i32 i64 i128 isize); 291 | } 292 | 293 | #[test] 294 | fn convert_between_float_and_bytes() { 295 | macro_rules! check_to_from_bytes { 296 | ($( $ty:ty )+) => {$( 297 | let n: $ty = 3.14; 298 | 299 | let be = <$ty as ToBytes>::to_be_bytes(&n); 300 | let le = <$ty as ToBytes>::to_le_bytes(&n); 301 | let ne = <$ty as ToBytes>::to_ne_bytes(&n); 302 | 303 | assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n); 304 | assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n); 305 | if cfg!(target_endian = "big") { 306 | assert_eq!(ne, be); 307 | assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n); 308 | } else { 309 | assert_eq!(ne, le); 310 | assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n); 311 | } 312 | )+} 313 | } 314 | 315 | check_to_from_bytes!(f32 f64); 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /src/ops/checked.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Div, Mul, Rem, Shl, Shr, Sub}; 2 | 3 | /// Performs addition, returning `None` if overflow occurred. 4 | pub trait CheckedAdd: Sized + Add { 5 | /// Adds two numbers, checking for overflow. If overflow happens, `None` is 6 | /// returned. 7 | fn checked_add(&self, v: &Self) -> Option; 8 | } 9 | 10 | macro_rules! checked_impl { 11 | ($trait_name:ident, $method:ident, $t:ty) => { 12 | impl $trait_name for $t { 13 | #[inline] 14 | fn $method(&self, v: &$t) -> Option<$t> { 15 | <$t>::$method(*self, *v) 16 | } 17 | } 18 | }; 19 | } 20 | 21 | checked_impl!(CheckedAdd, checked_add, u8); 22 | checked_impl!(CheckedAdd, checked_add, u16); 23 | checked_impl!(CheckedAdd, checked_add, u32); 24 | checked_impl!(CheckedAdd, checked_add, u64); 25 | checked_impl!(CheckedAdd, checked_add, usize); 26 | checked_impl!(CheckedAdd, checked_add, u128); 27 | 28 | checked_impl!(CheckedAdd, checked_add, i8); 29 | checked_impl!(CheckedAdd, checked_add, i16); 30 | checked_impl!(CheckedAdd, checked_add, i32); 31 | checked_impl!(CheckedAdd, checked_add, i64); 32 | checked_impl!(CheckedAdd, checked_add, isize); 33 | checked_impl!(CheckedAdd, checked_add, i128); 34 | 35 | /// Performs subtraction, returning `None` if overflow occurred. 36 | pub trait CheckedSub: Sized + Sub { 37 | /// Subtracts two numbers, checking for overflow. If overflow happens, 38 | /// `None` is returned. 39 | fn checked_sub(&self, v: &Self) -> Option; 40 | } 41 | 42 | checked_impl!(CheckedSub, checked_sub, u8); 43 | checked_impl!(CheckedSub, checked_sub, u16); 44 | checked_impl!(CheckedSub, checked_sub, u32); 45 | checked_impl!(CheckedSub, checked_sub, u64); 46 | checked_impl!(CheckedSub, checked_sub, usize); 47 | checked_impl!(CheckedSub, checked_sub, u128); 48 | 49 | checked_impl!(CheckedSub, checked_sub, i8); 50 | checked_impl!(CheckedSub, checked_sub, i16); 51 | checked_impl!(CheckedSub, checked_sub, i32); 52 | checked_impl!(CheckedSub, checked_sub, i64); 53 | checked_impl!(CheckedSub, checked_sub, isize); 54 | checked_impl!(CheckedSub, checked_sub, i128); 55 | 56 | /// Performs multiplication, returning `None` if overflow occurred. 57 | pub trait CheckedMul: Sized + Mul { 58 | /// Multiplies two numbers, checking for overflow. If overflow happens, 59 | /// `None` is returned. 60 | fn checked_mul(&self, v: &Self) -> Option; 61 | } 62 | 63 | checked_impl!(CheckedMul, checked_mul, u8); 64 | checked_impl!(CheckedMul, checked_mul, u16); 65 | checked_impl!(CheckedMul, checked_mul, u32); 66 | checked_impl!(CheckedMul, checked_mul, u64); 67 | checked_impl!(CheckedMul, checked_mul, usize); 68 | checked_impl!(CheckedMul, checked_mul, u128); 69 | 70 | checked_impl!(CheckedMul, checked_mul, i8); 71 | checked_impl!(CheckedMul, checked_mul, i16); 72 | checked_impl!(CheckedMul, checked_mul, i32); 73 | checked_impl!(CheckedMul, checked_mul, i64); 74 | checked_impl!(CheckedMul, checked_mul, isize); 75 | checked_impl!(CheckedMul, checked_mul, i128); 76 | 77 | /// Performs division, returning `None` on division by zero or if overflow 78 | /// occurred. 79 | pub trait CheckedDiv: Sized + Div { 80 | /// Divides two numbers, checking for overflow and division by 81 | /// zero. If any of that happens, `None` is returned. 82 | fn checked_div(&self, v: &Self) -> Option; 83 | } 84 | 85 | checked_impl!(CheckedDiv, checked_div, u8); 86 | checked_impl!(CheckedDiv, checked_div, u16); 87 | checked_impl!(CheckedDiv, checked_div, u32); 88 | checked_impl!(CheckedDiv, checked_div, u64); 89 | checked_impl!(CheckedDiv, checked_div, usize); 90 | checked_impl!(CheckedDiv, checked_div, u128); 91 | 92 | checked_impl!(CheckedDiv, checked_div, i8); 93 | checked_impl!(CheckedDiv, checked_div, i16); 94 | checked_impl!(CheckedDiv, checked_div, i32); 95 | checked_impl!(CheckedDiv, checked_div, i64); 96 | checked_impl!(CheckedDiv, checked_div, isize); 97 | checked_impl!(CheckedDiv, checked_div, i128); 98 | 99 | /// Performs integral remainder, returning `None` on division by zero or if 100 | /// overflow occurred. 101 | pub trait CheckedRem: Sized + Rem { 102 | /// Finds the remainder of dividing two numbers, checking for overflow and 103 | /// division by zero. If any of that happens, `None` is returned. 104 | /// 105 | /// # Examples 106 | /// 107 | /// ``` 108 | /// use num_traits::CheckedRem; 109 | /// use std::i32::MIN; 110 | /// 111 | /// assert_eq!(CheckedRem::checked_rem(&10, &7), Some(3)); 112 | /// assert_eq!(CheckedRem::checked_rem(&10, &-7), Some(3)); 113 | /// assert_eq!(CheckedRem::checked_rem(&-10, &7), Some(-3)); 114 | /// assert_eq!(CheckedRem::checked_rem(&-10, &-7), Some(-3)); 115 | /// 116 | /// assert_eq!(CheckedRem::checked_rem(&10, &0), None); 117 | /// 118 | /// assert_eq!(CheckedRem::checked_rem(&MIN, &1), Some(0)); 119 | /// assert_eq!(CheckedRem::checked_rem(&MIN, &-1), None); 120 | /// ``` 121 | fn checked_rem(&self, v: &Self) -> Option; 122 | } 123 | 124 | checked_impl!(CheckedRem, checked_rem, u8); 125 | checked_impl!(CheckedRem, checked_rem, u16); 126 | checked_impl!(CheckedRem, checked_rem, u32); 127 | checked_impl!(CheckedRem, checked_rem, u64); 128 | checked_impl!(CheckedRem, checked_rem, usize); 129 | checked_impl!(CheckedRem, checked_rem, u128); 130 | 131 | checked_impl!(CheckedRem, checked_rem, i8); 132 | checked_impl!(CheckedRem, checked_rem, i16); 133 | checked_impl!(CheckedRem, checked_rem, i32); 134 | checked_impl!(CheckedRem, checked_rem, i64); 135 | checked_impl!(CheckedRem, checked_rem, isize); 136 | checked_impl!(CheckedRem, checked_rem, i128); 137 | 138 | macro_rules! checked_impl_unary { 139 | ($trait_name:ident, $method:ident, $t:ty) => { 140 | impl $trait_name for $t { 141 | #[inline] 142 | fn $method(&self) -> Option<$t> { 143 | <$t>::$method(*self) 144 | } 145 | } 146 | }; 147 | } 148 | 149 | /// Performs negation, returning `None` if the result can't be represented. 150 | pub trait CheckedNeg: Sized { 151 | /// Negates a number, returning `None` for results that can't be represented, like signed `MIN` 152 | /// values that can't be positive, or non-zero unsigned values that can't be negative. 153 | /// 154 | /// # Examples 155 | /// 156 | /// ``` 157 | /// use num_traits::CheckedNeg; 158 | /// use std::i32::MIN; 159 | /// 160 | /// assert_eq!(CheckedNeg::checked_neg(&1_i32), Some(-1)); 161 | /// assert_eq!(CheckedNeg::checked_neg(&-1_i32), Some(1)); 162 | /// assert_eq!(CheckedNeg::checked_neg(&MIN), None); 163 | /// 164 | /// assert_eq!(CheckedNeg::checked_neg(&0_u32), Some(0)); 165 | /// assert_eq!(CheckedNeg::checked_neg(&1_u32), None); 166 | /// ``` 167 | fn checked_neg(&self) -> Option; 168 | } 169 | 170 | checked_impl_unary!(CheckedNeg, checked_neg, u8); 171 | checked_impl_unary!(CheckedNeg, checked_neg, u16); 172 | checked_impl_unary!(CheckedNeg, checked_neg, u32); 173 | checked_impl_unary!(CheckedNeg, checked_neg, u64); 174 | checked_impl_unary!(CheckedNeg, checked_neg, usize); 175 | checked_impl_unary!(CheckedNeg, checked_neg, u128); 176 | 177 | checked_impl_unary!(CheckedNeg, checked_neg, i8); 178 | checked_impl_unary!(CheckedNeg, checked_neg, i16); 179 | checked_impl_unary!(CheckedNeg, checked_neg, i32); 180 | checked_impl_unary!(CheckedNeg, checked_neg, i64); 181 | checked_impl_unary!(CheckedNeg, checked_neg, isize); 182 | checked_impl_unary!(CheckedNeg, checked_neg, i128); 183 | 184 | /// Performs shift left, returning `None` on shifts larger than or equal to 185 | /// the type width. 186 | pub trait CheckedShl: Sized + Shl { 187 | /// Checked shift left. Computes `self << rhs`, returning `None` 188 | /// if `rhs` is larger than or equal to the number of bits in `self`. 189 | /// 190 | /// ``` 191 | /// use num_traits::CheckedShl; 192 | /// 193 | /// let x: u16 = 0x0001; 194 | /// 195 | /// assert_eq!(CheckedShl::checked_shl(&x, 0), Some(0x0001)); 196 | /// assert_eq!(CheckedShl::checked_shl(&x, 1), Some(0x0002)); 197 | /// assert_eq!(CheckedShl::checked_shl(&x, 15), Some(0x8000)); 198 | /// assert_eq!(CheckedShl::checked_shl(&x, 16), None); 199 | /// ``` 200 | fn checked_shl(&self, rhs: u32) -> Option; 201 | } 202 | 203 | macro_rules! checked_shift_impl { 204 | ($trait_name:ident, $method:ident, $t:ty) => { 205 | impl $trait_name for $t { 206 | #[inline] 207 | fn $method(&self, rhs: u32) -> Option<$t> { 208 | <$t>::$method(*self, rhs) 209 | } 210 | } 211 | }; 212 | } 213 | 214 | checked_shift_impl!(CheckedShl, checked_shl, u8); 215 | checked_shift_impl!(CheckedShl, checked_shl, u16); 216 | checked_shift_impl!(CheckedShl, checked_shl, u32); 217 | checked_shift_impl!(CheckedShl, checked_shl, u64); 218 | checked_shift_impl!(CheckedShl, checked_shl, usize); 219 | checked_shift_impl!(CheckedShl, checked_shl, u128); 220 | 221 | checked_shift_impl!(CheckedShl, checked_shl, i8); 222 | checked_shift_impl!(CheckedShl, checked_shl, i16); 223 | checked_shift_impl!(CheckedShl, checked_shl, i32); 224 | checked_shift_impl!(CheckedShl, checked_shl, i64); 225 | checked_shift_impl!(CheckedShl, checked_shl, isize); 226 | checked_shift_impl!(CheckedShl, checked_shl, i128); 227 | 228 | /// Performs shift right, returning `None` on shifts larger than or equal to 229 | /// the type width. 230 | pub trait CheckedShr: Sized + Shr { 231 | /// Checked shift right. Computes `self >> rhs`, returning `None` 232 | /// if `rhs` is larger than or equal to the number of bits in `self`. 233 | /// 234 | /// ``` 235 | /// use num_traits::CheckedShr; 236 | /// 237 | /// let x: u16 = 0x8000; 238 | /// 239 | /// assert_eq!(CheckedShr::checked_shr(&x, 0), Some(0x8000)); 240 | /// assert_eq!(CheckedShr::checked_shr(&x, 1), Some(0x4000)); 241 | /// assert_eq!(CheckedShr::checked_shr(&x, 15), Some(0x0001)); 242 | /// assert_eq!(CheckedShr::checked_shr(&x, 16), None); 243 | /// ``` 244 | fn checked_shr(&self, rhs: u32) -> Option; 245 | } 246 | 247 | checked_shift_impl!(CheckedShr, checked_shr, u8); 248 | checked_shift_impl!(CheckedShr, checked_shr, u16); 249 | checked_shift_impl!(CheckedShr, checked_shr, u32); 250 | checked_shift_impl!(CheckedShr, checked_shr, u64); 251 | checked_shift_impl!(CheckedShr, checked_shr, usize); 252 | checked_shift_impl!(CheckedShr, checked_shr, u128); 253 | 254 | checked_shift_impl!(CheckedShr, checked_shr, i8); 255 | checked_shift_impl!(CheckedShr, checked_shr, i16); 256 | checked_shift_impl!(CheckedShr, checked_shr, i32); 257 | checked_shift_impl!(CheckedShr, checked_shr, i64); 258 | checked_shift_impl!(CheckedShr, checked_shr, isize); 259 | checked_shift_impl!(CheckedShr, checked_shr, i128); 260 | -------------------------------------------------------------------------------- /src/ops/euclid.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Div, Rem}; 2 | 3 | pub trait Euclid: Sized + Div + Rem { 4 | /// Calculates Euclidean division, the matching method for `rem_euclid`. 5 | /// 6 | /// This computes the integer `n` such that 7 | /// `self = n * v + self.rem_euclid(v)`. 8 | /// In other words, the result is `self / v` rounded to the integer `n` 9 | /// such that `self >= n * v`. 10 | /// 11 | /// # Examples 12 | /// 13 | /// ``` 14 | /// use num_traits::Euclid; 15 | /// 16 | /// let a: i32 = 7; 17 | /// let b: i32 = 4; 18 | /// assert_eq!(Euclid::div_euclid(&a, &b), 1); // 7 > 4 * 1 19 | /// assert_eq!(Euclid::div_euclid(&-a, &b), -2); // -7 >= 4 * -2 20 | /// assert_eq!(Euclid::div_euclid(&a, &-b), -1); // 7 >= -4 * -1 21 | /// assert_eq!(Euclid::div_euclid(&-a, &-b), 2); // -7 >= -4 * 2 22 | /// ``` 23 | fn div_euclid(&self, v: &Self) -> Self; 24 | 25 | /// Calculates the least nonnegative remainder of `self (mod v)`. 26 | /// 27 | /// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in 28 | /// most cases. However, due to a floating point round-off error it can 29 | /// result in `r == v.abs()`, violating the mathematical definition, if 30 | /// `self` is much smaller than `v.abs()` in magnitude and `self < 0.0`. 31 | /// This result is not an element of the function's codomain, but it is the 32 | /// closest floating point number in the real numbers and thus fulfills the 33 | /// property `self == self.div_euclid(v) * v + self.rem_euclid(v)` 34 | /// approximatively. 35 | /// 36 | /// # Examples 37 | /// 38 | /// ``` 39 | /// use num_traits::Euclid; 40 | /// 41 | /// let a: i32 = 7; 42 | /// let b: i32 = 4; 43 | /// assert_eq!(Euclid::rem_euclid(&a, &b), 3); 44 | /// assert_eq!(Euclid::rem_euclid(&-a, &b), 1); 45 | /// assert_eq!(Euclid::rem_euclid(&a, &-b), 3); 46 | /// assert_eq!(Euclid::rem_euclid(&-a, &-b), 1); 47 | /// ``` 48 | fn rem_euclid(&self, v: &Self) -> Self; 49 | 50 | /// Returns both the quotient and remainder from Euclidean division. 51 | /// 52 | /// By default, it internally calls both `Euclid::div_euclid` and `Euclid::rem_euclid`, 53 | /// but it can be overridden in order to implement some optimization. 54 | /// 55 | /// # Examples 56 | /// 57 | /// ``` 58 | /// # use num_traits::Euclid; 59 | /// let x = 5u8; 60 | /// let y = 3u8; 61 | /// 62 | /// let div = Euclid::div_euclid(&x, &y); 63 | /// let rem = Euclid::rem_euclid(&x, &y); 64 | /// 65 | /// assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y)); 66 | /// ``` 67 | fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { 68 | (self.div_euclid(v), self.rem_euclid(v)) 69 | } 70 | } 71 | 72 | macro_rules! euclid_forward_impl { 73 | ($($t:ty)*) => {$( 74 | impl Euclid for $t { 75 | #[inline] 76 | fn div_euclid(&self, v: &$t) -> Self { 77 | <$t>::div_euclid(*self, *v) 78 | } 79 | 80 | #[inline] 81 | fn rem_euclid(&self, v: &$t) -> Self { 82 | <$t>::rem_euclid(*self, *v) 83 | } 84 | } 85 | )*} 86 | } 87 | 88 | euclid_forward_impl!(isize i8 i16 i32 i64 i128); 89 | euclid_forward_impl!(usize u8 u16 u32 u64 u128); 90 | 91 | #[cfg(feature = "std")] 92 | euclid_forward_impl!(f32 f64); 93 | 94 | #[cfg(not(feature = "std"))] 95 | impl Euclid for f32 { 96 | #[inline] 97 | fn div_euclid(&self, v: &f32) -> f32 { 98 | let q = ::trunc(self / v); 99 | if self % v < 0.0 { 100 | return if *v > 0.0 { q - 1.0 } else { q + 1.0 }; 101 | } 102 | q 103 | } 104 | 105 | #[inline] 106 | fn rem_euclid(&self, v: &f32) -> f32 { 107 | let r = self % v; 108 | if r < 0.0 { 109 | r + ::abs(*v) 110 | } else { 111 | r 112 | } 113 | } 114 | } 115 | 116 | #[cfg(not(feature = "std"))] 117 | impl Euclid for f64 { 118 | #[inline] 119 | fn div_euclid(&self, v: &f64) -> f64 { 120 | let q = ::trunc(self / v); 121 | if self % v < 0.0 { 122 | return if *v > 0.0 { q - 1.0 } else { q + 1.0 }; 123 | } 124 | q 125 | } 126 | 127 | #[inline] 128 | fn rem_euclid(&self, v: &f64) -> f64 { 129 | let r = self % v; 130 | if r < 0.0 { 131 | r + ::abs(*v) 132 | } else { 133 | r 134 | } 135 | } 136 | } 137 | 138 | pub trait CheckedEuclid: Euclid { 139 | /// Performs euclid division, returning `None` on division by zero or if 140 | /// overflow occurred. 141 | fn checked_div_euclid(&self, v: &Self) -> Option; 142 | 143 | /// Finds the euclid remainder of dividing two numbers, returning `None` on 144 | /// division by zero or if overflow occurred. 145 | fn checked_rem_euclid(&self, v: &Self) -> Option; 146 | 147 | /// Returns both the quotient and remainder from checked Euclidean division, 148 | /// returning `None` on division by zero or if overflow occurred. 149 | /// 150 | /// By default, it internally calls both `CheckedEuclid::checked_div_euclid` and `CheckedEuclid::checked_rem_euclid`, 151 | /// but it can be overridden in order to implement some optimization. 152 | /// # Examples 153 | /// 154 | /// ``` 155 | /// # use num_traits::CheckedEuclid; 156 | /// let x = 5u8; 157 | /// let y = 3u8; 158 | /// 159 | /// let div = CheckedEuclid::checked_div_euclid(&x, &y); 160 | /// let rem = CheckedEuclid::checked_rem_euclid(&x, &y); 161 | /// 162 | /// assert_eq!(Some((div.unwrap(), rem.unwrap())), CheckedEuclid::checked_div_rem_euclid(&x, &y)); 163 | /// ``` 164 | fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { 165 | Some((self.checked_div_euclid(v)?, self.checked_rem_euclid(v)?)) 166 | } 167 | } 168 | 169 | macro_rules! checked_euclid_forward_impl { 170 | ($($t:ty)*) => {$( 171 | impl CheckedEuclid for $t { 172 | #[inline] 173 | fn checked_div_euclid(&self, v: &$t) -> Option { 174 | <$t>::checked_div_euclid(*self, *v) 175 | } 176 | 177 | #[inline] 178 | fn checked_rem_euclid(&self, v: &$t) -> Option { 179 | <$t>::checked_rem_euclid(*self, *v) 180 | } 181 | } 182 | )*} 183 | } 184 | 185 | checked_euclid_forward_impl!(isize i8 i16 i32 i64 i128); 186 | checked_euclid_forward_impl!(usize u8 u16 u32 u64 u128); 187 | 188 | #[cfg(test)] 189 | mod tests { 190 | use super::*; 191 | 192 | #[test] 193 | fn euclid_unsigned() { 194 | macro_rules! test_euclid { 195 | ($($t:ident)+) => { 196 | $( 197 | { 198 | let x: $t = 10; 199 | let y: $t = 3; 200 | let div = Euclid::div_euclid(&x, &y); 201 | let rem = Euclid::rem_euclid(&x, &y); 202 | assert_eq!(div, 3); 203 | assert_eq!(rem, 1); 204 | assert_eq!((div, rem), Euclid::div_rem_euclid(&x, &y)); 205 | } 206 | )+ 207 | }; 208 | } 209 | 210 | test_euclid!(usize u8 u16 u32 u64); 211 | } 212 | 213 | #[test] 214 | fn euclid_signed() { 215 | macro_rules! test_euclid { 216 | ($($t:ident)+) => { 217 | $( 218 | { 219 | let x: $t = 10; 220 | let y: $t = -3; 221 | assert_eq!(Euclid::div_euclid(&x, &y), -3); 222 | assert_eq!(Euclid::div_euclid(&-x, &y), 4); 223 | assert_eq!(Euclid::rem_euclid(&x, &y), 1); 224 | assert_eq!(Euclid::rem_euclid(&-x, &y), 2); 225 | assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y)); 226 | let x: $t = $t::min_value() + 1; 227 | let y: $t = -1; 228 | assert_eq!(Euclid::div_euclid(&x, &y), $t::max_value()); 229 | } 230 | )+ 231 | }; 232 | } 233 | 234 | test_euclid!(isize i8 i16 i32 i64 i128); 235 | } 236 | 237 | #[test] 238 | fn euclid_float() { 239 | macro_rules! test_euclid { 240 | ($($t:ident)+) => { 241 | $( 242 | { 243 | let x: $t = 12.1; 244 | let y: $t = 3.2; 245 | assert!(Euclid::div_euclid(&x, &y) * y + Euclid::rem_euclid(&x, &y) - x 246 | <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); 247 | assert!(Euclid::div_euclid(&x, &-y) * -y + Euclid::rem_euclid(&x, &-y) - x 248 | <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); 249 | assert!(Euclid::div_euclid(&-x, &y) * y + Euclid::rem_euclid(&-x, &y) + x 250 | <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); 251 | assert!(Euclid::div_euclid(&-x, &-y) * -y + Euclid::rem_euclid(&-x, &-y) + x 252 | <= 46.4 * <$t as crate::float::FloatCore>::epsilon()); 253 | assert_eq!((Euclid::div_euclid(&x, &y), Euclid::rem_euclid(&x, &y)), Euclid::div_rem_euclid(&x, &y)); 254 | } 255 | )+ 256 | }; 257 | } 258 | 259 | test_euclid!(f32 f64); 260 | } 261 | 262 | #[test] 263 | fn euclid_checked() { 264 | macro_rules! test_euclid_checked { 265 | ($($t:ident)+) => { 266 | $( 267 | { 268 | assert_eq!(CheckedEuclid::checked_div_euclid(&$t::min_value(), &-1), None); 269 | assert_eq!(CheckedEuclid::checked_rem_euclid(&$t::min_value(), &-1), None); 270 | assert_eq!(CheckedEuclid::checked_div_euclid(&1, &0), None); 271 | assert_eq!(CheckedEuclid::checked_rem_euclid(&1, &0), None); 272 | } 273 | )+ 274 | }; 275 | } 276 | 277 | test_euclid_checked!(isize i8 i16 i32 i64 i128); 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /src/ops/inv.rs: -------------------------------------------------------------------------------- 1 | /// Unary operator for retrieving the multiplicative inverse, or reciprocal, of a value. 2 | pub trait Inv { 3 | /// The result after applying the operator. 4 | type Output; 5 | 6 | /// Returns the multiplicative inverse of `self`. 7 | /// 8 | /// # Examples 9 | /// 10 | /// ``` 11 | /// use std::f64::INFINITY; 12 | /// use num_traits::Inv; 13 | /// 14 | /// assert_eq!(7.0.inv() * 7.0, 1.0); 15 | /// assert_eq!((-0.0).inv(), -INFINITY); 16 | /// ``` 17 | fn inv(self) -> Self::Output; 18 | } 19 | 20 | impl Inv for f32 { 21 | type Output = f32; 22 | #[inline] 23 | fn inv(self) -> f32 { 24 | 1.0 / self 25 | } 26 | } 27 | impl Inv for f64 { 28 | type Output = f64; 29 | #[inline] 30 | fn inv(self) -> f64 { 31 | 1.0 / self 32 | } 33 | } 34 | impl<'a> Inv for &'a f32 { 35 | type Output = f32; 36 | #[inline] 37 | fn inv(self) -> f32 { 38 | 1.0 / *self 39 | } 40 | } 41 | impl<'a> Inv for &'a f64 { 42 | type Output = f64; 43 | #[inline] 44 | fn inv(self) -> f64 { 45 | 1.0 / *self 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ops/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bytes; 2 | pub mod checked; 3 | pub mod euclid; 4 | pub mod inv; 5 | pub mod mul_add; 6 | pub mod overflowing; 7 | pub mod saturating; 8 | pub mod wrapping; 9 | -------------------------------------------------------------------------------- /src/ops/mul_add.rs: -------------------------------------------------------------------------------- 1 | /// Fused multiply-add. Computes `(self * a) + b` with only one rounding 2 | /// error, yielding a more accurate result than an unfused multiply-add. 3 | /// 4 | /// Using `mul_add` can be more performant than an unfused multiply-add if 5 | /// the target architecture has a dedicated `fma` CPU instruction. 6 | /// 7 | /// Note that `A` and `B` are `Self` by default, but this is not mandatory. 8 | /// 9 | /// # Example 10 | /// 11 | /// ``` 12 | /// use std::f32; 13 | /// 14 | /// let m = 10.0_f32; 15 | /// let x = 4.0_f32; 16 | /// let b = 60.0_f32; 17 | /// 18 | /// // 100.0 19 | /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); 20 | /// 21 | /// assert!(abs_difference <= 100.0 * f32::EPSILON); 22 | /// ``` 23 | pub trait MulAdd { 24 | /// The resulting type after applying the fused multiply-add. 25 | type Output; 26 | 27 | /// Performs the fused multiply-add operation `(self * a) + b` 28 | fn mul_add(self, a: A, b: B) -> Self::Output; 29 | } 30 | 31 | /// The fused multiply-add assignment operation `*self = (*self * a) + b` 32 | pub trait MulAddAssign { 33 | /// Performs the fused multiply-add assignment operation `*self = (*self * a) + b` 34 | fn mul_add_assign(&mut self, a: A, b: B); 35 | } 36 | 37 | #[cfg(any(feature = "std", feature = "libm"))] 38 | impl MulAdd for f32 { 39 | type Output = Self; 40 | 41 | #[inline] 42 | fn mul_add(self, a: Self, b: Self) -> Self::Output { 43 | ::mul_add(self, a, b) 44 | } 45 | } 46 | 47 | #[cfg(any(feature = "std", feature = "libm"))] 48 | impl MulAdd for f64 { 49 | type Output = Self; 50 | 51 | #[inline] 52 | fn mul_add(self, a: Self, b: Self) -> Self::Output { 53 | ::mul_add(self, a, b) 54 | } 55 | } 56 | 57 | macro_rules! mul_add_impl { 58 | ($trait_name:ident for $($t:ty)*) => {$( 59 | impl $trait_name for $t { 60 | type Output = Self; 61 | 62 | #[inline] 63 | fn mul_add(self, a: Self, b: Self) -> Self::Output { 64 | (self * a) + b 65 | } 66 | } 67 | )*} 68 | } 69 | 70 | mul_add_impl!(MulAdd for isize i8 i16 i32 i64 i128); 71 | mul_add_impl!(MulAdd for usize u8 u16 u32 u64 u128); 72 | 73 | #[cfg(any(feature = "std", feature = "libm"))] 74 | impl MulAddAssign for f32 { 75 | #[inline] 76 | fn mul_add_assign(&mut self, a: Self, b: Self) { 77 | *self = ::mul_add(*self, a, b) 78 | } 79 | } 80 | 81 | #[cfg(any(feature = "std", feature = "libm"))] 82 | impl MulAddAssign for f64 { 83 | #[inline] 84 | fn mul_add_assign(&mut self, a: Self, b: Self) { 85 | *self = ::mul_add(*self, a, b) 86 | } 87 | } 88 | 89 | macro_rules! mul_add_assign_impl { 90 | ($trait_name:ident for $($t:ty)*) => {$( 91 | impl $trait_name for $t { 92 | #[inline] 93 | fn mul_add_assign(&mut self, a: Self, b: Self) { 94 | *self = (*self * a) + b 95 | } 96 | } 97 | )*} 98 | } 99 | 100 | mul_add_assign_impl!(MulAddAssign for isize i8 i16 i32 i64 i128); 101 | mul_add_assign_impl!(MulAddAssign for usize u8 u16 u32 u64 u128); 102 | 103 | #[cfg(test)] 104 | mod tests { 105 | use super::*; 106 | 107 | #[test] 108 | fn mul_add_integer() { 109 | macro_rules! test_mul_add { 110 | ($($t:ident)+) => { 111 | $( 112 | { 113 | let m: $t = 2; 114 | let x: $t = 3; 115 | let b: $t = 4; 116 | 117 | assert_eq!(MulAdd::mul_add(m, x, b), (m*x + b)); 118 | } 119 | )+ 120 | }; 121 | } 122 | 123 | test_mul_add!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); 124 | } 125 | 126 | #[test] 127 | #[cfg(feature = "std")] 128 | fn mul_add_float() { 129 | macro_rules! test_mul_add { 130 | ($($t:ident)+) => { 131 | $( 132 | { 133 | use core::$t; 134 | 135 | let m: $t = 12.0; 136 | let x: $t = 3.4; 137 | let b: $t = 5.6; 138 | 139 | let abs_difference = (MulAdd::mul_add(m, x, b) - (m*x + b)).abs(); 140 | 141 | assert!(abs_difference <= 46.4 * $t::EPSILON); 142 | } 143 | )+ 144 | }; 145 | } 146 | 147 | test_mul_add!(f32 f64); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/ops/overflowing.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Mul, Sub}; 2 | use core::{i128, i16, i32, i64, i8, isize}; 3 | use core::{u128, u16, u32, u64, u8, usize}; 4 | 5 | macro_rules! overflowing_impl { 6 | ($trait_name:ident, $method:ident, $t:ty) => { 7 | impl $trait_name for $t { 8 | #[inline] 9 | fn $method(&self, v: &Self) -> (Self, bool) { 10 | <$t>::$method(*self, *v) 11 | } 12 | } 13 | }; 14 | } 15 | 16 | /// Performs addition with a flag for overflow. 17 | pub trait OverflowingAdd: Sized + Add { 18 | /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur. 19 | /// If an overflow would have occurred then the wrapped value is returned. 20 | fn overflowing_add(&self, v: &Self) -> (Self, bool); 21 | } 22 | 23 | overflowing_impl!(OverflowingAdd, overflowing_add, u8); 24 | overflowing_impl!(OverflowingAdd, overflowing_add, u16); 25 | overflowing_impl!(OverflowingAdd, overflowing_add, u32); 26 | overflowing_impl!(OverflowingAdd, overflowing_add, u64); 27 | overflowing_impl!(OverflowingAdd, overflowing_add, usize); 28 | overflowing_impl!(OverflowingAdd, overflowing_add, u128); 29 | 30 | overflowing_impl!(OverflowingAdd, overflowing_add, i8); 31 | overflowing_impl!(OverflowingAdd, overflowing_add, i16); 32 | overflowing_impl!(OverflowingAdd, overflowing_add, i32); 33 | overflowing_impl!(OverflowingAdd, overflowing_add, i64); 34 | overflowing_impl!(OverflowingAdd, overflowing_add, isize); 35 | overflowing_impl!(OverflowingAdd, overflowing_add, i128); 36 | 37 | /// Performs substraction with a flag for overflow. 38 | pub trait OverflowingSub: Sized + Sub { 39 | /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur. 40 | /// If an overflow would have occurred then the wrapped value is returned. 41 | fn overflowing_sub(&self, v: &Self) -> (Self, bool); 42 | } 43 | 44 | overflowing_impl!(OverflowingSub, overflowing_sub, u8); 45 | overflowing_impl!(OverflowingSub, overflowing_sub, u16); 46 | overflowing_impl!(OverflowingSub, overflowing_sub, u32); 47 | overflowing_impl!(OverflowingSub, overflowing_sub, u64); 48 | overflowing_impl!(OverflowingSub, overflowing_sub, usize); 49 | overflowing_impl!(OverflowingSub, overflowing_sub, u128); 50 | 51 | overflowing_impl!(OverflowingSub, overflowing_sub, i8); 52 | overflowing_impl!(OverflowingSub, overflowing_sub, i16); 53 | overflowing_impl!(OverflowingSub, overflowing_sub, i32); 54 | overflowing_impl!(OverflowingSub, overflowing_sub, i64); 55 | overflowing_impl!(OverflowingSub, overflowing_sub, isize); 56 | overflowing_impl!(OverflowingSub, overflowing_sub, i128); 57 | 58 | /// Performs multiplication with a flag for overflow. 59 | pub trait OverflowingMul: Sized + Mul { 60 | /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur. 61 | /// If an overflow would have occurred then the wrapped value is returned. 62 | fn overflowing_mul(&self, v: &Self) -> (Self, bool); 63 | } 64 | 65 | overflowing_impl!(OverflowingMul, overflowing_mul, u8); 66 | overflowing_impl!(OverflowingMul, overflowing_mul, u16); 67 | overflowing_impl!(OverflowingMul, overflowing_mul, u32); 68 | overflowing_impl!(OverflowingMul, overflowing_mul, u64); 69 | overflowing_impl!(OverflowingMul, overflowing_mul, usize); 70 | overflowing_impl!(OverflowingMul, overflowing_mul, u128); 71 | 72 | overflowing_impl!(OverflowingMul, overflowing_mul, i8); 73 | overflowing_impl!(OverflowingMul, overflowing_mul, i16); 74 | overflowing_impl!(OverflowingMul, overflowing_mul, i32); 75 | overflowing_impl!(OverflowingMul, overflowing_mul, i64); 76 | overflowing_impl!(OverflowingMul, overflowing_mul, isize); 77 | overflowing_impl!(OverflowingMul, overflowing_mul, i128); 78 | 79 | #[test] 80 | fn test_overflowing_traits() { 81 | fn overflowing_add(a: T, b: T) -> (T, bool) { 82 | a.overflowing_add(&b) 83 | } 84 | fn overflowing_sub(a: T, b: T) -> (T, bool) { 85 | a.overflowing_sub(&b) 86 | } 87 | fn overflowing_mul(a: T, b: T) -> (T, bool) { 88 | a.overflowing_mul(&b) 89 | } 90 | assert_eq!(overflowing_add(5i16, 2), (7, false)); 91 | assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true)); 92 | assert_eq!(overflowing_sub(5i16, 2), (3, false)); 93 | assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true)); 94 | assert_eq!(overflowing_mul(5i16, 2), (10, false)); 95 | assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true)); 96 | } 97 | -------------------------------------------------------------------------------- /src/ops/saturating.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Mul, Sub}; 2 | 3 | /// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and 4 | /// `SaturatingMul` instead. 5 | pub trait Saturating { 6 | /// Saturating addition operator. 7 | /// Returns a+b, saturating at the numeric bounds instead of overflowing. 8 | fn saturating_add(self, v: Self) -> Self; 9 | 10 | /// Saturating subtraction operator. 11 | /// Returns a-b, saturating at the numeric bounds instead of overflowing. 12 | fn saturating_sub(self, v: Self) -> Self; 13 | } 14 | 15 | macro_rules! deprecated_saturating_impl { 16 | ($trait_name:ident for $($t:ty)*) => {$( 17 | impl $trait_name for $t { 18 | #[inline] 19 | fn saturating_add(self, v: Self) -> Self { 20 | Self::saturating_add(self, v) 21 | } 22 | 23 | #[inline] 24 | fn saturating_sub(self, v: Self) -> Self { 25 | Self::saturating_sub(self, v) 26 | } 27 | } 28 | )*} 29 | } 30 | 31 | deprecated_saturating_impl!(Saturating for isize i8 i16 i32 i64 i128); 32 | deprecated_saturating_impl!(Saturating for usize u8 u16 u32 u64 u128); 33 | 34 | macro_rules! saturating_impl { 35 | ($trait_name:ident, $method:ident, $t:ty) => { 36 | impl $trait_name for $t { 37 | #[inline] 38 | fn $method(&self, v: &Self) -> Self { 39 | <$t>::$method(*self, *v) 40 | } 41 | } 42 | }; 43 | } 44 | 45 | /// Performs addition that saturates at the numeric bounds instead of overflowing. 46 | pub trait SaturatingAdd: Sized + Add { 47 | /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of 48 | /// the type. 49 | fn saturating_add(&self, v: &Self) -> Self; 50 | } 51 | 52 | saturating_impl!(SaturatingAdd, saturating_add, u8); 53 | saturating_impl!(SaturatingAdd, saturating_add, u16); 54 | saturating_impl!(SaturatingAdd, saturating_add, u32); 55 | saturating_impl!(SaturatingAdd, saturating_add, u64); 56 | saturating_impl!(SaturatingAdd, saturating_add, usize); 57 | saturating_impl!(SaturatingAdd, saturating_add, u128); 58 | 59 | saturating_impl!(SaturatingAdd, saturating_add, i8); 60 | saturating_impl!(SaturatingAdd, saturating_add, i16); 61 | saturating_impl!(SaturatingAdd, saturating_add, i32); 62 | saturating_impl!(SaturatingAdd, saturating_add, i64); 63 | saturating_impl!(SaturatingAdd, saturating_add, isize); 64 | saturating_impl!(SaturatingAdd, saturating_add, i128); 65 | 66 | /// Performs subtraction that saturates at the numeric bounds instead of overflowing. 67 | pub trait SaturatingSub: Sized + Sub { 68 | /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of 69 | /// the type. 70 | fn saturating_sub(&self, v: &Self) -> Self; 71 | } 72 | 73 | saturating_impl!(SaturatingSub, saturating_sub, u8); 74 | saturating_impl!(SaturatingSub, saturating_sub, u16); 75 | saturating_impl!(SaturatingSub, saturating_sub, u32); 76 | saturating_impl!(SaturatingSub, saturating_sub, u64); 77 | saturating_impl!(SaturatingSub, saturating_sub, usize); 78 | saturating_impl!(SaturatingSub, saturating_sub, u128); 79 | 80 | saturating_impl!(SaturatingSub, saturating_sub, i8); 81 | saturating_impl!(SaturatingSub, saturating_sub, i16); 82 | saturating_impl!(SaturatingSub, saturating_sub, i32); 83 | saturating_impl!(SaturatingSub, saturating_sub, i64); 84 | saturating_impl!(SaturatingSub, saturating_sub, isize); 85 | saturating_impl!(SaturatingSub, saturating_sub, i128); 86 | 87 | /// Performs multiplication that saturates at the numeric bounds instead of overflowing. 88 | pub trait SaturatingMul: Sized + Mul { 89 | /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of 90 | /// the type. 91 | fn saturating_mul(&self, v: &Self) -> Self; 92 | } 93 | 94 | saturating_impl!(SaturatingMul, saturating_mul, u8); 95 | saturating_impl!(SaturatingMul, saturating_mul, u16); 96 | saturating_impl!(SaturatingMul, saturating_mul, u32); 97 | saturating_impl!(SaturatingMul, saturating_mul, u64); 98 | saturating_impl!(SaturatingMul, saturating_mul, usize); 99 | saturating_impl!(SaturatingMul, saturating_mul, u128); 100 | 101 | saturating_impl!(SaturatingMul, saturating_mul, i8); 102 | saturating_impl!(SaturatingMul, saturating_mul, i16); 103 | saturating_impl!(SaturatingMul, saturating_mul, i32); 104 | saturating_impl!(SaturatingMul, saturating_mul, i64); 105 | saturating_impl!(SaturatingMul, saturating_mul, isize); 106 | saturating_impl!(SaturatingMul, saturating_mul, i128); 107 | 108 | // TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable. 109 | 110 | #[test] 111 | fn test_saturating_traits() { 112 | fn saturating_add(a: T, b: T) -> T { 113 | a.saturating_add(&b) 114 | } 115 | fn saturating_sub(a: T, b: T) -> T { 116 | a.saturating_sub(&b) 117 | } 118 | fn saturating_mul(a: T, b: T) -> T { 119 | a.saturating_mul(&b) 120 | } 121 | assert_eq!(saturating_add(255, 1), 255u8); 122 | assert_eq!(saturating_add(127, 1), 127i8); 123 | assert_eq!(saturating_add(-128, -1), -128i8); 124 | assert_eq!(saturating_sub(0, 1), 0u8); 125 | assert_eq!(saturating_sub(-128, 1), -128i8); 126 | assert_eq!(saturating_sub(127, -1), 127i8); 127 | assert_eq!(saturating_mul(255, 2), 255u8); 128 | assert_eq!(saturating_mul(127, 2), 127i8); 129 | assert_eq!(saturating_mul(-128, 2), -128i8); 130 | } 131 | -------------------------------------------------------------------------------- /src/ops/wrapping.rs: -------------------------------------------------------------------------------- 1 | use core::num::Wrapping; 2 | use core::ops::{Add, Mul, Neg, Shl, Shr, Sub}; 3 | 4 | macro_rules! wrapping_impl { 5 | ($trait_name:ident, $method:ident, $t:ty) => { 6 | impl $trait_name for $t { 7 | #[inline] 8 | fn $method(&self, v: &Self) -> Self { 9 | <$t>::$method(*self, *v) 10 | } 11 | } 12 | }; 13 | ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => { 14 | impl $trait_name<$rhs> for $t { 15 | #[inline] 16 | fn $method(&self, v: &$rhs) -> Self { 17 | <$t>::$method(*self, *v) 18 | } 19 | } 20 | }; 21 | } 22 | 23 | /// Performs addition that wraps around on overflow. 24 | pub trait WrappingAdd: Sized + Add { 25 | /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of 26 | /// the type. 27 | fn wrapping_add(&self, v: &Self) -> Self; 28 | } 29 | 30 | wrapping_impl!(WrappingAdd, wrapping_add, u8); 31 | wrapping_impl!(WrappingAdd, wrapping_add, u16); 32 | wrapping_impl!(WrappingAdd, wrapping_add, u32); 33 | wrapping_impl!(WrappingAdd, wrapping_add, u64); 34 | wrapping_impl!(WrappingAdd, wrapping_add, usize); 35 | wrapping_impl!(WrappingAdd, wrapping_add, u128); 36 | 37 | wrapping_impl!(WrappingAdd, wrapping_add, i8); 38 | wrapping_impl!(WrappingAdd, wrapping_add, i16); 39 | wrapping_impl!(WrappingAdd, wrapping_add, i32); 40 | wrapping_impl!(WrappingAdd, wrapping_add, i64); 41 | wrapping_impl!(WrappingAdd, wrapping_add, isize); 42 | wrapping_impl!(WrappingAdd, wrapping_add, i128); 43 | 44 | /// Performs subtraction that wraps around on overflow. 45 | pub trait WrappingSub: Sized + Sub { 46 | /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary 47 | /// of the type. 48 | fn wrapping_sub(&self, v: &Self) -> Self; 49 | } 50 | 51 | wrapping_impl!(WrappingSub, wrapping_sub, u8); 52 | wrapping_impl!(WrappingSub, wrapping_sub, u16); 53 | wrapping_impl!(WrappingSub, wrapping_sub, u32); 54 | wrapping_impl!(WrappingSub, wrapping_sub, u64); 55 | wrapping_impl!(WrappingSub, wrapping_sub, usize); 56 | wrapping_impl!(WrappingSub, wrapping_sub, u128); 57 | 58 | wrapping_impl!(WrappingSub, wrapping_sub, i8); 59 | wrapping_impl!(WrappingSub, wrapping_sub, i16); 60 | wrapping_impl!(WrappingSub, wrapping_sub, i32); 61 | wrapping_impl!(WrappingSub, wrapping_sub, i64); 62 | wrapping_impl!(WrappingSub, wrapping_sub, isize); 63 | wrapping_impl!(WrappingSub, wrapping_sub, i128); 64 | 65 | /// Performs multiplication that wraps around on overflow. 66 | pub trait WrappingMul: Sized + Mul { 67 | /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary 68 | /// of the type. 69 | fn wrapping_mul(&self, v: &Self) -> Self; 70 | } 71 | 72 | wrapping_impl!(WrappingMul, wrapping_mul, u8); 73 | wrapping_impl!(WrappingMul, wrapping_mul, u16); 74 | wrapping_impl!(WrappingMul, wrapping_mul, u32); 75 | wrapping_impl!(WrappingMul, wrapping_mul, u64); 76 | wrapping_impl!(WrappingMul, wrapping_mul, usize); 77 | wrapping_impl!(WrappingMul, wrapping_mul, u128); 78 | 79 | wrapping_impl!(WrappingMul, wrapping_mul, i8); 80 | wrapping_impl!(WrappingMul, wrapping_mul, i16); 81 | wrapping_impl!(WrappingMul, wrapping_mul, i32); 82 | wrapping_impl!(WrappingMul, wrapping_mul, i64); 83 | wrapping_impl!(WrappingMul, wrapping_mul, isize); 84 | wrapping_impl!(WrappingMul, wrapping_mul, i128); 85 | 86 | macro_rules! wrapping_unary_impl { 87 | ($trait_name:ident, $method:ident, $t:ty) => { 88 | impl $trait_name for $t { 89 | #[inline] 90 | fn $method(&self) -> $t { 91 | <$t>::$method(*self) 92 | } 93 | } 94 | }; 95 | } 96 | 97 | /// Performs a negation that does not panic. 98 | pub trait WrappingNeg: Sized { 99 | /// Wrapping (modular) negation. Computes `-self`, 100 | /// wrapping around at the boundary of the type. 101 | /// 102 | /// Since unsigned types do not have negative equivalents 103 | /// all applications of this function will wrap (except for `-0`). 104 | /// For values smaller than the corresponding signed type's maximum 105 | /// the result is the same as casting the corresponding signed value. 106 | /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where 107 | /// `MAX` is the corresponding signed type's maximum. 108 | /// 109 | /// ``` 110 | /// use num_traits::WrappingNeg; 111 | /// 112 | /// assert_eq!(100i8.wrapping_neg(), -100); 113 | /// assert_eq!((-100i8).wrapping_neg(), 100); 114 | /// assert_eq!((-128i8).wrapping_neg(), -128); // wrapped! 115 | /// ``` 116 | fn wrapping_neg(&self) -> Self; 117 | } 118 | 119 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8); 120 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, u16); 121 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, u32); 122 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, u64); 123 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, usize); 124 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, u128); 125 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, i8); 126 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, i16); 127 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, i32); 128 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, i64); 129 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, isize); 130 | wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128); 131 | 132 | macro_rules! wrapping_shift_impl { 133 | ($trait_name:ident, $method:ident, $t:ty) => { 134 | impl $trait_name for $t { 135 | #[inline] 136 | fn $method(&self, rhs: u32) -> $t { 137 | <$t>::$method(*self, rhs) 138 | } 139 | } 140 | }; 141 | } 142 | 143 | /// Performs a left shift that does not panic. 144 | pub trait WrappingShl: Sized + Shl { 145 | /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, 146 | /// where `mask` removes any high order bits of `rhs` that would 147 | /// cause the shift to exceed the bitwidth of the type. 148 | /// 149 | /// ``` 150 | /// use num_traits::WrappingShl; 151 | /// 152 | /// let x: u16 = 0x0001; 153 | /// 154 | /// assert_eq!(WrappingShl::wrapping_shl(&x, 0), 0x0001); 155 | /// assert_eq!(WrappingShl::wrapping_shl(&x, 1), 0x0002); 156 | /// assert_eq!(WrappingShl::wrapping_shl(&x, 15), 0x8000); 157 | /// assert_eq!(WrappingShl::wrapping_shl(&x, 16), 0x0001); 158 | /// ``` 159 | fn wrapping_shl(&self, rhs: u32) -> Self; 160 | } 161 | 162 | wrapping_shift_impl!(WrappingShl, wrapping_shl, u8); 163 | wrapping_shift_impl!(WrappingShl, wrapping_shl, u16); 164 | wrapping_shift_impl!(WrappingShl, wrapping_shl, u32); 165 | wrapping_shift_impl!(WrappingShl, wrapping_shl, u64); 166 | wrapping_shift_impl!(WrappingShl, wrapping_shl, usize); 167 | wrapping_shift_impl!(WrappingShl, wrapping_shl, u128); 168 | 169 | wrapping_shift_impl!(WrappingShl, wrapping_shl, i8); 170 | wrapping_shift_impl!(WrappingShl, wrapping_shl, i16); 171 | wrapping_shift_impl!(WrappingShl, wrapping_shl, i32); 172 | wrapping_shift_impl!(WrappingShl, wrapping_shl, i64); 173 | wrapping_shift_impl!(WrappingShl, wrapping_shl, isize); 174 | wrapping_shift_impl!(WrappingShl, wrapping_shl, i128); 175 | 176 | /// Performs a right shift that does not panic. 177 | pub trait WrappingShr: Sized + Shr { 178 | /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, 179 | /// where `mask` removes any high order bits of `rhs` that would 180 | /// cause the shift to exceed the bitwidth of the type. 181 | /// 182 | /// ``` 183 | /// use num_traits::WrappingShr; 184 | /// 185 | /// let x: u16 = 0x8000; 186 | /// 187 | /// assert_eq!(WrappingShr::wrapping_shr(&x, 0), 0x8000); 188 | /// assert_eq!(WrappingShr::wrapping_shr(&x, 1), 0x4000); 189 | /// assert_eq!(WrappingShr::wrapping_shr(&x, 15), 0x0001); 190 | /// assert_eq!(WrappingShr::wrapping_shr(&x, 16), 0x8000); 191 | /// ``` 192 | fn wrapping_shr(&self, rhs: u32) -> Self; 193 | } 194 | 195 | wrapping_shift_impl!(WrappingShr, wrapping_shr, u8); 196 | wrapping_shift_impl!(WrappingShr, wrapping_shr, u16); 197 | wrapping_shift_impl!(WrappingShr, wrapping_shr, u32); 198 | wrapping_shift_impl!(WrappingShr, wrapping_shr, u64); 199 | wrapping_shift_impl!(WrappingShr, wrapping_shr, usize); 200 | wrapping_shift_impl!(WrappingShr, wrapping_shr, u128); 201 | 202 | wrapping_shift_impl!(WrappingShr, wrapping_shr, i8); 203 | wrapping_shift_impl!(WrappingShr, wrapping_shr, i16); 204 | wrapping_shift_impl!(WrappingShr, wrapping_shr, i32); 205 | wrapping_shift_impl!(WrappingShr, wrapping_shr, i64); 206 | wrapping_shift_impl!(WrappingShr, wrapping_shr, isize); 207 | wrapping_shift_impl!(WrappingShr, wrapping_shr, i128); 208 | 209 | // Well this is a bit funny, but all the more appropriate. 210 | impl WrappingAdd for Wrapping 211 | where 212 | Wrapping: Add>, 213 | { 214 | fn wrapping_add(&self, v: &Self) -> Self { 215 | Wrapping(self.0.wrapping_add(&v.0)) 216 | } 217 | } 218 | impl WrappingSub for Wrapping 219 | where 220 | Wrapping: Sub>, 221 | { 222 | fn wrapping_sub(&self, v: &Self) -> Self { 223 | Wrapping(self.0.wrapping_sub(&v.0)) 224 | } 225 | } 226 | impl WrappingMul for Wrapping 227 | where 228 | Wrapping: Mul>, 229 | { 230 | fn wrapping_mul(&self, v: &Self) -> Self { 231 | Wrapping(self.0.wrapping_mul(&v.0)) 232 | } 233 | } 234 | impl WrappingNeg for Wrapping 235 | where 236 | Wrapping: Neg>, 237 | { 238 | fn wrapping_neg(&self) -> Self { 239 | Wrapping(self.0.wrapping_neg()) 240 | } 241 | } 242 | impl WrappingShl for Wrapping 243 | where 244 | Wrapping: Shl>, 245 | { 246 | fn wrapping_shl(&self, rhs: u32) -> Self { 247 | Wrapping(self.0.wrapping_shl(rhs)) 248 | } 249 | } 250 | impl WrappingShr for Wrapping 251 | where 252 | Wrapping: Shr>, 253 | { 254 | fn wrapping_shr(&self, rhs: u32) -> Self { 255 | Wrapping(self.0.wrapping_shr(rhs)) 256 | } 257 | } 258 | 259 | #[test] 260 | fn test_wrapping_traits() { 261 | fn wrapping_add(a: T, b: T) -> T { 262 | a.wrapping_add(&b) 263 | } 264 | fn wrapping_sub(a: T, b: T) -> T { 265 | a.wrapping_sub(&b) 266 | } 267 | fn wrapping_mul(a: T, b: T) -> T { 268 | a.wrapping_mul(&b) 269 | } 270 | fn wrapping_neg(a: T) -> T { 271 | a.wrapping_neg() 272 | } 273 | fn wrapping_shl(a: T, b: u32) -> T { 274 | a.wrapping_shl(b) 275 | } 276 | fn wrapping_shr(a: T, b: u32) -> T { 277 | a.wrapping_shr(b) 278 | } 279 | assert_eq!(wrapping_add(255, 1), 0u8); 280 | assert_eq!(wrapping_sub(0, 1), 255u8); 281 | assert_eq!(wrapping_mul(255, 2), 254u8); 282 | assert_eq!(wrapping_neg(255), 1u8); 283 | assert_eq!(wrapping_shl(255, 8), 255u8); 284 | assert_eq!(wrapping_shr(255, 8), 255u8); 285 | assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0); 286 | assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0); 287 | assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0); 288 | assert_eq!(wrapping_neg(255), (-Wrapping(255u8)).0); 289 | assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0); 290 | assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0); 291 | } 292 | 293 | #[test] 294 | fn wrapping_is_wrappingadd() { 295 | fn require_wrappingadd(_: &T) {} 296 | require_wrappingadd(&Wrapping(42)); 297 | } 298 | 299 | #[test] 300 | fn wrapping_is_wrappingsub() { 301 | fn require_wrappingsub(_: &T) {} 302 | require_wrappingsub(&Wrapping(42)); 303 | } 304 | 305 | #[test] 306 | fn wrapping_is_wrappingmul() { 307 | fn require_wrappingmul(_: &T) {} 308 | require_wrappingmul(&Wrapping(42)); 309 | } 310 | 311 | #[test] 312 | fn wrapping_is_wrappingneg() { 313 | fn require_wrappingneg(_: &T) {} 314 | require_wrappingneg(&Wrapping(42)); 315 | } 316 | 317 | #[test] 318 | fn wrapping_is_wrappingshl() { 319 | fn require_wrappingshl(_: &T) {} 320 | require_wrappingshl(&Wrapping(42)); 321 | } 322 | 323 | #[test] 324 | fn wrapping_is_wrappingshr() { 325 | fn require_wrappingshr(_: &T) {} 326 | require_wrappingshr(&Wrapping(42)); 327 | } 328 | -------------------------------------------------------------------------------- /src/pow.rs: -------------------------------------------------------------------------------- 1 | use crate::{CheckedMul, One}; 2 | use core::num::Wrapping; 3 | use core::ops::Mul; 4 | 5 | /// Binary operator for raising a value to a power. 6 | pub trait Pow { 7 | /// The result after applying the operator. 8 | type Output; 9 | 10 | /// Returns `self` to the power `rhs`. 11 | /// 12 | /// # Examples 13 | /// 14 | /// ``` 15 | /// use num_traits::Pow; 16 | /// assert_eq!(Pow::pow(10u32, 2u32), 100); 17 | /// ``` 18 | fn pow(self, rhs: RHS) -> Self::Output; 19 | } 20 | 21 | macro_rules! pow_impl { 22 | ($t:ty) => { 23 | pow_impl!($t, u8); 24 | pow_impl!($t, usize); 25 | 26 | // FIXME: these should be possible 27 | // pow_impl!($t, u16); 28 | // pow_impl!($t, u32); 29 | // pow_impl!($t, u64); 30 | }; 31 | ($t:ty, $rhs:ty) => { 32 | pow_impl!($t, $rhs, usize, pow); 33 | }; 34 | ($t:ty, $rhs:ty, $desired_rhs:ty, $method:expr) => { 35 | impl Pow<$rhs> for $t { 36 | type Output = $t; 37 | #[inline] 38 | fn pow(self, rhs: $rhs) -> $t { 39 | ($method)(self, <$desired_rhs>::from(rhs)) 40 | } 41 | } 42 | 43 | impl<'a> Pow<&'a $rhs> for $t { 44 | type Output = $t; 45 | #[inline] 46 | fn pow(self, rhs: &'a $rhs) -> $t { 47 | ($method)(self, <$desired_rhs>::from(*rhs)) 48 | } 49 | } 50 | 51 | impl<'a> Pow<$rhs> for &'a $t { 52 | type Output = $t; 53 | #[inline] 54 | fn pow(self, rhs: $rhs) -> $t { 55 | ($method)(*self, <$desired_rhs>::from(rhs)) 56 | } 57 | } 58 | 59 | impl<'a, 'b> Pow<&'a $rhs> for &'b $t { 60 | type Output = $t; 61 | #[inline] 62 | fn pow(self, rhs: &'a $rhs) -> $t { 63 | ($method)(*self, <$desired_rhs>::from(*rhs)) 64 | } 65 | } 66 | }; 67 | } 68 | 69 | pow_impl!(u8, u8, u32, u8::pow); 70 | pow_impl!(u8, u16, u32, u8::pow); 71 | pow_impl!(u8, u32, u32, u8::pow); 72 | pow_impl!(u8, usize); 73 | pow_impl!(i8, u8, u32, i8::pow); 74 | pow_impl!(i8, u16, u32, i8::pow); 75 | pow_impl!(i8, u32, u32, i8::pow); 76 | pow_impl!(i8, usize); 77 | pow_impl!(u16, u8, u32, u16::pow); 78 | pow_impl!(u16, u16, u32, u16::pow); 79 | pow_impl!(u16, u32, u32, u16::pow); 80 | pow_impl!(u16, usize); 81 | pow_impl!(i16, u8, u32, i16::pow); 82 | pow_impl!(i16, u16, u32, i16::pow); 83 | pow_impl!(i16, u32, u32, i16::pow); 84 | pow_impl!(i16, usize); 85 | pow_impl!(u32, u8, u32, u32::pow); 86 | pow_impl!(u32, u16, u32, u32::pow); 87 | pow_impl!(u32, u32, u32, u32::pow); 88 | pow_impl!(u32, usize); 89 | pow_impl!(i32, u8, u32, i32::pow); 90 | pow_impl!(i32, u16, u32, i32::pow); 91 | pow_impl!(i32, u32, u32, i32::pow); 92 | pow_impl!(i32, usize); 93 | pow_impl!(u64, u8, u32, u64::pow); 94 | pow_impl!(u64, u16, u32, u64::pow); 95 | pow_impl!(u64, u32, u32, u64::pow); 96 | pow_impl!(u64, usize); 97 | pow_impl!(i64, u8, u32, i64::pow); 98 | pow_impl!(i64, u16, u32, i64::pow); 99 | pow_impl!(i64, u32, u32, i64::pow); 100 | pow_impl!(i64, usize); 101 | 102 | pow_impl!(u128, u8, u32, u128::pow); 103 | pow_impl!(u128, u16, u32, u128::pow); 104 | pow_impl!(u128, u32, u32, u128::pow); 105 | pow_impl!(u128, usize); 106 | 107 | pow_impl!(i128, u8, u32, i128::pow); 108 | pow_impl!(i128, u16, u32, i128::pow); 109 | pow_impl!(i128, u32, u32, i128::pow); 110 | pow_impl!(i128, usize); 111 | 112 | pow_impl!(usize, u8, u32, usize::pow); 113 | pow_impl!(usize, u16, u32, usize::pow); 114 | pow_impl!(usize, u32, u32, usize::pow); 115 | pow_impl!(usize, usize); 116 | pow_impl!(isize, u8, u32, isize::pow); 117 | pow_impl!(isize, u16, u32, isize::pow); 118 | pow_impl!(isize, u32, u32, isize::pow); 119 | pow_impl!(isize, usize); 120 | pow_impl!(Wrapping); 121 | pow_impl!(Wrapping); 122 | pow_impl!(Wrapping); 123 | pow_impl!(Wrapping); 124 | pow_impl!(Wrapping); 125 | pow_impl!(Wrapping); 126 | pow_impl!(Wrapping); 127 | pow_impl!(Wrapping); 128 | pow_impl!(Wrapping); 129 | pow_impl!(Wrapping); 130 | pow_impl!(Wrapping); 131 | pow_impl!(Wrapping); 132 | 133 | // FIXME: these should be possible 134 | // pow_impl!(u8, u64); 135 | // pow_impl!(i16, u64); 136 | // pow_impl!(i8, u64); 137 | // pow_impl!(u16, u64); 138 | // pow_impl!(u32, u64); 139 | // pow_impl!(i32, u64); 140 | // pow_impl!(u64, u64); 141 | // pow_impl!(i64, u64); 142 | // pow_impl!(usize, u64); 143 | // pow_impl!(isize, u64); 144 | 145 | #[cfg(any(feature = "std", feature = "libm"))] 146 | mod float_impls { 147 | use super::Pow; 148 | use crate::Float; 149 | 150 | pow_impl!(f32, i8, i32, ::powi); 151 | pow_impl!(f32, u8, i32, ::powi); 152 | pow_impl!(f32, i16, i32, ::powi); 153 | pow_impl!(f32, u16, i32, ::powi); 154 | pow_impl!(f32, i32, i32, ::powi); 155 | pow_impl!(f64, i8, i32, ::powi); 156 | pow_impl!(f64, u8, i32, ::powi); 157 | pow_impl!(f64, i16, i32, ::powi); 158 | pow_impl!(f64, u16, i32, ::powi); 159 | pow_impl!(f64, i32, i32, ::powi); 160 | pow_impl!(f32, f32, f32, ::powf); 161 | pow_impl!(f64, f32, f64, ::powf); 162 | pow_impl!(f64, f64, f64, ::powf); 163 | } 164 | 165 | /// Raises a value to the power of exp, using exponentiation by squaring. 166 | /// 167 | /// Note that `0⁰` (`pow(0, 0)`) returns `1`. Mathematically this is undefined. 168 | /// 169 | /// # Example 170 | /// 171 | /// ```rust 172 | /// use num_traits::pow; 173 | /// 174 | /// assert_eq!(pow(2i8, 4), 16); 175 | /// assert_eq!(pow(6u8, 3), 216); 176 | /// assert_eq!(pow(0u8, 0), 1); // Be aware if this case affects you 177 | /// ``` 178 | #[inline] 179 | pub fn pow>(mut base: T, mut exp: usize) -> T { 180 | if exp == 0 { 181 | return T::one(); 182 | } 183 | 184 | while exp & 1 == 0 { 185 | base = base.clone() * base; 186 | exp >>= 1; 187 | } 188 | if exp == 1 { 189 | return base; 190 | } 191 | 192 | let mut acc = base.clone(); 193 | while exp > 1 { 194 | exp >>= 1; 195 | base = base.clone() * base; 196 | if exp & 1 == 1 { 197 | acc = acc * base.clone(); 198 | } 199 | } 200 | acc 201 | } 202 | 203 | /// Raises a value to the power of exp, returning `None` if an overflow occurred. 204 | /// 205 | /// Note that `0⁰` (`checked_pow(0, 0)`) returns `Some(1)`. Mathematically this is undefined. 206 | /// 207 | /// Otherwise same as the `pow` function. 208 | /// 209 | /// # Example 210 | /// 211 | /// ```rust 212 | /// use num_traits::checked_pow; 213 | /// 214 | /// assert_eq!(checked_pow(2i8, 4), Some(16)); 215 | /// assert_eq!(checked_pow(7i8, 8), None); 216 | /// assert_eq!(checked_pow(7u32, 8), Some(5_764_801)); 217 | /// assert_eq!(checked_pow(0u32, 0), Some(1)); // Be aware if this case affect you 218 | /// ``` 219 | #[inline] 220 | pub fn checked_pow(mut base: T, mut exp: usize) -> Option { 221 | if exp == 0 { 222 | return Some(T::one()); 223 | } 224 | 225 | while exp & 1 == 0 { 226 | base = base.checked_mul(&base)?; 227 | exp >>= 1; 228 | } 229 | if exp == 1 { 230 | return Some(base); 231 | } 232 | 233 | let mut acc = base.clone(); 234 | while exp > 1 { 235 | exp >>= 1; 236 | base = base.checked_mul(&base)?; 237 | if exp & 1 == 1 { 238 | acc = acc.checked_mul(&base)?; 239 | } 240 | } 241 | Some(acc) 242 | } 243 | -------------------------------------------------------------------------------- /src/real.rs: -------------------------------------------------------------------------------- 1 | #![cfg(any(feature = "std", feature = "libm"))] 2 | 3 | use core::ops::Neg; 4 | 5 | use crate::{Float, Num, NumCast}; 6 | 7 | // NOTE: These doctests have the same issue as those in src/float.rs. 8 | // They're testing the inherent methods directly, and not those of `Real`. 9 | 10 | /// A trait for real number types that do not necessarily have 11 | /// floating-point-specific characteristics such as NaN and infinity. 12 | /// 13 | /// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type) 14 | /// for a list of data types that could meaningfully implement this trait. 15 | /// 16 | /// This trait is only available with the `std` feature, or with the `libm` feature otherwise. 17 | pub trait Real: Num + Copy + NumCast + PartialOrd + Neg { 18 | /// Returns the smallest finite value that this type can represent. 19 | /// 20 | /// ``` 21 | /// use num_traits::real::Real; 22 | /// use std::f64; 23 | /// 24 | /// let x: f64 = Real::min_value(); 25 | /// 26 | /// assert_eq!(x, f64::MIN); 27 | /// ``` 28 | fn min_value() -> Self; 29 | 30 | /// Returns the smallest positive, normalized value that this type can represent. 31 | /// 32 | /// ``` 33 | /// use num_traits::real::Real; 34 | /// use std::f64; 35 | /// 36 | /// let x: f64 = Real::min_positive_value(); 37 | /// 38 | /// assert_eq!(x, f64::MIN_POSITIVE); 39 | /// ``` 40 | fn min_positive_value() -> Self; 41 | 42 | /// Returns epsilon, a small positive value. 43 | /// 44 | /// ``` 45 | /// use num_traits::real::Real; 46 | /// use std::f64; 47 | /// 48 | /// let x: f64 = Real::epsilon(); 49 | /// 50 | /// assert_eq!(x, f64::EPSILON); 51 | /// ``` 52 | /// 53 | /// # Panics 54 | /// 55 | /// The default implementation will panic if `f32::EPSILON` cannot 56 | /// be cast to `Self`. 57 | fn epsilon() -> Self; 58 | 59 | /// Returns the largest finite value that this type can represent. 60 | /// 61 | /// ``` 62 | /// use num_traits::real::Real; 63 | /// use std::f64; 64 | /// 65 | /// let x: f64 = Real::max_value(); 66 | /// assert_eq!(x, f64::MAX); 67 | /// ``` 68 | fn max_value() -> Self; 69 | 70 | /// Returns the largest integer less than or equal to a number. 71 | /// 72 | /// ``` 73 | /// use num_traits::real::Real; 74 | /// 75 | /// let f = 3.99; 76 | /// let g = 3.0; 77 | /// 78 | /// assert_eq!(f.floor(), 3.0); 79 | /// assert_eq!(g.floor(), 3.0); 80 | /// ``` 81 | fn floor(self) -> Self; 82 | 83 | /// Returns the smallest integer greater than or equal to a number. 84 | /// 85 | /// ``` 86 | /// use num_traits::real::Real; 87 | /// 88 | /// let f = 3.01; 89 | /// let g = 4.0; 90 | /// 91 | /// assert_eq!(f.ceil(), 4.0); 92 | /// assert_eq!(g.ceil(), 4.0); 93 | /// ``` 94 | fn ceil(self) -> Self; 95 | 96 | /// Returns the nearest integer to a number. Round half-way cases away from 97 | /// `0.0`. 98 | /// 99 | /// ``` 100 | /// use num_traits::real::Real; 101 | /// 102 | /// let f = 3.3; 103 | /// let g = -3.3; 104 | /// 105 | /// assert_eq!(f.round(), 3.0); 106 | /// assert_eq!(g.round(), -3.0); 107 | /// ``` 108 | fn round(self) -> Self; 109 | 110 | /// Return the integer part of a number. 111 | /// 112 | /// ``` 113 | /// use num_traits::real::Real; 114 | /// 115 | /// let f = 3.3; 116 | /// let g = -3.7; 117 | /// 118 | /// assert_eq!(f.trunc(), 3.0); 119 | /// assert_eq!(g.trunc(), -3.0); 120 | /// ``` 121 | fn trunc(self) -> Self; 122 | 123 | /// Returns the fractional part of a number. 124 | /// 125 | /// ``` 126 | /// use num_traits::real::Real; 127 | /// 128 | /// let x = 3.5; 129 | /// let y = -3.5; 130 | /// let abs_difference_x = (x.fract() - 0.5).abs(); 131 | /// let abs_difference_y = (y.fract() - (-0.5)).abs(); 132 | /// 133 | /// assert!(abs_difference_x < 1e-10); 134 | /// assert!(abs_difference_y < 1e-10); 135 | /// ``` 136 | fn fract(self) -> Self; 137 | 138 | /// Computes the absolute value of `self`. Returns `Float::nan()` if the 139 | /// number is `Float::nan()`. 140 | /// 141 | /// ``` 142 | /// use num_traits::real::Real; 143 | /// use std::f64; 144 | /// 145 | /// let x = 3.5; 146 | /// let y = -3.5; 147 | /// 148 | /// let abs_difference_x = (x.abs() - x).abs(); 149 | /// let abs_difference_y = (y.abs() - (-y)).abs(); 150 | /// 151 | /// assert!(abs_difference_x < 1e-10); 152 | /// assert!(abs_difference_y < 1e-10); 153 | /// 154 | /// assert!(::num_traits::Float::is_nan(f64::NAN.abs())); 155 | /// ``` 156 | fn abs(self) -> Self; 157 | 158 | /// Returns a number that represents the sign of `self`. 159 | /// 160 | /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()` 161 | /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()` 162 | /// - `Float::nan()` if the number is `Float::nan()` 163 | /// 164 | /// ``` 165 | /// use num_traits::real::Real; 166 | /// use std::f64; 167 | /// 168 | /// let f = 3.5; 169 | /// 170 | /// assert_eq!(f.signum(), 1.0); 171 | /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); 172 | /// 173 | /// assert!(f64::NAN.signum().is_nan()); 174 | /// ``` 175 | fn signum(self) -> Self; 176 | 177 | /// Returns `true` if `self` is positive, including `+0.0`, 178 | /// `Float::infinity()`, and with newer versions of Rust `f64::NAN`. 179 | /// 180 | /// ``` 181 | /// use num_traits::real::Real; 182 | /// use std::f64; 183 | /// 184 | /// let neg_nan: f64 = -f64::NAN; 185 | /// 186 | /// let f = 7.0; 187 | /// let g = -7.0; 188 | /// 189 | /// assert!(f.is_sign_positive()); 190 | /// assert!(!g.is_sign_positive()); 191 | /// assert!(!neg_nan.is_sign_positive()); 192 | /// ``` 193 | fn is_sign_positive(self) -> bool; 194 | 195 | /// Returns `true` if `self` is negative, including `-0.0`, 196 | /// `Float::neg_infinity()`, and with newer versions of Rust `-f64::NAN`. 197 | /// 198 | /// ``` 199 | /// use num_traits::real::Real; 200 | /// use std::f64; 201 | /// 202 | /// let nan: f64 = f64::NAN; 203 | /// 204 | /// let f = 7.0; 205 | /// let g = -7.0; 206 | /// 207 | /// assert!(!f.is_sign_negative()); 208 | /// assert!(g.is_sign_negative()); 209 | /// assert!(!nan.is_sign_negative()); 210 | /// ``` 211 | fn is_sign_negative(self) -> bool; 212 | 213 | /// Fused multiply-add. Computes `(self * a) + b` with only one rounding 214 | /// error, yielding a more accurate result than an unfused multiply-add. 215 | /// 216 | /// Using `mul_add` can be more performant than an unfused multiply-add if 217 | /// the target architecture has a dedicated `fma` CPU instruction. 218 | /// 219 | /// ``` 220 | /// use num_traits::real::Real; 221 | /// 222 | /// let m = 10.0; 223 | /// let x = 4.0; 224 | /// let b = 60.0; 225 | /// 226 | /// // 100.0 227 | /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); 228 | /// 229 | /// assert!(abs_difference < 1e-10); 230 | /// ``` 231 | fn mul_add(self, a: Self, b: Self) -> Self; 232 | 233 | /// Take the reciprocal (inverse) of a number, `1/x`. 234 | /// 235 | /// ``` 236 | /// use num_traits::real::Real; 237 | /// 238 | /// let x = 2.0; 239 | /// let abs_difference = (x.recip() - (1.0/x)).abs(); 240 | /// 241 | /// assert!(abs_difference < 1e-10); 242 | /// ``` 243 | fn recip(self) -> Self; 244 | 245 | /// Raise a number to an integer power. 246 | /// 247 | /// Using this function is generally faster than using `powf` 248 | /// 249 | /// ``` 250 | /// use num_traits::real::Real; 251 | /// 252 | /// let x = 2.0; 253 | /// let abs_difference = (x.powi(2) - x*x).abs(); 254 | /// 255 | /// assert!(abs_difference < 1e-10); 256 | /// ``` 257 | fn powi(self, n: i32) -> Self; 258 | 259 | /// Raise a number to a real number power. 260 | /// 261 | /// ``` 262 | /// use num_traits::real::Real; 263 | /// 264 | /// let x = 2.0; 265 | /// let abs_difference = (x.powf(2.0) - x*x).abs(); 266 | /// 267 | /// assert!(abs_difference < 1e-10); 268 | /// ``` 269 | fn powf(self, n: Self) -> Self; 270 | 271 | /// Take the square root of a number. 272 | /// 273 | /// Returns NaN if `self` is a negative floating-point number. 274 | /// 275 | /// # Panics 276 | /// 277 | /// If the implementing type doesn't support NaN, this method should panic if `self < 0`. 278 | /// 279 | /// ``` 280 | /// use num_traits::real::Real; 281 | /// 282 | /// let positive = 4.0; 283 | /// let negative = -4.0; 284 | /// 285 | /// let abs_difference = (positive.sqrt() - 2.0).abs(); 286 | /// 287 | /// assert!(abs_difference < 1e-10); 288 | /// assert!(::num_traits::Float::is_nan(negative.sqrt())); 289 | /// ``` 290 | fn sqrt(self) -> Self; 291 | 292 | /// Returns `e^(self)`, (the exponential function). 293 | /// 294 | /// ``` 295 | /// use num_traits::real::Real; 296 | /// 297 | /// let one = 1.0; 298 | /// // e^1 299 | /// let e = one.exp(); 300 | /// 301 | /// // ln(e) - 1 == 0 302 | /// let abs_difference = (e.ln() - 1.0).abs(); 303 | /// 304 | /// assert!(abs_difference < 1e-10); 305 | /// ``` 306 | fn exp(self) -> Self; 307 | 308 | /// Returns `2^(self)`. 309 | /// 310 | /// ``` 311 | /// use num_traits::real::Real; 312 | /// 313 | /// let f = 2.0; 314 | /// 315 | /// // 2^2 - 4 == 0 316 | /// let abs_difference = (f.exp2() - 4.0).abs(); 317 | /// 318 | /// assert!(abs_difference < 1e-10); 319 | /// ``` 320 | fn exp2(self) -> Self; 321 | 322 | /// Returns the natural logarithm of the number. 323 | /// 324 | /// # Panics 325 | /// 326 | /// If `self <= 0` and this type does not support a NaN representation, this function should panic. 327 | /// 328 | /// ``` 329 | /// use num_traits::real::Real; 330 | /// 331 | /// let one = 1.0; 332 | /// // e^1 333 | /// let e = one.exp(); 334 | /// 335 | /// // ln(e) - 1 == 0 336 | /// let abs_difference = (e.ln() - 1.0).abs(); 337 | /// 338 | /// assert!(abs_difference < 1e-10); 339 | /// ``` 340 | fn ln(self) -> Self; 341 | 342 | /// Returns the logarithm of the number with respect to an arbitrary base. 343 | /// 344 | /// # Panics 345 | /// 346 | /// If `self <= 0` and this type does not support a NaN representation, this function should panic. 347 | /// 348 | /// ``` 349 | /// use num_traits::real::Real; 350 | /// 351 | /// let ten = 10.0; 352 | /// let two = 2.0; 353 | /// 354 | /// // log10(10) - 1 == 0 355 | /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); 356 | /// 357 | /// // log2(2) - 1 == 0 358 | /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); 359 | /// 360 | /// assert!(abs_difference_10 < 1e-10); 361 | /// assert!(abs_difference_2 < 1e-10); 362 | /// ``` 363 | fn log(self, base: Self) -> Self; 364 | 365 | /// Returns the base 2 logarithm of the number. 366 | /// 367 | /// # Panics 368 | /// 369 | /// If `self <= 0` and this type does not support a NaN representation, this function should panic. 370 | /// 371 | /// ``` 372 | /// use num_traits::real::Real; 373 | /// 374 | /// let two = 2.0; 375 | /// 376 | /// // log2(2) - 1 == 0 377 | /// let abs_difference = (two.log2() - 1.0).abs(); 378 | /// 379 | /// assert!(abs_difference < 1e-10); 380 | /// ``` 381 | fn log2(self) -> Self; 382 | 383 | /// Returns the base 10 logarithm of the number. 384 | /// 385 | /// # Panics 386 | /// 387 | /// If `self <= 0` and this type does not support a NaN representation, this function should panic. 388 | /// 389 | /// 390 | /// ``` 391 | /// use num_traits::real::Real; 392 | /// 393 | /// let ten = 10.0; 394 | /// 395 | /// // log10(10) - 1 == 0 396 | /// let abs_difference = (ten.log10() - 1.0).abs(); 397 | /// 398 | /// assert!(abs_difference < 1e-10); 399 | /// ``` 400 | fn log10(self) -> Self; 401 | 402 | /// Converts radians to degrees. 403 | /// 404 | /// ``` 405 | /// use std::f64::consts; 406 | /// 407 | /// let angle = consts::PI; 408 | /// 409 | /// let abs_difference = (angle.to_degrees() - 180.0).abs(); 410 | /// 411 | /// assert!(abs_difference < 1e-10); 412 | /// ``` 413 | fn to_degrees(self) -> Self; 414 | 415 | /// Converts degrees to radians. 416 | /// 417 | /// ``` 418 | /// use std::f64::consts; 419 | /// 420 | /// let angle = 180.0_f64; 421 | /// 422 | /// let abs_difference = (angle.to_radians() - consts::PI).abs(); 423 | /// 424 | /// assert!(abs_difference < 1e-10); 425 | /// ``` 426 | fn to_radians(self) -> Self; 427 | 428 | /// Returns the maximum of the two numbers. 429 | /// 430 | /// ``` 431 | /// use num_traits::real::Real; 432 | /// 433 | /// let x = 1.0; 434 | /// let y = 2.0; 435 | /// 436 | /// assert_eq!(x.max(y), y); 437 | /// ``` 438 | fn max(self, other: Self) -> Self; 439 | 440 | /// Returns the minimum of the two numbers. 441 | /// 442 | /// ``` 443 | /// use num_traits::real::Real; 444 | /// 445 | /// let x = 1.0; 446 | /// let y = 2.0; 447 | /// 448 | /// assert_eq!(x.min(y), x); 449 | /// ``` 450 | fn min(self, other: Self) -> Self; 451 | 452 | /// The positive difference of two numbers. 453 | /// 454 | /// * If `self <= other`: `0:0` 455 | /// * Else: `self - other` 456 | /// 457 | /// ``` 458 | /// use num_traits::real::Real; 459 | /// 460 | /// let x = 3.0; 461 | /// let y = -3.0; 462 | /// 463 | /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); 464 | /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); 465 | /// 466 | /// assert!(abs_difference_x < 1e-10); 467 | /// assert!(abs_difference_y < 1e-10); 468 | /// ``` 469 | fn abs_sub(self, other: Self) -> Self; 470 | 471 | /// Take the cubic root of a number. 472 | /// 473 | /// ``` 474 | /// use num_traits::real::Real; 475 | /// 476 | /// let x = 8.0; 477 | /// 478 | /// // x^(1/3) - 2 == 0 479 | /// let abs_difference = (x.cbrt() - 2.0).abs(); 480 | /// 481 | /// assert!(abs_difference < 1e-10); 482 | /// ``` 483 | fn cbrt(self) -> Self; 484 | 485 | /// Calculate the length of the hypotenuse of a right-angle triangle given 486 | /// legs of length `x` and `y`. 487 | /// 488 | /// ``` 489 | /// use num_traits::real::Real; 490 | /// 491 | /// let x = 2.0; 492 | /// let y = 3.0; 493 | /// 494 | /// // sqrt(x^2 + y^2) 495 | /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); 496 | /// 497 | /// assert!(abs_difference < 1e-10); 498 | /// ``` 499 | fn hypot(self, other: Self) -> Self; 500 | 501 | /// Computes the sine of a number (in radians). 502 | /// 503 | /// ``` 504 | /// use num_traits::real::Real; 505 | /// use std::f64; 506 | /// 507 | /// let x = f64::consts::PI/2.0; 508 | /// 509 | /// let abs_difference = (x.sin() - 1.0).abs(); 510 | /// 511 | /// assert!(abs_difference < 1e-10); 512 | /// ``` 513 | fn sin(self) -> Self; 514 | 515 | /// Computes the cosine of a number (in radians). 516 | /// 517 | /// ``` 518 | /// use num_traits::real::Real; 519 | /// use std::f64; 520 | /// 521 | /// let x = 2.0*f64::consts::PI; 522 | /// 523 | /// let abs_difference = (x.cos() - 1.0).abs(); 524 | /// 525 | /// assert!(abs_difference < 1e-10); 526 | /// ``` 527 | fn cos(self) -> Self; 528 | 529 | /// Computes the tangent of a number (in radians). 530 | /// 531 | /// ``` 532 | /// use num_traits::real::Real; 533 | /// use std::f64; 534 | /// 535 | /// let x = f64::consts::PI/4.0; 536 | /// let abs_difference = (x.tan() - 1.0).abs(); 537 | /// 538 | /// assert!(abs_difference < 1e-14); 539 | /// ``` 540 | fn tan(self) -> Self; 541 | 542 | /// Computes the arcsine of a number. Return value is in radians in 543 | /// the range [-pi/2, pi/2] or NaN if the number is outside the range 544 | /// [-1, 1]. 545 | /// 546 | /// # Panics 547 | /// 548 | /// If this type does not support a NaN representation, this function should panic 549 | /// if the number is outside the range [-1, 1]. 550 | /// 551 | /// ``` 552 | /// use num_traits::real::Real; 553 | /// use std::f64; 554 | /// 555 | /// let f = f64::consts::PI / 2.0; 556 | /// 557 | /// // asin(sin(pi/2)) 558 | /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); 559 | /// 560 | /// assert!(abs_difference < 1e-10); 561 | /// ``` 562 | fn asin(self) -> Self; 563 | 564 | /// Computes the arccosine of a number. Return value is in radians in 565 | /// the range [0, pi] or NaN if the number is outside the range 566 | /// [-1, 1]. 567 | /// 568 | /// # Panics 569 | /// 570 | /// If this type does not support a NaN representation, this function should panic 571 | /// if the number is outside the range [-1, 1]. 572 | /// 573 | /// ``` 574 | /// use num_traits::real::Real; 575 | /// use std::f64; 576 | /// 577 | /// let f = f64::consts::PI / 4.0; 578 | /// 579 | /// // acos(cos(pi/4)) 580 | /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); 581 | /// 582 | /// assert!(abs_difference < 1e-10); 583 | /// ``` 584 | fn acos(self) -> Self; 585 | 586 | /// Computes the arctangent of a number. Return value is in radians in the 587 | /// range [-pi/2, pi/2]; 588 | /// 589 | /// ``` 590 | /// use num_traits::real::Real; 591 | /// 592 | /// let f = 1.0; 593 | /// 594 | /// // atan(tan(1)) 595 | /// let abs_difference = (f.tan().atan() - 1.0).abs(); 596 | /// 597 | /// assert!(abs_difference < 1e-10); 598 | /// ``` 599 | fn atan(self) -> Self; 600 | 601 | /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). 602 | /// 603 | /// * `x = 0`, `y = 0`: `0` 604 | /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` 605 | /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` 606 | /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` 607 | /// 608 | /// ``` 609 | /// use num_traits::real::Real; 610 | /// use std::f64; 611 | /// 612 | /// let pi = f64::consts::PI; 613 | /// // All angles from horizontal right (+x) 614 | /// // 45 deg counter-clockwise 615 | /// let x1 = 3.0; 616 | /// let y1 = -3.0; 617 | /// 618 | /// // 135 deg clockwise 619 | /// let x2 = -3.0; 620 | /// let y2 = 3.0; 621 | /// 622 | /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); 623 | /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); 624 | /// 625 | /// assert!(abs_difference_1 < 1e-10); 626 | /// assert!(abs_difference_2 < 1e-10); 627 | /// ``` 628 | fn atan2(self, other: Self) -> Self; 629 | 630 | /// Simultaneously computes the sine and cosine of the number, `x`. Returns 631 | /// `(sin(x), cos(x))`. 632 | /// 633 | /// ``` 634 | /// use num_traits::real::Real; 635 | /// use std::f64; 636 | /// 637 | /// let x = f64::consts::PI/4.0; 638 | /// let f = x.sin_cos(); 639 | /// 640 | /// let abs_difference_0 = (f.0 - x.sin()).abs(); 641 | /// let abs_difference_1 = (f.1 - x.cos()).abs(); 642 | /// 643 | /// assert!(abs_difference_0 < 1e-10); 644 | /// assert!(abs_difference_0 < 1e-10); 645 | /// ``` 646 | fn sin_cos(self) -> (Self, Self); 647 | 648 | /// Returns `e^(self) - 1` in a way that is accurate even if the 649 | /// number is close to zero. 650 | /// 651 | /// ``` 652 | /// use num_traits::real::Real; 653 | /// 654 | /// let x = 7.0; 655 | /// 656 | /// // e^(ln(7)) - 1 657 | /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); 658 | /// 659 | /// assert!(abs_difference < 1e-10); 660 | /// ``` 661 | fn exp_m1(self) -> Self; 662 | 663 | /// Returns `ln(1+n)` (natural logarithm) more accurately than if 664 | /// the operations were performed separately. 665 | /// 666 | /// # Panics 667 | /// 668 | /// If this type does not support a NaN representation, this function should panic 669 | /// if `self-1 <= 0`. 670 | /// 671 | /// ``` 672 | /// use num_traits::real::Real; 673 | /// use std::f64; 674 | /// 675 | /// let x = f64::consts::E - 1.0; 676 | /// 677 | /// // ln(1 + (e - 1)) == ln(e) == 1 678 | /// let abs_difference = (x.ln_1p() - 1.0).abs(); 679 | /// 680 | /// assert!(abs_difference < 1e-10); 681 | /// ``` 682 | fn ln_1p(self) -> Self; 683 | 684 | /// Hyperbolic sine function. 685 | /// 686 | /// ``` 687 | /// use num_traits::real::Real; 688 | /// use std::f64; 689 | /// 690 | /// let e = f64::consts::E; 691 | /// let x = 1.0; 692 | /// 693 | /// let f = x.sinh(); 694 | /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` 695 | /// let g = (e*e - 1.0)/(2.0*e); 696 | /// let abs_difference = (f - g).abs(); 697 | /// 698 | /// assert!(abs_difference < 1e-10); 699 | /// ``` 700 | fn sinh(self) -> Self; 701 | 702 | /// Hyperbolic cosine function. 703 | /// 704 | /// ``` 705 | /// use num_traits::real::Real; 706 | /// use std::f64; 707 | /// 708 | /// let e = f64::consts::E; 709 | /// let x = 1.0; 710 | /// let f = x.cosh(); 711 | /// // Solving cosh() at 1 gives this result 712 | /// let g = (e*e + 1.0)/(2.0*e); 713 | /// let abs_difference = (f - g).abs(); 714 | /// 715 | /// // Same result 716 | /// assert!(abs_difference < 1.0e-10); 717 | /// ``` 718 | fn cosh(self) -> Self; 719 | 720 | /// Hyperbolic tangent function. 721 | /// 722 | /// ``` 723 | /// use num_traits::real::Real; 724 | /// use std::f64; 725 | /// 726 | /// let e = f64::consts::E; 727 | /// let x = 1.0; 728 | /// 729 | /// let f = x.tanh(); 730 | /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` 731 | /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); 732 | /// let abs_difference = (f - g).abs(); 733 | /// 734 | /// assert!(abs_difference < 1.0e-10); 735 | /// ``` 736 | fn tanh(self) -> Self; 737 | 738 | /// Inverse hyperbolic sine function. 739 | /// 740 | /// ``` 741 | /// use num_traits::real::Real; 742 | /// 743 | /// let x = 1.0; 744 | /// let f = x.sinh().asinh(); 745 | /// 746 | /// let abs_difference = (f - x).abs(); 747 | /// 748 | /// assert!(abs_difference < 1.0e-10); 749 | /// ``` 750 | fn asinh(self) -> Self; 751 | 752 | /// Inverse hyperbolic cosine function. 753 | /// 754 | /// ``` 755 | /// use num_traits::real::Real; 756 | /// 757 | /// let x = 1.0; 758 | /// let f = x.cosh().acosh(); 759 | /// 760 | /// let abs_difference = (f - x).abs(); 761 | /// 762 | /// assert!(abs_difference < 1.0e-10); 763 | /// ``` 764 | fn acosh(self) -> Self; 765 | 766 | /// Inverse hyperbolic tangent function. 767 | /// 768 | /// ``` 769 | /// use num_traits::real::Real; 770 | /// use std::f64; 771 | /// 772 | /// let e = f64::consts::E; 773 | /// let f = e.tanh().atanh(); 774 | /// 775 | /// let abs_difference = (f - e).abs(); 776 | /// 777 | /// assert!(abs_difference < 1.0e-10); 778 | /// ``` 779 | fn atanh(self) -> Self; 780 | } 781 | 782 | impl Real for T { 783 | forward! { 784 | Float::min_value() -> Self; 785 | Float::min_positive_value() -> Self; 786 | Float::epsilon() -> Self; 787 | Float::max_value() -> Self; 788 | } 789 | forward! { 790 | Float::floor(self) -> Self; 791 | Float::ceil(self) -> Self; 792 | Float::round(self) -> Self; 793 | Float::trunc(self) -> Self; 794 | Float::fract(self) -> Self; 795 | Float::abs(self) -> Self; 796 | Float::signum(self) -> Self; 797 | Float::is_sign_positive(self) -> bool; 798 | Float::is_sign_negative(self) -> bool; 799 | Float::mul_add(self, a: Self, b: Self) -> Self; 800 | Float::recip(self) -> Self; 801 | Float::powi(self, n: i32) -> Self; 802 | Float::powf(self, n: Self) -> Self; 803 | Float::sqrt(self) -> Self; 804 | Float::exp(self) -> Self; 805 | Float::exp2(self) -> Self; 806 | Float::ln(self) -> Self; 807 | Float::log(self, base: Self) -> Self; 808 | Float::log2(self) -> Self; 809 | Float::log10(self) -> Self; 810 | Float::to_degrees(self) -> Self; 811 | Float::to_radians(self) -> Self; 812 | Float::max(self, other: Self) -> Self; 813 | Float::min(self, other: Self) -> Self; 814 | Float::abs_sub(self, other: Self) -> Self; 815 | Float::cbrt(self) -> Self; 816 | Float::hypot(self, other: Self) -> Self; 817 | Float::sin(self) -> Self; 818 | Float::cos(self) -> Self; 819 | Float::tan(self) -> Self; 820 | Float::asin(self) -> Self; 821 | Float::acos(self) -> Self; 822 | Float::atan(self) -> Self; 823 | Float::atan2(self, other: Self) -> Self; 824 | Float::sin_cos(self) -> (Self, Self); 825 | Float::exp_m1(self) -> Self; 826 | Float::ln_1p(self) -> Self; 827 | Float::sinh(self) -> Self; 828 | Float::cosh(self) -> Self; 829 | Float::tanh(self) -> Self; 830 | Float::asinh(self) -> Self; 831 | Float::acosh(self) -> Self; 832 | Float::atanh(self) -> Self; 833 | } 834 | } 835 | -------------------------------------------------------------------------------- /src/sign.rs: -------------------------------------------------------------------------------- 1 | use core::num::Wrapping; 2 | use core::ops::Neg; 3 | 4 | use crate::float::FloatCore; 5 | use crate::Num; 6 | 7 | /// Useful functions for signed numbers (i.e. numbers that can be negative). 8 | pub trait Signed: Sized + Num + Neg { 9 | /// Computes the absolute value. 10 | /// 11 | /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`. 12 | /// 13 | /// For signed integers, `::MIN` will be returned if the number is `::MIN`. 14 | fn abs(&self) -> Self; 15 | 16 | /// The positive difference of two numbers. 17 | /// 18 | /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference 19 | /// between `self` and `other` is returned. 20 | fn abs_sub(&self, other: &Self) -> Self; 21 | 22 | /// Returns the sign of the number. 23 | /// 24 | /// For `f32` and `f64`: 25 | /// 26 | /// * `1.0` if the number is positive, `+0.0` or `INFINITY` 27 | /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` 28 | /// * `NaN` if the number is `NaN` 29 | /// 30 | /// For signed integers: 31 | /// 32 | /// * `0` if the number is zero 33 | /// * `1` if the number is positive 34 | /// * `-1` if the number is negative 35 | fn signum(&self) -> Self; 36 | 37 | /// Returns true if the number is positive and false if the number is zero or negative. 38 | fn is_positive(&self) -> bool; 39 | 40 | /// Returns true if the number is negative and false if the number is zero or positive. 41 | fn is_negative(&self) -> bool; 42 | } 43 | 44 | macro_rules! signed_impl { 45 | ($($t:ty)*) => ($( 46 | impl Signed for $t { 47 | #[inline] 48 | fn abs(&self) -> $t { 49 | if self.is_negative() { -*self } else { *self } 50 | } 51 | 52 | #[inline] 53 | fn abs_sub(&self, other: &$t) -> $t { 54 | if *self <= *other { 0 } else { *self - *other } 55 | } 56 | 57 | #[inline] 58 | fn signum(&self) -> $t { 59 | match *self { 60 | n if n > 0 => 1, 61 | 0 => 0, 62 | _ => -1, 63 | } 64 | } 65 | 66 | #[inline] 67 | fn is_positive(&self) -> bool { *self > 0 } 68 | 69 | #[inline] 70 | fn is_negative(&self) -> bool { *self < 0 } 71 | } 72 | )*) 73 | } 74 | 75 | signed_impl!(isize i8 i16 i32 i64 i128); 76 | 77 | impl Signed for Wrapping 78 | where 79 | Wrapping: Num + Neg>, 80 | { 81 | #[inline] 82 | fn abs(&self) -> Self { 83 | Wrapping(self.0.abs()) 84 | } 85 | 86 | #[inline] 87 | fn abs_sub(&self, other: &Self) -> Self { 88 | Wrapping(self.0.abs_sub(&other.0)) 89 | } 90 | 91 | #[inline] 92 | fn signum(&self) -> Self { 93 | Wrapping(self.0.signum()) 94 | } 95 | 96 | #[inline] 97 | fn is_positive(&self) -> bool { 98 | self.0.is_positive() 99 | } 100 | 101 | #[inline] 102 | fn is_negative(&self) -> bool { 103 | self.0.is_negative() 104 | } 105 | } 106 | 107 | macro_rules! signed_float_impl { 108 | ($t:ty) => { 109 | impl Signed for $t { 110 | /// Computes the absolute value. Returns `NAN` if the number is `NAN`. 111 | #[inline] 112 | fn abs(&self) -> $t { 113 | FloatCore::abs(*self) 114 | } 115 | 116 | /// The positive difference of two numbers. Returns `0.0` if the number is 117 | /// less than or equal to `other`, otherwise the difference between`self` 118 | /// and `other` is returned. 119 | #[inline] 120 | fn abs_sub(&self, other: &$t) -> $t { 121 | if *self <= *other { 122 | 0. 123 | } else { 124 | *self - *other 125 | } 126 | } 127 | 128 | /// # Returns 129 | /// 130 | /// - `1.0` if the number is positive, `+0.0` or `INFINITY` 131 | /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` 132 | /// - `NAN` if the number is NaN 133 | #[inline] 134 | fn signum(&self) -> $t { 135 | FloatCore::signum(*self) 136 | } 137 | 138 | /// Returns `true` if the number is positive, including `+0.0` and `INFINITY` 139 | #[inline] 140 | fn is_positive(&self) -> bool { 141 | FloatCore::is_sign_positive(*self) 142 | } 143 | 144 | /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY` 145 | #[inline] 146 | fn is_negative(&self) -> bool { 147 | FloatCore::is_sign_negative(*self) 148 | } 149 | } 150 | }; 151 | } 152 | 153 | signed_float_impl!(f32); 154 | signed_float_impl!(f64); 155 | 156 | /// Computes the absolute value. 157 | /// 158 | /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN` 159 | /// 160 | /// For signed integers, `::MIN` will be returned if the number is `::MIN`. 161 | #[inline(always)] 162 | pub fn abs(value: T) -> T { 163 | value.abs() 164 | } 165 | 166 | /// The positive difference of two numbers. 167 | /// 168 | /// Returns zero if `x` is less than or equal to `y`, otherwise the difference 169 | /// between `x` and `y` is returned. 170 | #[inline(always)] 171 | pub fn abs_sub(x: T, y: T) -> T { 172 | x.abs_sub(&y) 173 | } 174 | 175 | /// Returns the sign of the number. 176 | /// 177 | /// For `f32` and `f64`: 178 | /// 179 | /// * `1.0` if the number is positive, `+0.0` or `INFINITY` 180 | /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` 181 | /// * `NaN` if the number is `NaN` 182 | /// 183 | /// For signed integers: 184 | /// 185 | /// * `0` if the number is zero 186 | /// * `1` if the number is positive 187 | /// * `-1` if the number is negative 188 | #[inline(always)] 189 | pub fn signum(value: T) -> T { 190 | value.signum() 191 | } 192 | 193 | /// A trait for values which cannot be negative 194 | pub trait Unsigned: Num {} 195 | 196 | macro_rules! empty_trait_impl { 197 | ($name:ident for $($t:ty)*) => ($( 198 | impl $name for $t {} 199 | )*) 200 | } 201 | 202 | empty_trait_impl!(Unsigned for usize u8 u16 u32 u64 u128); 203 | 204 | impl Unsigned for Wrapping where Wrapping: Num {} 205 | 206 | #[test] 207 | fn unsigned_wrapping_is_unsigned() { 208 | fn require_unsigned(_: &T) {} 209 | require_unsigned(&Wrapping(42_u32)); 210 | } 211 | 212 | #[test] 213 | fn signed_wrapping_is_signed() { 214 | fn require_signed(_: &T) {} 215 | require_signed(&Wrapping(-42)); 216 | } 217 | -------------------------------------------------------------------------------- /tests/cast.rs: -------------------------------------------------------------------------------- 1 | //! Tests of `num_traits::cast`. 2 | 3 | #![cfg_attr(not(feature = "std"), no_std)] 4 | 5 | use num_traits::cast::*; 6 | use num_traits::Bounded; 7 | 8 | use core::{f32, f64}; 9 | use core::{i128, i16, i32, i64, i8, isize}; 10 | use core::{u128, u16, u32, u64, u8, usize}; 11 | 12 | use core::fmt::Debug; 13 | use core::mem; 14 | use core::num::Wrapping; 15 | 16 | #[test] 17 | fn to_primitive_float() { 18 | let f32_toolarge = 1e39f64; 19 | assert_eq!(f32_toolarge.to_f32(), Some(f32::INFINITY)); 20 | assert_eq!((-f32_toolarge).to_f32(), Some(f32::NEG_INFINITY)); 21 | assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX)); 22 | assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX)); 23 | assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY)); 24 | assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY)); 25 | assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan())); 26 | } 27 | 28 | #[test] 29 | fn wrapping_to_primitive() { 30 | macro_rules! test_wrapping_to_primitive { 31 | ($($t:ty)+) => { 32 | $({ 33 | let i: $t = 0; 34 | let w = Wrapping(i); 35 | assert_eq!(i.to_u8(), w.to_u8()); 36 | assert_eq!(i.to_u16(), w.to_u16()); 37 | assert_eq!(i.to_u32(), w.to_u32()); 38 | assert_eq!(i.to_u64(), w.to_u64()); 39 | assert_eq!(i.to_usize(), w.to_usize()); 40 | assert_eq!(i.to_i8(), w.to_i8()); 41 | assert_eq!(i.to_i16(), w.to_i16()); 42 | assert_eq!(i.to_i32(), w.to_i32()); 43 | assert_eq!(i.to_i64(), w.to_i64()); 44 | assert_eq!(i.to_isize(), w.to_isize()); 45 | assert_eq!(i.to_f32(), w.to_f32()); 46 | assert_eq!(i.to_f64(), w.to_f64()); 47 | })+ 48 | }; 49 | } 50 | 51 | test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); 52 | } 53 | 54 | #[test] 55 | fn wrapping_is_toprimitive() { 56 | fn require_toprimitive(_: &T) {} 57 | require_toprimitive(&Wrapping(42)); 58 | } 59 | 60 | #[test] 61 | fn wrapping_is_fromprimitive() { 62 | fn require_fromprimitive(_: &T) {} 63 | require_fromprimitive(&Wrapping(42)); 64 | } 65 | 66 | #[test] 67 | fn wrapping_is_numcast() { 68 | fn require_numcast(_: &T) {} 69 | require_numcast(&Wrapping(42)); 70 | } 71 | 72 | #[test] 73 | fn as_primitive() { 74 | let x: f32 = (1.625f64).as_(); 75 | assert_eq!(x, 1.625f32); 76 | 77 | let x: f32 = (3.14159265358979323846f64).as_(); 78 | assert_eq!(x, 3.1415927f32); 79 | 80 | let x: u8 = (768i16).as_(); 81 | assert_eq!(x, 0); 82 | } 83 | 84 | #[test] 85 | fn float_to_integer_checks_overflow() { 86 | // This will overflow an i32 87 | let source: f64 = 1.0e+123f64; 88 | 89 | // Expect the overflow to be caught 90 | assert_eq!(cast::(source), None); 91 | } 92 | 93 | #[test] 94 | fn cast_to_int_checks_overflow() { 95 | let big_f: f64 = 1.0e123; 96 | let normal_f: f64 = 1.0; 97 | let small_f: f64 = -1.0e123; 98 | assert_eq!(None, cast::(big_f)); 99 | assert_eq!(None, cast::(big_f)); 100 | assert_eq!(None, cast::(big_f)); 101 | assert_eq!(None, cast::(big_f)); 102 | assert_eq!(None, cast::(big_f)); 103 | 104 | assert_eq!(Some(normal_f as isize), cast::(normal_f)); 105 | assert_eq!(Some(normal_f as i8), cast::(normal_f)); 106 | assert_eq!(Some(normal_f as i16), cast::(normal_f)); 107 | assert_eq!(Some(normal_f as i32), cast::(normal_f)); 108 | assert_eq!(Some(normal_f as i64), cast::(normal_f)); 109 | 110 | assert_eq!(None, cast::(small_f)); 111 | assert_eq!(None, cast::(small_f)); 112 | assert_eq!(None, cast::(small_f)); 113 | assert_eq!(None, cast::(small_f)); 114 | assert_eq!(None, cast::(small_f)); 115 | } 116 | 117 | #[test] 118 | fn cast_to_unsigned_int_checks_overflow() { 119 | let big_f: f64 = 1.0e123; 120 | let normal_f: f64 = 1.0; 121 | let small_f: f64 = -1.0e123; 122 | assert_eq!(None, cast::(big_f)); 123 | assert_eq!(None, cast::(big_f)); 124 | assert_eq!(None, cast::(big_f)); 125 | assert_eq!(None, cast::(big_f)); 126 | assert_eq!(None, cast::(big_f)); 127 | 128 | assert_eq!(Some(normal_f as usize), cast::(normal_f)); 129 | assert_eq!(Some(normal_f as u8), cast::(normal_f)); 130 | assert_eq!(Some(normal_f as u16), cast::(normal_f)); 131 | assert_eq!(Some(normal_f as u32), cast::(normal_f)); 132 | assert_eq!(Some(normal_f as u64), cast::(normal_f)); 133 | 134 | assert_eq!(None, cast::(small_f)); 135 | assert_eq!(None, cast::(small_f)); 136 | assert_eq!(None, cast::(small_f)); 137 | assert_eq!(None, cast::(small_f)); 138 | assert_eq!(None, cast::(small_f)); 139 | } 140 | 141 | #[test] 142 | fn cast_to_i128_checks_overflow() { 143 | let big_f: f64 = 1.0e123; 144 | let normal_f: f64 = 1.0; 145 | let small_f: f64 = -1.0e123; 146 | assert_eq!(None, cast::(big_f)); 147 | assert_eq!(None, cast::(big_f)); 148 | 149 | assert_eq!(Some(normal_f as i128), cast::(normal_f)); 150 | assert_eq!(Some(normal_f as u128), cast::(normal_f)); 151 | 152 | assert_eq!(None, cast::(small_f)); 153 | assert_eq!(None, cast::(small_f)); 154 | } 155 | 156 | #[cfg(feature = "std")] 157 | fn dbg(args: ::core::fmt::Arguments<'_>) { 158 | println!("{}", args); 159 | } 160 | 161 | #[cfg(not(feature = "std"))] 162 | fn dbg(_: ::core::fmt::Arguments) {} 163 | 164 | // Rust 1.8 doesn't handle cfg on macros correctly 165 | macro_rules! dbg { ($($tok:tt)*) => { dbg(format_args!($($tok)*)) } } 166 | 167 | macro_rules! float_test_edge { 168 | ($f:ident -> $($t:ident)+) => { $({ 169 | dbg!("testing cast edge cases for {} -> {}", stringify!($f), stringify!($t)); 170 | 171 | let small = if $t::MIN == 0 || mem::size_of::<$t>() < mem::size_of::<$f>() { 172 | $t::MIN as $f - 1.0 173 | } else { 174 | ($t::MIN as $f).raw_inc().floor() 175 | }; 176 | let fmin = small.raw_dec(); 177 | dbg!(" testing min {}\n\tvs. {:.0}\n\tand {:.0}", $t::MIN, fmin, small); 178 | assert_eq!(Some($t::MIN), cast::<$f, $t>($t::MIN as $f)); 179 | assert_eq!(Some($t::MIN), cast::<$f, $t>(fmin)); 180 | assert_eq!(None, cast::<$f, $t>(small)); 181 | 182 | let (max, large) = if mem::size_of::<$t>() < mem::size_of::<$f>() { 183 | ($t::MAX, $t::MAX as $f + 1.0) 184 | } else { 185 | let large = $t::MAX as $f; // rounds up! 186 | let max = large.raw_dec() as $t; // the next smallest possible 187 | assert_eq!(max.count_ones(), $f::MANTISSA_DIGITS); 188 | (max, large) 189 | }; 190 | let fmax = large.raw_dec(); 191 | dbg!(" testing max {}\n\tvs. {:.0}\n\tand {:.0}", max, fmax, large); 192 | assert_eq!(Some(max), cast::<$f, $t>(max as $f)); 193 | assert_eq!(Some(max), cast::<$f, $t>(fmax)); 194 | assert_eq!(None, cast::<$f, $t>(large)); 195 | 196 | dbg!(" testing non-finite values"); 197 | assert_eq!(None, cast::<$f, $t>($f::NAN)); 198 | assert_eq!(None, cast::<$f, $t>($f::INFINITY)); 199 | assert_eq!(None, cast::<$f, $t>($f::NEG_INFINITY)); 200 | })+} 201 | } 202 | 203 | trait RawOffset: Sized { 204 | fn raw_inc(self) -> Self; 205 | fn raw_dec(self) -> Self; 206 | } 207 | 208 | impl RawOffset for f32 { 209 | fn raw_inc(self) -> Self { 210 | Self::from_bits(self.to_bits() + 1) 211 | } 212 | 213 | fn raw_dec(self) -> Self { 214 | Self::from_bits(self.to_bits() - 1) 215 | } 216 | } 217 | 218 | impl RawOffset for f64 { 219 | fn raw_inc(self) -> Self { 220 | Self::from_bits(self.to_bits() + 1) 221 | } 222 | 223 | fn raw_dec(self) -> Self { 224 | Self::from_bits(self.to_bits() - 1) 225 | } 226 | } 227 | 228 | #[test] 229 | fn cast_float_to_int_edge_cases() { 230 | float_test_edge!(f32 -> isize i8 i16 i32 i64); 231 | float_test_edge!(f32 -> usize u8 u16 u32 u64); 232 | float_test_edge!(f64 -> isize i8 i16 i32 i64); 233 | float_test_edge!(f64 -> usize u8 u16 u32 u64); 234 | } 235 | 236 | #[test] 237 | fn cast_float_to_i128_edge_cases() { 238 | float_test_edge!(f32 -> i128 u128); 239 | float_test_edge!(f64 -> i128 u128); 240 | } 241 | 242 | macro_rules! int_test_edge { 243 | ($f:ident -> { $($t:ident)+ } with $BigS:ident $BigU:ident ) => { $({ 244 | #[allow(arithmetic_overflow)] // https://github.com/rust-lang/rust/issues/109731 245 | fn test_edge() { 246 | dbg!("testing cast edge cases for {} -> {}", stringify!($f), stringify!($t)); 247 | 248 | match ($f::MIN as $BigS).cmp(&($t::MIN as $BigS)) { 249 | Greater => { 250 | assert_eq!(Some($f::MIN as $t), cast::<$f, $t>($f::MIN)); 251 | } 252 | Equal => { 253 | assert_eq!(Some($t::MIN), cast::<$f, $t>($f::MIN)); 254 | } 255 | Less => { 256 | let min = $t::MIN as $f; 257 | assert_eq!(Some($t::MIN), cast::<$f, $t>(min)); 258 | assert_eq!(None, cast::<$f, $t>(min - 1)); 259 | } 260 | } 261 | 262 | match ($f::MAX as $BigU).cmp(&($t::MAX as $BigU)) { 263 | Greater => { 264 | let max = $t::MAX as $f; 265 | assert_eq!(Some($t::MAX), cast::<$f, $t>(max)); 266 | assert_eq!(None, cast::<$f, $t>(max + 1)); 267 | } 268 | Equal => { 269 | assert_eq!(Some($t::MAX), cast::<$f, $t>($f::MAX)); 270 | } 271 | Less => { 272 | assert_eq!(Some($f::MAX as $t), cast::<$f, $t>($f::MAX)); 273 | } 274 | } 275 | } 276 | test_edge(); 277 | })+} 278 | } 279 | 280 | #[test] 281 | fn cast_int_to_int_edge_cases() { 282 | use core::cmp::Ordering::*; 283 | 284 | macro_rules! test_edge { 285 | ($( $from:ident )+) => { $({ 286 | int_test_edge!($from -> { isize i8 i16 i32 i64 } with i64 u64); 287 | int_test_edge!($from -> { usize u8 u16 u32 u64 } with i64 u64); 288 | })+} 289 | } 290 | 291 | test_edge!(isize i8 i16 i32 i64); 292 | test_edge!(usize u8 u16 u32 u64); 293 | } 294 | 295 | #[test] 296 | fn cast_int_to_128_edge_cases() { 297 | use core::cmp::Ordering::*; 298 | 299 | macro_rules! test_edge { 300 | ($( $t:ident )+) => { 301 | $( 302 | int_test_edge!($t -> { i128 u128 } with i128 u128); 303 | )+ 304 | int_test_edge!(i128 -> { $( $t )+ } with i128 u128); 305 | int_test_edge!(u128 -> { $( $t )+ } with i128 u128); 306 | } 307 | } 308 | 309 | test_edge!(isize i8 i16 i32 i64 i128); 310 | test_edge!(usize u8 u16 u32 u64 u128); 311 | } 312 | 313 | #[test] 314 | fn newtype_from_primitive() { 315 | #[derive(PartialEq, Debug)] 316 | struct New(T); 317 | 318 | // minimal impl 319 | impl FromPrimitive for New { 320 | fn from_i64(n: i64) -> Option { 321 | T::from_i64(n).map(New) 322 | } 323 | 324 | fn from_u64(n: u64) -> Option { 325 | T::from_u64(n).map(New) 326 | } 327 | } 328 | 329 | macro_rules! assert_eq_from { 330 | ($( $from:ident )+) => {$( 331 | assert_eq!(T::$from(Bounded::min_value()).map(New), 332 | New::::$from(Bounded::min_value())); 333 | assert_eq!(T::$from(Bounded::max_value()).map(New), 334 | New::::$from(Bounded::max_value())); 335 | )+} 336 | } 337 | 338 | fn check() { 339 | assert_eq_from!(from_i8 from_i16 from_i32 from_i64 from_isize); 340 | assert_eq_from!(from_u8 from_u16 from_u32 from_u64 from_usize); 341 | assert_eq_from!(from_f32 from_f64); 342 | } 343 | 344 | macro_rules! check { 345 | ($( $ty:ty )+) => {$( check::<$ty>(); )+} 346 | } 347 | check!(i8 i16 i32 i64 isize); 348 | check!(u8 u16 u32 u64 usize); 349 | } 350 | 351 | #[test] 352 | fn newtype_to_primitive() { 353 | #[derive(PartialEq, Debug)] 354 | struct New(T); 355 | 356 | // minimal impl 357 | impl ToPrimitive for New { 358 | fn to_i64(&self) -> Option { 359 | self.0.to_i64() 360 | } 361 | 362 | fn to_u64(&self) -> Option { 363 | self.0.to_u64() 364 | } 365 | } 366 | 367 | macro_rules! assert_eq_to { 368 | ($( $to:ident )+) => {$( 369 | assert_eq!(T::$to(&Bounded::min_value()), 370 | New::::$to(&New(Bounded::min_value()))); 371 | assert_eq!(T::$to(&Bounded::max_value()), 372 | New::::$to(&New(Bounded::max_value()))); 373 | )+} 374 | } 375 | 376 | fn check() { 377 | assert_eq_to!(to_i8 to_i16 to_i32 to_i64 to_isize); 378 | assert_eq_to!(to_u8 to_u16 to_u32 to_u64 to_usize); 379 | assert_eq_to!(to_f32 to_f64); 380 | } 381 | 382 | macro_rules! check { 383 | ($( $ty:ty )+) => {$( check::<$ty>(); )+} 384 | } 385 | check!(i8 i16 i32 i64 isize); 386 | check!(u8 u16 u32 u64 usize); 387 | } 388 | --------------------------------------------------------------------------------